From e2c076da0b595591c5646916cf2b629404489709 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 13 Oct 2011 14:49:55 +0000 Subject: finish ATS API implementation --- src/ats/ats_api_performance.c | 160 ++++++++++++++++++++++++++++++++++++--- src/ats/ats_api_scheduling.c | 8 +- src/include/gnunet_ats_service.h | 10 +-- 3 files changed, 158 insertions(+), 20 deletions(-) diff --git a/src/ats/ats_api_performance.c b/src/ats/ats_api_performance.c index cf948da48..fd733911d 100644 --- a/src/ats/ats_api_performance.c +++ b/src/ats/ats_api_performance.c @@ -86,12 +86,12 @@ struct GNUNET_ATS_ReservationContext /** * Function to call on result. */ - GNUNET_ATS_ReservationCallback info; + GNUNET_ATS_ReservationCallback rcb; /** - * Closure for 'info' + * Closure for 'rcb' */ - void *info_cls; + void *rcb_cls; /** * Do we need to undo this reservation if it succeeded? Set to @@ -237,6 +237,123 @@ do_transmit (struct GNUNET_ATS_PerformanceHandle *ph) } +/** + * We received a peer information message. Validate and process it. + * + * @param ph our context with the callback + * @param msg the message + * @return GNUNET_OK if the message was well-formed + */ +static int +process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph, + const struct GNUNET_MessageHeader *msg) +{ + const struct PeerInformationMessage *pi; + const struct GNUNET_TRANSPORT_ATS_Information *atsi; + const char *address; + const char *plugin_name; + uint16_t address_length; + uint16_t plugin_name_length; + uint32_t ats_count; + + if (ph->infocb == NULL) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (ntohs (msg->size) < sizeof (struct PeerInformationMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + pi = (const struct PeerInformationMessage*) msg; + ats_count = ntohl (pi->ats_count); + address_length = ntohs (pi->address_length); + plugin_name_length = ntohs (pi->plugin_name_length); + atsi = (const struct GNUNET_TRANSPORT_ATS_Information*) &pi[1]; + address = (const char*) &atsi[ats_count]; + plugin_name = &address[address_length]; + if ( (address_length + + plugin_name_length + + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + + sizeof (struct PeerInformationMessage) != ntohs (msg->size)) || + (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_TRANSPORT_ATS_Information)) || + (plugin_name[plugin_name_length - 1] != '\0') ) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + ph->infocb (ph->infocb_cls, + &pi->peer, + plugin_name, + address, address_length, + pi->bandwidth_out, + pi->bandwidth_in, + atsi, + ats_count); + return GNUNET_OK; +} + + +/** + * We received a reservation result message. Validate and process it. + * + * @param ph our context with the callback + * @param msg the message + * @return GNUNET_OK if the message was well-formed + */ +static int +process_rr_message (struct GNUNET_ATS_PerformanceHandle *ph, + const struct GNUNET_MessageHeader *msg) +{ + const struct ReservationResultMessage *rr; + struct GNUNET_ATS_ReservationContext *rc; + int32_t amount; + + if (ph->infocb == NULL) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (ntohs (msg->size) < sizeof (struct ReservationResultMessage)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + rr = (const struct ReservationResultMessage*) msg; + amount = ntohl (rr->amount); + rc = ph->reservation_head; + if (0 != memcmp (&rr->peer, + &rc->peer, + sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + GNUNET_CONTAINER_DLL_remove (ph->reservation_head, + ph->reservation_tail, + rc); + if ( (amount == 0) || + (rc->rcb != NULL) ) + { + /* tell client if not cancelled */ + if (rc->rcb != NULL) + rc->rcb (rc->rcb_cls, + &rr->peer, + amount, + GNUNET_TIME_relative_ntoh (rr->res_delay)); + GNUNET_free (rc); + return GNUNET_OK; + } + GNUNET_free (rc); + /* amount non-zero, but client cancelled, consider undo! */ + if (GNUNET_YES != rc->undo) + return GNUNET_OK; /* do not try to undo failed undos or negative amounts */ + (void) GNUNET_ATS_reserve_bandwidth (ph, &rr->peer, -amount, NULL, NULL); + return GNUNET_OK; +} + + /** * Type of a function to call when we receive a message * from the service. @@ -259,7 +376,24 @@ process_ats_message (void *cls, } switch (ntohs (msg->type)) { - // FIXME + case GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION: + if (GNUNET_OK != process_pi_message (ph, msg)) + { + GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO); + ph->client = NULL; + reconnect (ph); + return; + } + break; + case GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT: + if (GNUNET_OK != process_rr_message (ph, msg)) + { + GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO); + ph->client = NULL; + reconnect (ph); + return; + } + break; default: GNUNET_break (0); GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO); @@ -359,7 +493,7 @@ GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph) GNUNET_CONTAINER_DLL_remove (ph->reservation_head, ph->reservation_tail, rc); - GNUNET_break (NULL == rc->info); + GNUNET_break (NULL == rc->rcb); GNUNET_free (p); } GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO); @@ -376,8 +510,8 @@ GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph) * @param peer identifies the peer * @param amount reserve N bytes for receiving, negative * amounts can be used to undo a (recent) reservation; - * @param info function to call with the resulting reservation information - * @param info_cls closure for info + * @param rcb function to call with the resulting reservation information + * @param rcb_cls closure for info * @return NULL on error * @deprecated will be replaced soon */ @@ -385,8 +519,8 @@ struct GNUNET_ATS_ReservationContext * GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, int32_t amount, - GNUNET_ATS_ReservationCallback info, - void *info_cls) + GNUNET_ATS_ReservationCallback rcb, + void *rcb_cls) { struct GNUNET_ATS_ReservationContext *rc; struct PendingMessage *p; @@ -395,8 +529,10 @@ GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph, rc = GNUNET_malloc (sizeof (struct GNUNET_ATS_ReservationContext)); rc->size = amount; rc->peer = *peer; - rc->info = info; - rc->info_cls = info_cls; + rc->rcb = rcb; + rc->rcb_cls = rcb_cls; + if ( (rc != NULL) && (amount > 0) ) + rc->undo = GNUNET_YES; GNUNET_CONTAINER_DLL_insert_tail (ph->reservation_head, ph->reservation_tail, rc); @@ -426,7 +562,7 @@ void GNUNET_ATS_reserve_bandwidth_cancel (struct GNUNET_ATS_ReservationContext *rc) { - rc->info = NULL; + rc->rcb = NULL; } diff --git a/src/ats/ats_api_scheduling.c b/src/ats/ats_api_scheduling.c index 8b3e849b2..93cd7eab4 100644 --- a/src/ats/ats_api_scheduling.c +++ b/src/ats/ats_api_scheduling.c @@ -281,6 +281,7 @@ process_ats_message (void *cls, const char *address; const char *plugin_name; uint16_t address_length; + uint16_t plugin_name_length; uint32_t ats_count; if (NULL == msg) @@ -305,12 +306,13 @@ process_ats_message (void *cls, atsi = (const struct GNUNET_TRANSPORT_ATS_Information*) &m[1]; address = (const char*) &atsi[ats_count]; plugin_name = &address[address_length]; - if ( (ntohs (m->address_length) + - ntohs (m->plugin_name_length) + + plugin_name_length = ntohs (m->plugin_name_length); + if ( (address_length + + plugin_name_length + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + sizeof (struct AddressSuggestionMessage) != ntohs (msg->size)) || (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_TRANSPORT_ATS_Information)) || - (plugin_name[ntohs (m->plugin_name_length) - 1] != '\0') ) + (plugin_name[plugin_name_length - 1] != '\0') ) { GNUNET_break (0); GNUNET_CLIENT_disconnect (sh->client, GNUNET_NO); diff --git a/src/include/gnunet_ats_service.h b/src/include/gnunet_ats_service.h index 79be70ce4..0213f0ed1 100644 --- a/src/include/gnunet_ats_service.h +++ b/src/include/gnunet_ats_service.h @@ -225,7 +225,7 @@ GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg, * @param ph handle */ void -GNUNET_ATS_performance_done (struct GNUNET_ATS_SchedulingHandle *ph); +GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph); /** @@ -264,8 +264,8 @@ struct GNUNET_ATS_ReservationContext; * @param peer identifies the peer * @param amount reserve N bytes for receiving, negative * amounts can be used to undo a (recent) reservation; - * @param info function to call with the resulting reservation information - * @param info_cls closure for info + * @param rcb function to call with the resulting reservation information + * @param rcb_cls closure for info * @return NULL on error * @deprecated will be replaced soon */ @@ -273,8 +273,8 @@ struct GNUNET_ATS_ReservationContext * GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, int32_t amount, - GNUNET_ATS_ReservationCallback info, - void *info_cls); + GNUNET_ATS_ReservationCallback rcb, + void *rcb_cls); /** -- cgit v1.2.3