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.
1751}1752}1753return false;1754}1756void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {1757AssertLockNotHeld(m_nodes_mutex);1759struct sockaddr_storage sockaddr;1760socklen_t len = sizeof(sockaddr);1761auto sock = hListenSocket.sock->Accept((struct sockaddr*)&sockaddr, &len);1763if (!sock) {1764const int nErr = WSAGetLastError();1765if (nErr != WSAEWOULDBLOCK) {1766LogInfo("socket error accept failed: %s\n", NetworkErrorString(nErr));1767}1768return;1769}1771CService addr;1772if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr, len)) {1773LogWarning("Unknown socket family\n");1774} else {1775addr = MaybeFlipIPv6toCJDNS(addr);1776}1778const CService addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock))};1780NetPermissionFlags permission_flags = NetPermissionFlags::None;1781hListenSocket.AddSocketPermissionFlags(permission_flags);1783CreateNodeFromAcceptedSocket(std::move(sock), permission_flags, addr_bind, addr);1784}1786void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,1787NetPermissionFlags permission_flags,1788const CService& addr_bind,1789const CService& addr)1790{1791AssertLockNotHeld(m_nodes_mutex);1793int nInbound = 0;1795const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();1797// Tor inbound connections do not reveal the peer's actual network address.1798// Therefore do not apply address-based whitelist permissions to them.1799AddWhitelistPermissionFlags(permission_flags, inbound_onion ? std::optional<CNetAddr>{} : addr, vWhitelistedRangeIncoming);1801{1802LOCK(m_nodes_mutex);1803for (const CNode* pnode : m_nodes) {1804if (pnode->IsInboundConn()) nInbound++;1805}1806}1808if (!fNetworkActive) {1809LogDebug(BCLog::NET, "connection from %s dropped: not accepting new connections\n", addr.ToStringAddrPort());1810return;1811}1813if (!sock->IsSelectable()) {1814LogInfo("connection from %s dropped: non-selectable socket\n", addr.ToStringAddrPort());1815return;1816}1818// According to the internet TCP_NODELAY is not carried into accepted sockets1819// on all platforms. Set it again here just to be sure.1820const int on{1};1821if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {1822LogDebug(BCLog::NET, "connection from %s: unable to set TCP_NODELAY, continuing anyway\n",1823addr.ToStringAddrPort());1824}1826// Don't accept connections from banned peers.1827bool banned = m_banman && m_banman->IsBanned(addr);1828if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && banned)1829{1830LogDebug(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToStringAddrPort());1831return;1832}1834// Only accept connections from discouraged peers if our inbound slots aren't (almost) full.1835bool discouraged = m_banman && m_banman->IsDiscouraged(addr);1836if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && nInbound + 1 >= m_max_inbound && discouraged)1837{1838LogDebug(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToStringAddrPort());1839return;1840}1842if (nInbound >= m_max_inbound)1843{1844if (!AttemptToEvictConnection(/*evict_tx_relay_peer_only=*/false)) {1845// No connection to evict, disconnect the new connection1846LogDebug(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");1847return;1848}1849}1851NodeId id = GetNewNodeId();1852uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();1854// The V2Transport transparently falls back to V1 behavior when an incoming V1 connection is1855// detected, so use it whenever we signal NODE_P2P_V2.1856ServiceFlags local_services = GetLocalServices();1857const bool use_v2transport(local_services & NODE_P2P_V2);1859uint64_t network_id = GetDeterministicRandomizer(RANDOMIZER_ID_NETWORKKEY)1860.Write(inbound_onion ? NET_ONION : addr.GetNetClass())1861.Write(addr_bind.GetAddrBytes())1862.Write(addr_bind.GetPort()) // inbound connections use bind port1863.Finalize();1864CNode* pnode = new CNode(id,1865std::move(sock),1866CAddress{addr, NODE_NONE},1867CalculateKeyedNetGroup(addr),1868nonce,1869addr_bind,1870/*addrNameIn=*/"",1871ConnectionType::INBOUND,1872inbound_onion,1873network_id,1874CNodeOptions{1875.permission_flags = permission_flags,1876.prefer_evict = discouraged,1877.recv_flood_size = nReceiveFloodSize,1878.use_v2transport = use_v2transport,1879});1880pnode->AddRef();1881m_msgproc->InitializeNode(*pnode, local_services);1882{1883LOCK(m_nodes_mutex);1884m_nodes.push_back(pnode);1885}1886LogDebug(BCLog::NET, "connection from %s accepted\n", addr.ToStringAddrPort());1887TRACEPOINT(net, inbound_connection,1888pnode->GetId(),1889pnode->m_addr_name.c_str(),1890pnode->ConnectionTypeAsString().c_str(),1891pnode->ConnectedThroughNetwork(),1892GetNodeCount(ConnectionDirection::In));1894// We received a new connection, harvest entropy from the time (and our peer count)1895RandAddEvent((uint32_t)id);1896}1898bool CConnman::AddConnection(const std::string& address, ConnectionType conn_type, bool use_v2transport = false)1899{1900AssertLockNotHeld(m_nodes_mutex);1901AssertLockNotHeld(m_unused_i2p_sessions_mutex);1902std::optional<int> max_connections;1903switch (conn_type) {1904case ConnectionType::INBOUND:1905case ConnectionType::MANUAL:1906case ConnectionType::PRIVATE_BROADCAST:1907return false;1908case ConnectionType::OUTBOUND_FULL_RELAY:1909max_connections = m_max_outbound_full_relay;1910break;1911case ConnectionType::BLOCK_RELAY:1912max_connections = m_max_outbound_block_relay;1913break;1914// no limit for ADDR_FETCH because -seednode has no limit either1915case ConnectionType::ADDR_FETCH:1916break;1917// no limit for FEELER connections since they're short-lived1918case ConnectionType::FEELER:1919break;1920} // no default case, so the compiler can warn about missing cases1922// Count existing connections1923int existing_connections = WITH_LOCK(m_nodes_mutex,1924return std::count_if(m_nodes.begin(), m_nodes.end(), [conn_type](CNode* node) { return node->m_conn_type == conn_type; }););1926// Max connections of specified type already exist1927if (max_connections != std::nullopt && existing_connections >= max_connections) return false;1929// Max total outbound connections already exist1930CountingSemaphoreGrant<> grant(*semOutbound, true);1931if (!grant) return false;1933OpenNetworkConnection(/*addrConnect=*/CAddress{},1934/*fCountFailure=*/false,1935/*grant_outbound=*/std::move(grant),1936/*pszDest=*/address.c_str(),1937/*conn_type=*/conn_type,1938/*use_v2transport=*/use_v2transport,1939/*proxy_override=*/std::nullopt);1940return true;1941}1943void CConnman::DisconnectNodes()1944{1945AssertLockNotHeld(m_nodes_mutex);1946AssertLockNotHeld(m_reconnections_mutex);1948// Use a temporary variable to accumulate desired reconnections, so we don't need1949// m_reconnections_mutex while holding m_nodes_mutex.1950decltype(m_reconnections) reconnections_to_add;1952{1953LOCK(m_nodes_mutex);1955const bool network_active{fNetworkActive};1956if (!network_active) {1957// Disconnect any connected nodes1958for (CNode* pnode : m_nodes) {1959if (!pnode->fDisconnect) {1960LogDebug(BCLog::NET, "Network not active, %s", pnode->DisconnectMsg());1961pnode->fDisconnect = true;1962}1963}1964}1966// Disconnect unused nodes1967std::vector<CNode*> nodes_copy = m_nodes;1968for (CNode* pnode : nodes_copy)1969{1970if (pnode->fDisconnect)1971{1972// remove from m_nodes1973m_nodes.erase(remove(m_nodes.begin(), m_nodes.end(), pnode), m_nodes.end());1975// Add to reconnection list if appropriate. We don't reconnect right here, because1976// the creation of a connection is a blocking operation (up to several seconds),1977// and we don't want to hold up the socket handler thread for that long.1978if (network_active && pnode->m_transport->ShouldReconnectV1()) {1979reconnections_to_add.push_back({1980.proxy_override = pnode->m_proxy_override,1981.addr_connect = pnode->addr,1982.grant = std::move(pnode->grantOutbound),1983.destination = pnode->m_dest,1984.conn_type = pnode->m_conn_type,1985.use_v2transport = false});1986LogDebug(BCLog::NET, "retrying with v1 transport protocol for peer=%d\n", pnode->GetId());1987}1989// release outbound grant (if any)1990pnode->grantOutbound.Release();1992// close socket and cleanup1993pnode->CloseSocketDisconnect();1995// update connection count by network1996if (pnode->IsManualOrFullOutboundConn()) --m_network_conn_counts[pnode->addr.GetNetwork()];1998// hold in disconnected pool until all refs are released1999pnode->Release();2000m_nodes_disconnected.push_back(pnode);