diff --git a/include/ircd/server/request.h b/include/ircd/server/request.h index 35651b3e5..b96d2a04e 100644 --- a/include/ircd/server/request.h +++ b/include/ircd/server/request.h @@ -48,10 +48,14 @@ struct ircd::server::out /// This is where buffers are supplied to receive data from the remote /// server. /// +/// As a feature, when content == head, the head buffer is considered +/// as a contiguous buffer for both head and content; the content buffer +/// will be updated to point to any data after the head is received. +/// struct ircd::server::in { mutable_buffer head; - mutable_buffer content; + mutable_buffer content {head}; }; /// This is a handle for being a client to another server. This handle will diff --git a/ircd/server.cc b/ircd/server.cc index 8d243889d..1285283eb 100644 --- a/ircd/server.cc +++ b/ircd/server.cc @@ -1785,6 +1785,27 @@ ircd::server::tag::read_head(const const_buffer &buffer, data(req.in.head) + head_read, beyond_head_len }; + // Before changing the user's head buffer, we branch for a feature that + // allows the user to receive head and content into a single contiguous + // buffer by assigning in.content = in.head. + const bool contiguous + { + data(req.in.content) == data(req.in.head) + }; + + if(contiguous) + { + const auto content_max + { + std::max(ssize_t(size(req.in.content) - head_read), ssize_t(0)) + }; + + req.in.content = mutable_buffer + { + data(req.in.head) + head_read, size_t(content_max) + }; + } + // Resize the user's head buffer tight to the head; this is how we convey // the size of the dome back to the user. req.in.head = mutable_buffer @@ -1829,7 +1850,10 @@ ircd::server::tag::read_head(const const_buffer &buffer, // Any partial content was written to the head buffer by accident, // that has to be copied over to the content buffer. - this->content_read += copy(req.in.content, partial_content); + if(!contiguous) + this->content_read += copy(req.in.content, partial_content); + else + this->content_read += size(partial_content); // Anything remaining is not our response and must be given back assert(beyond_head_len >= content_read);