giving client API option for auto-retry, making more often use of transmit_and_get_re...
authorChristian Grothoff <christian@grothoff.org>
Sat, 24 Oct 2009 21:45:44 +0000 (21:45 +0000)
committerChristian Grothoff <christian@grothoff.org>
Sat, 24 Oct 2009 21:45:44 +0000 (21:45 +0000)
25 files changed:
src/arm/arm_api.c
src/arm/test_gnunet_arm.sh
src/core/core_api.c
src/datastore/Makefile.am
src/datastore/datastore_api.c
src/datastore/perf_datastore_api.c
src/datastore/test_datastore_api.c
src/datastore/test_datastore_api_data.conf
src/datastore/test_datastore_api_management.c
src/fs/fs.h
src/fs/fs_download.c
src/fs/fs_list_indexed.c
src/fs/fs_publish.c
src/fs/fs_search.c
src/fs/fs_unindex.c
src/include/gnunet_client_lib.h
src/peerinfo/peerinfo_api.c
src/statistics/statistics_api.c
src/transport/transport_api.c
src/util/client.c
src/util/resolver_api.c
src/util/test_client.c
src/util/test_server_disconnect.c
src/util/test_server_with_client.c
src/util/test_service.c

index 49e25b38ddb57804b28b5afd59e6945293f413d8..00ddddaabbf1818afc84b568a4583133ba336acb 100644 (file)
 #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);
 }
 
 
index ce4396cfbfe1ecb45d5818c9cf4a36a1f2d0b7d2..d36c2ca38180271337c30d28650e1a376a2d8946 100755 (executable)
@@ -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"
 
 
index 89bae05252caeea6ab054cd58af2c19920fe05a2..2157584ab7ca6132e050ab6e18507af0ba5e081b 100644 (file)
@@ -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);
index e4de8fcfa62247ccf88e12c18e9656d3f8870aa5..b9d8ec38f3d8424729e5406997f36cd431b35b82 100644 (file)
@@ -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 = \
index f6d7480de3dcf2d4ec69b86437d18a8df68ad8d3..a9058fa049977a3fcd0d8826b6724d108a986a2b 100644 (file)
@@ -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;
index 1bee3ee57253627e70b5f9efb772543e8f0c165b..e454e69f077be38968b2f03aaa17570f5a37cb5d 100644 (file)
@@ -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
index a63f0425f85d09749b29c12acc54d2be092ea01c..6a63e8e2661a88eda65a623bac09c2d368772528 100644 (file)
@@ -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
index 815bce0b808a0fac275b2526d92719b8b1df12a4..a09bfae0ee72cba746589e582f6b3770fd5780c6 100644 (file)
@@ -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
index 22d4aff25c40f74273e413b00225804fdf057d1e..c9fc9c8c5c7c940d53d6f7a0d47f2037197371cf 100644 (file)
@@ -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
index 8270d38ba3a134c308f7ce64305babc53c5356b8..2cac304a3dddd01c8484a980e82e413331b1eae7 100644 (file)
@@ -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
index 22b92aa09391172a5ce32d90684f8b90fd7dd902..e92eb85c1a6434b97c242ba4b796ab13d21cae78 100644 (file)
@@ -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)
index 1a404a078051e25012304084cea09f547fed47d0..9ef205ca0269553a4466be870b93d58edd603686 100644 (file)
@@ -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 */
index 3501416ad8eeb7951e0558ff97967c41a0274239..34a13f55c8e90c1de958a570e15ef2afc9ba7d01 100644 (file)
@@ -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);
index ae681577fa7d36d4a5c1c24167567082a958f7ee..94b8b20823c97e3368fc943456b12e68ddb01b2a 100644 (file)
@@ -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;
index 4a57c7d596457960f5856a86f9d70f242854ce54..0374e1db2b3628e18498f07986ff2dc3489670f0 100644 (file)
@@ -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);
 }
index 20842de5c238be7458e8a4e2e44acee265cc10f6..c78df41c7c59a993420f9b661b18a3c76ced01d3 100644 (file)
@@ -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);
 
index 14efa17082531543514440bca234b50759a8bfcd..d02ec3f2d6c3bedc9422859667f8fd10ba364107 100644 (file)
@@ -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, &copy_and_free, cc);
+                                       ADD_PEER_TIMEOUT, 
+                                      GNUNET_YES,
+                                      &copy_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, &copy_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 */
index 21b8ecd8ab782607ff63a913ff7156c217e3a2ab..cc0a1b11a6c3042f6fdb5a46b30d54dc2e9d0b75 100644 (file)
@@ -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,
index 0ddd3b86ba44f5c9181b4d7adbf5dd07fec48593..7ffff30d9b75e92c435d8dd3b84a253ed8b8567b 100644 (file)
@@ -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;
     }
index bdb258b733e607fb4343016c0f04551e4bbfa409..75d90b074c482991b3bd42b9e632928f196e34e2 100644 (file)
 
 #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;
 }
 
 
index cbd8392bfff8b212061ed54ff745752c96b808e0..5dede1c09d927513d11ceba76ec9e7a9792db1c1 100644 (file)
@@ -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);
 }
 
 /**
index cda8025acb3aa7a6efe492be961c29dd05a92323..04efd951b4cf6452229b3961536ad2270a791485 100644 (file)
@@ -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
index 84e9c7ccd1d201d5f0e8f4dc34f06746cae135ca..9aff7fc72dd74aca613f0bc39775045fdaf87ff8 100644 (file)
@@ -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,
                                        &notify_ready, NULL);
 }
 
index 4f3048f340ea8aba6ef6a34f369f790b81ec7153..2558fd10c960ece026ff778c976abde63bb55cc1 100644 (file)
@@ -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,
                                        &notify_ready, NULL);
 }
 
index f615b0cf9e315225495e4ce009efe470c735be10..f615e7eb446363d9fbe6ad303b9bc155413a4575 100644 (file)
@@ -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);
 }