summaryrefslogtreecommitdiff
path: root/http/http2_connection.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'http/http2_connection.hpp')
-rw-r--r--http/http2_connection.hpp123
1 files changed, 56 insertions, 67 deletions
diff --git a/http/http2_connection.hpp b/http/http2_connection.hpp
index 95d184e67b..a9e91d7a97 100644
--- a/http/http2_connection.hpp
+++ b/http/http2_connection.hpp
@@ -21,7 +21,6 @@
#include <boost/beast/http/parser.hpp>
#include <boost/beast/http/read.hpp>
#include <boost/beast/http/serializer.hpp>
-#include <boost/beast/http/string_body.hpp>
#include <boost/beast/http/write.hpp>
#include <boost/beast/ssl/ssl_stream.hpp>
#include <boost/beast/websocket.hpp>
@@ -35,9 +34,9 @@ namespace crow
struct Http2StreamData
{
- crow::Request req{};
- crow::Response res{};
- size_t sentSofar = 0;
+ Request req{};
+ Response res{};
+ std::optional<bmcweb::FileBody::writer> writer;
};
template <typename Adaptor, typename Handler>
@@ -48,14 +47,10 @@ class HTTP2Connection :
public:
HTTP2Connection(Adaptor&& adaptorIn, Handler* handlerIn,
- std::function<std::string()>& getCachedDateStrF
-
- ) :
+ std::function<std::string()>& getCachedDateStrF) :
adaptor(std::move(adaptorIn)),
-
- ngSession(initializeNghttp2Session()),
-
- handler(handlerIn), getCachedDateStr(getCachedDateStrF)
+ ngSession(initializeNghttp2Session()), handler(handlerIn),
+ getCachedDateStr(getCachedDateStrF)
{}
void start()
@@ -103,59 +98,46 @@ class HTTP2Connection :
}
Http2StreamData& stream = streamIt->second;
BMCWEB_LOG_DEBUG("File read callback length: {}", length);
- crow::Response& res = stream.res;
-
- Response::string_response* body =
- boost::variant2::get_if<Response::string_response>(&res.response);
- Response::file_response* fbody =
- boost::variant2::get_if<Response::file_response>(&res.response);
-
- size_t size = res.size();
- BMCWEB_LOG_DEBUG("total: {} send_sofar: {}", size, stream.sentSofar);
- size_t toSend = std::min(size - stream.sentSofar, length);
- BMCWEB_LOG_DEBUG("Copying {} bytes to buf", toSend);
-
- if (body != nullptr)
+ boost::beast::error_code ec;
+ boost::optional<std::pair<boost::asio::const_buffer, bool>> out =
+ stream.writer->getWithMaxSize(ec, length);
+ if (ec)
{
- std::string::const_iterator bodyBegin = body->body().begin();
- std::advance(bodyBegin, stream.sentSofar);
-
- memcpy(buf, &*bodyBegin, toSend);
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
- else if (fbody != nullptr)
- {
- boost::system::error_code ec;
- size_t nread = fbody->body().file().read(buf, toSend, ec);
- if (ec || nread != toSend)
- {
- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
- }
+ if (!out)
+ {
+ *dataFlags |= NGHTTP2_DATA_FLAG_EOF;
+ return 0;
}
- else
+
+ BMCWEB_LOG_DEBUG("Send chunk of size: {}", out->first.size());
+ if (length < out->first.size())
{
+ // Should never happen because of length limit on get() above
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
- stream.sentSofar += toSend;
+ BMCWEB_LOG_DEBUG("Copying {} bytes to buf", out->first.size());
+ memcpy(buf, out->first.data(), out->first.size());
- if (stream.sentSofar >= size)
+ if (!out->second)
{
- BMCWEB_LOG_DEBUG("Setting OEF flag");
+ BMCWEB_LOG_DEBUG("Setting OEF and nocopy flag");
*dataFlags |= NGHTTP2_DATA_FLAG_EOF;
//*dataFlags |= NGHTTP2_DATA_FLAG_NO_COPY;
}
- return static_cast<ssize_t>(toSend);
+ return static_cast<ssize_t>(out->first.size());
}
nghttp2_nv headerFromStringViews(std::string_view name,
- std::string_view value)
+ std::string_view value, uint8_t flags)
{
uint8_t* nameData = std::bit_cast<uint8_t*>(name.data());
uint8_t* valueData = std::bit_cast<uint8_t*>(value.data());
- return {nameData, valueData, name.size(), value.size(),
- NGHTTP2_NV_FLAG_NONE};
+ return {nameData, valueData, name.size(), value.size(), flags};
}
int sendResponse(Response& completedRes, int32_t streamId)
@@ -178,14 +160,18 @@ class HTTP2Connection :
boost::beast::http::fields& fields = thisRes.fields();
std::string code = std::to_string(thisRes.resultInt());
- hdr.emplace_back(headerFromStringViews(":status", code));
+ hdr.emplace_back(
+ headerFromStringViews(":status", code, NGHTTP2_NV_FLAG_NONE));
for (const boost::beast::http::fields::value_type& header : fields)
{
- hdr.emplace_back(
- headerFromStringViews(header.name_string(), header.value()));
+ hdr.emplace_back(headerFromStringViews(
+ header.name_string(), header.value(),
+ NGHTTP2_NV_FLAG_NO_COPY_VALUE | NGHTTP2_NV_FLAG_NO_COPY_NAME));
}
Http2StreamData& stream = it->second;
- stream.sentSofar = 0;
+ crow::Response& res = stream.res;
+ http::response<bmcweb::FileBody>& fbody = res.response;
+ stream.writer.emplace(fbody.base(), fbody.body());
nghttp2_data_provider dataPrd{
.source = {.fd = 0},
@@ -480,7 +466,7 @@ class HTTP2Connection :
static ssize_t onSendCallbackStatic(nghttp2_session* session,
const uint8_t* data, size_t length,
- int flags /* flags */, void* userData)
+ int flags, void* userData)
{
return userPtrToSelf(userData).onSendCallback(session, data, length,
flags);
@@ -519,36 +505,39 @@ class HTTP2Connection :
return;
}
inBuffer.commit(bytesTransferred);
-
- size_t consumed = 0;
- for (const auto bufferIt : inBuffer.data())
+ // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+ for (const auto* it =
+ boost::asio::buffer_sequence_begin(inBuffer.data());
+ it != boost::asio::buffer_sequence_end(inBuffer.data()); it++)
{
- std::span<const uint8_t> bufferSpan{
- std::bit_cast<const uint8_t*>(bufferIt.data()),
- bufferIt.size()};
- BMCWEB_LOG_DEBUG("http2 is getting {} bytes",
- bufferSpan.size());
- ssize_t readLen = ngSession.memRecv(bufferSpan);
- if (readLen <= 0)
+ // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+ while (inBuffer.size() > 0)
{
- BMCWEB_LOG_ERROR("nghttp2_session_mem_recv returned {}",
- readLen);
- close();
- return;
+ std::span<const uint8_t> bufferSpan{
+ std::bit_cast<const uint8_t*>(it->data()), it->size()};
+ BMCWEB_LOG_DEBUG("http2 is getting {} bytes",
+ bufferSpan.size());
+ ssize_t readLen = ngSession.memRecv(bufferSpan);
+ if (readLen <= 0)
+ {
+ BMCWEB_LOG_ERROR("nghttp2_session_mem_recv returned {}",
+ readLen);
+ close();
+ return;
+ }
+ inBuffer.consume(static_cast<size_t>(readLen));
}
- consumed += static_cast<size_t>(readLen);
}
- inBuffer.consume(consumed);
doRead();
});
}
// A mapping from http2 stream ID to Stream Data
- boost::container::flat_map<int32_t, Http2StreamData> streams;
+ std::map<int32_t, Http2StreamData> streams;
boost::beast::multi_buffer sendBuffer;
- boost::beast::multi_buffer inBuffer;
+ boost::beast::flat_static_buffer<8192> inBuffer;
Adaptor adaptor;
bool isWriting = false;