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.
251std::memcpy(buf, m_contents.data() + m_consumed, consume_bytes);252if ((flags & MSG_PEEK) == 0) {253m_consumed += consume_bytes;254}255return consume_bytes;256}258StaticContentsSock& StaticContentsSock::operator=(Sock&& other)259{260assert(false && "Move of Sock into StaticContentsSock not allowed.");261return *this;262}264ssize_t DynSock::Pipe::GetBytes(void* buf, size_t len, int flags)265{266WAIT_LOCK(m_mutex, lock);268if (m_data.empty()) {269if (m_eof) {270return 0;271}272errno = EAGAIN; // Same as recv(2) on a non-blocking socket.273return -1;274}276const size_t read_bytes{std::min(len, m_data.size())};278std::memcpy(buf, m_data.data(), read_bytes);279if ((flags & MSG_PEEK) == 0) {280m_data.erase(m_data.begin(), m_data.begin() + read_bytes);281}283return read_bytes;284}286std::optional<CNetMessage> DynSock::Pipe::GetNetMsg()287{288V1Transport transport{NodeId{0}};290{291WAIT_LOCK(m_mutex, lock);293WaitForDataOrEof(lock);294if (m_eof && m_data.empty()) {295return std::nullopt;296}298for (;;) {299std::span<const uint8_t> s{m_data};300if (!transport.ReceivedBytes(s)) { // Consumed bytes are removed from the front of s.301return std::nullopt;302}303m_data.erase(m_data.begin(), m_data.begin() + m_data.size() - s.size());304if (transport.ReceivedMessageComplete()) {305break;306}307if (m_data.empty()) {308WaitForDataOrEof(lock);309if (m_eof && m_data.empty()) {310return std::nullopt;311}312}313}314}316bool reject{false};317CNetMessage msg{transport.GetReceivedMessage(/*time=*/{}, reject)};318if (reject) {319return std::nullopt;320}321return std::make_optional<CNetMessage>(std::move(msg));322}324void DynSock::Pipe::PushBytes(const void* buf, size_t len)325{326LOCK(m_mutex);327const uint8_t* b = static_cast<const uint8_t*>(buf);328m_data.insert(m_data.end(), b, b + len);329m_cond.notify_all();330}332void DynSock::Pipe::Eof()333{334LOCK(m_mutex);335m_eof = true;336m_cond.notify_all();337}339void DynSock::Pipe::WaitForDataOrEof(UniqueLock<Mutex>& lock)340{341Assert(lock.mutex() == &m_mutex);343m_cond.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(m_mutex) {344AssertLockHeld(m_mutex);345return !m_data.empty() || m_eof;346});347}349DynSock::DynSock(std::shared_ptr<Pipes> pipes, Queue* accept_sockets)350: m_pipes{pipes}, m_accept_sockets{accept_sockets}351{352}354DynSock::DynSock(std::shared_ptr<Pipes> pipes)355: m_pipes{pipes}, m_accept_sockets{}356{357}359DynSock::~DynSock()360{361m_pipes->send.Eof();362}364ssize_t DynSock::Recv(void* buf, size_t len, int flags) const365{366return m_pipes->recv.GetBytes(buf, len, flags);367}369ssize_t DynSock::Send(const void* buf, size_t len, int) const370{371m_pipes->send.PushBytes(buf, len);372return len;373}375std::unique_ptr<Sock> DynSock::Accept(sockaddr* addr, socklen_t* addr_len) const376{377assert(m_accept_sockets && "Accept() called on non-listening DynSock");378ZeroSock::Accept(addr, addr_len);379return m_accept_sockets->Pop().value_or(nullptr);380}382bool DynSock::Wait(std::chrono::milliseconds timeout,383Event requested,384Event* occurred) const385{386EventsPerSock ev;387ev.emplace(this, Events{requested});388const bool ret{WaitMany(timeout, ev)};389if (occurred != nullptr) {390*occurred = ev.begin()->second.occurred;391}392return ret;393}395bool DynSock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const396{397const auto deadline = std::chrono::steady_clock::now() + timeout;398bool at_least_one_event_occurred{false};400for (;;) {401// Check all sockets for readiness without waiting.402for (auto& [sock, events] : events_per_sock) {403if ((events.requested & Sock::SendEvent) != 0) {404// Always ready for Send().405events.occurred |= Sock::SendEvent;406at_least_one_event_occurred = true;407}409if ((events.requested & Sock::RecvEvent) != 0) {410auto dyn_sock = reinterpret_cast<const DynSock*>(sock.get());411uint8_t b;412if (dyn_sock->m_pipes->recv.GetBytes(&b, 1, MSG_PEEK) == 1 || (dyn_sock->m_accept_sockets && !dyn_sock->m_accept_sockets->Empty())) {413events.occurred |= Sock::RecvEvent;414at_least_one_event_occurred = true;415}416}417}419if (at_least_one_event_occurred || std::chrono::steady_clock::now() > deadline) {420break;421}423std::this_thread::sleep_for(10ms);424}426return true;427}429DynSock& DynSock::operator=(Sock&&)430{431assert(false && "Move of Sock into DynSock not allowed.");432return *this;433}
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.