Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
502const std::string& GetOrigin() const { return m_origin; }503const CService& GetPeer() const { return m_addr; }504std::shared_ptr<Sock> GetSock() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex) { return WITH_LOCK(m_sock_mutex, return m_sock;); }505bool ReadyToSend() const EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex) { return WITH_LOCK(m_send_mutex, return m_send_ready;); }506bool ReceiveBufferEmpty() const { return m_recv_buffer.empty(); }508void Send(const HTTPResponse& res, std::span<const std::byte> reply_body, bool keep_alive) EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex, !m_sock_mutex);509void Receive() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex);511bool MaybeDisconnect(std::chrono::time_point<SteadyClock> now, std::chrono::seconds rpcservertimeout, bool disconnect_all);513/**514* Try to read an HTTPRequest from a client's receive buffer.515* Only complete requests are returned, incomplete requests are516* left in the buffer to wait for more data. Some read errors517* will mark this client for disconnection.518*/519static std::unique_ptr<HTTPRequest> TryReadRequest(const std::shared_ptr<HTTPRemoteClient>& client) EXCLUSIVE_LOCKS_REQUIRED(!client->m_send_mutex);521/**522* Push data (if there is any) from client's m_send_buffer to the connected socket.523* @returns false if we are done with this client and HTTPServer can skip the next read operation from it.524*/525bool MaybeSendBytesFromBuffer() EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex, !m_sock_mutex);527/**528* Used to determine if an incomplete request is in progress.529* @returns nullptr after a complete request is moved to a worker thread,530* but before reading any new data from m_recv_buffer.531*/532const HTTPRequest* GetRequest() const { return m_req.get(); }534//! Used for tests.535const std::string& GetRecvBuffer() const { return m_recv_buffer; }537protected:538//! Used for tests.539std::string& MutateRecvBuffer() { return m_recv_buffer; }541private:542/**543* Try to read an HTTP request from the receive buffer.544* Updates HTTPRequest.m_state and drains buffer on error.545* @param[in] req A HTTPRequest to read into546* @throws std::runtime_error if request is unreadable or violates protocol547*/548void ReadRequest(HTTPRequest& req);550//! ID provided by HTTPServer upon connection and instantiation551const HTTPServer::Id m_id;553//! Remote address of connected client554const CService m_addr;556//! IP:port of connected client, cached for logging purposes557const std::string m_origin;559/**560* In lieu of an intermediate transport class like p2p uses,561* we copy data from the socket buffer to the client object562* and attempt to read HTTP requests from here.563*/564std::string m_recv_buffer{};566//! Running total of bytes read from this client's socket.567uint64_t m_total_bytes_received{0};569//! Requests from a client must be processed in the order in which570//! they were received, blocking on a per-client basis. We read571//! one request at a time from the socket buffer then pass it to a worker.572std::unique_ptr<HTTPRequest> m_req;574//! Set to true by the I/O thread when a request is popped off575//! and passed to a worker thread, reset to false by the worker thread.576//! Only one request per connection is ever in flight.577std::atomic_bool m_req_busy{false};579/**580* Response data destined for this client.581* Written to by http worker threads, read and erased by HTTPServer I/O thread582*/583/// @{584mutable Mutex m_send_mutex;585std::vector<std::byte> m_send_buffer GUARDED_BY(m_send_mutex);586/// @}588/**589* Set true by worker threads after writing a response to m_send_buffer.590* Set false by the HTTPServer I/O thread after flushing m_send_buffer.591* Checked in the HTTPServer I/O loop to decide whether to poll the socket for592* writeability or readability.593* Guarded by m_send_mutex so it stays consistent with m_send_buffer's emptiness:594* the two must always be updated together under the same lock.595*/596bool m_send_ready GUARDED_BY(m_send_mutex){false};598/**599* Mutex that serializes the Send() and Recv() calls on `m_sock`. Reading600* from the client occurs in the I/O thread but writing back to a client601* may occur in a worker thread.602*/603Mutex m_sock_mutex;605/**606* Underlying socket.607* `shared_ptr` (instead of `unique_ptr`) is used to avoid premature close of the608* underlying file descriptor by one thread while another thread is poll(2)-ing609* it for activity.610* @see https://github.com/bitcoin/bitcoin/issues/21744 for details.611*/612std::shared_ptr<Sock> m_sock GUARDED_BY(m_sock_mutex);614//! Initialized to true while server waits for first request from client.615//! Set to false after data is written to m_send_buffer and then that buffer is flushed to client.616//! Reset to true when we receive new request data from client.617//! Checked during DisconnectClients() and set by read/write operations618//! called in either the HTTPServer I/O loop or by a worker thread during an "optimistic send".619//! `m_connection_busy=true` can be overridden by `m_disconnect=true` (we disconnect).620std::atomic_bool m_connection_busy{true};622//! Client has requested to keep the connection open after all requests have been responded to.623//! Set by (potentially multiple) worker threads and checked in the HTTPServer I/O loop.624//! `m_keep_alive=true` can be overridden `by HTTPServer.m_disconnect_all_clients` (we disconnect).625std::atomic_bool m_keep_alive{false};627//! Flag this client for disconnection on next loop.628//! Either we have encountered a permanent error, or both sides of the socket are done629//! with the connection, e.g. our reply to a "Connection: close" request has been sent.630//! Might be set in a worker thread or in the I/O thread. When set to `true` we disconnect,631//! possibly overriding all other disconnect flags.632std::atomic_bool m_disconnect{false};634//! Timestamp of last send or receive activity, used for -rpcservertimeout.635//! Due to optimistic sends it may be updated in either a worker thread or in the636//! I/O thread. It is checked in the I/O thread to disconnect idle clients.637std::atomic<SteadySeconds> m_idle_since;638};640/** Initialize HTTP server.641* Call this before RegisterHTTPHandler or EventBase().642*/643bool InitHTTPServer();645/** Start HTTP server.646* This is separate from InitHTTPServer to give users race-condition-free time647* to register their handlers between InitHTTPServer and StartHTTPServer.648*/649void StartHTTPServer();651/** Interrupt HTTP server threads */652void InterruptHTTPServer();654/** Stop HTTP server */655void StopHTTPServer();657#endif // BITCOIN_HTTPSERVER_H
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.