diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-04-25 11:06:54 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-04-25 11:06:54 +0200 |
commit | f78be920bdff51d185ee0f53b1aeb84b5a8ae765 (patch) | |
tree | e03ab32a3e3ddcecf588e98d83ed84bcdd614d9d /src/transport/gnunet-service-tng.c | |
parent | 5a2043c744571ae72252d5c9c66443121adc22d8 (diff) | |
download | gnunet-f78be920bdff51d185ee0f53b1aeb84b5a8ae765.tar.gz gnunet-f78be920bdff51d185ee0f53b1aeb84b5a8ae765.zip |
complete handle_client_send()
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r-- | src/transport/gnunet-service-tng.c | 321 |
1 files changed, 202 insertions, 119 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 2f7129478..baf443f03 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -923,6 +923,41 @@ enum ClientType | |||
923 | 923 | ||
924 | 924 | ||
925 | /** | 925 | /** |
926 | * Which transmission options are allowable for transmission? | ||
927 | * Interpreted bit-wise! | ||
928 | */ | ||
929 | enum RouteMessageOptions | ||
930 | { | ||
931 | /** | ||
932 | * Only confirmed, non-DV direct neighbours. | ||
933 | */ | ||
934 | RMO_NONE = 0, | ||
935 | |||
936 | /** | ||
937 | * We are allowed to use DV routing for this @a hdr | ||
938 | */ | ||
939 | RMO_DV_ALLOWED = 1, | ||
940 | |||
941 | /** | ||
942 | * We are allowed to use unconfirmed queues or DV routes for this message | ||
943 | */ | ||
944 | RMO_UNCONFIRMED_ALLOWED = 2, | ||
945 | |||
946 | /** | ||
947 | * Reliable and unreliable, DV and non-DV are all acceptable. | ||
948 | */ | ||
949 | RMO_ANYTHING_GOES = (RMO_DV_ALLOWED | RMO_UNCONFIRMED_ALLOWED), | ||
950 | |||
951 | /** | ||
952 | * If we have multiple choices, it is OK to send this message | ||
953 | * over multiple channels at the same time to improve loss tolerance. | ||
954 | * (We do at most 2 transmissions.) | ||
955 | */ | ||
956 | RMO_REDUNDANT = 4 | ||
957 | }; | ||
958 | |||
959 | |||
960 | /** | ||
926 | * When did we launch this DV learning activity? | 961 | * When did we launch this DV learning activity? |
927 | */ | 962 | */ |
928 | struct LearnLaunchEntry | 963 | struct LearnLaunchEntry |
@@ -3453,6 +3488,130 @@ check_queue_timeouts (void *cls) | |||
3453 | 3488 | ||
3454 | 3489 | ||
3455 | /** | 3490 | /** |
3491 | * Create a DV Box message. | ||
3492 | * | ||
3493 | * @param total_hops how many hops did the message take so far | ||
3494 | * @param num_hops length of the @a hops array | ||
3495 | * @param origin origin of the message | ||
3496 | * @param hops next peer(s) to the destination, including destination | ||
3497 | * @param payload payload of the box | ||
3498 | * @param payload_size number of bytes in @a payload | ||
3499 | * @return boxed message (caller must #GNUNET_free() it). | ||
3500 | */ | ||
3501 | static struct TransportDVBoxMessage * | ||
3502 | create_dv_box (uint16_t total_hops, | ||
3503 | const struct GNUNET_PeerIdentity *origin, | ||
3504 | const struct GNUNET_PeerIdentity *target, | ||
3505 | uint16_t num_hops, | ||
3506 | const struct GNUNET_PeerIdentity *hops, | ||
3507 | const void *payload, | ||
3508 | uint16_t payload_size) | ||
3509 | { | ||
3510 | struct TransportDVBoxMessage *dvb; | ||
3511 | struct GNUNET_PeerIdentity *dhops; | ||
3512 | |||
3513 | GNUNET_assert (UINT16_MAX < | ||
3514 | sizeof (struct TransportDVBoxMessage) + | ||
3515 | sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + | ||
3516 | payload_size); | ||
3517 | dvb = GNUNET_malloc (sizeof (struct TransportDVBoxMessage) + | ||
3518 | sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + | ||
3519 | payload_size); | ||
3520 | dvb->header.size = | ||
3521 | htons (sizeof (struct TransportDVBoxMessage) + | ||
3522 | sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + payload_size); | ||
3523 | dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); | ||
3524 | dvb->total_hops = htons (total_hops); | ||
3525 | dvb->num_hops = htons (num_hops + 1); | ||
3526 | dvb->origin = *origin; | ||
3527 | dhops = (struct GNUNET_PeerIdentity *) &dvb[1]; | ||
3528 | memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity)); | ||
3529 | dhops[num_hops] = *target; | ||
3530 | memcpy (&dhops[num_hops + 1], payload, payload_size); | ||
3531 | return dvb; | ||
3532 | } | ||
3533 | |||
3534 | |||
3535 | /** | ||
3536 | * Pick @a hops_array_length random DV paths satisfying @a options | ||
3537 | * | ||
3538 | * @param dv data structure to pick paths from | ||
3539 | * @param options constraints to satisfy | ||
3540 | * @param hops_array[out] set to the result | ||
3541 | * @param hops_array_length length of the @a hops_array | ||
3542 | * @return number of entries set in @a hops_array | ||
3543 | */ | ||
3544 | static unsigned int | ||
3545 | pick_random_dv_hops (const struct DistanceVector *dv, | ||
3546 | enum RouteMessageOptions options, | ||
3547 | struct DistanceVectorHop **hops_array, | ||
3548 | unsigned int hops_array_length) | ||
3549 | { | ||
3550 | uint64_t choices[hops_array_length]; | ||
3551 | uint64_t num_dv; | ||
3552 | unsigned int dv_count; | ||
3553 | |||
3554 | /* Pick random vectors, but weighted by distance, giving more weight | ||
3555 | to shorter vectors */ | ||
3556 | num_dv = 0; | ||
3557 | dv_count = 0; | ||
3558 | for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; | ||
3559 | pos = pos->next_dv) | ||
3560 | { | ||
3561 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && | ||
3562 | (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until) | ||
3563 | .rel_value_us == 0)) | ||
3564 | continue; /* pos unconfirmed and confirmed required */ | ||
3565 | num_dv += MAX_DV_HOPS_ALLOWED - pos->distance; | ||
3566 | dv_count++; | ||
3567 | } | ||
3568 | if (0 == dv_count) | ||
3569 | return 0; | ||
3570 | if (dv_count <= hops_array_length) | ||
3571 | { | ||
3572 | dv_count = 0; | ||
3573 | for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; | ||
3574 | pos = pos->next_dv) | ||
3575 | hops_array[dv_count++] = pos; | ||
3576 | return dv_count; | ||
3577 | } | ||
3578 | for (unsigned int i = 0; i < hops_array_length; i++) | ||
3579 | { | ||
3580 | int ok = GNUNET_NO; | ||
3581 | while (GNUNET_NO == ok) | ||
3582 | { | ||
3583 | choices[i] = | ||
3584 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv); | ||
3585 | ok = GNUNET_YES; | ||
3586 | for (unsigned int j = 0; j < i; j++) | ||
3587 | if (choices[i] == choices[j]) | ||
3588 | { | ||
3589 | ok = GNUNET_NO; | ||
3590 | break; | ||
3591 | } | ||
3592 | } | ||
3593 | } | ||
3594 | dv_count = 0; | ||
3595 | num_dv = 0; | ||
3596 | for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; | ||
3597 | pos = pos->next_dv) | ||
3598 | { | ||
3599 | uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance; | ||
3600 | |||
3601 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && | ||
3602 | (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until) | ||
3603 | .rel_value_us == 0)) | ||
3604 | continue; /* pos unconfirmed and confirmed required */ | ||
3605 | for (unsigned int i = 0; i < hops_array_length; i++) | ||
3606 | if ((num_dv <= choices[i]) && (num_dv + delta > choices[i])) | ||
3607 | hops_array[dv_count++] = pos; | ||
3608 | num_dv += delta; | ||
3609 | } | ||
3610 | return dv_count; | ||
3611 | } | ||
3612 | |||
3613 | |||
3614 | /** | ||
3456 | * Client asked for transmission to a peer. Process the request. | 3615 | * Client asked for transmission to a peer. Process the request. |
3457 | * | 3616 | * |
3458 | * @param cls the client | 3617 | * @param cls the client |
@@ -3471,6 +3630,7 @@ handle_client_send (void *cls, const struct OutboundMessage *obm) | |||
3471 | int was_empty; | 3630 | int was_empty; |
3472 | const void *payload; | 3631 | const void *payload; |
3473 | size_t payload_size; | 3632 | size_t payload_size; |
3633 | struct TransportDVBoxMessage *dvb; | ||
3474 | 3634 | ||
3475 | GNUNET_assert (CT_CORE == tc->type); | 3635 | GNUNET_assert (CT_CORE == tc->type); |
3476 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; | 3636 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; |
@@ -3504,18 +3664,26 @@ handle_client_send (void *cls, const struct OutboundMessage *obm) | |||
3504 | } | 3664 | } |
3505 | if (NULL == target) | 3665 | if (NULL == target) |
3506 | { | 3666 | { |
3507 | // FIXME: overall, similar logic exists already for DV boxing, | 3667 | unsigned int res; |
3508 | // re-use! | 3668 | struct DistanceVectorHop *dvh; |
3509 | 3669 | ||
3510 | // FIXME: dvh = pick_dv_hop (dv); | 3670 | res = pick_random_dv_hops (dv, RMO_NONE, &dvh, 1); |
3671 | GNUNET_assert (1 == res); | ||
3511 | target = dvh->next_hop; | 3672 | target = dvh->next_hop; |
3512 | // FIXME: dv box message here! | 3673 | dvb = create_dv_box (0, |
3513 | // FIXME: set payload & payload_size to box (and free box below!) | 3674 | &GST_my_identity, |
3675 | &obm->peer, | ||
3676 | dvh->distance, | ||
3677 | dvh->path, | ||
3678 | &obm[1], | ||
3679 | bytes_msg); | ||
3680 | payload = dvb; | ||
3681 | payload_size = ntohs (dvb->header.size); | ||
3514 | } | 3682 | } |
3515 | else | 3683 | else |
3516 | { | 3684 | { |
3517 | dvh = NULL; | 3685 | dvh = NULL; |
3518 | // box = NULL; | 3686 | dvb = NULL; |
3519 | payload = &obm[1]; | 3687 | payload = &obm[1]; |
3520 | payload_size = bytes_msg; | 3688 | payload_size = bytes_msg; |
3521 | } | 3689 | } |
@@ -3527,8 +3695,9 @@ handle_client_send (void *cls, const struct OutboundMessage *obm) | |||
3527 | pm->bytes_msg = payload_size; | 3695 | pm->bytes_msg = payload_size; |
3528 | pm->timeout = | 3696 | pm->timeout = |
3529 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout)); | 3697 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_ntoh (obm->timeout)); |
3530 | memcpy (&pm[1], &obm[1], payload_size); | 3698 | memcpy (&pm[1], payload, payload_size); |
3531 | // FIXME: GNUNET_free_non_null (box); | 3699 | GNUNET_free_non_null (dvb); |
3700 | dvb = NULL; | ||
3532 | pm->dvh = dvh; | 3701 | pm->dvh = dvh; |
3533 | if (NULL != dvh) | 3702 | if (NULL != dvh) |
3534 | { | 3703 | { |
@@ -3810,41 +3979,6 @@ queue_send_msg (struct Queue *queue, | |||
3810 | 3979 | ||
3811 | 3980 | ||
3812 | /** | 3981 | /** |
3813 | * Which transmission options are allowable for transmission? | ||
3814 | * Interpreted bit-wise! | ||
3815 | */ | ||
3816 | enum RouteMessageOptions | ||
3817 | { | ||
3818 | /** | ||
3819 | * Only confirmed, non-DV direct neighbours. | ||
3820 | */ | ||
3821 | RMO_NONE = 0, | ||
3822 | |||
3823 | /** | ||
3824 | * We are allowed to use DV routing for this @a hdr | ||
3825 | */ | ||
3826 | RMO_DV_ALLOWED = 1, | ||
3827 | |||
3828 | /** | ||
3829 | * We are allowed to use unconfirmed queues or DV routes for this message | ||
3830 | */ | ||
3831 | RMO_UNCONFIRMED_ALLOWED = 2, | ||
3832 | |||
3833 | /** | ||
3834 | * Reliable and unreliable, DV and non-DV are all acceptable. | ||
3835 | */ | ||
3836 | RMO_ANYTHING_GOES = (RMO_DV_ALLOWED | RMO_UNCONFIRMED_ALLOWED), | ||
3837 | |||
3838 | /** | ||
3839 | * If we have multiple choices, it is OK to send this message | ||
3840 | * over multiple channels at the same time to improve loss tolerance. | ||
3841 | * (We do at most 2 transmissions.) | ||
3842 | */ | ||
3843 | RMO_REDUNDANT = 4 | ||
3844 | }; | ||
3845 | |||
3846 | |||
3847 | /** | ||
3848 | * Pick a queue of @a n under constraints @a options and schedule | 3982 | * Pick a queue of @a n under constraints @a options and schedule |
3849 | * transmission of @a hdr. | 3983 | * transmission of @a hdr. |
3850 | * | 3984 | * |
@@ -3927,22 +4061,17 @@ forward_via_dvh (const struct DistanceVectorHop *dvh, | |||
3927 | const struct GNUNET_MessageHeader *payload, | 4061 | const struct GNUNET_MessageHeader *payload, |
3928 | enum RouteMessageOptions options) | 4062 | enum RouteMessageOptions options) |
3929 | { | 4063 | { |
3930 | uint16_t mlen = ntohs (payload->size); | 4064 | struct TransportDVBoxMessage *dvb; |
3931 | char boxram[sizeof (struct TransportDVBoxMessage) + | ||
3932 | (dvh->distance + 1) * sizeof (struct GNUNET_PeerIdentity) + | ||
3933 | mlen] GNUNET_ALIGN; | ||
3934 | struct TransportDVBoxMessage *box = (struct TransportDVBoxMessage *) boxram; | ||
3935 | struct GNUNET_PeerIdentity *path = (struct GNUNET_PeerIdentity *) &box[1]; | ||
3936 | 4065 | ||
3937 | box->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); | 4066 | dvb = create_dv_box (0, |
3938 | box->header.size = htons (sizeof (boxram)); | 4067 | &GST_my_identity, |
3939 | box->total_hops = htons (0); | 4068 | &dvh->dv->target, |
3940 | box->num_hops = htons (dvh->distance + 1); | 4069 | dvh->distance, |
3941 | box->origin = GST_my_identity; | 4070 | dvh->path, |
3942 | memcpy (path, dvh->path, dvh->distance * sizeof (struct GNUNET_PeerIdentity)); | 4071 | payload, |
3943 | path[dvh->distance] = dvh->dv->target; | 4072 | ntohs (payload->size)); |
3944 | memcpy (&path[dvh->distance + 1], payload, mlen); | 4073 | route_via_neighbour (dvh->next_hop, &dvb->header, options); |
3945 | route_via_neighbour (dvh->next_hop, &box->header, options); | 4074 | GNUNET_free (dvb); |
3946 | } | 4075 | } |
3947 | 4076 | ||
3948 | 4077 | ||
@@ -3960,52 +4089,15 @@ route_via_dv (const struct DistanceVector *dv, | |||
3960 | const struct GNUNET_MessageHeader *hdr, | 4089 | const struct GNUNET_MessageHeader *hdr, |
3961 | enum RouteMessageOptions options) | 4090 | enum RouteMessageOptions options) |
3962 | { | 4091 | { |
3963 | struct DistanceVectorHop *h1; | 4092 | struct DistanceVectorHop *hops[2]; |
3964 | struct DistanceVectorHop *h2; | 4093 | unsigned int res; |
3965 | uint64_t num_dv; | ||
3966 | uint64_t choice1; | ||
3967 | uint64_t choice2; | ||
3968 | |||
3969 | /* Pick random vectors, but weighted by distance, giving more weight | ||
3970 | to shorter vectors */ | ||
3971 | num_dv = 0; | ||
3972 | for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; | ||
3973 | pos = pos->next_dv) | ||
3974 | { | ||
3975 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && | ||
3976 | (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until) | ||
3977 | .rel_value_us == 0)) | ||
3978 | continue; /* pos unconfirmed and confirmed required */ | ||
3979 | num_dv += MAX_DV_HOPS_ALLOWED - pos->distance; | ||
3980 | } | ||
3981 | if (0 == num_dv) | ||
3982 | { | ||
3983 | GNUNET_break (0); | ||
3984 | return; | ||
3985 | } | ||
3986 | choice1 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv); | ||
3987 | choice2 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, num_dv); | ||
3988 | num_dv = 0; | ||
3989 | h1 = NULL; | ||
3990 | h2 = NULL; | ||
3991 | for (struct DistanceVectorHop *pos = dv->dv_head; NULL != pos; | ||
3992 | pos = pos->next_dv) | ||
3993 | { | ||
3994 | uint32_t delta = MAX_DV_HOPS_ALLOWED - pos->distance; | ||
3995 | 4094 | ||
3996 | if ((0 == (options & RMO_UNCONFIRMED_ALLOWED)) && | 4095 | res = pick_random_dv_hops (dv, |
3997 | (GNUNET_TIME_absolute_get_remaining (pos->path_valid_until) | 4096 | options, |
3998 | .rel_value_us == 0)) | 4097 | hops, |
3999 | continue; /* pos unconfirmed and confirmed required */ | 4098 | (0 == (options & RMO_REDUNDANT)) ? 1 : 2); |
4000 | if ((num_dv <= choice1) && (num_dv + delta > choice1)) | 4099 | for (unsigned int i = 0; i < res; i++) |
4001 | h1 = pos; | 4100 | forward_via_dvh (hops[i], hdr, options & (~RMO_REDUNDANT)); |
4002 | if ((num_dv <= choice2) && (num_dv + delta > choice2)) | ||
4003 | h2 = pos; | ||
4004 | num_dv += delta; | ||
4005 | } | ||
4006 | forward_via_dvh (h1, hdr, options & (~RMO_REDUNDANT)); | ||
4007 | if (0 == (options & RMO_REDUNDANT)) | ||
4008 | forward_via_dvh (h2, hdr, options & (~RMO_REDUNDANT)); | ||
4009 | } | 4101 | } |
4010 | 4102 | ||
4011 | 4103 | ||
@@ -6418,25 +6510,16 @@ forward_dv_box (struct Neighbour *next_hop, | |||
6418 | uint16_t payload_size) | 6510 | uint16_t payload_size) |
6419 | { | 6511 | { |
6420 | struct TransportDVBoxMessage *dvb; | 6512 | struct TransportDVBoxMessage *dvb; |
6421 | struct GNUNET_PeerIdentity *dhops; | ||
6422 | 6513 | ||
6423 | GNUNET_assert (UINT16_MAX < sizeof (struct TransportDVBoxMessage) + | 6514 | dvb = create_dv_box (total_hops, |
6424 | sizeof (struct GNUNET_PeerIdentity) * num_hops + | 6515 | origin, |
6425 | payload_size); | 6516 | &hops[num_hops - 1] /* == target */, |
6426 | dvb = GNUNET_malloc (sizeof (struct TransportDVBoxMessage) + | 6517 | num_hops - 1 /* do not count target twice */, |
6427 | sizeof (struct GNUNET_PeerIdentity) * num_hops + | 6518 | hops, |
6519 | payload, | ||
6428 | payload_size); | 6520 | payload_size); |
6429 | dvb->header.size = | ||
6430 | htons (sizeof (struct TransportDVBoxMessage) + | ||
6431 | sizeof (struct GNUNET_PeerIdentity) * num_hops + payload_size); | ||
6432 | dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); | ||
6433 | dvb->total_hops = htons (total_hops); | ||
6434 | dvb->num_hops = htons (num_hops); | ||
6435 | dvb->origin = *origin; | ||
6436 | dhops = (struct GNUNET_PeerIdentity *) &dvb[1]; | ||
6437 | memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity)); | ||
6438 | memcpy (&dhops[num_hops], payload, payload_size); | ||
6439 | route_message (&next_hop->pid, &dvb->header, RMO_NONE); | 6521 | route_message (&next_hop->pid, &dvb->header, RMO_NONE); |
6522 | GNUNET_free (dvb); | ||
6440 | } | 6523 | } |
6441 | 6524 | ||
6442 | 6525 | ||