aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-tng.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r--src/transport/gnunet-service-tng.c321
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 */
929enum 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 */
928struct LearnLaunchEntry 963struct 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 */
3501static struct TransportDVBoxMessage *
3502create_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 */
3544static unsigned int
3545pick_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 */
3816enum 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