From 809befdaec48b27239d930b7e6b268c60c333612 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 13 Oct 2011 14:06:14 +0000 Subject: API change to make mwachs happy --- src/ats/ats_api_performance.c | 368 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 356 insertions(+), 12 deletions(-) (limited to 'src/ats/ats_api_performance.c') diff --git a/src/ats/ats_api_performance.c b/src/ats/ats_api_performance.c index e23c9bdf3..85f4ae71e 100644 --- a/src/ats/ats_api_performance.c +++ b/src/ats/ats_api_performance.c @@ -18,24 +18,300 @@ Boston, MA 02111-1307, USA. */ /** - * @file include/gnunet_ats_service.h + * @file ats/ats_api_performance.c * @brief automatic transport selection and outbound bandwidth determination * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" +#include "ats.h" + + +/** + * Message in linked list we should send to the ATS service. The + * actual binary message follows this struct. + */ +struct PendingMessage +{ + + /** + * Kept in a DLL. + */ + struct PendingMessage *next; + + /** + * Kept in a DLL. + */ + struct PendingMessage *prev; + + /** + * Size of the message. + */ + size_t size; + + /** + * Is this the 'ATS_START' message? + */ + int is_init; +}; + + +/** + * Linked list of pending reservations. + */ +struct GNUNET_ATS_ReservationContext +{ + + /** + * Kept in a DLL. + */ + struct GNUNET_ATS_ReservationContext *next; + + /** + * Kept in a DLL. + */ + struct GNUNET_ATS_ReservationContext *prev; + + /** + * Target peer. + */ + struct GNUNET_PeerIdentity peer; + + /** + * Desired reservation + */ + int32_t size; + + /** + * Function to call on result. + */ + GNUNET_ATS_ReservationCallback info; + + /** + * Closure for 'info' + */ + void *info_cls; + + /** + * Do we need to undo this reservation if it succeeded? Set to + * GNUNET_YES if a reservation is cancelled. (at that point, 'info' + * is also set to NULL; however, info will ALSO be NULL for the + * reservation context that is created to undo the original request, + * so 'info' being NULL cannot be used to check if undo is + * required). + */ + int undo; +}; -/* ******************************** Performance API ***************************** */ /** * ATS Handle to obtain and/or modify performance information. */ struct GNUNET_ATS_PerformanceHandle { + + /** + * Our configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Callback to invoke on performance changes. + */ + GNUNET_ATS_PeerInformationCallback infocb; + + /** + * Closure for 'infocb'. + */ + void *infocb_cls; + + /** + * Connection to ATS service. + */ + struct GNUNET_CLIENT_Connection *client; + + /** + * Head of list of messages for the ATS service. + */ + struct PendingMessage *pending_head; + + /** + * Tail of list of messages for the ATS service + */ + struct PendingMessage *pending_tail; + + /** + * Head of linked list of pending reservation requests. + */ + struct GNUNET_ATS_ReservationContext *reservation_head; + + /** + * Tail of linked list of pending reservation requests. + */ + struct GNUNET_ATS_ReservationContext *reservation_tail; + + /** + * Current request for transmission to ATS. + */ + struct GNUNET_CLIENT_TransmitHandle *th; + }; +/** + * Re-establish the connection to the ATS service. + * + * @param sh handle to use to re-connect. + */ +static void +reconnect (struct GNUNET_ATS_PerformanceHandle *ph); + + +/** + * Transmit messages from the message queue to the service + * (if there are any, and if we are not already trying). + * + * @param sh handle to use + */ +static void +do_transmit (struct GNUNET_ATS_PerformanceHandle *ph); + + +/** + * We can now transmit a message to ATS. Do it. + * + * @param cls the 'struct GNUNET_ATS_SchedulingHandle' + * @param size number of bytes we can transmit to ATS + * @param buf where to copy the messages + * @return number of bytes copied into buf + */ +static size_t +transmit_message_to_ats (void *cls, + size_t size, + void *buf) +{ + struct GNUNET_ATS_PerformanceHandle *ph = cls; + struct PendingMessage *p; + size_t ret; + char *cbuf; + + ph->th = NULL; + ret = 0; + cbuf = buf; + while ( (NULL != (p = ph->pending_head)) && + (p->size <= size) ) + { + memcpy (&cbuf[ret], &p[1], p->size); + ret += p->size; + GNUNET_CONTAINER_DLL_remove (ph->pending_head, + ph->pending_tail, + p); + GNUNET_free (p); + } + do_transmit (ph); + return ret; +} + + +/** + * Transmit messages from the message queue to the service + * (if there are any, and if we are not already trying). + * + * @param ph handle to use + */ +static void +do_transmit (struct GNUNET_ATS_PerformanceHandle *ph) +{ + struct PendingMessage *p; + + if (NULL != ph->th) + return; + if (NULL == (p = ph->pending_head)) + return; + ph->th = GNUNET_CLIENT_notify_transmit_ready (ph->client, + p->size, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, + &transmit_message_to_ats, ph); +} + + +/** + * Type of a function to call when we receive a message + * from the service. + * + * @param cls the 'struct GNUNET_ATS_SchedulingHandle' + * @param msg message received, NULL on timeout or fatal error + */ +static void +process_ats_message (void *cls, + const struct GNUNET_MessageHeader *msg) +{ + struct GNUNET_ATS_PerformanceHandle *ph = cls; + + if (NULL == msg) + { + GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO); + ph->client = NULL; + reconnect (ph); + return; + } + switch (ntohs (msg->type)) + { + // FIXME + default: + GNUNET_break (0); + GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO); + ph->client = NULL; + reconnect (ph); + return; + } + GNUNET_CLIENT_receive (ph->client, + &process_ats_message, ph, + GNUNET_TIME_UNIT_FOREVER_REL); +} + + +/** + * Re-establish the connection to the ATS service. + * + * @param ph handle to use to re-connect. + */ +static void +reconnect (struct GNUNET_ATS_PerformanceHandle *ph) +{ + struct PendingMessage *p; + struct ClientStartMessage *init; + + GNUNET_assert (NULL == ph->client); + ph->client = GNUNET_CLIENT_connect ("ats", ph->cfg); + GNUNET_assert (NULL != ph->client); + GNUNET_CLIENT_receive (ph->client, + &process_ats_message, ph, + GNUNET_TIME_UNIT_FOREVER_REL); + if ( (NULL == (p = ph->pending_head)) || + (GNUNET_YES != p->is_init) ) + { + p = GNUNET_malloc (sizeof (struct PendingMessage) + + sizeof (struct ClientStartMessage)); + p->size = sizeof (struct ClientStartMessage); + p->is_init = GNUNET_YES; + init = (struct ClientStartMessage *) &p[1]; + init->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_START); + init->header.size = htons (sizeof (struct ClientStartMessage)); + init->start_flag = htonl ((ph->infocb == NULL) + ? START_FLAG_PERFORMANCE_NO_PIC + : START_FLAG_PERFORMANCE_WITH_PIC); + GNUNET_CONTAINER_DLL_insert (ph->pending_head, + ph->pending_tail, + p); + } + do_transmit (ph); +} + + + /** * Get handle to access performance API of the ATS subsystem. * @@ -49,7 +325,14 @@ GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ATS_PeerInformationCallback infocb, void *infocb_cls) { - return NULL; + struct GNUNET_ATS_PerformanceHandle *ph; + + ph = GNUNET_malloc (sizeof (struct GNUNET_ATS_PerformanceHandle)); + ph->cfg = cfg; + ph->infocb = infocb; + ph->infocb_cls = infocb_cls; + reconnect (ph); + return ph; } @@ -61,17 +344,29 @@ GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg, void GNUNET_ATS_performance_done (struct GNUNET_ATS_SchedulingHandle *ph) { + struct PendingMessage *p; + struct GNUNET_ATS_ReservationContext *rc; + + while (NULL != (p = ph->pending_head)) + { + GNUNET_CONTAINER_DLL_remove (ph->pending_head, + ph->pending_tail, + p); + GNUNET_free (p); + } + while (NULL != (rc = ph->reservation_head)) + { + GNUNET_CONTAINER_DLL_remove (ph->reservation_head, + ph->reservation_tail, + rc); + GNUNET_break (NULL == rc->info); + GNUNET_free (p); + } + GNUNET_CLIENT_disconnect (ph->client, GNUNET_NO); + GNUNET_free (ph); } -/** - * Context that can be used to cancel a peer information request. - */ -struct GNUNET_ATS_ReservationContext -{ -}; - - /** * Reserve inbound bandwidth from the given peer. ATS will look at * the current amount of traffic we receive from the peer and ensure @@ -93,7 +388,32 @@ GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph, GNUNET_ATS_ReservationCallback info, void *info_cls) { - return NULL; + struct GNUNET_ATS_ReservationContext *rc; + struct PendingMessage *p; + struct ReservationRequestMessage *m; + + rc = GNUNET_malloc (sizeof (struct GNUNET_ATS_ReservationContext)); + rc->size = amount; + rc->peer = *peer; + rc->info = info; + rc->info_cls = info_cls; + GNUNET_CONTAINER_DLL_insert_tail (ph->reservation_head, + ph->reservation_tail, + rc); + + p = GNUNET_malloc (sizeof (struct PendingMessage) + + sizeof (struct ReservationRequestMessage)); + p->size = sizeof (struct ReservationRequestMessage); + p->is_init = GNUNET_NO; + m = (struct ReservationRequestMessage*) &p[1]; + m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE); + m->header.size = htons (sizeof (struct ReservationRequestMessage)); + m->amount = htonl (amount); + m->peer = *peer; + GNUNET_CONTAINER_DLL_insert_tail (ph->pending_head, + ph->pending_tail, + p); + return rc; } @@ -106,6 +426,7 @@ void GNUNET_ATS_reserve_bandwidth_cancel (struct GNUNET_ATS_ReservationContext *rc) { + rc->info = NULL; } @@ -122,6 +443,29 @@ GNUNET_ATS_change_preference (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, ...) { + struct PendingMessage *p; + struct ChangePreferenceMessage *m; + size_t msize; + uint32_t count; + struct PreferenceInformation *pi; + + // FIXME: set 'count' + p = GNUNET_malloc (sizeof (struct PendingMessage) + + sizeof (struct ChangePreferenceMessage) + + count * sizeof (struct PreferenceInformation)); + p->size = msize; + p->is_init = GNUNET_NO; + m = (struct ReservationRequestMessage*) &p[1]; + m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE); + m->header.size = htons (msize); + m->num_preferences = htonl (count); + m->peer = *peer; + pi = (struct PreferenceInformation*) &m[1]; + // FIXME: fill in 'pi' + + GNUNET_CONTAINER_DLL_insert_tail (ph->pending_head, + ph->pending_tail, + p); } /* end of ats_api_performance.c */ -- cgit v1.2.3