[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 05/07: Re-written chunk footer generation function as a
From: |
gnunet |
Subject: |
[libmicrohttpd] 05/07: Re-written chunk footer generation function as a separate function |
Date: |
Wed, 28 Jul 2021 10:37:04 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit bbf0a2969c28a404439af922b7a01420ebc98300
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Sun Jun 6 18:23:03 2021 +0300
Re-written chunk footer generation function as a separate function
Separated reply footer generation from reply header generation.
---
src/microhttpd/connection.c | 188 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 187 insertions(+), 1 deletion(-)
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 2d3d5671..4ef6c5c3 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1307,6 +1307,121 @@ try_grow_read_buffer (struct MHD_Connection *connection,
}
+/**
+ * Shrink connection read buffer to the zero of data in the buffer
+ * @param connection the connection whose read buffer is being manipulated
+ */
+static void
+connection_shrink_read_buffer (struct MHD_Connection *connection)
+{
+ struct MHD_Connection *const c = connection; /**< a short alias */
+ void *new_buf;
+
+ if (NULL == c->read_buffer)
+ {
+ mhd_assert (0 == c->read_buffer_size);
+ mhd_assert (0 == c->read_buffer_offset);
+ c->read_buffer = NULL;
+ return;
+ }
+
+ mhd_assert (c->read_buffer_offset <= c->read_buffer_size);
+ new_buf = MHD_pool_reallocate (c->pool, c->read_buffer, c->read_buffer_size,
+ c->read_buffer_offset);
+ mhd_assert (c->read_buffer == new_buf);
+ c->read_buffer_size = c->read_buffer_offset;
+ if (0 == c->read_buffer_size)
+ c->read_buffer = NULL;
+}
+
+
+/**
+ * Allocate the maximum available amount of memory from MemoryPool
+ * for write buffer.
+ * @param connection the connection whose write buffer is being manipulated
+ * @return the size of free space in write buffer, may be smaller
+ * than requested size.
+ */
+static size_t
+connection_maximize_write_buffer (struct MHD_Connection *connection)
+{
+ struct MHD_Connection *const c = connection; /**< a short alias */
+ struct MemoryPool *const pool = connection->pool;
+ void *new_buf;
+ size_t new_size;
+
+ mhd_assert ((NULL != c->write_buffer) || (0 == c->write_buffer_size));
+ mhd_assert (c->write_buffer_append_offset >= c->write_buffer_send_offset);
+ mhd_assert (c->write_buffer_size >= c->write_buffer_append_offset);
+
+ new_size = c->write_buffer_size + MHD_pool_get_free (pool);
+ new_buf = MHD_pool_reallocate (pool,
+ c->write_buffer,
+ c->write_buffer_size,
+ new_size);
+ /* Buffer position must not be moved.
+ * Position could be moved only if buffer was allocated 'from_end',
+ * which cannot happen. */
+ mhd_assert ((c->write_buffer == new_buf) || (NULL == c->write_buffer));
+ c->write_buffer = new_buf;
+ c->write_buffer_size = new_size;
+ if (c->write_buffer_send_offset == c->write_buffer_append_offset)
+ {
+ /* All data have been sent, reset offsets to zero. */
+ c->write_buffer_send_offset = 0;
+ c->write_buffer_append_offset = 0;
+ }
+
+ return c->write_buffer_size - c->write_buffer_append_offset;
+}
+
+
+/**
+ * Shrink connection write buffer to the size of unsent data.
+ *
+ * @note: The number of calls of this function should be limited to avoid extra
+ * zeroing of the memory.
+ * @param connection the connection whose write buffer is being manipulated
+ * @param connection the connection to manipulate write buffer
+ */
+static void
+connection_shrink_write_buffer (struct MHD_Connection *connection)
+{
+ struct MHD_Connection *const c = connection; /**< a short alias */
+ struct MemoryPool *const pool = connection->pool;
+ void *new_buf;
+
+ mhd_assert ((NULL != c->write_buffer) || (0 == c->write_buffer_size));
+ mhd_assert (c->write_buffer_append_offset >= c->write_buffer_send_offset);
+ mhd_assert (c->write_buffer_size >= c->write_buffer_append_offset);
+
+ if (NULL == c->write_buffer)
+ return;
+ if (c->write_buffer_append_offset == c->write_buffer_size)
+ return;
+
+ new_buf = MHD_pool_reallocate (pool, c->write_buffer, c->write_buffer_size,
+ c->write_buffer_append_offset);
+ mhd_assert (c->write_buffer == new_buf);
+ c->write_buffer_size = c->write_buffer_append_offset;
+}
+
+
+/**
+ * Switch connection from recv mode to send mode.
+ *
+ * Current request header or body will not be read anymore,
+ * response must be assigned to connection.
+ * @param connection the connection to prepare for sending.
+ */
+static void
+connection_switch_from_recv_to_send (struct MHD_Connection *connection)
+{
+ /* Read buffer is not needed for this request, shrink it.*/
+ connection_shrink_read_buffer (connection);
+}
+
+
/**
* Allocate the connection's write buffer and fill it with all of the
* headers (or footers, if we have already sent the body) from the
@@ -1681,6 +1796,72 @@ build_header_response (struct MHD_Connection *connection)
}
+/**
+ * Allocate the connection's write buffer (if necessary) and fill it
+ * with response footers.
+ * Works only for chunked responses as other responses do not need
+ * and do not support any kind of footers.
+ *
+ * @param connection the connection
+ * @return #MHD_YES on success, #MHD_NO on failure (out of memory)
+ */
+static enum MHD_Result
+build_connection_chunked_response_footer (struct MHD_Connection *connection)
+{
+ char *buf; /**< the buffer to write footers to */
+ size_t buf_size; /**< the size of the @a buf */
+ size_t used_size; /**< the used size of the @a buf */
+ struct MHD_Connection *const c = connection; /**< a short alias */
+ struct MHD_HTTP_Header *pos;
+
+ /* TODO: replace with 'use_chunked_send' */
+ mhd_assert (connection->have_chunked_upload);
+ /* TODO: allow combining of the final footer with the last chunk,
+ * modify the next assert. */
+ mhd_assert (MHD_CONNECTION_BODY_SENT == connection->state);
+ mhd_assert (NULL != c->response);
+
+ buf_size = connection_maximize_write_buffer (c);
+ /* '2' is the minimal size of chunked footer ("\r\n") */
+ if (buf_size < 2)
+ return MHD_NO;
+ buf = c->write_buffer + c->write_buffer_append_offset;
+ used_size = 0;
+
+ for (pos = c->response->first_header; NULL != pos; pos = pos->next)
+ {
+ if (MHD_FOOTER_KIND == pos->kind)
+ {
+ size_t new_used_size; /* resulting size with this header */
+ /* '4' is colon, space, linefeeds */
+ new_used_size = used_size + pos->header_size + pos->value_size + 4;
+ if (new_used_size > buf_size)
+ return MHD_NO;
+ memcpy (buf + used_size, pos->header, pos->header_size);
+ used_size += pos->header_size;
+ buf[used_size++] = ':';
+ buf[used_size++] = ' ';
+ memcpy (buf + used_size, pos->value, pos->value_size);
+ used_size += pos->value_size;
+ buf[used_size++] = '\r';
+ buf[used_size++] = '\n';
+ mhd_assert (used_size == new_used_size);
+ }
+ }
+ if (used_size + 2 > buf_size)
+ return MHD_NO;
+ memcpy (buf + used_size, "\r\n", 2);
+ used_size += 2;
+
+ c->write_buffer_append_offset += used_size;
+ mhd_assert (c->write_buffer_append_offset <= c->write_buffer_size);
+
+ /* TODO: remove shrink */
+ connection_shrink_write_buffer (c);
+ return MHD_YES;
+}
+
+
/**
* We encountered an error processing the request.
* Handle it properly by stopping to read data
@@ -3805,6 +3986,8 @@ MHD_connection_handle_idle (struct MHD_Connection
*connection)
continue;
if (NULL == connection->response)
break; /* try again next time */
+
+ connection_switch_from_recv_to_send (connection);
if (MHD_NO == build_header_response (connection))
{
/* oops - close! */
@@ -3918,7 +4101,10 @@ MHD_connection_handle_idle (struct MHD_Connection
*connection)
/* mutex was already unlocked by try_ready_chunked_body */
break;
case MHD_CONNECTION_BODY_SENT:
- if (MHD_NO == build_header_response (connection))
+ /* TODO: replace with 'use_chunked_send' */
+ mhd_assert (connection->have_chunked_upload);
+
+ if (MHD_NO == build_connection_chunked_response_footer (connection))
{
/* oops - close! */
CONNECTION_CLOSE_ERROR (connection,
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] branch master updated (237aebfa -> 182ed3a0), gnunet, 2021/07/28
- [libmicrohttpd] 02/07: try_ready_chunked_body: use new string function, fixes., gnunet, 2021/07/28
- [libmicrohttpd] 03/07: response: use auto flag for chunked encoding header, gnunet, 2021/07/28
- [libmicrohttpd] 07/07: response: use macro instead of string for connection header, gnunet, 2021/07/28
- [libmicrohttpd] 05/07: Re-written chunk footer generation function as a separate function,
gnunet <=
- [libmicrohttpd] 01/07: Added internal functions for printing decimal and hex numbers, gnunet, 2021/07/28
- [libmicrohttpd] 04/07: keepalive_possible(): check whether app requested close, gnunet, 2021/07/28
- [libmicrohttpd] 06/07: Added new public API function MHD_get_reason_phrase_len_for(), gnunet, 2021/07/28