HTTPServer: use a queue to pipeline requests from each connected client

See https://www.rfc-editor.org/rfc/rfc7230#section-6.3.2

> A server MAY process a sequence of pipelined requests in
  parallel if they all have safe methods (Section 4.2.1 of [RFC7231]),
  but it MUST send the corresponding responses in the same order that
  the requests were received.

We choose NOT to process requests in parallel. They are executed in
the order recevied as well as responded to in the order received.
This prevents race conditions where old state may get sent in response
to requests that are very quick to process but were requested later on
in the queue.
This commit is contained in:
Matthew Zipkin
2025-04-03 12:28:42 -04:00
parent 5ef1b80a09
commit 7ee7df988e
2 changed files with 33 additions and 4 deletions

View File

@@ -6,6 +6,7 @@
#define BITCOIN_HTTPSERVER_H
#include <atomic>
#include <deque>
#include <functional>
#include <memory>
#include <optional>
@@ -538,6 +539,16 @@ public:
*/
std::vector<std::byte> m_recv_buffer{};
//! Requests from a client must be processed in the order in which
//! they were received, blocking on a per-client basis. We won't
//! process the next request in the queue if we are currently busy
//! handling a previous request.
std::deque<std::unique_ptr<HTTPRequest>> m_req_queue;
//! Set to true by the I/O thread when a request is popped off
//! and passed to a worker thread, reset to false by the worker thread.
std::atomic_bool m_req_busy{false};
/**
* Response data destined for this client.
* Written to by http worker threads, read and erased by HTTPServer I/O thread