Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
httpserver.h
Go to the documentation of this file.
1// Copyright (c) 2015-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_HTTPSERVER_H
6#define BITCOIN_HTTPSERVER_H
7
8#include <atomic>
9#include <functional>
10#include <memory>
11#include <optional>
12#include <span>
13#include <stdexcept>
14#include <string>
15#include <vector>
16
17#include <netaddress.h>
18#include <rpc/protocol.h>
19#include <util/byte_units.h>
20#include <util/expected.h>
21#include <util/sock.h>
22#include <util/strencodings.h>
23#include <util/string.h>
24#include <util/threadinterrupt.h>
25#include <util/time.h>
26
27namespace util {
28class SignalInterrupt;
29} // namespace util
30
34inline constexpr int DEFAULT_HTTP_THREADS=16;
35
40inline constexpr int DEFAULT_HTTP_WORKQUEUE=64;
41
42inline constexpr int DEFAULT_HTTP_SERVER_TIMEOUT=30;
43
47inline constexpr int DEFAULT_MAX_HTTP_CONNECTIONS = 16;
48
50 UNKNOWN,
51 GET,
52 POST,
53 HEAD,
54 PUT
55};
56
57class HTTPRequest;
58
60using HTTPRequestHandler = std::function<void(HTTPRequest* req, const std::string&)>;
61
66void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler);
68void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch);
69
70namespace bitcoin_http {
72inline constexpr size_t MIN_REQUEST_LINE_LENGTH = std::string_view("GET / HTTP/1.0").size();
73
78inline constexpr size_t MAX_HEADERS_SIZE{8192};
79
82inline constexpr uint64_t MAX_BODY_SIZE{32_MiB};
83
86struct ContentTooLargeError : std::runtime_error {
87 using std::runtime_error::runtime_error;
88};
89} // namespace bitcoin_http
90
92{
93public:
99 std::optional<std::string> FindFirst(std::string_view key) const;
104 std::vector<std::string_view> FindAll(std::string_view key) const LIFETIMEBOUND;
105 void Write(std::string&& key, std::string&& value);
109 void RemoveAll(std::string_view key);
119 bool Read(util::LineReader& reader, bool write = true);
120 std::string Stringify() const;
121
122private:
127 std::vector<std::pair<std::string, std::string>> m_headers;
128
130 size_t m_consumed{0};
131};
132
144
145struct HTTPResponse {
149
150 std::string StringifyHeaders() const;
151};
152
153class HTTPRemoteClient;
154
156{
157public:
158 enum class State {
159 Init,
161 NeedsBody,
162 Complete,
163 Error
164 };
165
166 explicit HTTPRequest(const std::shared_ptr<HTTPRemoteClient>& client) : m_client{client} {}
168 explicit HTTPRequest() : m_client{} {}
169
177
178 void WriteReply(HTTPStatusCode status, std::span<const std::byte> reply_body = {});
179 void WriteReply(HTTPStatusCode status, std::string_view reply_body_view)
180 {
181 WriteReply(status, std::as_bytes(std::span{reply_body_view}));
182 }
183
185 std::shared_ptr<HTTPRemoteClient> GetClient() const { return m_client.lock(); }
186
187 // These methods reimplement the API from http_libevent::HTTPRequest
188 // for downstream JSONRPC and REST modules.
189 std::string GetURI() const { return m_target; }
190 CService GetPeer() const;
192 std::optional<std::string> GetQueryParameter(std::string_view key) const;
193 std::optional<std::string> GetHeader(std::string_view hdr) const;
194 std::string ReadBody() const { return m_body; }
195 void WriteHeader(std::string&& hdr, std::string&& value);
196 std::optional<uint64_t> GetChunkSize() const { return m_chunk_size; }
198
199 State GetState() const { return m_state; }
200
201private:
215
217 std::string m_target;
220 std::string m_body;
221
223 std::weak_ptr<HTTPRemoteClient> m_client;
224
227
228 // If a large request is sent with "Transfer-encoding: chunked" we may
229 // read the chunk size in a separate I/O loop iteration than the chunk
230 // of data itself. Store the chunk size value here until the chunk is read.
231 std::optional<uint64_t> m_chunk_size;
232 // We may also read a large chunk over multiple loop iterations.
233 // Track the progress of the chunk here.
235
236 State m_state = State::Init;
237};
238
240{
241public:
245 using Id = uint64_t;
246
247 explicit HTTPServer(std::function<void(std::unique_ptr<HTTPRequest>&&)> func)
248 : m_request_dispatcher{std::move(func)} {}
249
250 virtual ~HTTPServer()
251 {
252 Assume(!m_thread_socket_handler.joinable()); // Missing call to JoinSocketsThreads()
253 Assume(m_connected.empty()); // Missing call to DisconnectClients(), or disconnect flags not set
254 Assume(m_listen.empty()); // Missing call to StopListening()
255 }
256
260 bool InitHTTPAllowList();
261
268
272 void StopListening();
273
277 size_t GetListeningSocketCount() const { return m_listen.size(); }
278
282 size_t GetConnectionsCount() const { return m_connected_size.load(std::memory_order_acquire); }
283
287 void StartSocketsThreads();
288
292 void JoinSocketsThreads();
293
298
303
308 void SetRequestHandler(std::function<void(std::unique_ptr<HTTPRequest>&&)> func)
310 {
312 m_request_dispatcher = std::move(func));
313 }
314
322
326 void SetServerTimeout(std::chrono::seconds seconds) { m_rpcservertimeout = seconds; }
327
332
338
339private:
343 std::vector<std::shared_ptr<Sock>> m_listen;
344
348 std::atomic<Id> m_next_id{0};
349
356 std::vector<std::shared_ptr<HTTPRemoteClient>> m_connected;
357
362 std::atomic_bool m_stop_accepting{false};
363
369 std::atomic_bool m_disconnect_all_clients{false};
370
376 std::atomic<size_t> m_connected_size{0};
377
382 struct IOReadiness {
389
395 std::unordered_map<Sock::EventsPerSock::key_type,
396 std::shared_ptr<HTTPRemoteClient>,
400 };
401
406
412
421 std::function<void(std::unique_ptr<HTTPRequest>&&)> m_request_dispatcher GUARDED_BY(m_request_dispatcher_mutex);
423
428
432 std::vector<CSubNet> m_allow_subnets;
433
437 bool ClientAllowed(const CNetAddr& netaddr) const;
438
443
450 std::unique_ptr<Sock> AcceptConnection(const Sock& listen_sock, CService& addr);
451
455 Id GetNewId();
456
463 void NewSockAccepted(std::unique_ptr<Sock>&& sock, const CService& addr);
464
469 void SocketHandlerConnected(const IOReadiness& io_readiness) const
471
476 void SocketHandlerListening(const Sock::EventsPerSock& events_per_sock);
477
483 IOReadiness GenerateWaitSockets() const;
484
490
497 void DisconnectClients();
498};
499
500std::optional<std::string> GetQueryParameterFromUri(std::string_view uri, std::string_view key);
501
503{
504public:
505 explicit HTTPRemoteClient(HTTPServer::Id id, const CService& addr, std::unique_ptr<Sock> socket)
506 : m_id(id), m_addr(addr), m_origin(addr.ToStringAddrPort()), m_sock{std::move(socket)}, m_idle_since{MockableSteadyClock::now()} {}
507
508 // Disable copies (should only be used as shared pointers)
511
512 HTTPServer::Id GetId() const { return m_id; }
513 const std::string& GetOrigin() const LIFETIMEBOUND { return m_origin; }
514 const CService& GetPeer() const LIFETIMEBOUND { return m_addr; }
515 std::shared_ptr<Sock> GetSock() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex) { return WITH_LOCK(m_sock_mutex, return m_sock;); }
516 bool ReadyToSend() const EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex) { return WITH_LOCK(m_send_mutex, return m_send_ready;); }
517 bool ReceiveBufferEmpty() const { return m_recv_buffer.empty(); }
518
519 void Send(const HTTPResponse& res, std::span<const std::byte> reply_body, bool keep_alive) EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex, !m_sock_mutex);
520 void Receive() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex);
521
522 bool ShouldDisconnect(MockableSteadyClock::time_point now, std::chrono::seconds rpcservertimeout, bool disconnect_all) const;
523
531
536 bool MaybeSendBytesFromBuffer() EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex, !m_sock_mutex);
537
543 const HTTPRequest* GetRequest() const LIFETIMEBOUND { return m_req.get(); }
544
546 const std::string& GetRecvBuffer() const LIFETIMEBOUND { return m_recv_buffer; }
547
548protected:
550 std::string& MutateRecvBuffer() { return m_recv_buffer; }
551
552private:
553 std::unique_ptr<HTTPRequest> TryReadRequestInternal() EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex);
554
556 const HTTPServer::Id m_id;
557
559 const CService m_addr;
560
562 const std::string m_origin;
563
569 std::string m_recv_buffer{};
570
572 uint64_t m_total_bytes_received{0};
573
577 std::unique_ptr<HTTPRequest> m_req;
578
582 std::atomic_bool m_req_busy{false};
583
591 std::vector<std::byte> m_send_buffer GUARDED_BY(m_send_mutex);
593
602 bool m_send_ready GUARDED_BY(m_send_mutex){false};
603
610
618 std::shared_ptr<Sock> m_sock GUARDED_BY(m_sock_mutex);
619
626 std::atomic_bool m_connection_busy{true};
627
631 std::atomic_bool m_keep_alive{false};
632
638 std::atomic_bool m_disconnect{false};
639
643 std::atomic<MockableSteadyClock::time_point> m_idle_since;
644};
645
649bool InitHTTPServer();
650
655void StartHTTPServer();
656
659
661void StopHTTPServer();
662
663#endif // BITCOIN_HTTPSERVER_H
#define LIFETIMEBOUND
Definition attributes.h:12
#define Assume(val)
Assume is the identity function.
Definition check.h:131
Network address.
Definition netaddress.h:113
A combination of a network address (CNetAddr) and a (TCP) port.
Definition netaddress.h:531
A helper class for interruptible sleeps.
std::optional< std::string > FindFirst(std::string_view key) const
size_t m_consumed
Track total bytes consumed in Read() for limit checks.
Definition httpserver.h:130
void RemoveAll(std::string_view key)
std::vector< std::pair< std::string, std::string > > m_headers
Headers can have duplicate field names, so we use a vector of key-value pairs instead of a map.
Definition httpserver.h:127
std::string Stringify() const
void Write(std::string &&key, std::string &&value)
std::vector< std::string_view > FindAll(std::string_view key) const LIFETIMEBOUND
bool ReceiveBufferEmpty() const
Definition httpserver.h:517
bool m_send_ready GUARDED_BY(m_send_mutex)
Set true by worker threads after writing a response to m_send_buffer.
Definition httpserver.h:602
std::vector< std::byte > m_send_buffer GUARDED_BY(m_send_mutex)
HTTPServer::Id GetId() const
Definition httpserver.h:512
std::string & MutateRecvBuffer()
Used for tests.
Definition httpserver.h:550
bool ReadyToSend() const EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
Definition httpserver.h:516
HTTPRemoteClient(HTTPServer::Id id, const CService &addr, std::unique_ptr< Sock > socket)
Definition httpserver.h:505
std::shared_ptr< Sock > m_sock GUARDED_BY(m_sock_mutex)
Underlying socket.
std::shared_ptr< Sock > GetSock() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex)
Definition httpserver.h:515
std::unique_ptr< HTTPRequest > m_req
Requests from a client must be processed in the order in which they were received,...
Definition httpserver.h:577
Mutex m_sock_mutex
Mutex that serializes the Send() and Recv() calls on m_sock.
Definition httpserver.h:609
HTTPRemoteClient(const HTTPRemoteClient &)=delete
const CService & GetPeer() const LIFETIMEBOUND
Definition httpserver.h:514
std::atomic< MockableSteadyClock::time_point > m_idle_since
Timestamp of last send or receive activity, used for -rpcservertimeout.
Definition httpserver.h:643
const std::string & GetOrigin() const LIFETIMEBOUND
Definition httpserver.h:513
HTTPRemoteClient & operator=(const HTTPRemoteClient &)=delete
const std::string & GetRecvBuffer() const LIFETIMEBOUND
Used for tests.
Definition httpserver.h:546
void WriteHeader(std::string &&hdr, std::string &&value)
std::optional< uint64_t > m_chunk_size
Definition httpserver.h:231
std::optional< std::string > GetQueryParameter(std::string_view key) const
std::string GetURI() const
Definition httpserver.h:189
State m_state
Definition httpserver.h:236
std::string m_target
Definition httpserver.h:217
bool LoadHeaders(util::LineReader &reader)
HTTPHeaders m_headers
Definition httpserver.h:219
void WriteReply(HTTPStatusCode status, std::string_view reply_body_view)
Definition httpserver.h:179
bool LoadControlData(util::LineReader &reader)
State Load(util::LineReader &reader)
Try to read an HTTP request or part of it.
HTTPVersion m_version
Definition httpserver.h:218
uint64_t m_chunk_read
Definition httpserver.h:234
std::weak_ptr< HTTPRemoteClient > m_client
Pointer to the client that made the request so we know who to respond to.
Definition httpserver.h:223
std::optional< std::string > GetHeader(std::string_view hdr) const
HTTPRequest()
Construct with a null client for unit tests.
Definition httpserver.h:168
HTTPRequestMethod m_method
Definition httpserver.h:216
std::shared_ptr< HTTPRemoteClient > GetClient() const
Definition httpserver.h:185
HTTPRequestMethod GetRequestMethod() const
Definition httpserver.h:191
std::string m_body
Definition httpserver.h:220
std::string ReadBody() const
Definition httpserver.h:194
HTTPRequest(const std::shared_ptr< HTTPRemoteClient > &client)
Definition httpserver.h:166
bool LoadBody(util::LineReader &reader)
uint64_t GetChunkProgress() const
Definition httpserver.h:197
void WriteReply(HTTPStatusCode status, std::span< const std::byte > reply_body={})
State GetState() const
Definition httpserver.h:199
CService GetPeer() const
const HTTPVersion & GetVersion() const LIFETIMEBOUND
Definition httpserver.h:184
std::optional< uint64_t > GetChunkSize() const
Definition httpserver.h:196
HTTPHeaders m_response_headers
Response headers may be set in advance before response body is known.
Definition httpserver.h:226
std::atomic< Id > m_next_id
The id to assign to the next created connection.
Definition httpserver.h:348
HTTPServer(std::function< void(std::unique_ptr< HTTPRequest > &&)> func)
Definition httpserver.h:247
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
Check connected and listening sockets for IO readiness and process them accordingly.
void JoinSocketsThreads()
Join (wait for) the threads started by StartSocketsThreads() to exit.
std::function< void(std::unique_ptr< HTTPRequest > &&)> m_request_dispatcher GUARDED_BY(m_request_dispatcher_mutex)
void InterruptNet()
Stop network activity.
Definition httpserver.h:297
std::vector< std::shared_ptr< HTTPRemoteClient > > m_connected
List of HTTPRemoteClients with connected sockets.
Definition httpserver.h:356
int m_rpcmaxconnections
Maximum amount of concurrent connections.
Definition httpserver.h:442
void StopAccepting()
Stop accepting new connections in the I/O loop.
Definition httpserver.h:321
CThreadInterrupt m_interrupt_net
This is signaled when network activity should cease.
Definition httpserver.h:405
void SocketHandlerConnected(const IOReadiness &io_readiness) const EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
Do the read/write for connected sockets that are ready for IO.
std::atomic_bool m_disconnect_all_clients
Flag used during shutdown.
Definition httpserver.h:369
Id GetNewId()
Generate an id for a newly created connection.
void SetMaxConnections(int max_conn)
Set the maximum amount of connected HTTPClients (-rpcmaxconnections)
Definition httpserver.h:331
void DisconnectClients()
Close underlying socket connections for flagged clients by removing their shared pointer from m_conne...
util::Expected< void, std::string > BindAndStartListening(const CService &to)
Bind to a new address:port, start listening and add the listen socket to m_listen.
std::vector< CSubNet > m_allow_subnets
List of subnets to allow HTTP connections from.
Definition httpserver.h:432
void ClearConnectedClients()
Force-remove all remaining clients from m_connected without waiting for graceful disconnection.
std::atomic< size_t > m_connected_size
The number of connected sockets.
Definition httpserver.h:376
std::vector< std::shared_ptr< Sock > > m_listen
List of listening sockets.
Definition httpserver.h:343
std::atomic_bool m_stop_accepting
Flag used during shutdown to stop accepting new connections.
Definition httpserver.h:362
void SocketHandlerListening(const Sock::EventsPerSock &events_per_sock)
Accept incoming connections, one from each read-ready listening socket.
IOReadiness GenerateWaitSockets() const
Generate a collection of sockets to check for IO readiness.
std::thread m_thread_socket_handler
Thread that sends to and receives from sockets and accepts connections.
Definition httpserver.h:411
uint64_t Id
Each connection is assigned an unique id of this type.
Definition httpserver.h:245
std::chrono::seconds m_rpcservertimeout
Idle timeout after which clients are disconnected.
Definition httpserver.h:427
void SetServerTimeout(std::chrono::seconds seconds)
Set the idle client timeout (-rpcservertimeout)
Definition httpserver.h:326
void StopListening()
Stop listening by closing all listening sockets.
size_t GetConnectionsCount() const
Get the number of HTTPRemoteClients we are connected to.
Definition httpserver.h:282
void NewSockAccepted(std::unique_ptr< Sock > &&sock, const CService &addr)
After a new socket with a client has been created, configure its flags, make a new HTTPRemoteClient a...
void SetRequestHandler(std::function< void(std::unique_ptr< HTTPRequest > &&)> func) EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
Update the request handler method.
Definition httpserver.h:308
virtual ~HTTPServer()
Definition httpserver.h:250
bool ClientAllowed(const CNetAddr &netaddr) const
Check an incoming connection's source IP against the allow list.
size_t GetListeningSocketCount() const
Get the number of sockets the server is bound to and listening on.
Definition httpserver.h:277
bool InitHTTPAllowList()
Parse the user's -rpcallowip settings and populate m_allow_subnets.
void DisconnectAllClients()
Start disconnecting clients when possible in the I/O loop.
Definition httpserver.h:302
Mutex m_request_dispatcher_mutex
Definition httpserver.h:420
std::unique_ptr< Sock > AcceptConnection(const Sock &listen_sock, CService &addr)
Accept a connection.
void StartSocketsThreads()
Start the necessary threads for sockets IO.
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
Definition sock.h:35
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
Definition sock.h:225
The util::Expected class provides a standard way for low-level functions to return either error value...
Definition expected.h:44
Helper class that manages an interrupt flag, and allows a thread or signal to interrupt another threa...
void InterruptHTTPServer()
Interrupt HTTP server threads.
constexpr int DEFAULT_MAX_HTTP_CONNECTIONS
Maximum number of connected HTTP clients.
Definition httpserver.h:47
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
std::function< void(HTTPRequest *req, const std::string &)> HTTPRequestHandler
Handler for requests to a certain HTTP path.
Definition httpserver.h:60
void StartHTTPServer()
Start HTTP server.
constexpr int DEFAULT_HTTP_SERVER_TIMEOUT
Definition httpserver.h:42
bool InitHTTPServer()
Initialize HTTP server.
constexpr int DEFAULT_HTTP_THREADS
The default value for -rpcthreads.
Definition httpserver.h:34
constexpr int DEFAULT_HTTP_WORKQUEUE
The default value for -rpcworkqueue.
Definition httpserver.h:40
HTTPRequestMethod
Definition httpserver.h:49
void StopHTTPServer()
Stop HTTP server.
std::optional< std::string > GetQueryParameterFromUri(std::string_view uri, std::string_view key)
util::LineReader reader
std::unique_ptr< ProxyClient< messages::FooInterface > > client
constexpr uint64_t MAX_BODY_SIZE
Maximum size of an HTTP request body received from a client.
Definition httpserver.h:82
constexpr size_t MIN_REQUEST_LINE_LENGTH
Shortest valid request line, used by libevent in evhttp_parse_request_line()
Definition httpserver.h:72
constexpr size_t MAX_HEADERS_SIZE
Maximum size of each headers line in an HTTP request, also the maximum size of all headers total.
Definition httpserver.h:78
const char * prefix
Definition rest.cpp:1201
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
Definition rest.cpp:1202
HTTPStatusCode
HTTP status codes.
Definition protocol.h:13
@ HTTP_INTERNAL_SERVER_ERROR
Definition protocol.h:22
HTTPVersion version
Definition httpserver.h:146
std::string StringifyHeaders() const
HTTPHeaders headers
Definition httpserver.h:148
Info about which socket has which event ready and a reverse map back to the HTTPRemoteClient that own...
Definition httpserver.h:382
std::unordered_map< Sock::EventsPerSock::key_type, std::shared_ptr< HTTPRemoteClient >, Sock::HashSharedPtrSock, Sock::EqualSharedPtrSock > httpclients_per_sock
Map of socket -> HTTPRemoteClient.
Definition httpserver.h:399
Sock::EventsPerSock events_per_sock
Map of socket -> socket events.
Definition httpserver.h:388
uint8_t minor
Definition httpserver.h:141
uint8_t major
Definition httpserver.h:140
Version of SteadyClock that is mockable in the context of tests (via FakeSteadyClock,...
Definition time.h:47
Thrown when a request body exceeds MAX_BODY_SIZE (or will exceed, in chunked transfer) so the server ...
Definition httpserver.h:86
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition sync.h:299
#define EXCLUSIVE_LOCKS_REQUIRED(...)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82