Christian Grothoff hace 1 año
padre
commit
7d0ef5a5a4

+ 56 - 4
src/include/microhttpd2_main.h.in

@@ -1129,16 +1129,19 @@ struct MHD_DynContentZCIoVec
    * The number of elements in @a iov
    * The number of elements in @a iov
    */
    */
   unsigned int iov_count;
   unsigned int iov_count;
+
   /**
   /**
    * The pointer to the array with @a iov_count elements.
    * The pointer to the array with @a iov_count elements.
    */
    */
   const struct MHD_IoVec *iov;
   const struct MHD_IoVec *iov;
+
   /**
   /**
    * The callback to free resources.
    * The callback to free resources.
    * It is called once the full array of iov elements is sent.
    * It is called once the full array of iov elements is sent.
    * No callback is called if NULL.
    * No callback is called if NULL.
    */
    */
   MHD_FreeCallback iov_fcb;
   MHD_FreeCallback iov_fcb;
+
   /**
   /**
    * The parameter for @a iov_fcb
    * The parameter for @a iov_fcb
    */
    */
@@ -1149,6 +1152,7 @@ struct MHD_DynContentZCIoVec
  * The action type returned by Dynamic Content Creator callback
  * The action type returned by Dynamic Content Creator callback
  */
  */
 struct MHD_DynamicContentCreatorAction;
 struct MHD_DynamicContentCreatorAction;
+
 /**
 /**
  * The context used for Dynamic Content Creator callback
  * The context used for Dynamic Content Creator callback
  */
  */
@@ -1163,7 +1167,7 @@ struct MHD_DynamicContentCreatorContext;
  * The total size of the data in the buffer and in @a iov_data must
  * The total size of the data in the buffer and in @a iov_data must
  * be non-zero.
  * be non-zero.
  * @param[in,out] ctx the pointer the context as provided to the callback
  * @param[in,out] ctx the pointer the context as provided to the callback
- * @param data_size the amount of the data placed to the provided buffer,
+ * @param data_size the amount of the data placed to the provided buffer (not @a iov_data),
  *                  cannot be larger than provided buffer size,
  *                  cannot be larger than provided buffer size,
  *                  must be non-zero if @a iov_data is NULL or has no data,
  *                  must be non-zero if @a iov_data is NULL or has no data,
  * @param iov_data the optional pointer to the iov data,
  * @param iov_data the optional pointer to the iov data,
