From 95d1725ce3f2deafa33f697f5cb54ab6c557d415 Mon Sep 17 00:00:00 2001 From: "Evgeny Grin (Karlson2k)" Date: Mon, 23 Aug 2021 22:20:50 +0300 Subject: [PATCH] Connection: allocate persistent connection memory with helper The new helper function may reduce read or write buffer to make available the required amount of memory. This allow to use entire pool for read or write buffer. --- src/microhttpd/connection.c | 86 +++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 5cbb30ed..89528031 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c @@ -186,6 +186,77 @@ str_conn_error_ (ssize_t mhd_err_code) } +/** + * Allocate memory from connection's memory pool. + * If memory pool doesn't have enough free memory but read of write buffer + * have some unused memory, the size of the buffer will be reduced as needed. + * @param connection the connection to use + * @param size the size of allocated memory area + * @return pointer to allocated memory region in the pool or + * NULL if no memory is available + */ +static void* +connection_alloc_memory (struct MHD_Connection *connection, + size_t size) +{ + struct MHD_Connection *const c = connection; /* a short alias */ + struct MemoryPool *const pool = c->pool; /* a short alias */ + size_t required_free_size; /**< The required amount of free memory */ + size_t pool_free; /**< The amount of free memory in the pool */ + void *res; + + required_free_size = MHD_pool_alloc_size (size); + pool_free = MHD_pool_get_free (pool); + if (pool_free < required_free_size) + { + size_t need_to_free = required_free_size - pool_free; + mhd_assert (MHD_pool_alloc_size (need_to_free) == need_to_free); + if (NULL != c->write_buffer) + { + /* The connection is in the sending phase */ + mhd_assert (MHD_CONNECTION_START_REPLY <= c->state); + if (c->write_buffer_size - c->write_buffer_append_offset >= need_to_free) + { + char *buf; + buf = MHD_pool_reallocate (pool, + c->write_buffer, + c->write_buffer_size, + c->write_buffer_size - need_to_free); + mhd_assert (c->write_buffer == buf); +#ifdef NDEBUG + (void) buf; /* mute compiler warning */ +#endif + } + else + return NULL; + } + else if (NULL != c->read_buffer) + { + /* The connection is in the receiving phase */ + if (c->read_buffer_size - c->read_buffer_offset >= need_to_free) + { + char *buf; + buf = MHD_pool_reallocate (pool, + c->read_buffer, + c->read_buffer_size, + c->read_buffer_size - need_to_free); + mhd_assert (c->read_buffer == buf); +#ifdef NDEBUG + (void) buf; /* mute compiler warning */ +#endif + } + else + return NULL; + } + else + return NULL; + } + res = MHD_pool_allocate (pool, size, true); + mhd_assert (NULL != res); /* It has been checked that pool has enough space */ + return res; +} + + #endif /* HAVE_MESSAGES */ /** @@ -365,9 +436,8 @@ MHD_set_connection_value_n_nocheck_ (struct MHD_Connection *connection, { struct MHD_HTTP_Header *pos; - pos = MHD_pool_allocate (connection->pool, - sizeof (struct MHD_HTTP_Header), - true); + pos = connection_alloc_memory (connection, + sizeof (struct MHD_HTTP_Header)); if (NULL == pos) return MHD_NO; pos->header = (char *) key; @@ -920,9 +990,8 @@ try_ready_normal_body (struct MHD_Connection *connection) if (NULL != connection->resp_iov.iov) return MHD_YES; copy_size = response->data_iovcnt * sizeof(MHD_iovec_); - connection->resp_iov.iov = MHD_pool_allocate (connection->pool, - copy_size, - true); + connection->resp_iov.iov = connection_alloc_memory (connection, + copy_size); if (NULL == connection->resp_iov.iov) { MHD_mutex_unlock_chk_ (&response->mutex); @@ -2503,9 +2572,8 @@ parse_cookie_header (struct MHD_Connection *connection) &hdr, &hdr_len)) return MHD_YES; - cpy = MHD_pool_allocate (connection->pool, - hdr_len + 1, - true); + cpy = connection_alloc_memory (connection, + hdr_len + 1); if (NULL == cpy) { #ifdef HAVE_MESSAGES