From c412beacbf4ac46ec85632d0f28e2fe3fe093c56 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 26 Feb 2018 21:56:05 -0800 Subject: [PATCH] ircd::server: Add dynamic content allocation after receiving head. --- include/ircd/server/request.h | 12 ++++++++++++ ircd/server.cc | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/ircd/server/request.h b/include/ircd/server/request.h index d38b80274..7fbe0fd69 100644 --- a/include/ircd/server/request.h +++ b/include/ircd/server/request.h @@ -61,6 +61,12 @@ struct ircd::server::in /// received so far. This is only invoked for content, not for the head; /// however the first time it is invoked it is safe to view the in.head std::function progress; + + /// The dynamic buffer is a convenience that allows for the content buffer + /// to be allocated on demand once the head is received and the length is + /// known. To use dynamic, set the content buffer to nothing (i.e default + /// constructed mutable_buffer). + unique_buffer dynamic; }; /// This is a handle for being a client to another server. This handle will @@ -108,6 +114,12 @@ struct ircd::server::request::opts /// received is returned in the value and exceptions are thrown when no /// code can be returned. bool http_exceptions {true}; + + /// Only applies when using the dynamic content allocation feature; this + /// limits the size of that allocation in case the remote sends a larger + /// content-length value. If the remote sends more content, the behavior + /// is the same as if specifying an in.content buffer of this size. + size_t content_length_maxalloc {256_MiB}; }; inline diff --git a/ircd/server.cc b/ircd/server.cc index 6c4196e7e..09c0393c2 100644 --- a/ircd/server.cc +++ b/ircd/server.cc @@ -1944,6 +1944,25 @@ ircd::server::tag::read_head(const const_buffer &buffer, data(beyond_head) + size(partial_content), beyond_content_len }; + // We branch for a feature that allows dynamic allocation of the content + // buffer if the user did not specify any buffer. + const bool dynamic + { + null(req.in.content) + }; + + if(dynamic) + { + assert(req.opts); + const size_t alloc_size + { + std::min(head.content_length, req.opts->content_length_maxalloc) + }; + + req.in.dynamic = unique_buffer{alloc_size}; + req.in.content = req.in.dynamic; + } + // Reduce the user's content buffer to the content-length. This is sort of // how we convey the content-length back to the user. The buffer size will // eventually reflect how much content was actually received; the user can