@@ -1184,13 +1188,52 @@ MHD_DCC_action_continue_zc (
 MHD_FN_PAR_NONNULL_ (1)
 MHD_FN_PAR_NONNULL_ (1)
 MHD_FN_PAR_CSTR_ (4);
 MHD_FN_PAR_CSTR_ (4);
 
 
-#define MHD_DCC_action_continue(ctx,data_size,chunk_ext) \
+
+/**
+ * Set action to "continue processing", the data is provided in the
+ * buffer and/or in the zero-copy @a iov_data.
+ * If data is provided both in the buffer and @a ivo_data then
+ * data in the buffer sent first, following the iov data.
+ * The total size of the data in the buffer and in @a iov_data must
+ * be non-zero.
+ * @param[in,out] ctx the pointer the context as provided to the callback
+ * @param data_size the amount of the data placed to the provided buffer (not @a iov_data),
+ *                  cannot be larger than provided buffer size,
+ *                  must be non-zero.
+ * @param chunk_ext the optional pointer to chunk extension string,
+ *                  can be NULL to not use chunk extension,
+ *                  ignored if chunked encoding is not used
+ * @return the pointer to the action if succeed,
+ *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
+ */
+#define MHD_DCC_action_continue_ce(ctx,data_size,chunk_ext) \
         MHD_DCC_action_continue_zc (ctx, data_size, NULL, chunk_ext)
         MHD_DCC_action_continue_zc (ctx, data_size, NULL, chunk_ext)
 
 
+
+/**
+ * Set action to "continue processing", the data is provided in the
+ * buffer and/or in the zero-copy @a iov_data.
+ * If data is provided both in the buffer and @a ivo_data then
+ * data in the buffer sent first, following the iov data.
+ * The total size of the data in the buffer and in @a iov_data must
+ * be non-zero.
+ * @param[in,out] ctx the pointer the context as provided to the callback
+ * @param data_size the amount of the data placed to the provided buffer;
+ *                  cannot be larger than provided buffer size,
+ *                  must be non-zero.
+ *
+ * @return the pointer to the action if succeed,
+ *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
+ */
+#define MHD_DCC_action_continue(ctx,data_size) \
+        MHD_DCC_action_continue_ce (ctx, data_size, NULL)
+
+
 /**
 /**
  * Set action to "finished".
  * Set action to "finished".
  * If function failed for any reason, the action is automatically
  * If function failed for any reason, the action is automatically
  * set to "stop with error".
  * set to "stop with error".
+ *
  * @param[in,out] ctx the pointer the context as provided to the callback
  * @param[in,out] ctx the pointer the context as provided to the callback
  * @param num_footers number of elements in the @a footers array,
  * @param num_footers number of elements in the @a footers array,
  *                    must be zero if @a footers is NULL
  *                    must be zero if @a footers is NULL
@@ -1209,8 +1252,17 @@ MHD_DCC_action_finished_with_footer (
 MHD_FN_PAR_NONNULL_ (1);
 MHD_FN_PAR_NONNULL_ (1);
 
 
 
 
-#define MHD_DCC_action_finished(action) \
-        MHD_DCC_set_action_finished_with_footer (action, 0, NULL)
+/**
+ * Set action to "finished".
+ * If function failed for any reason, the action is automatically
+ * set to "stop with error".
+ *
+ * @param[in,out] ctx the pointer the context as provided to the callback
+ * @return the pointer to the action if succeed,
+ *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
+ */
+#define MHD_DCC_action_finished(ctx) \
+        MHD_DCC_set_action_finished_with_footer (ctx, 0, NULL)
 
 
 
 
 /**
 /**

+ 29 - 0
src/tests/client_server/libtest.h

@@ -218,6 +218,35 @@ MHDT_server_reply_text (
   uint_fast64_t upload_size);
   uint_fast64_t upload_size);
 
 
 
 
+/**
+ * Returns the text from @a cls as the response to any
+ * request, but using chunks by returning @a cls
+ * word-wise (breaking into chunks at spaces).
+ *
+ * @param cls argument given together with the function
+ *        pointer when the handler was registered with MHD
+ * @param request the request object
+ * @param path the requested uri (without arguments after "?")
+ * @param method the HTTP method used (#MHD_HTTP_METHOD_GET,
+ *        #MHD_HTTP_METHOD_PUT, etc.)
+ * @param upload_size the size of the message upload content payload,
+ *                    #MHD_SIZE_UNKNOWN for chunked uploads (if the
+ *                    final chunk has not been processed yet)
+ * @return action how to proceed, NULL
+ *         if the request must be aborted due to a serious
+ *         error while handling the request (implies closure
+ *         of underling data stream, for HTTP/1.1 it means
+ *         socket closure).
+ */
+const struct MHD_Action *
+MHDT_server_reply_chunked_text (
+  void *cls,
+  struct MHD_Request *MHD_RESTRICT request,
+  const struct MHD_String *MHD_RESTRICT path,
+  enum MHD_HTTP_Method method,
+  uint_fast64_t upload_size);
+
+
 /**
 /**
  * Returns writes text from @a cls to a temporary file
  * Returns writes text from @a cls to a temporary file
  * and then uses the file descriptor to serve the
  * and then uses the file descriptor to serve the

+ 82 - 0
src/tests/client_server/libtest_convenience_server_reply.c

@@ -366,3 +366,85 @@ MHDT_server_reply_check_upload (
                                          &check_upload_cb,
                                          &check_upload_cb,
                                          (void *) want);
                                          (void *) want);
 }
 }
+
+
+/**
+ * Closure for #chunk_return.
+ */
+struct ChunkContext
+{
+  /**
+   * Where we are in the buffer.
+   */
+  const char *pos;
+};
+
+
+/**
+ * Function that returns a string in chunks.
+ *
+ * @param dyn_cont_cls must be a `struct ChunkContext`
+ * @param ctx the context to produce the action to return,
+ *            the pointer is only valid until the callback returns
+ * @param pos position in the datastream to access;
+ *        note that if a `struct MHD_Response` object is re-used,
+ *        it is possible for the same content reader to
+ *        be queried multiple times for the same data;
+ *        however, if a `struct MHD_Response` is not re-used,
+ *        libmicrohttpd guarantees that "pos" will be
+ *        the sum of all data sizes provided by this callback
+ * @param[out] buf where to copy the data
+ * @param max maximum number of bytes to copy to @a buf (size of @a buf)
+ * @return action to use,
+ *         NULL in case of any error (the response will be aborted)
+ */
+static const struct MHD_DynamicContentCreatorAction *
+chunk_return (void *cls,
+              struct MHD_DynamicContentCreatorContext *ctx,
+              uint_fast64_t pos,
+              void *buf,
+              size_t max)
+{
+  struct ChunkContext *cc = cls;
+  size_t imax = strlen (cc->pos);
+  const char *space = strchr (cc->pos, ' ');
+
+  if (0 == imax)
+    return MHD_DCC_action_finished (ctx);
+  if (imax > space - cc->pos + 1)
+    imax = space - cc->pos;
+  if (imax > max)
+    imax = max;
+  memcpy (buf,
+          cc->pos,
+          imax);
+  cc->pos += imax;
+  return MHD_DCC_action_continue (ctx,
+                                  imax);
+}
+
+
+const struct MHD_Action *
+MHDT_server_reply_chunked_text (
+  void *cls,
+  struct MHD_Request *MHD_RESTRICT request,
+  const struct MHD_String *MHD_RESTRICT path,
+  enum MHD_HTTP_Method method,
+  uint_fast64_t upload_size)
+{
+  const char *text = cls;
+  struct ChunkContext *cc;
+
+  cc = malloc (sizeof (struct ChunkContext));
+  if (NULL == cc)
+    return NULL;
+  cc->pos = text;
+
+  return MHD_action_from_response (
+    request,
+    MHD_response_from_callback (MHD_HTTP_STATUS_OK,
+                                MHD_SIZE_UNKNOWN,
+                                &chunk_return,
+                                cc,
+                                &free));
+}

+ 8 - 0
src/tests/client_server/test_client_server.c

@@ -238,6 +238,14 @@ main (int argc, char *argv[])
       .timeout_ms = 5000,
       .timeout_ms = 5000,
       .num_clients = 1
       .num_clients = 1
     },
     },
+    {
+      .label = "chunked response get",
+      .server_cb = &MHDT_server_reply_chunked_text,
+      .server_cb_cls = "Hello world",
+      .client_cb = &MHDT_client_get_root,
+      .client_cb_cls = "Hello world",
+      .timeout_ms = 2500,
+    },
     // TODO: chunked download
     // TODO: chunked download
     {
     {
       .label = NULL,
       .label = NULL,