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.
1// Copyright (c) 2020-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_UTIL_SOCK_H6#define BITCOIN_UTIL_SOCK_H8#include <compat/compat.h>9#include <util/time.h>11#include <cstdint>12#include <limits>13#include <memory>14#include <span>15#include <string>16#include <unordered_map>18class CThreadInterrupt;20/**21* Maximum time to wait for I/O readiness.22* It will take up until this time to break off in case of an interruption.23*/24inline constexpr auto MAX_WAIT_FOR_IO = 1s;26inline bool IOErrorIsPermanent(int err)27{28return err != WSAEAGAIN && err != WSAEINTR && err != WSAEWOULDBLOCK && err != WSAEINPROGRESS;29}31/**32* RAII helper class that manages a socket and closes it automatically when it goes out of scope.33*/34class Sock35{36public:37Sock() = delete;39/**40* Take ownership of an existent socket.41*/42explicit Sock(SOCKET s);44/**45* Copy constructor, disabled because closing the same socket twice is undesirable.46*/47Sock(const Sock&) = delete;49/**50* Move constructor, grab the socket from another object and close ours (if set).51*/52Sock(Sock&& other);54/**55* Destructor, close the socket or do nothing if empty.56*/57virtual ~Sock();59/**60* Copy assignment operator, disabled because closing the same socket twice is undesirable.61*/62Sock& operator=(const Sock&) = delete;64/**65* Move assignment operator, grab the socket from another object and close ours (if set).66*/67virtual Sock& operator=(Sock&& other);69/**70* send(2) wrapper. Equivalent to `send(m_socket, data, len, flags);`. Code that uses this71* wrapper can be unit tested if this method is overridden by a mock Sock implementation.72*/73[[nodiscard]] virtual ssize_t Send(const void* data, size_t len, int flags) const;75/**76* recv(2) wrapper. Equivalent to `recv(m_socket, buf, len, flags);`. Code that uses this77* wrapper can be unit tested if this method is overridden by a mock Sock implementation.78*/79[[nodiscard]] virtual ssize_t Recv(void* buf, size_t len, int flags) const;81/**82* connect(2) wrapper. Equivalent to `connect(m_socket, addr, addrlen)`. Code that uses this83* wrapper can be unit tested if this method is overridden by a mock Sock implementation.84*/85[[nodiscard]] virtual int Connect(const sockaddr* addr, socklen_t addr_len) const;87/**88* bind(2) wrapper. Equivalent to `bind(m_socket, addr, addr_len)`. Code that uses this89* wrapper can be unit tested if this method is overridden by a mock Sock implementation.90*/91[[nodiscard]] virtual int Bind(const sockaddr* addr, socklen_t addr_len) const;93/**94* listen(2) wrapper. Equivalent to `listen(m_socket, backlog)`. Code that uses this95* wrapper can be unit tested if this method is overridden by a mock Sock implementation.96*/97[[nodiscard]] virtual int Listen(int backlog) const;99/**100* accept(2) wrapper. Equivalent to `std::make_unique<Sock>(accept(m_socket, addr, addr_len))`.101* Code that uses this wrapper can be unit tested if this method is overridden by a mock Sock102* implementation.103* The returned unique_ptr is empty if `accept()` failed in which case errno will be set.104*/105[[nodiscard]] virtual std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const;107/**108* getsockopt(2) wrapper. Equivalent to109* `getsockopt(m_socket, level, opt_name, opt_val, opt_len)`. Code that uses this110* wrapper can be unit tested if this method is overridden by a mock Sock implementation.111*/112[[nodiscard]] virtual int GetSockOpt(int level,113int opt_name,114void* opt_val,115socklen_t* opt_len) const;117/**118* setsockopt(2) wrapper. Equivalent to119* `setsockopt(m_socket, level, opt_name, opt_val, opt_len)`. Code that uses this120* wrapper can be unit tested if this method is overridden by a mock Sock implementation.121*/122[[nodiscard]] virtual int SetSockOpt(int level,123int opt_name,124const void* opt_val,125socklen_t opt_len) const;127/**128* getsockname(2) wrapper. Equivalent to129* `getsockname(m_socket, name, name_len)`. Code that uses this130* wrapper can be unit tested if this method is overridden by a mock Sock implementation.131*/132[[nodiscard]] virtual int GetSockName(sockaddr* name, socklen_t* name_len) const;134/**135* Set the non-blocking option on the socket.136* @return true if set successfully137*/138[[nodiscard]] virtual bool SetNonBlocking() const;140/**141* Check if the underlying socket can be used for `select(2)` (or the `Wait()` method).142* @return true if selectable143*/144[[nodiscard]] virtual bool IsSelectable() const;146using Event = uint8_t;148/**149* If passed to `Wait()`, then it will wait for readiness to read from the socket.150*/151static constexpr Event RecvEvent = 0b001;153/**154* If passed to `Wait()`, then it will wait for readiness to send to the socket.155*/156static constexpr Event SendEvent = 0b010;158/**159* Ignored if passed to `Wait()`, but could be set in the occurred events if an160* exceptional condition has occurred on the socket or if it has been disconnected.161*/162static constexpr Event ErrorEvent = 0b100;164/**165* Wait for readiness for input (recv) or output (send).166* @param[in] timeout Wait this much for at least one of the requested events to occur.167* @param[in] requested Wait for those events, bitwise-or of `RecvEvent` and `SendEvent`.168* @param[out] occurred If not nullptr and the function returns `true`, then this169* indicates which of the requested events occurred (`ErrorEvent` will be added, even if170* not requested, if an exceptional event occurs on the socket).171* A timeout is indicated by return value of `true` and `occurred` being set to 0.172* @return true on success (or timeout, if `occurred` of 0 is returned), false otherwise173*/174[[nodiscard]] virtual bool Wait(std::chrono::milliseconds timeout,175Event requested,176Event* occurred = nullptr) const;178/**179* Auxiliary requested/occurred events to wait for in `WaitMany()`.180*/181struct Events {182explicit Events(Event req) : requested{req} {}183Event requested;184Event occurred{0};185};187struct HashSharedPtrSock {188size_t operator()(const std::shared_ptr<const Sock>& s) const189{190return s ? s->m_socket : std::numeric_limits<SOCKET>::max();191}192};194struct EqualSharedPtrSock {195bool operator()(const std::shared_ptr<const Sock>& lhs,196const std::shared_ptr<const Sock>& rhs) const197{198if (lhs && rhs) {199return lhs->m_socket == rhs->m_socket;200}201if (!lhs && !rhs) {202return true;203}204return false;205}206};208/**209* On which socket to wait for what events in `WaitMany()`.210* The `shared_ptr` is copied into the map to ensure that the `Sock` object211* is not destroyed (its destructor would close the underlying socket).212* If this happens shortly before or after we call `poll(2)` and a new213* socket gets created under the same file descriptor number then the report214* from `WaitMany()` will be bogus.215*/216using EventsPerSock = std::unordered_map<std::shared_ptr<const Sock>, Events, HashSharedPtrSock, EqualSharedPtrSock>;218/**219* Same as `Wait()`, but wait on many sockets within the same timeout.220* @param[in] timeout Wait this long for at least one of the requested events to occur.221* @param[in,out] events_per_sock Wait for the requested events on these sockets and set222* `occurred` for the events that actually occurred.223* @return true on success (or timeout, if all `what[].occurred` are returned as 0),224* false otherwise225*/226[[nodiscard]] virtual bool WaitMany(std::chrono::milliseconds timeout,227EventsPerSock& events_per_sock) const;229/* Higher level, convenience, methods. These may throw. */231/**232* Send the given data, retrying on transient errors.233* @param[in] data Data to send.234* @param[in] timeout Timeout for the entire operation.235* @param[in] interrupt If this is signaled then the operation is canceled.236* @throws std::runtime_error if the operation cannot be completed. In this case only some of237* the data will be written to the socket.238*/239virtual void SendComplete(std::span<const unsigned char> data,240std::chrono::milliseconds timeout,241CThreadInterrupt& interrupt) const;243/**244* Convenience method, equivalent to `SendComplete(MakeUCharSpan(data), timeout, interrupt)`.245*/246virtual void SendComplete(std::span<const char> data,247std::chrono::milliseconds timeout,248CThreadInterrupt& interrupt) const;250/**
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.