5#ifndef BITCOIN_HTTPSERVER_H
6#define BITCOIN_HTTPSERVER_H
24#include <util/threadinterrupt.h>
86 using std::runtime_error::runtime_error;
98 std::optional<std::string>
FindFirst(std::string_view key)
const;
103 std::vector<std::string_view>
FindAll(std::string_view key)
const;
104 void Write(std::string&& key, std::string&& value);
126 std::vector<std::pair<std::string, std::string>>
m_headers;
177 WriteReply(status, std::as_bytes(std::span{reply_body_view}));
189 std::optional<std::string>
GetHeader(std::string_view hdr)
const;
191 void WriteHeader(std::string&& hdr, std::string&& value);
237 explicit HTTPServer(std::function<
void(std::unique_ptr<HTTPRequest>&&)> func)
238 : m_request_dispatcher{
std::move(func)} {}
302 m_request_dispatcher = std::move(func));
385 std::unordered_map<Sock::EventsPerSock::key_type,
386 std::shared_ptr<HTTPRemoteClient>,
495 : m_id(id), m_addr(addr), m_origin(addr.ToStringAddrPort()), m_sock{
std::move(socket)}, m_idle_since{
Now<
SteadySeconds>()} {}
501 const std::string&
GetOrigin()
const {
return m_origin; }
510 bool MaybeDisconnect(
std::chrono::time_point<
SteadyClock> now,
std::chrono::seconds rpcservertimeout,
bool disconnect_all);
563 std::string m_recv_buffer{};
573 std::atomic_bool m_req_busy{
false};
581 std::vector<std::byte> m_send_buffer
GUARDED_BY(m_send_mutex);
616 std::atomic_bool m_connection_busy{
true};
621 std::atomic_bool m_keep_alive{
false};
628 std::atomic_bool m_disconnect{
false};
#define Assume(val)
Assume is the identity function.
A combination of a network address (CNetAddr) and a (TCP) port.
A helper class for interruptible sleeps.
bool ReceiveBufferEmpty() const
const std::string & GetRecvBuffer() const
Used for tests.
bool m_send_ready GUARDED_BY(m_send_mutex)
Set true by worker threads after writing a response to m_send_buffer.
std::vector< std::byte > m_send_buffer GUARDED_BY(m_send_mutex)
Mutex m_send_mutex
Response data destined for this client.
std::string & MutateRecvBuffer()
Used for tests.
const std::string & GetOrigin() const
bool ReadyToSend() const EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex)
const std::string m_origin
IP:port of connected client, cached for logging purposes.
const CService & GetPeer() const
const HTTPServer::Id m_id
ID provided by HTTPServer upon connection and instantiation.
HTTPRemoteClient(HTTPServer::Id id, const CService &addr, std::unique_ptr< Sock > socket)
std::shared_ptr< Sock > m_sock GUARDED_BY(m_sock_mutex)
Underlying socket.
std::shared_ptr< Sock > GetSock() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex)
std::atomic< SteadySeconds > m_idle_since
Timestamp of last send or receive activity, used for -rpcservertimeout.
std::unique_ptr< HTTPRequest > m_req
Requests from a client must be processed in the order in which they were received,...
Mutex m_sock_mutex
Mutex that serializes the Send() and Recv() calls on m_sock.
const CService m_addr
Remote address of connected client.
HTTPRemoteClient(const HTTPRemoteClient &)=delete
HTTPRemoteClient & operator=(const HTTPRemoteClient &)=delete
void WriteHeader(std::string &&hdr, std::string &&value)
const HTTPVersion & GetVersion() const
std::optional< uint64_t > m_chunk_size
std::optional< std::string > GetQueryParameter(std::string_view key) const
std::string GetURI() const
bool LoadHeaders(util::LineReader &reader)
void WriteReply(HTTPStatusCode status, std::string_view reply_body_view)
bool LoadControlData(util::LineReader &reader)
Methods that attempt to parse HTTP request fields line-by-line from a receive buffer.
std::weak_ptr< HTTPRemoteClient > m_client
Pointer to the client that made the request so we know who to respond to.
std::optional< std::string > GetHeader(std::string_view hdr) const
HTTPRequest()
Construct with a null client for unit tests.
HTTPRequestMethod m_method
std::shared_ptr< HTTPRemoteClient > GetClient() const
HTTPRequestMethod GetRequestMethod() const
std::string ReadBody() const
HTTPRequest(const std::shared_ptr< HTTPRemoteClient > &client)
bool LoadBody(util::LineReader &reader)
uint64_t GetChunkProgress() const
void SetState(State state)
void WriteReply(HTTPStatusCode status, std::span< const std::byte > reply_body={})
std::optional< uint64_t > GetChunkSize() const
HTTPHeaders m_response_headers
Response headers may be set in advance before response body is known.
std::atomic< Id > m_next_id
The id to assign to the next created connection.
HTTPServer(std::function< void(std::unique_ptr< HTTPRequest > &&)> func)
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.
std::vector< std::shared_ptr< HTTPRemoteClient > > m_connected
List of HTTPRemoteClients with connected sockets.
int m_rpcmaxconnections
Maximum amount of concurrent connections.
void StopAccepting()
Stop accepting new connections in the I/O loop.
CThreadInterrupt m_interrupt_net
This is signaled when network activity should cease.
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.
Id GetNewId()
Generate an id for a newly created connection.
void SetMaxConnections(int max_conn)
Set the maximum amount of connected HTTPClients (-rpcmaxconnections)
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.
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.
std::vector< std::shared_ptr< Sock > > m_listen
List of listening sockets.
std::atomic_bool m_stop_accepting
Flag used during shutdown to stop accepting new connections.
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.
uint64_t Id
Each connection is assigned an unique id of this type.
std::chrono::seconds m_rpcservertimeout
Idle timeout after which clients are disconnected.
void SetServerTimeout(std::chrono::seconds seconds)
Set the idle client timeout (-rpcservertimeout)
void StopListening()
Stop listening by closing all listening sockets.
size_t GetConnectionsCount() const
Get the number of HTTPRemoteClients we are connected to.
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.
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.
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.
Mutex m_request_dispatcher_mutex
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.
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
The util::Expected class provides a standard way for low-level functions to return either error value...
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.
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.
void StartHTTPServer()
Start HTTP server.
constexpr int DEFAULT_HTTP_SERVER_TIMEOUT
bool InitHTTPServer()
Initialize HTTP server.
constexpr int DEFAULT_HTTP_THREADS
The default value for -rpcthreads.
constexpr int DEFAULT_HTTP_WORKQUEUE
The default value for -rpcworkqueue.
void StopHTTPServer()
Stop HTTP server.
std::optional< std::string > GetQueryParameterFromUri(std::string_view uri, std::string_view key)
std::unique_ptr< ProxyClient< messages::FooInterface > > client
std::thread thread
Thread variable should be after other struct members so the thread does not start until the other mem...
constexpr uint64_t MAX_BODY_SIZE
Maximum size of an HTTP request body.
constexpr size_t MIN_REQUEST_LINE_LENGTH
Shortest valid request line, used by libevent in evhttp_parse_request_line()
constexpr size_t MAX_HEADERS_SIZE
Maximum size of each headers line in an HTTP request, also the maximum size of all headers total.
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
HTTPStatusCode
HTTP status codes.
@ HTTP_INTERNAL_SERVER_ERROR
std::string StringifyHeaders() const
Info about which socket has which event ready and a reverse map back to the HTTPRemoteClient that own...
std::unordered_map< Sock::EventsPerSock::key_type, std::shared_ptr< HTTPRemoteClient >, Sock::HashSharedPtrSock, Sock::EqualSharedPtrSock > httpclients_per_sock
Map of socket -> HTTPRemoteClient.
Sock::EventsPerSock events_per_sock
Map of socket -> socket events.
uint8_t major
Default HTTP protocol version 1.1 is used by error responses when a request is unreadable.
Thrown when a request body exceeds MAX_BODY_SIZE (or will exceed, in chunked transfer) so the server ...
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::chrono::steady_clock SteadyClock
T Now()
Return the current time point cast to the given precision.
std::chrono::time_point< std::chrono::steady_clock, std::chrono::seconds > SteadySeconds