Replace libevent with our own HTTP and socket-handling implementation #32061

pull pinheadmz wants to merge 30 commits into bitcoin:master from pinheadmz:http-rewrite-13march2025 changing 24 files +2710 −606
  1. pinheadmz commented at 7:32 pm on March 13, 2025: member

    This is a major component of removing libevent as a dependency of the project

    It is based on #30988 but only in the sense that it copies the Sockman class introduced in that PR. The p2p / Connman refactor isn’t needed for HTTP and therefore this branch can be reviewed and merged independently of the p2p changes.

    Commit strategy:

    • Import sockman.{h,cpp} from #30988
    • Assert current behavior of HTTP with additional functional tests, including copying from libevent’s tests
    • Implement a few helper functions for strings, timestamps, etc needed by HTTP protocol
    • Isolate the existing libevent-based HTTP server in a namespace http_libevent
    • Implement HTTP in a new namespace http_bitcoin (the namespace manages duplicate HTTPRequest definitions, etc)
    • Switch bitcoind from the libevent server to the new server
    • Clean up (delete http_libevent)

    I am currently seeing about a 10% speed up in the functional tests on my own arm/macos machine.

    Integration testing:

    I am testing the new HTTP server by forking projects that integrate with bitcoin via HTTP and running their integration tests with bitcoind built from this branch (on Github actions). I will continue adding integrations over time, and re-running these CI tests as this branch gets rebased:

  2. DrahtBot commented at 7:32 pm on March 13, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32061.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK romanz
    Concept ACK laanwj, vasild, fjahr, w0xlt

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #32408 (tests: Expand HTTP coverage to assert libevent behavior by pinheadmz)
    • #31929 (http: Make server shutdown more robust by hodlinator)
    • #31672 (rpc: add cpu_load to getpeerinfo by vasild)
    • #27731 (Prevent file descriptor exhaustion from too many RPC calls by fjahr)
    • #26022 (Add util::ResultPtr class by ryanofsky)
    • #25665 (refactor: Add util::Result failure values, multiple error and warning messages by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    1. In httpserver.h comment: “Each connection is assigned an unique id of this type.” → “Each connection is assigned a unique id of this type.”
    2. In SockMan::ConnectAndMakeId documentation: “…if the later is used…” → “…if the latter is used…”
      No other typographic or grammatical errors were found.
  3. pinheadmz marked this as a draft on Mar 13, 2025
  4. DrahtBot added the label CI failed on Mar 13, 2025
  5. DrahtBot commented at 8:29 pm on March 13, 2025: contributor

    🚧 At least one of the CI tasks failed. Debug: https://github.com/bitcoin/bitcoin/runs/38735177073

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  6. laanwj added the label RPC/REST/ZMQ on Mar 14, 2025
  7. laanwj commented at 12:52 pm on March 14, 2025: member
    Concept ACK, nice work
  8. vasild commented at 1:57 pm on March 14, 2025: contributor
    Concept ACK
  9. fjahr commented at 8:29 pm on March 14, 2025: contributor

    Concept ACK

    My understanding from the low-level networking discussion at CoreDev was that this wouldn’t build on top of sockman. I guess the devil is in the details but can you address that in what sense the current approach follows what was discussed there? Thanks!

  10. pinheadmz commented at 0:03 am on March 15, 2025: member

    My understanding from the low-level networking discussion at CoreDev was that this wouldn’t build on top of sockman. I guess the devil is in the details but can you address that in what sense the current approach follows what was discussed there? Thanks!

    Sure, by coredev I had already written most of this implementation (based on sockman) but the performance was bad, and that was part of the motivation behind the deep-dive talk. However, by the end of the week I had reviewed that code in person with smart attendees and not only improved the performance of my code but started to improve performance vs master branch as well! Those updates came in the days just after the deep-dive discussion.

    SOME kind of sockman is needed to replace libevent. The one @vasild wrote does actually seem to work well for this purpose as well as for p2p, and it would be “nice” to only have to maintain one I/O loop structure in bitcoind. @theuni is investigating how a sockman for http could be optimized if it had no other purpose, and I think that is the kind of feedback that will help us decide which path to take.

  11. pinheadmz force-pushed on Mar 18, 2025
  12. pinheadmz force-pushed on Mar 18, 2025
  13. vasild commented at 12:22 pm on March 19, 2025: contributor

    SOME kind of sockman is needed to replace libevent … it would be “nice” to only have to maintain one I/O loop structure in bitcoind.

    :100:

  14. pinheadmz force-pushed on Mar 19, 2025
  15. DrahtBot added the label Needs rebase on Mar 20, 2025
  16. pinheadmz force-pushed on Mar 20, 2025
  17. pinheadmz force-pushed on Mar 20, 2025
  18. DrahtBot removed the label Needs rebase on Mar 20, 2025
  19. pinheadmz force-pushed on Mar 21, 2025
  20. DrahtBot added the label Needs rebase on Mar 24, 2025
  21. pinheadmz force-pushed on Mar 29, 2025
  22. pinheadmz force-pushed on Mar 29, 2025
  23. DrahtBot removed the label CI failed on Mar 30, 2025
  24. DrahtBot removed the label Needs rebase on Mar 30, 2025
  25. pinheadmz force-pushed on Mar 31, 2025
  26. pinheadmz commented at 10:18 am on March 31, 2025: member

    I rebased this branch on a single squashed commit from #30988 essentially just cherry-picking sockman.{h,cpp} by @vasild and leaving out the p2p refactor. This will make rebase maintenance on master a lot easier by reducing conflicting scope, and hopefully also makes review easier. It also means to some extent this PR can be merged independently of #30988, and also gives @theuni some room to rewrite a specific HTTP sockman if a more efficient purpose-focused module can be written. (Will update PR description in a moment)

    I’ve finally gotten all CI to pass so I’m going to mark this PR as ready for review as I move on to integration testing with all the bitcoin client libraries I can find!

  27. pinheadmz marked this as ready for review on Mar 31, 2025
  28. pinheadmz renamed this:
    [draft] Replace libevent with our own HTTP and socket-handling implementation
    Replace libevent with our own HTTP and socket-handling implementation
    on Mar 31, 2025
  29. pinheadmz force-pushed on Apr 3, 2025
  30. pinheadmz commented at 7:14 pm on April 3, 2025: member
    rebase to a225633e34 includes a new test for “pipelining” HTTP requests (thanks @theuni for pointing out this oversight) and also adds a queue of requests to each HTTPClient to ensure requests are processed in series, in the order they were received.
  31. Introduce a new low-level socket managing class `SockMan` cfe5eba446
  32. test: cover http pipelining 00d18bbe09
  33. test: cover -rpcservertimeout
    Testing this requires adding an option to TestNode to force
    the test framework to establish a new HTTP connection for
    every RPC. Otherwise, attempting to reuse a persistent connection
    would cause framework RPCs during startup and shutdown to fail.
    5ec06529bb
  34. test: cover "chunked" Transfer-Encoding f259121f30
  35. string: implement ParseUInt64Hex 4c83785d1d
  36. string: add CaseInsensitiveComparator
    https://httpwg.org/specs/rfc9110.html#rfc.section.5.1
    Field names in HTTP headers are case-insensitive. This
    comparator will be used in the headers map to search by key.
    In libevent these are compared in lowercase:
      evhttp_find_header()
      evutil_ascii_strcasecmp()
      EVUTIL_TOLOWER_()
    144a777f86
  37. pinheadmz force-pushed on Apr 3, 2025
  38. DrahtBot added the label CI failed on Apr 3, 2025
  39. DrahtBot removed the label CI failed on Apr 4, 2025
  40. w0xlt commented at 7:06 pm on April 17, 2025: contributor
    Concept ACK.
  41. in src/common/sockman.cpp:396 in cfe5eba446 outdated
    391+        LogPrintf("connection from %s dropped: non-selectable socket\n", them.ToStringAddrPort());
    392+        return;
    393+    }
    394+
    395+    // According to the internet TCP_NODELAY is not carried into accepted sockets
    396+    // on all platforms.  Set it again here just to be sure.
    


    romanz commented at 5:44 am on April 21, 2025:
    nit: this comment seems to be incorrect, since TCP_NODELAY is only set once by SockMan.

    pinheadmz commented at 1:53 pm on April 28, 2025:

    This comment may need to be applied upstream in #30988

    FWIW, the Sockman backend might not be what we end up going with, as @theuni and I are considering an alternative.

  42. in src/util/time.cpp:127 in aeb8352a9d outdated
    118@@ -116,6 +119,20 @@ std::optional<int64_t> ParseISO8601DateTime(std::string_view str)
    119     return int64_t{TicksSinceEpoch<std::chrono::seconds>(tp)};
    120 }
    121 
    122+std::string FormatRFC7231DateTime(int64_t nTime)
    123+{
    124+    const std::chrono::sys_seconds secs{std::chrono::seconds{nTime}};
    125+    const auto days{std::chrono::floor<std::chrono::days>(secs)};
    126+    // 1970-01-01 was a Thursday
    127+    std::string weekday{weekdays[(days.time_since_epoch().count() + 4) % 7]};
    


    romanz commented at 5:49 am on April 21, 2025:
    nit: weekday and month can be a string_view.

    pinheadmz commented at 5:38 pm on April 28, 2025:
    done
  43. in src/util/strencodings.cpp:503 in a1e151c774 outdated
    496@@ -497,3 +497,10 @@ std::optional<uint64_t> ParseByteUnits(std::string_view str, ByteUnit default_mu
    497     }
    498     return *parsed_num * unit_amount;
    499 }
    500+
    501+std::vector<std::byte> StringToBuffer(const std::string& str)
    502+{
    503+    return std::vector<std::byte>(
    


    romanz commented at 6:03 am on April 21, 2025:

    nit: maybe using std::span will be simpler? For example:

    0    auto span = std::as_bytes(std::span(str));
    1    return {span.begin(), span.end()};
    

    pinheadmz commented at 3:38 pm on April 28, 2025:
    Great thanks, done.
  44. in src/util/string.cpp:30 in a1e151c774 outdated
    25+
    26+    auto line_start = it;
    27+    std::string line{};
    28+    while (it != end) {
    29+        char c = static_cast<char>(*it);
    30+        line += c;
    


    romanz commented at 6:33 am on April 21, 2025:

    Maybe it would be better (performance-wise) to create the string after the loop is over?

     0std::optional<std::string> LineReader::ReadLine()
     1{
     2    if (it == end) {
     3        return std::nullopt;
     4    }
     5
     6    auto line_start = it;
     7    size_t count = 0;
     8    while (it != end) {
     9        char c = static_cast<char>(*it);
    10        ++it;
    11        ++count;
    12        if (c == '\n') break;
    13        if (count >= max_read) throw std::runtime_error("max_read exceeded by LineReader");
    14    }
    15    const std::byte *data = &*line_start;
    16    std::string line{reinterpret_cast<const char *>(data), count};
    17    line = TrimString(line); // delete trailing \r and/or \n
    18    return line;
    19}
    

    pinheadmz commented at 3:43 pm on April 28, 2025:
    awesome, done
  45. in src/util/string.cpp:36 in a1e151c774 outdated
    31+        ++it;
    32+        if (c == '\n') break;
    33+        if ((size_t)std::distance(line_start, it) >= max_read) throw std::runtime_error("max_read exceeded by LineReader");
    34+    }
    35+
    36+    line = TrimString(line); // delete trailing \r and/or \n
    


    romanz commented at 6:35 am on April 21, 2025:
    Can we return a string_view to the internal buffer? (preventing allocation & copy)

    pinheadmz commented at 5:31 pm on April 28, 2025:
    by internal buffer I assume you mean m_recv_buffer which im trying to copy from into the HTTPRequest object, then clear the buffer. I left another response about maybe changing the type of that buffer to reduce unnecessary copies, but am going to leave it alone for this current rebase. What I did here though was swap out TrimString() with TrimStringView() so at least that’s one less.
  46. in src/util/string.cpp:45 in a1e151c774 outdated
    40+// Ignores max_read but won't overflow
    41+std::string LineReader::ReadLength(size_t len)
    42+{
    43+    if (len == 0) return "";
    44+    if (Left() < len) throw std::runtime_error("Not enough data in buffer");
    45+    std::string out(reinterpret_cast<const char*>(&(*it)), len);
    


    romanz commented at 6:37 am on April 21, 2025:
    Can we return a string_view to the internal buffer? (preventing allocation & copy)

    pinheadmz commented at 5:36 pm on April 28, 2025:
    I think I addressed this already by taking your suggestion here https://github.com/bitcoin/bitcoin/pull/32061/files#r2052024440

    romanz commented at 10:15 am on May 3, 2025:

    7d30118401 seems to still return a std::string:

    0$ git grep ReadLength
    1src/util/string.cpp:  std::string LineReader::ReadLength(size_t len)
    2src/util/string.h:    std::string ReadLength(size_t len);
    

    pinheadmz commented at 1:43 pm on May 9, 2025:
    Oh I see I misunderstood. For now I want LineReader to return new string objects because it reads directly from the HTTPClient’s m_recv_buffer which is then erased. I know we can prevent that copy by being more clever with m_recv_buffer and I still plan on exploring that, maybe as a follow up? It’s nice and simple now and there is a clean separation between the socket layer receiving data and the HTTPRequest

    romanz commented at 1:46 pm on May 9, 2025:
    Sounds good, thanks for the context :)
  47. in src/httpserver.cpp:787 in 70d003ca10 outdated
    780@@ -781,3 +781,69 @@ void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
    781         pathHandlers.erase(i);
    782     }
    783 }
    784+
    785+
    786+namespace http_bitcoin {
    787+std::optional<std::string> HTTPHeaders::Find(const std::string key) const
    


    romanz commented at 6:48 am on April 21, 2025:
    nit: consider using string_view instead of string here and below.

    pinheadmz commented at 7:42 pm on April 28, 2025:
    done.

    romanz commented at 10:23 am on May 3, 2025:
    nit: key & value can also be a string_view (here and below)

    pinheadmz commented at 1:48 pm on May 9, 2025:
    Cool will address this nit on next rebase thanks!
  48. in src/httpserver.cpp:840 in 70d003ca10 outdated
    835+}
    836+
    837+std::string HTTPHeaders::Stringify() const
    838+{
    839+    std::string out;
    840+    for (auto it = m_map.begin(); it != m_map.end(); ++it) {
    


    romanz commented at 4:11 pm on April 21, 2025:

    nit: maybe the following would be simpler?

    0    for (const auto& [k, v] : m_map) {
    1        out += k + ": " + v + "\r\n";
    2    }
    

    pinheadmz commented at 7:41 pm on April 28, 2025:
    thanks I’ll take it!
  49. in src/httpserver.cpp:643 in 482382bd14 outdated
    915+    if (!req->LoadBody(reader)) return false;
    916+
    917+    // Remove the bytes read out of the buffer.
    918+    // If one of the above calls throws an error, the caller must
    919+    // catch it and disconnect the client.
    920+    m_recv_buffer.erase(
    


    romanz commented at 8:49 am on April 27, 2025:
    nit: maybe it’s better to return a std::span from m_recv_buffer to avoid a copy here.

    pinheadmz commented at 3:21 pm on April 28, 2025:
    we’d still want to erase the data after fulfilling the request though (if I’m understanding your comment correctly). Would it make more sense if m_recv_buffer was a std::deque or something where we can truncate the structure without copying/moving/shifting left?

    romanz commented at 5:53 am on April 30, 2025:

    Would it make more sense if m_recv_buffer was a std::deque or something where we can truncate the structure without copying/moving/shifting left?

    Sounds good :)

  50. in src/httpserver.cpp:531 in 73c3c2e3d3 outdated
    940@@ -940,6 +941,92 @@ bool HTTPRequest::LoadBody(LineReader& reader)
    941     }
    942 }
    943 
    944+void HTTPRequest::WriteReply(HTTPStatusCode status, std::span<const std::byte> reply_body)
    


    romanz commented at 9:02 am on April 27, 2025:
    Would it be possible to allow writing a reply composed of several span<byte>? It should allow sending while serializing a response object.

    pinheadmz commented at 2:33 pm on April 28, 2025:
    Could this be done in a followup? I actually just checked #30321 to see why we didn’t do this back then – I remember when that was authored and merged but I didn’t realize you were the author!

    romanz commented at 5:54 am on April 30, 2025:
    Sure, thanks :)
  51. in src/httpserver.cpp:605 in 73c3c2e3d3 outdated
    1009+        m_client->m_send_buffer.insert(m_client->m_send_buffer.end(), headers_bytes.begin(), headers_bytes.end());
    1010+
    1011+        // We've been using std::span up until now but it is finally time to copy
    1012+        // data. The original data will go out of scope when WriteReply() returns.
    1013+        // This is analogous to the memcpy() in libevent's evbuffer_add()
    1014+        m_client->m_send_buffer.insert(m_client->m_send_buffer.end(), reply_body.begin(), reply_body.end());
    


    romanz commented at 9:04 am on April 27, 2025:
    Maybe use a list of buffers (instead a single FIFO buffer)?

    pinheadmz commented at 3:06 pm on April 28, 2025:
    I don’t understand – would that be an optimization? It’s not really a FIFO, since we insert at the end of the buffer here but send data from the begin() of the buffer in SendBytesFromBuffer()

    romanz commented at 5:57 am on April 30, 2025:

    I suggest considering a similar approach to libevent’s evbuffers:

    evbuffers are represented using a linked list of memory chunks, with pointers to the first and last chunk in the chain.

    https://libevent.org/doc/buffer_8h.html


    romanz commented at 6:45 am on May 1, 2025:
    Thinking about it, doing the copy here is definitely fine for now (we can optimize it in a following PR).
  52. in src/httpserver.h:275 in 73c3c2e3d3 outdated
    270+    // Response headers may be set in advance before response body is known
    271+    HTTPHeaders m_response_headers;
    272+    void WriteReply(HTTPStatusCode status, std::span<const std::byte> reply_body = {});
    273+    void WriteReply(HTTPStatusCode status, const char* reply_body) {
    274+        auto reply_body_view = std::string_view(reply_body);
    275+        std::span<const std::byte> byte_span(reinterpret_cast<const std::byte*>(reply_body_view.data()), reply_body_view.size());
    


    romanz commented at 9:16 am on April 27, 2025:

    nit: can be simplified using

    0    void WriteReply(HTTPStatusCode status, std::string_view reply_body_view)
    1    {
    2        WriteReply(status, std::as_bytes(std::span{reply_body_view}));
    3    }
    

    pinheadmz commented at 3:36 pm on April 28, 2025:
    awesome thanks
  53. in src/httpserver.h:137 in 6a6285d268 outdated
    170+    {
    171+        auto reply_body_view = std::string_view(reply_body);
    172+        std::span<const std::byte> byte_span(reinterpret_cast<const std::byte*>(reply_body_view.data()), reply_body_view.size());
    173+        WriteReply(status, byte_span);
    174+    }
    175+    void WriteReply(HTTPStatusCode status, const std::string& reply_body)
    


    romanz commented at 9:20 am on April 27, 2025:
    Can be removed if we’ll add WriteReply(HTTPStatusCode status, std::string_view reply_body_view) (see above).

    pinheadmz commented at 3:36 pm on April 28, 2025:
    👍
  54. in src/httpserver.cpp:246 in 90761d5026 outdated
    242@@ -243,18 +243,18 @@ static bool InitHTTPAllowList()
    243 }
    244 
    245 /** HTTP request method as string - use for logging only */
    246-std::string RequestMethodString(HTTPRequest::RequestMethod m)
    247+std::string RequestMethodString(HTTPRequestMethod m)
    


    romanz commented at 9:43 am on April 27, 2025:

    nit:

    0std::string_view RequestMethodString(HTTPRequestMethod m)
    

    pinheadmz commented at 1:59 pm on April 28, 2025:
    done
  55. in src/httpserver.cpp:980 in b828fa1e29 outdated
    975+    if (end == std::string::npos) {
    976+        end = decoded_uri.length();
    977+    }
    978+    const std::string query{decoded_uri.substr(start + 1, end - start - 1)};
    979+    // find requested parameter in query
    980+    const std::vector<std::string> params{SplitString(query, "&")};
    


    romanz commented at 9:44 am on April 27, 2025:
    nit: wouldn’t it copy the substrings?

    pinheadmz commented at 2:12 pm on April 28, 2025:
    You’re right thanks, I haven’t been dilligent about using string_view when copying isn’t needed. Fixed that here and also in HTTPRequest::LoadControlData()
  56. in src/httpserver.cpp:994 in b828fa1e29 outdated
    989+        }
    990+    }
    991+    return std::nullopt;
    992+}
    993+
    994+std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr) const
    


    romanz commented at 9:45 am on April 27, 2025:

    nit:

    0std::pair<bool, std::string_view> HTTPRequest::GetHeader(const std::string& hdr) const
    

    pinheadmz commented at 2:28 pm on April 28, 2025:
    thanks, for this fix I added a new commit instead of a fixup. The reason is because in the “story” of the commits, GetHeader() is already defined and used by the legacy HTTP server returning a string, and the goal at this point is to match the exiting API. But we can optimize it after the big “switch HTTP servers” commit.
  57. romanz commented at 1:00 pm on April 27, 2025: contributor
    LGTM, many thanks! Added some comments/suggestions above :)
  58. time: implement and test RFC7231 timestamp string
    HTTP 1.1 responses require a timestamp header with a
    specific format, specified in:
    https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1
    5c5de980b1
  59. string: add LineReader
    This is a helper struct to parse HTTP messages from data in buffers
    from sockets. HTTP messages begin with headers which are
    CRLF-terminated lines (\n or \r\n) followed by an arbitrary amount of
    body data. Whitespace is trimmed from the field lines but not the body.
    
    https://httpwg.org/specs/rfc9110.html#rfc.section.5
    43b4d0d2f3
  60. http: enclose libevent-dependent code in a namespace
    This commit is a no-op to isolate HTTP methods and objects that
    depend on libevent. Following commits will add replacement objects
    and methods in a new namespace for testing and review before
    switching over the server.
    6dd5723178
  61. http: Implement HTTPHeaders class
    see:
    https://www.rfc-editor.org/rfc/rfc2616#section-4.2
    https://www.rfc-editor.org/rfc/rfc7231#section-5
    https://www.rfc-editor.org/rfc/rfc7231#section-7
    https://httpwg.org/specs/rfc9111.html#header.field.definitions
    e95c6f5b65
  62. http: Implement HTTPResponse class
    HTTP Response message:
    https://datatracker.ietf.org/doc/html/rfc1945#section-6
    
    Status line (first line of response):
    https://datatracker.ietf.org/doc/html/rfc1945#section-6.1
    
    Status code definitions:
    https://datatracker.ietf.org/doc/html/rfc1945#section-9
    037a626499
  63. http: Implement HTTPRequest class
    HTTP Request message:
    https://datatracker.ietf.org/doc/html/rfc1945#section-5
    
    Request Line aka Control Line aka first line:
    https://datatracker.ietf.org/doc/html/rfc1945#section-5.1
    
    See message_read_status() in libevent http.c for how
    `MORE_DATA_EXPECTED` is handled there
    67aa660c77
  64. http: Begin implementation of HTTPClient and HTTPServer df11fc1173
  65. http: read requests from connected clients 980a9cd3d3
  66. http: support "chunked" Transfer-Encoding d7778f426c
  67. http: compose and send replies to connected clients b55725130a
  68. http: disconnect clients ebdb6d446e
  69. Allow http workers to send data optimistically as an optimization 59b54fef7c
  70. http: 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.
    4c28395074
  71. define HTTP request methods at module level outside of class
    This is a refactor to prepare for matching the API of HTTPRequest
    definitions in both namespaces http_bitcoin and http_libevent. In
    particular, to provide a consistent return type for GetRequestMethod()
    in both classes.
    7a1359064e
  72. Add helper methods to HTTPRequest to match original API
    These methods are called by http_request_cb() and are present in the
    original http_libevent::HTTPRequest.
    bbc9c55974
  73. refactor: split http_request_cb into libevent callback and dispatch
    The original function is passed to libevent as a callback when HTTP
    requests are received and processed. It wrapped the libevent request
    object in a http_libevent::HTTPRequest and then handed that off to
    bitcoin for basic checks and finally dispatch to worker threads.
    
    In this commit we split the function after the
    http_libevent::HTTPRequest is created, and pass that object to a new
    function that maintains the logic of checking and dispatching.
    
    This will be the merge point for http_libevent and http_bitcoin,
    where HTTPRequest objects from either namespace have the same
    downstream lifecycle.
    2bea6bc887
  74. refactor: split HTTPBindAddresses into config parse and libevent setup
    The original function was already naturally split into two chunks:
    First, we parse and validate the users' RPC configuration for IPs and
    ports. Next we bind libevent's http server to the appropriate
    endpoints.
    
    This commit splits these chunks into two separate functions, leaving
    the argument parsing in the common space of the module and moving the
    libevent-specific binding into the http_libevent namespace.
    
    A future commit will implement http_bitcoin::HTTPBindAddresses to
    bind the validate list of endpoints by the new HTTP server.
    1ab4aac359
  75. http: implement new server control methods to match legacy API 84e1818563
  76. http: disconnect after idle timeout (-rpcservertimeout) b90f808e30
  77. use CScheduler for HTTPRPCTimer
    This removes the dependency on libevent for scheduled events,
    like re-locking a wallet some time after decryption.
    2950597694
  78. http: switch servers from libevent to bitcoin be97857d14
  79. fuzz: switch http_libevent::HTTPRequest to http_bitcoin::HTTPRequest 7856f20fec
  80. http: using string_view to avoid unnecessary copy in Headers 54a36093f7
  81. httpserver: delete libevent! 7d30118401
  82. pinheadmz force-pushed on Apr 29, 2025
  83. pinheadmz commented at 1:23 pm on April 29, 2025: member
    Thanks so much for the great review @romanz I took most of your suggestions, there’s still an open question about m_recv_buffer but I really appreciate all your attention to string copying!
  84. romanz commented at 7:54 am on May 3, 2025: contributor
  85. DrahtBot requested review from laanwj on May 3, 2025
  86. DrahtBot requested review from fjahr on May 3, 2025
  87. DrahtBot requested review from vasild on May 3, 2025

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-05-09 15:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me