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.
251* @param[in] len Write up to this number of bytes.252* @param[in] flags Same as the flags of `recv(2)`. Just `MSG_PEEK` is honored.253* @return The number of bytes written to `buf`. `0` if `Eof()` has been called.254* If no bytes are available then `-1` is returned and `errno` is set to `EAGAIN`.255*/256ssize_t GetBytes(void* buf, size_t len, int flags = 0) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);258/**259* Deserialize a `CNetMessage` and remove it from the pipe.260* If not enough bytes are available then the function will wait. If parsing fails261* or EOF is signaled to the pipe, then `std::nullopt` is returned.262*/263std::optional<CNetMessage> GetNetMsg() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);265/**266* Push bytes to the pipe.267*/268void PushBytes(const void* buf, size_t len) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);270/**271* Construct and push CNetMessage to the pipe.272*/273template <typename... Args>274void PushNetMsg(const std::string& type, Args&&... payload) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);276/**277* Signal end-of-file on the receiving end (`GetBytes()` or `GetNetMsg()`).278*/279void Eof() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);281private:282/**283* Return when there is some data to read or EOF has been signaled.284* @param[in,out] lock Unique lock that must have been derived from `m_mutex` by `WAIT_LOCK(m_mutex, lock)`.285*/286void WaitForDataOrEof(UniqueLock<Mutex>& lock) EXCLUSIVE_LOCKS_REQUIRED(m_mutex);288Mutex m_mutex;289std::condition_variable m_cond;290std::vector<uint8_t> m_data GUARDED_BY(m_mutex);291bool m_eof GUARDED_BY(m_mutex){false};292};294struct Pipes {295Pipe recv;296Pipe send;297};299/**300* A basic thread-safe queue, used for queuing sockets to be returned by Accept().301*/302class Queue303{304public:305using S = std::unique_ptr<DynSock>;307void Push(S s) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)308{309LOCK(m_mutex);310m_queue.push(std::move(s));311}313std::optional<S> Pop() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)314{315LOCK(m_mutex);316if (m_queue.empty()) {317return std::nullopt;318}319S front{std::move(m_queue.front())};320m_queue.pop();321return front;322}324bool Empty() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)325{326LOCK(m_mutex);327return m_queue.empty();328}330private:331mutable Mutex m_mutex;332std::queue<S> m_queue GUARDED_BY(m_mutex);333};335/**336* Create a new mocked sock.337* @param[in] pipes Send/recv pipes used by the Send() and Recv() methods.338* @param[in] accept_sockets Sockets to return by the Accept() method.339*/340explicit DynSock(std::shared_ptr<Pipes> pipes, Queue* accept_sockets LIFETIMEBOUND);342/**343* Create a new mocked sock that represents a connected socket. It has pipes344* for data transport but there is no queue because connected sockets do345* not introduce new connected sockets.346* @param[in] pipes Send/recv pipes used by the Send() and Recv() methods.347*/348explicit DynSock(std::shared_ptr<Pipes> pipes);350~DynSock();352ssize_t Recv(void* buf, size_t len, int flags) const override;354ssize_t Send(const void* buf, size_t len, int) const override;356std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;358bool Wait(std::chrono::milliseconds timeout,359Event requested,360Event* occurred = nullptr) const override;362bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;364private:365DynSock& operator=(Sock&&) override;367std::shared_ptr<Pipes> m_pipes;368Queue* const m_accept_sockets;369};371template <typename... Args>372void DynSock::Pipe::PushNetMsg(const std::string& type, Args&&... payload)373{374auto msg = NetMsg::Make(type, std::forward<Args>(payload)...);375V1Transport transport{NodeId{0}};377const bool queued{transport.SetMessageToSend(msg)};378assert(queued);380LOCK(m_mutex);382for (;;) {383const auto& [bytes, _more, _msg_type] = transport.GetBytesToSend(/*have_next_message=*/true);384if (bytes.empty()) {385break;386}387m_data.insert(m_data.end(), bytes.begin(), bytes.end());388transport.MarkBytesSent(bytes.size());389}391m_cond.notify_all();392}394std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context);396#endif // BITCOIN_TEST_UTIL_NET_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.