From 47d7779091557516cda70ab9038dc2d460b0b3bb Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 24 Oct 2009 21:45:44 +0000 Subject: [PATCH] giving client API option for auto-retry, making more often use of transmit_and_get_response API and removing auto-retry code where enhanced client API can be used for it --- src/arm/arm_api.c | 174 ++--------- src/arm/test_gnunet_arm.sh | 2 +- src/core/core_api.c | 10 +- src/datastore/Makefile.am | 1 + src/datastore/datastore_api.c | 132 ++------ src/datastore/perf_datastore_api.c | 4 +- src/datastore/test_datastore_api.c | 4 +- src/datastore/test_datastore_api_data.conf | 17 + src/datastore/test_datastore_api_management.c | 4 +- src/fs/fs.h | 2 +- src/fs/fs_download.c | 11 +- src/fs/fs_list_indexed.c | 59 +--- src/fs/fs_publish.c | 1 + src/fs/fs_search.c | 2 + src/fs/fs_unindex.c | 1 + src/include/gnunet_client_lib.h | 35 ++- src/peerinfo/peerinfo_api.c | 50 +-- src/statistics/statistics_api.c | 4 +- src/transport/transport_api.c | 7 +- src/util/client.c | 295 ++++++++++++++++-- src/util/resolver_api.c | 114 +------ src/util/test_client.c | 3 +- src/util/test_server_disconnect.c | 1 + src/util/test_server_with_client.c | 1 + src/util/test_service.c | 2 + 25 files changed, 449 insertions(+), 487 deletions(-) diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c index 49e25b38d..00ddddaab 100644 --- a/src/arm/arm_api.c +++ b/src/arm/arm_api.c @@ -32,19 +32,6 @@ #include "gnunet_server_lib.h" #include "arm.h" -/** - * How often do we re-try tranmsitting requests to ARM before - * giving up? Note that if we succeeded transmitting a request - * but failed to read a response, we do NOT re-try (since that - * might result in ARM getting a request twice). - */ -#define MAX_ATTEMPTS 4 - -/** - * Minimum delay between attempts to talk to ARM. - */ -#define MIN_RETRY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100) - /** * How long are we willing to wait for a service operation during the multi-operation @@ -142,28 +129,11 @@ struct RequestContext */ void *cls; - /** - * The service that is being manipulated. Do not free. - */ - const char *service_name; - /** * Timeout for the operation. */ struct GNUNET_TIME_Absolute timeout; - /** - * Length of service_name plus one. - */ - size_t slen; - - /** - * Number of attempts left for transmitting the request to ARM. - * We may fail the first time (say because ARM is not yet up), - * in which case we wait a bit and re-try (timeout permitting). - */ - unsigned int attempts_left; - /** * Type of the request expressed as a message type (start or stop). */ @@ -302,121 +272,6 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg) } -/** - * We've failed to transmit the request to the ARM service. - * Report our failure and clean up the state. - * - * @param sctx the state of the (now failed) request - */ -static void -report_transmit_failure (struct RequestContext *sctx) -{ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Error while trying to transmit to ARM service\n")); - if (sctx->callback != NULL) - sctx->callback (sctx->cls, GNUNET_SYSERR); - GNUNET_free (sctx); -} - - -/** - * Transmit a request for a service status change to the - * ARM service. - * - * @param cls the "struct RequestContext" identifying the request - * @param size how many bytes are available in buf - * @param buf where to write the request, NULL on error - * @return number of bytes written to buf - */ -static size_t -send_service_msg (void *cls, size_t size, void *buf); - - -/** - * We've failed to transmit the request to the ARM service but - * are now going to try again. - * - * @param cls state of the request - * @param tc task context (unused) - */ -static void -retry_request (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct RequestContext *sctx = cls; - - if (NULL == - GNUNET_CLIENT_notify_transmit_ready (sctx->h->client, - sctx->slen + - sizeof (struct - GNUNET_MessageHeader), - GNUNET_TIME_absolute_get_remaining (sctx->timeout), - &send_service_msg, - sctx)) - { - report_transmit_failure (sctx); - return; - } -} - - -/** - * Transmit a request for a service status change to the - * ARM service. - * - * @param cls the "struct RequestContext" identifying the request - * @param size how many bytes are available in buf - * @param buf where to write the request, NULL on error - * @return number of bytes written to buf - */ -static size_t -send_service_msg (void *cls, size_t size, void *buf) -{ - struct RequestContext *sctx = cls; - struct GNUNET_MessageHeader *msg; - struct GNUNET_TIME_Relative rem; - - if (buf == NULL) - { - GNUNET_CLIENT_disconnect (sctx->h->client); - sctx->h->client = GNUNET_CLIENT_connect (sctx->h->sched, - "arm", - sctx->h->cfg); - GNUNET_assert (sctx->h->client != NULL); - rem = GNUNET_TIME_absolute_get_remaining (sctx->timeout); - if ( (sctx->attempts_left-- > 0) && - (rem.value > 0) ) - { - GNUNET_SCHEDULER_add_delayed (sctx->h->sched, - GNUNET_NO, - GNUNET_SCHEDULER_PRIORITY_KEEP, - GNUNET_SCHEDULER_NO_TASK, - GNUNET_TIME_relative_min (MIN_RETRY_DELAY, - rem), - &retry_request, - sctx); - return 0; - } - report_transmit_failure (sctx); - return 0; - } -#if DEBUG_ARM - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Transmitting service request to ARM.\n")); -#endif - GNUNET_assert (size >= sctx->slen); - msg = buf; - msg->size = htons (sizeof (struct GNUNET_MessageHeader) + sctx->slen); - msg->type = htons (sctx->type); - memcpy (&msg[1], sctx->service_name, sctx->slen); - GNUNET_CLIENT_receive (sctx->h->client, - &handle_response, - sctx, - GNUNET_TIME_absolute_get_remaining (sctx->timeout)); - return sctx->slen + sizeof (struct GNUNET_MessageHeader); -} - - /** * Start or stop a service. * @@ -435,6 +290,7 @@ change_service (struct GNUNET_ARM_Handle *h, { struct RequestContext *sctx; size_t slen; + struct GNUNET_MessageHeader *msg; slen = strlen (service_name) + 1; if (slen + sizeof (struct GNUNET_MessageHeader) > @@ -453,15 +309,29 @@ change_service (struct GNUNET_ARM_Handle *h, sctx->h = h; sctx->callback = cb; sctx->cls = cb_cls; - sctx->service_name = (const char*) &sctx[1]; - memcpy (&sctx[1], - service_name, - slen); sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); - sctx->slen = slen; - sctx->attempts_left = MAX_ATTEMPTS; sctx->type = type; - retry_request (sctx, NULL); + msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader) + slen); + msg->size = htons (sizeof (struct GNUNET_MessageHeader) + slen); + msg->type = htons (sctx->type); + memcpy (&msg[1], service_name, slen); + if (GNUNET_OK != + GNUNET_CLIENT_transmit_and_get_response (sctx->h->client, + msg, + GNUNET_TIME_absolute_get_remaining (sctx->timeout), + GNUNET_YES, + &handle_response, + sctx)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Error while trying to transmit to ARM service\n")); + if (cb != NULL) + cb (cb_cls, GNUNET_SYSERR); + GNUNET_free (sctx); + GNUNET_free (msg); + return; + } + GNUNET_free (msg); } diff --git a/src/arm/test_gnunet_arm.sh b/src/arm/test_gnunet_arm.sh index ce4396cfb..d36c2ca38 100755 --- a/src/arm/test_gnunet_arm.sh +++ b/src/arm/test_gnunet_arm.sh @@ -1,7 +1,7 @@ #!/bin/sh exe="./gnunet-arm -c test_arm_api_data.conf" -out=`mktemp /tmp/test-gnunetd-arm-logXXXXXXXX` +out=`mktemp /tmp/test-gnunet-arm-logXXXXXXXX` #DEBUG="-L DEBUG" diff --git a/src/core/core_api.c b/src/core/core_api.c index 89bae0525..2157584ab 100644 --- a/src/core/core_api.c +++ b/src/core/core_api.c @@ -94,7 +94,7 @@ struct GNUNET_CORE_Handle /** * Handle for our current transmission request. */ - struct GNUNET_CONNECTION_TransmitHandle *th; + struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of doubly-linked list of pending requests. @@ -257,6 +257,7 @@ reconnect (struct GNUNET_CORE_Handle *h) sizeof (struct InitMessage) + sizeof (uint16_t) * h->hcnt, GNUNET_TIME_UNIT_SECONDS, + GNUNET_NO, &transmit_start, h); } @@ -346,7 +347,9 @@ trigger_next_request (struct GNUNET_CORE_Handle *h) h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, th->msize, GNUNET_TIME_absolute_get_remaining - (th->timeout), &request_start, + (th->timeout), + GNUNET_NO, + &request_start, h); } @@ -821,6 +824,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched, GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct InitMessage) + sizeof (uint16_t) * h->hcnt, timeout, + GNUNET_YES, &transmit_start, h); } @@ -834,7 +838,7 @@ void GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle) { if (handle->th != NULL) - GNUNET_CONNECTION_notify_transmit_ready_cancel (handle->th); + GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (handle->sched, handle->reconnect_task); GNUNET_CLIENT_disconnect (handle->client); diff --git a/src/datastore/Makefile.am b/src/datastore/Makefile.am index e4de8fcfa..b9d8ec38f 100644 --- a/src/datastore/Makefile.am +++ b/src/datastore/Makefile.am @@ -18,6 +18,7 @@ lib_LTLIBRARIES = \ libgnunetdatastore_la_SOURCES = \ datastore_api.c datastore.h plugin_datastore.h libgnunetdatastore_la_LIBADD = \ + $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetdatastore_la_LDFLAGS = \ diff --git a/src/datastore/datastore_api.c b/src/datastore/datastore_api.c index f6d7480de..a9058fa04 100644 --- a/src/datastore/datastore_api.c +++ b/src/datastore/datastore_api.c @@ -24,6 +24,7 @@ * @author Christian Grothoff */ #include "platform.h" +#include "gnunet_arm_service.h" #include "gnunet_datastore_service.h" #include "datastore.h" @@ -75,6 +76,7 @@ struct GNUNET_DATASTORE_Handle }; + /** * Connect to the datastore service. * @@ -95,6 +97,7 @@ struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (const struct c = GNUNET_CLIENT_connect (sched, "datastore", cfg); if (c == NULL) return NULL; /* oops */ + GNUNET_ARM_start_services (cfg, sched, "datastore", NULL); h = GNUNET_malloc (sizeof(struct GNUNET_DATASTORE_Handle) + GNUNET_SERVER_MAX_MESSAGE_SIZE); h->client = c; @@ -149,6 +152,7 @@ void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h, GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof(struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_MINUTES, + GNUNET_YES, &transmit_drop, h)) return; @@ -156,6 +160,7 @@ void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h, } if (h->client != NULL) GNUNET_CLIENT_disconnect (h->client); + GNUNET_ARM_stop_services (h->cfg, h->sched, "datastore", NULL); GNUNET_free (h); } @@ -232,51 +237,6 @@ with_status_response_handler (void *cls, } -/** - * Transmit message to datastore service and then - * read a status message. - * - * @param cls closure with handle to datastore - * @param size number of bytes we can transmit at most - * @param buf where to write transmission, NULL on - * timeout - * @return number of bytes copied to buf - */ -static size_t -transmit_get_status (void *cls, - size_t size, - void *buf) -{ - struct GNUNET_DATASTORE_Handle *h = cls; - GNUNET_DATASTORE_ContinuationWithStatus cont = h->response_proc; - uint16_t msize; - - if (buf == NULL) - { - h->message_size = 0; - h->response_proc = NULL; - cont (h->response_proc_cls, - GNUNET_SYSERR, - _("Error transmitting message to datastore service.")); - return 0; - } - msize = h->message_size; - GNUNET_assert (msize <= size); - memcpy (buf, &h[1], msize); -#if DEBUG_DATASTORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmitted %u byte message to datastore service, now waiting for status.\n", - msize); -#endif - h->message_size = 0; - GNUNET_CLIENT_receive (h->client, - &with_status_response_handler, - h, - GNUNET_TIME_absolute_get_remaining (h->timeout)); - return msize; -} - - /** * Helper function that will initiate the * transmission of a message to the datastore @@ -313,11 +273,13 @@ transmit_for_status (struct GNUNET_DATASTORE_Handle *h, h->response_proc_cls = cont_cls; h->timeout = GNUNET_TIME_relative_to_absolute (timeout); h->message_size = msize; - if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client, - msize, - timeout, - &transmit_get_status, - h)) + if (GNUNET_OK != + GNUNET_CLIENT_transmit_and_get_response (h->client, + hdr, + timeout, + GNUNET_YES, + &with_status_response_handler, + h)) { GNUNET_break (0); h->response_proc = NULL; @@ -570,54 +532,6 @@ with_result_response_handler (void *cls, } -/** - * Transmit message to datastore service and then - * read a result message. - * - * @param cls closure with handle to datastore - * @param size number of bytes we can transmit at most - * @param buf where to write transmission, NULL on - * timeout - * @return number of bytes copied to buf - */ -static size_t -transmit_get_result (void *cls, - size_t size, - void *buf) -{ - struct GNUNET_DATASTORE_Handle *h = cls; - GNUNET_DATASTORE_Iterator cont = h->response_proc; - uint16_t msize; - - if (buf == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Error transmitting message to datastore service.\n")); - h->response_proc = NULL; - h->message_size = 0; - cont (h->response_proc_cls, - NULL, 0, NULL, 0, 0, 0, - GNUNET_TIME_UNIT_ZERO_ABS, 0); - return 0; - } - msize = h->message_size; - GNUNET_assert (msize <= size); - memcpy (buf, &h[1], msize); -#if DEBUG_DATASTORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmitted %u byte message to datastore service, now waiting for result.\n", - msize); -#endif - h->message_size = 0; - GNUNET_CLIENT_receive (h->client, - &with_result_response_handler, - h, - GNUNET_TIME_absolute_get_remaining (h->timeout)); - return msize; -} - - - /** * Function called to trigger obtaining the next result * from the datastore. @@ -651,12 +565,10 @@ GNUNET_DATASTORE_get_next (struct GNUNET_DATASTORE_Handle *h, /** - * Helper function that will initiate the - * transmission of a message to the datastore - * service. The message must already be prepared - * and stored in the buffer at the end of the - * handle. The message must be of a type that - * expects a "DataMessage" in response. + * Helper function that will initiate the transmission of a message to + * the datastore service. The message must already be prepared and + * stored in the buffer at the end of the handle. The message must be + * of a type that expects a "DataMessage" in response. * * @param h handle to the service with prepared message * @param cont function to call with result @@ -686,11 +598,13 @@ transmit_for_result (struct GNUNET_DATASTORE_Handle *h, h->response_proc_cls = cont_cls; h->timeout = GNUNET_TIME_relative_to_absolute (timeout); h->message_size = msize; - if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client, - msize, - timeout, - &transmit_get_result, - h)) + if (GNUNET_OK != + GNUNET_CLIENT_transmit_and_get_response (h->client, + hdr, + timeout, + GNUNET_YES, + &with_result_response_handler, + h)) { GNUNET_break (0); h->response_proc = NULL; diff --git a/src/datastore/perf_datastore_api.c b/src/datastore/perf_datastore_api.c index 1bee3ee57..e454e69f0 100644 --- a/src/datastore/perf_datastore_api.c +++ b/src/datastore/perf_datastore_api.c @@ -358,8 +358,8 @@ check () struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; - pid = GNUNET_OS_start_process ("gnunet-service-datastore", - "gnunet-service-datastore", + pid = GNUNET_OS_start_process ("gnunet-service-arm", + "gnunet-service-arm", #if VERBOSE "-L", "DEBUG", #endif diff --git a/src/datastore/test_datastore_api.c b/src/datastore/test_datastore_api.c index a63f0425f..6a63e8e26 100644 --- a/src/datastore/test_datastore_api.c +++ b/src/datastore/test_datastore_api.c @@ -567,8 +567,8 @@ check () struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; - pid = GNUNET_OS_start_process ("gnunet-service-datastore", - "gnunet-service-datastore", + pid = GNUNET_OS_start_process ("gnunet-service-arm", + "gnunet-service-arm", #if VERBOSE "-L", "DEBUG", #endif diff --git a/src/datastore/test_datastore_api_data.conf b/src/datastore/test_datastore_api_data.conf index 815bce0b8..a09bfae0e 100644 --- a/src/datastore/test_datastore_api_data.conf +++ b/src/datastore/test_datastore_api_data.conf @@ -1,5 +1,15 @@ [PATHS] SERVICEHOME = /tmp/test-gnunetd-datastore/ +DEFAULTCONFIG = test_datastore_api_data.conf + +[arm] +DEFAULTSERVICES = resolver +PORT = 42466 +HOSTNAME = localhost + +[resolver] +PORT = 42464 +HOSTNAME = localhost [datastore] PORT = 22654 @@ -21,3 +31,10 @@ DATABASE = sqlite # REJECT_FROM = # REJECT_FROM6 = # PREFIX = + +[statistics] +PORT = 22667 +HOSTNAME = localhost + +[testing] +WEAKRANDOM = YES diff --git a/src/datastore/test_datastore_api_management.c b/src/datastore/test_datastore_api_management.c index 22d4aff25..c9fc9c8c5 100644 --- a/src/datastore/test_datastore_api_management.c +++ b/src/datastore/test_datastore_api_management.c @@ -335,8 +335,8 @@ check () struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; - pid = GNUNET_OS_start_process ("gnunet-service-datastore", - "gnunet-service-datastore", + pid = GNUNET_OS_start_process ("gnunet-service-arm", + "gnunet-service-arm", #if VERBOSE "-L", "DEBUG", #endif diff --git a/src/fs/fs.h b/src/fs/fs.h index 8270d38ba..2cac304a3 100644 --- a/src/fs/fs.h +++ b/src/fs/fs.h @@ -950,7 +950,7 @@ struct GNUNET_FS_DownloadContext * Non-NULL if we are currently having a request for * transmission pending with the client handle. */ - struct GNUNET_CONNECTION_TransmitHandle *th; + struct GNUNET_CLIENT_TransmitHandle *th; /** * Identity of the peer having the content, or all-zeros diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c index 22b92aa09..e92eb85c1 100644 --- a/src/fs/fs_download.c +++ b/src/fs/fs_download.c @@ -239,6 +239,7 @@ schedule_block_download (struct GNUNET_FS_DownloadContext *dc, dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client, sizeof (struct SearchMessage), GNUNET_CONSTANTS_SERVICE_TIMEOUT, + GNUNET_NO, &transmit_download_request, dc); @@ -366,7 +367,7 @@ process_result (struct GNUNET_FS_DownloadContext *dc, /* abort all pending requests */ if (NULL != dc->th) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (dc->th); + GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } GNUNET_CLIENT_disconnect (dc->client); @@ -432,7 +433,7 @@ process_result (struct GNUNET_FS_DownloadContext *dc, /* abort all pending requests */ if (NULL != dc->th) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (dc->th); + GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } GNUNET_CLIENT_disconnect (dc->client); @@ -618,6 +619,7 @@ transmit_download_request (void *cls, dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client, sizeof (struct SearchMessage), GNUNET_CONSTANTS_SERVICE_TIMEOUT, + GNUNET_NO, &transmit_download_request, dc); return msize; @@ -654,6 +656,7 @@ do_reconnect (void *cls, dc->th = GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct SearchMessage), GNUNET_CONSTANTS_SERVICE_TIMEOUT, + GNUNET_NO, &transmit_download_request, dc); GNUNET_CLIENT_receive (client, @@ -704,7 +707,7 @@ try_reconnect (struct GNUNET_FS_DownloadContext *dc) { if (NULL != dc->th) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (dc->th); + GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } GNUNET_CONTAINER_multihashmap_iterate (dc->active, @@ -892,7 +895,7 @@ GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, dc->task); if (NULL != dc->th) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (dc->th); + GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } if (NULL != dc->client) diff --git a/src/fs/fs_list_indexed.c b/src/fs/fs_list_indexed.c index 1a404a078..9ef205ca0 100644 --- a/src/fs/fs_list_indexed.c +++ b/src/fs/fs_list_indexed.c @@ -154,50 +154,6 @@ handle_index_info (void *cls, } -/** - * Transmit the request to get a list of all - * indexed files to the "FS" service. - * - * @param cls closure (of type "struct GetIndexedContext*") - * @param size number of bytes availabe in buf - * @param buf where to write the message, NULL on error - * @return number of bytes written to buf - */ -static size_t -transmit_get_indexed (void *cls, - size_t size, - void *buf) -{ - struct GetIndexedContext *gic = cls; - struct GNUNET_MessageHeader *hdr; - - if (NULL == buf) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Failed to transmit `%s' request to `%s' service.\n"), - "GET_INDEXED", - "fs"); - GNUNET_SCHEDULER_add_continuation (gic->h->sched, - GNUNET_NO, - gic->cont, - gic->cont_cls, - GNUNET_SCHEDULER_REASON_TIMEOUT); - GNUNET_CLIENT_disconnect (gic->client); - GNUNET_free (gic); - return 0; - } - GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); - hdr = buf; - hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); - hdr->type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET); - GNUNET_CLIENT_receive (gic->client, - &handle_index_info, - gic, - GNUNET_CONSTANTS_SERVICE_TIMEOUT); - return sizeof (struct GNUNET_MessageHeader); -} - - /** * Iterate over all indexed files. * @@ -218,6 +174,7 @@ GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h, { struct GNUNET_CLIENT_Connection *client; struct GetIndexedContext *gic; + struct GNUNET_MessageHeader msg; client = GNUNET_CLIENT_connect (h->sched, "fs", @@ -242,11 +199,15 @@ GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h, gic->iterator_cls = iterator_cls; gic->cont = cont; gic->cont_cls = cont_cls; - GNUNET_CLIENT_notify_transmit_ready (client, - sizeof (struct GNUNET_MessageHeader), - GNUNET_CONSTANTS_SERVICE_TIMEOUT, - &transmit_get_indexed, - gic); + msg.size = htons (sizeof (struct GNUNET_MessageHeader)); + msg.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET); + GNUNET_assert (GNUNET_OK == + GNUNET_CLIENT_transmit_and_get_response (client, + &msg, + GNUNET_CONSTANTS_SERVICE_TIMEOUT, + GNUNET_YES, + &handle_index_info, + gic)); } /* end of fs_list_indexed.c */ diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 3501416ad..34a13f55c 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c @@ -783,6 +783,7 @@ hash_for_index_cb (void *cls, GNUNET_CLIENT_transmit_and_get_response (client, &ism->header, GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, &process_index_start_response, sc); GNUNET_free (ism); diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index ae681577f..94b8b2082 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c @@ -694,6 +694,7 @@ do_reconnect (void *cls, GNUNET_CLIENT_notify_transmit_ready (client, size, GNUNET_CONSTANTS_SERVICE_TIMEOUT, + GNUNET_NO, &transmit_search_request, sc); } @@ -812,6 +813,7 @@ search_start (struct GNUNET_FS_Handle *h, GNUNET_CLIENT_notify_transmit_ready (client, size, GNUNET_CONSTANTS_SERVICE_TIMEOUT, + GNUNET_NO, &transmit_search_request, sc); return sc; diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c index 4a57c7d59..0374e1db2 100644 --- a/src/fs/fs_unindex.c +++ b/src/fs/fs_unindex.c @@ -379,6 +379,7 @@ process_hash (void *cls, GNUNET_CLIENT_transmit_and_get_response (uc->client, &req.header, GNUNET_CONSTANTS_SERVICE_TIMEOUT, + GNUNET_YES, &process_fs_response, uc); } diff --git a/src/include/gnunet_client_lib.h b/src/include/gnunet_client_lib.h index 20842de5c..c78df41c7 100644 --- a/src/include/gnunet_client_lib.h +++ b/src/include/gnunet_client_lib.h @@ -96,6 +96,12 @@ void GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *sock, struct GNUNET_TIME_Relative timeout); +/** + * Transmit handle for client connections. + */ +struct GNUNET_CLIENT_TransmitHandle; + + /** * Ask the client to call us once the specified number of bytes * are free in the transmission buffer. May call the notify @@ -105,20 +111,35 @@ void GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *sock, * @param size number of bytes to send * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? + * @param auto_retry if the connection to the service dies, should we + * automatically re-connect and retry (within the timeout period) + * or should we immediately fail in this case? Pass GNUNET_YES + * if the caller does not care about temporary connection errors, + * for example because the protocol is stateless * @param notify function to call * @param notify_cls closure for notify * @return NULL if someone else is already waiting to be notified * non-NULL if the notify callback was queued (can be used to cancel * using GNUNET_CONNECTION_notify_transmit_ready_cancel) */ -struct GNUNET_CONNECTION_TransmitHandle +struct GNUNET_CLIENT_TransmitHandle *GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *sock, size_t size, struct GNUNET_TIME_Relative timeout, + int auto_retry, GNUNET_CONNECTION_TransmitReadyNotify - notify, void *notify_cls); + notify, + void *notify_cls); +/** + * Cancel a request for notification. + * + * @param th handle from the original request. + */ +void +GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle *th); + /** * Convenience API that combines sending a request @@ -131,13 +152,21 @@ struct GNUNET_CONNECTION_TransmitHandle * @param hdr message to transmit * @param timeout when to give up (for both transmission * and for waiting for a response) + * @param auto_retry if the connection to the service dies, should we + * automatically re-connect and retry (within the timeout period) + * or should we immediately fail in this case? Pass GNUNET_YES + * if the caller does not care about temporary connection errors, + * for example because the protocol is stateless * @param rn function to call with the response * @param rn_cls closure for rn + * @return GNUNET_OK on success, GNUNET_SYSERR if a request + * is already pending */ -void +int GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection *sock, const struct GNUNET_MessageHeader *hdr, struct GNUNET_TIME_Relative timeout, + int auto_retry, GNUNET_CLIENT_MessageHandler rn, void *rn_cls); diff --git a/src/peerinfo/peerinfo_api.c b/src/peerinfo/peerinfo_api.c index 14efa1708..d02ec3f2d 100644 --- a/src/peerinfo/peerinfo_api.c +++ b/src/peerinfo/peerinfo_api.c @@ -106,7 +106,9 @@ GNUNET_PEERINFO_add_peer (const struct GNUNET_CONFIGURATION_Handle *cfg, cc->msg = &pam->header; GNUNET_CLIENT_notify_transmit_ready (client, ntohs (pam->header.size), - ADD_PEER_TIMEOUT, ©_and_free, cc); + ADD_PEER_TIMEOUT, + GNUNET_YES, + ©_and_free, cc); } @@ -203,36 +205,6 @@ info_handler (void *cls, const struct GNUNET_MessageHeader *msg) } -static size_t -copy_then_receive (void *cls, size_t size, void *buf) -{ - struct InfoContext *ic = cls; - const struct GNUNET_MessageHeader *msg = - (const struct GNUNET_MessageHeader *) &ic[1]; - uint16_t msize; - - if (buf == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Failed to transmit message of type %u to `%s' service.\n"), - ntohs (msg->type), "peerinfo"); - ic->callback (ic->callback_cls, NULL, NULL, 1); - GNUNET_CLIENT_disconnect (ic->client); - GNUNET_free (ic); - return 0; - } - msize = ntohs (msg->size); - GNUNET_assert (size >= msize); - memcpy (buf, msg, msize); - GNUNET_CLIENT_receive (ic->client, - &info_handler, - ic, - GNUNET_TIME_absolute_get_remaining (ic->timeout)); - return msize; -} - - /** * Call a method for each known matching host and change * its trust value. The method will be invoked once for @@ -293,8 +265,20 @@ GNUNET_PEERINFO_for_all (const struct GNUNET_CONFIGURATION_Handle *cfg, lpm->trust_change = htonl (trust_delta); memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity)); } - GNUNET_CLIENT_notify_transmit_ready (client, - hs, timeout, ©_then_receive, ihc); + if (GNUNET_OK != + GNUNET_CLIENT_transmit_and_get_response (client, + (const struct GNUNET_MessageHeader*) &ihc[1], + timeout, + GNUNET_YES, + &info_handler, + ihc)) + { + GNUNET_break (0); + ihc->callback (ihc->callback_cls, NULL, NULL, 1); + GNUNET_CLIENT_disconnect (ihc->client); + GNUNET_free (ihc); + return; + } } /* end of peerinfo_api.c */ diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c index 21b8ecd8a..cc0a1b11a 100644 --- a/src/statistics/statistics_api.c +++ b/src/statistics/statistics_api.c @@ -539,7 +539,9 @@ schedule_action (struct GNUNET_STATISTICS_Handle *h) if (NULL == GNUNET_CLIENT_notify_transmit_ready (h->client, h->current->msize, - timeout, &transmit_action, h)) + timeout, + GNUNET_YES, + &transmit_action, h)) { #if DEBUG_STATISTICS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c index 0ddd3b86b..7ffff30d9 100644 --- a/src/transport/transport_api.c +++ b/src/transport/transport_api.c @@ -278,7 +278,7 @@ struct GNUNET_TRANSPORT_Handle /** * Handle to our registration with the client for notification. */ - struct GNUNET_CONNECTION_TransmitHandle *network_handle; + struct GNUNET_CLIENT_TransmitHandle *network_handle; /** * Linked list of transmit handles that are waiting for the @@ -477,6 +477,7 @@ schedule_transmission (struct GNUNET_TRANSPORT_Handle *h) th->notify_size, GNUNET_TIME_absolute_get_remaining (th->timeout), + GNUNET_NO, &transport_notify_ready, h); GNUNET_assert (NULL != h->network_handle); @@ -1596,7 +1597,7 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) #endif if (h->network_handle != NULL) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (h->network_handle); + GNUNET_CLIENT_notify_transmit_ready_cancel (h->network_handle); h->network_handle = NULL; h->transmission_scheduled = GNUNET_NO; th = h->connect_ready_head; @@ -1986,7 +1987,7 @@ GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct h = th->handle; if ((h->connect_ready_head == NULL) && (h->network_handle != NULL)) { - GNUNET_CONNECTION_notify_transmit_ready_cancel (h->network_handle); + GNUNET_CLIENT_notify_transmit_ready_cancel (h->network_handle); h->network_handle = NULL; h->transmission_scheduled = GNUNET_NO; } diff --git a/src/util/client.c b/src/util/client.c index bdb258b73..75d90b074 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -36,6 +36,14 @@ #define DEBUG_CLIENT GNUNET_NO + +/** + * How often do we re-try tranmsitting requests before giving up? + * Note that if we succeeded transmitting a request but failed to read + * a response, we do NOT re-try. + */ +#define MAX_ATTEMPTS 10 + /** * Struct to refer to a GNUnet TCP connection. * This is more than just a socket because if the server @@ -55,6 +63,11 @@ struct GNUNET_CLIENT_Connection */ struct GNUNET_SCHEDULER_Handle *sched; + /** + * Our configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + /** * Name of the service we interact with. */ @@ -116,20 +129,11 @@ struct GNUNET_CLIENT_Connection }; -/** - * Get a connection with a service. - * - * @param sched scheduler to use - * @param service_name name of the service - * @param cfg configuration to use - * @return NULL on error (service unknown to configuration) - */ -struct GNUNET_CLIENT_Connection * -GNUNET_CLIENT_connect (struct GNUNET_SCHEDULER_Handle *sched, - const char *service_name, - const struct GNUNET_CONFIGURATION_Handle *cfg) +static struct GNUNET_CONNECTION_Handle * +do_connect (struct GNUNET_SCHEDULER_Handle *sched, + const char *service_name, + const struct GNUNET_CONFIGURATION_Handle *cfg) { - struct GNUNET_CLIENT_Connection *ret; struct GNUNET_CONNECTION_Handle *sock; char *hostname; unsigned long long port; @@ -164,12 +168,34 @@ GNUNET_CLIENT_connect (struct GNUNET_SCHEDULER_Handle *sched, port, GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_free (hostname); + return sock; +} + + +/** + * Get a connection with a service. + * + * @param sched scheduler to use + * @param service_name name of the service + * @param cfg configuration to use + * @return NULL on error (service unknown to configuration) + */ +struct GNUNET_CLIENT_Connection * +GNUNET_CLIENT_connect (struct GNUNET_SCHEDULER_Handle *sched, + const char *service_name, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_CLIENT_Connection *ret; + struct GNUNET_CONNECTION_Handle *sock; + + sock = do_connect (sched, service_name, cfg); if (sock == NULL) return NULL; ret = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_Connection)); ret->sock = sock; ret->sched = sched; ret->service_name = GNUNET_strdup (service_name); + ret->cfg = cfg; return ret; } @@ -520,6 +546,171 @@ GNUNET_CLIENT_service_test (struct GNUNET_SCHEDULER_Handle *sched, } +/** + * Handle for a transmission request. + */ +struct GNUNET_CLIENT_TransmitHandle +{ + /** + * Connection state. + */ + struct GNUNET_CLIENT_Connection *sock; + + /** + * Function to call to get the data for transmission. + */ + GNUNET_CONNECTION_TransmitReadyNotify notify; + + /** + * Closure for notify. + */ + void *notify_cls; + + /** + * Handle to the transmission with the underlying + * connection. + */ + struct GNUNET_CONNECTION_TransmitHandle *th; + + /** + * Timeout. + */ + struct GNUNET_TIME_Absolute timeout; + + /** + * If we are re-trying and are delaying to do so, + * handle to the scheduled task managing the delay. + */ + GNUNET_SCHEDULER_TaskIdentifier task; + + /** + * Number of bytes requested. + */ + size_t size; + + /** + * Are we allowed to re-try to connect without telling + * the user (of this API) about the connection troubles? + */ + int auto_retry; + + /** + * Number of attempts left for transmitting the request. We may + * fail the first time (say because the service is not yet up), in + * which case (if auto_retry is set) we wait a bit and re-try + * (timeout permitting). + */ + unsigned int attempts_left; + +}; + + + +/** + * Connection notifies us about failure or success of + * a transmission request. Either pass it on to our + * user or, if possible, retry. + * + * @param cls our "struct GNUNET_CLIENT_TransmissionHandle" + * @param size number of bytes available for transmission + * @param buf where to write them + * @return number of bytes written to buf + */ +static size_t +client_notify (void *cls, + size_t size, + void *buf); + + + +/** + * This task is run if we should re-try connection to the + * service after a while. + * + * @param cls our "struct GNUNET_CLIENT_TransmitHandle" of the request + * @param tc unused + */ +static void +client_delayed_retry (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CLIENT_TransmitHandle *th = cls; + + th->task = GNUNET_SCHEDULER_NO_TASK; + th->sock->sock = do_connect (th->sock->sched, + th->sock->service_name, + th->sock->cfg); + th->th = GNUNET_CONNECTION_notify_transmit_ready (th->sock->sock, + th->size, + GNUNET_TIME_absolute_get_remaining (th->timeout), + &client_notify, + th); + if (th->th == NULL) + { + GNUNET_break (0); + th->notify (th->notify_cls, 0, NULL); + GNUNET_free (th); + return; + } +} + + +/** + * Connection notifies us about failure or success of + * a transmission request. Either pass it on to our + * user or, if possible, retry. + * + * @param cls our "struct GNUNET_CLIENT_TransmissionHandle" + * @param size number of bytes available for transmission + * @param buf where to write them + * @return number of bytes written to buf + */ +static size_t +client_notify (void *cls, + size_t size, + void *buf) +{ + struct GNUNET_CLIENT_TransmitHandle *th = cls; + size_t ret; + struct GNUNET_TIME_Relative delay; + + if (buf == NULL) + { + delay = GNUNET_TIME_absolute_get_remaining (th->timeout); + delay.value /= 2; + if ( (GNUNET_YES != th->auto_retry) || + (0 == --th->attempts_left) || + (delay.value < 1) ) + { + GNUNET_break (0 == th->notify (th->notify_cls, + 0, + NULL)); + GNUNET_free (th); + return 0; + } + /* auto-retry */ + GNUNET_CONNECTION_destroy (th->sock->sock); + th->sock->sock = NULL; + th->th = NULL; + delay = GNUNET_TIME_relative_min (delay, GNUNET_TIME_UNIT_SECONDS); + th->task = GNUNET_SCHEDULER_add_delayed (th->sock->sched, + GNUNET_NO, + GNUNET_SCHEDULER_PRIORITY_KEEP, + GNUNET_SCHEDULER_NO_TASK, + delay, + &client_delayed_retry, + th); + return 0; + } + GNUNET_assert (size >= th->size); + ret = th->notify (th->notify_cls, + size, + buf); + GNUNET_free (th); + return ret; +} + + /** * Ask the client to call us once the specified number of bytes * are free in the transmission buffer. May call the notify @@ -529,21 +720,65 @@ GNUNET_CLIENT_service_test (struct GNUNET_SCHEDULER_Handle *sched, * @param size number of bytes to send * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? + * @param auto_retry if the connection to the service dies, should we + * automatically re-connect and retry (within the timeout period) + * or should we immediately fail in this case? Pass GNUNET_YES + * if the caller does not care about temporary connection errors, + * for example because the protocol is stateless * @param notify function to call * @param notify_cls closure for notify * @return NULL if our buffer will never hold size bytes, * a handle if the notify callback was queued (can be used to cancel) */ -struct GNUNET_CONNECTION_TransmitHandle * +struct GNUNET_CLIENT_TransmitHandle * GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *sock, size_t size, struct GNUNET_TIME_Relative timeout, + int auto_retry, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { - return GNUNET_CONNECTION_notify_transmit_ready (sock->sock, - size, - timeout, notify, notify_cls); + struct GNUNET_CLIENT_TransmitHandle *th; + + th = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_TransmitHandle)); + th->sock = sock; + th->size = size; + th->timeout = GNUNET_TIME_relative_to_absolute (timeout); + th->auto_retry = auto_retry; + th->notify = notify; + th->notify_cls = notify_cls; + th->attempts_left = MAX_ATTEMPTS; + th->th = GNUNET_CONNECTION_notify_transmit_ready (sock->sock, + size, + timeout, + &client_notify, + th); + if (NULL == th->th) + { + GNUNET_free (th); + return NULL; + } + return th; +} + + +/** + * Cancel a request for notification. + * + * @param th handle from the original request. + */ +void +GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle *th) +{ + if (th->task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (th->sock->sched, + th->task); + else + { + GNUNET_break (NULL != th->th); + GNUNET_CONNECTION_notify_transmit_ready_cancel (th->th); + } + GNUNET_free (th); } @@ -629,13 +864,21 @@ transmit_for_response (void *cls, * @param hdr message to transmit * @param timeout when to give up (for both transmission * and for waiting for a response) + * @param auto_retry if the connection to the service dies, should we + * automatically re-connect and retry (within the timeout period) + * or should we immediately fail in this case? Pass GNUNET_YES + * if the caller does not care about temporary connection errors, + * for example because the protocol is stateless * @param rn function to call with the response * @param rn_cls closure for rn + * @return GNUNET_OK on success, GNUNET_SYSERR if a request + * is already pending */ -void +int GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection *sock, const struct GNUNET_MessageHeader *hdr, struct GNUNET_TIME_Relative timeout, + int auto_retry, GNUNET_CLIENT_MessageHandler rn, void *rn_cls) { @@ -650,11 +893,17 @@ GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection *sock, tc->timeout = GNUNET_TIME_relative_to_absolute (timeout); tc->rn = rn; tc->rn_cls = rn_cls; - GNUNET_CLIENT_notify_transmit_ready (sock, - msize, - timeout, - &transmit_for_response, - tc); + if (NULL == GNUNET_CLIENT_notify_transmit_ready (sock, + msize, + timeout, + auto_retry, + &transmit_for_response, + tc)) + { + GNUNET_free (tc); + return GNUNET_SYSERR; + } + return GNUNET_OK; } diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c index cbd8392bf..5dede1c09 100644 --- a/src/util/resolver_api.c +++ b/src/util/resolver_api.c @@ -48,11 +48,6 @@ struct GetAddressContext */ void *cls; - /** - * FIXME. - */ - struct GNUNET_RESOLVER_GetMessage *msg; - /** * FIXME. */ @@ -237,43 +232,6 @@ handle_address_response (void *cls, const struct GNUNET_MessageHeader *msg) } -/** - * FIXME - * - * @param cls FIXME - * @param size number of bytes available in buf - * @param buf target buffer, NULL on error - * @return number of bytes written to buf - */ -static size_t -transmit_get_ip (void *cls, size_t size, void *buf) -{ - struct GetAddressContext *actx = cls; - uint16_t ms; - - if (buf == NULL) - { - /* timeout / error */ - GNUNET_free (actx->msg); - actx->callback (actx->cls, NULL, 0); - GNUNET_CLIENT_disconnect (actx->client); - GNUNET_free (actx); - return 0; - } - ms = ntohs (actx->msg->header.size); - GNUNET_assert (size >= ms); - memcpy (buf, actx->msg, ms); - GNUNET_free (actx->msg); - actx->msg = NULL; - GNUNET_CLIENT_receive (actx->client, - &handle_address_response, - actx, - GNUNET_TIME_absolute_get_remaining (actx->timeout)); - return ms; -} - - - /** * Convert a string to one or more IP addresses. * @@ -404,19 +362,19 @@ GNUNET_RESOLVER_ip_get (struct GNUNET_SCHEDULER_Handle *sched, actx->cls = callback_cls; actx->client = client; actx->timeout = GNUNET_TIME_relative_to_absolute (timeout); - actx->msg = msg; #if DEBUG_RESOLVER GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolver requests DNS resolution of hostname `%s'.\n"), hostname); #endif - if (NULL == - GNUNET_CLIENT_notify_transmit_ready (client, - slen + - sizeof (struct - GNUNET_RESOLVER_GetMessage), - timeout, &transmit_get_ip, actx)) + if (GNUNET_OK != + GNUNET_CLIENT_transmit_and_get_response (client, + &msg->header, + timeout, + GNUNET_YES, + &handle_address_response, + actx)) { GNUNET_free (msg); GNUNET_free (actx); @@ -424,6 +382,7 @@ GNUNET_RESOLVER_ip_get (struct GNUNET_SCHEDULER_Handle *sched, GNUNET_CLIENT_disconnect (client); return; } + GNUNET_free (msg); } @@ -443,11 +402,6 @@ struct GetHostnameContext */ void *cls; - /** - * FIXME. - */ - struct GNUNET_RESOLVER_GetMessage *msg; - /** * FIXME. */ @@ -515,43 +469,6 @@ handle_hostname_response (void *cls, const struct GNUNET_MessageHeader *msg) } -/** - * FIXME - * - * @param cls FIXME - * @param size number of bytes available in buf - * @param buf target buffer, NULL on error - * @return number of bytes written to buf - */ -static size_t -transmit_get_hostname (void *cls, size_t size, void *buf) -{ - struct GetHostnameContext *hctx = cls; - uint16_t msize; - - if (buf == NULL) - { - GNUNET_free (hctx->msg); - hctx->callback (hctx->cls, NULL); - GNUNET_CLIENT_disconnect (hctx->client); - GNUNET_free (hctx); - return 0; - } - msize = ntohs (hctx->msg->header.size); - GNUNET_assert (size >= msize); - memcpy (buf, hctx->msg, msize); - GNUNET_free (hctx->msg); - hctx->msg = NULL; - GNUNET_CLIENT_receive (hctx->client, - &handle_hostname_response, - hctx, - GNUNET_TIME_absolute_get_remaining (hctx->timeout)); - return msize; -} - - - - /** * Get an IP address as a string. * @@ -624,19 +541,20 @@ GNUNET_RESOLVER_hostname_get (struct GNUNET_SCHEDULER_Handle *sched, hctx->cls = cls; hctx->client = client; hctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); - hctx->msg = msg; - if (NULL == - GNUNET_CLIENT_notify_transmit_ready (client, - sizeof (struct - GNUNET_RESOLVER_GetMessage) - + salen, timeout, - &transmit_get_hostname, hctx)) + if (GNUNET_OK != + GNUNET_CLIENT_transmit_and_get_response (client, + &msg->header, + timeout, + GNUNET_YES, + &handle_hostname_response, + hctx)) { GNUNET_free (msg); callback (cls, NULL); GNUNET_CLIENT_disconnect (client); GNUNET_free (hctx); } + GNUNET_free (msg); } /** diff --git a/src/util/test_client.c b/src/util/test_client.c index cda8025ac..04efd951b 100644 --- a/src/util/test_client.c +++ b/src/util/test_client.c @@ -163,8 +163,9 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert (NULL != GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct - GNUNET_MessageHeader), + GNUNET_MessageHeader), GNUNET_TIME_UNIT_SECONDS, + GNUNET_NO, &make_msg, NULL)); GNUNET_CLIENT_receive (client, &recv_bounce, cls, GNUNET_TIME_relative_multiply diff --git a/src/util/test_server_disconnect.c b/src/util/test_server_disconnect.c index 84e9c7ccd..9aff7fc72 100644 --- a/src/util/test_server_disconnect.c +++ b/src/util/test_server_disconnect.c @@ -210,6 +210,7 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 256, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), + GNUNET_NO, ¬ify_ready, NULL); } diff --git a/src/util/test_server_with_client.c b/src/util/test_server_with_client.c index 4f3048f34..2558fd10c 100644 --- a/src/util/test_server_with_client.c +++ b/src/util/test_server_with_client.c @@ -184,6 +184,7 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 256, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), + GNUNET_NO, ¬ify_ready, NULL); } diff --git a/src/util/test_service.c b/src/util/test_service.c index f615b0cf9..f615e7eb4 100644 --- a/src/util/test_service.c +++ b/src/util/test_service.c @@ -87,6 +87,7 @@ ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_SECONDS, + GNUNET_NO, &build_msg, client); } @@ -170,6 +171,7 @@ ready6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_SECONDS, + GNUNET_NO, &build_msg, client); } -- 2.25.1