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.
3501SetNetworkActive(network_active);3502}3504NodeId CConnman::GetNewNodeId()3505{3506return nLastNodeId.fetch_add(1, std::memory_order_relaxed);3507}3509uint16_t CConnman::GetDefaultPort(Network net) const3510{3511return net == NET_I2P ? I2P_SAM31_PORT : m_params.GetDefaultPort();3512}3514uint16_t CConnman::GetDefaultPort(const std::string& addr) const3515{3516CNetAddr a;3517return a.SetSpecial(addr) ? GetDefaultPort(a.GetNetwork()) : m_params.GetDefaultPort();3518}3520bool CConnman::Bind(const CService& addr_, unsigned int flags, NetPermissionFlags permissions)3521{3522const CService addr{MaybeFlipIPv6toCJDNS(addr_)};3524bilingual_str strError;3525if (!BindListenPort(addr, strError, permissions)) {3526if ((flags & BF_REPORT_ERROR) && m_client_interface) {3527m_client_interface->ThreadSafeMessageBox(strError, CClientUIInterface::MSG_ERROR);3528}3529return false;3530}3532if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !NetPermissions::HasFlag(permissions, NetPermissionFlags::NoBan)) {3533AddLocal(addr, LOCAL_BIND);3534}3536return true;3537}3539bool CConnman::InitBinds(const Options& options)3540{3541for (const auto& addrBind : options.vBinds) {3542if (!Bind(addrBind, BF_REPORT_ERROR, NetPermissionFlags::None)) {3543return false;3544}3545}3546for (const auto& addrBind : options.vWhiteBinds) {3547if (!Bind(addrBind.m_service, BF_REPORT_ERROR, addrBind.m_flags)) {3548return false;3549}3550}3551for (const auto& addr_bind : options.onion_binds) {3552if (!Bind(addr_bind, BF_REPORT_ERROR | BF_DONT_ADVERTISE, NetPermissionFlags::None)) {3553return false;3554}3555}3556if (options.bind_on_any) {3557// Don't consider errors to bind on IPv6 "::" fatal because the host OS3558// may not have IPv6 support and the user did not explicitly ask us to3559// bind on that.3560const CService ipv6_any{in6_addr(COMPAT_IN6ADDR_ANY_INIT), GetListenPort()}; // ::3561Bind(ipv6_any, BF_NONE, NetPermissionFlags::None);3563struct in_addr inaddr_any;3564inaddr_any.s_addr = htonl(INADDR_ANY);3565const CService ipv4_any{inaddr_any, GetListenPort()}; // 0.0.0.03566if (!Bind(ipv4_any, BF_REPORT_ERROR, NetPermissionFlags::None)) {3567return false;3568}3569}3570return true;3571}3573bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)3574{3575AssertLockNotHeld(m_total_bytes_sent_mutex);3576Init(connOptions);3578if (fListen && !InitBinds(connOptions)) {3579if (m_client_interface) {3580m_client_interface->ThreadSafeMessageBox(3581_("Failed to listen on any port. Use -listen=0 if you want this."),3582CClientUIInterface::MSG_ERROR);3583}3584return false;3585}3587if (connOptions.m_i2p_accept_incoming) {3588if (const auto i2p_sam = GetProxy(NET_I2P)) {3589m_i2p_sam_session = std::make_unique<i2p::sam::Session>(gArgs.GetDataDirNet() / "i2p_private_key",3590*i2p_sam, m_interrupt_net);3591}3592}3594// Randomize the order in which we may query seednode to potentially prevent connecting to the same one every restart (and signal that we have restarted)3595std::vector<std::string> seed_nodes = connOptions.vSeedNodes;3596if (!seed_nodes.empty()) {3597std::shuffle(seed_nodes.begin(), seed_nodes.end(), FastRandomContext{});3598}3600if (m_use_addrman_outgoing) {3601// Load addresses from anchors.dat3602m_anchors = ReadAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME);3603if (m_anchors.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {3604m_anchors.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);3605}3606LogInfo("%i block-relay-only anchors will be tried for connections.\n", m_anchors.size());3607}3609if (m_client_interface) {3610m_client_interface->InitMessage(_("Starting network threads…"));3611}3613fAddressesInitialized = true;3615if (semOutbound == nullptr) {3616// initialize semaphore3617semOutbound = std::make_unique<std::counting_semaphore<>>(std::min(m_max_automatic_outbound, m_max_automatic_connections));3618}3619if (semAddnode == nullptr) {3620// initialize semaphore3621semAddnode = std::make_unique<std::counting_semaphore<>>(m_max_addnode);3622}3624//3625// Start threads3626//3627assert(m_msgproc);3628m_interrupt_net->reset();3629flagInterruptMsgProc = false;3631{3632LOCK(mutexMsgProc);3633fMsgProcWake = false;3634}3636// Send and receive from sockets, accept connections3637threadSocketHandler = std::thread(&util::TraceThread, "net", [this] { ThreadSocketHandler(); });3639if (!gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED))3640LogInfo("DNS seeding disabled\n");3641else3642threadDNSAddressSeed = std::thread(&util::TraceThread, "dnsseed", [this] { ThreadDNSAddressSeed(); });3644// Initiate manual connections3645threadOpenAddedConnections = std::thread(&util::TraceThread, "addcon", [this] { ThreadOpenAddedConnections(); });3647if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {3648if (m_client_interface) {3649m_client_interface->ThreadSafeMessageBox(3650_("Cannot provide specific connections and have addrman find outgoing connections at the same time."),3651CClientUIInterface::MSG_ERROR);3652}3653return false;3654}3655if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) {3656threadOpenConnections = std::thread(3657&util::TraceThread, "opencon",3658[this, connect = connOptions.m_specified_outgoing, seed_nodes = std::move(seed_nodes)] { ThreadOpenConnections(connect, seed_nodes); });3659}3661// Process messages3662threadMessageHandler = std::thread(&util::TraceThread, "msghand", [this] { ThreadMessageHandler(); });3664if (m_i2p_sam_session) {3665threadI2PAcceptIncoming =3666std::thread(&util::TraceThread, "i2paccept", [this] { ThreadI2PAcceptIncoming(); });3667}3669if (gArgs.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)) {3670threadPrivateBroadcast =3671std::thread(&util::TraceThread, "privbcast", [this] { ThreadPrivateBroadcast(); });3672}3674// Dump network addresses3675scheduler.scheduleEvery([this] { DumpAddresses(); }, DUMP_PEERS_INTERVAL);3677// Run the ASMap Health check once and then schedule it to run every 24h.3678if (m_netgroupman.UsingASMap()) {3679ASMapHealthCheck();3680scheduler.scheduleEvery([this] { ASMapHealthCheck(); }, ASMAP_HEALTH_CHECK_INTERVAL);3681}3683return true;3684}3686class CNetCleanup3687{3688public:3689CNetCleanup() = default;3691~CNetCleanup()3692{3693#ifdef WIN323694// Shutdown Windows Sockets3695WSACleanup();3696#endif3697}3698};3699static CNetCleanup instance_of_cnetcleanup;3701void CConnman::Interrupt()3702{3703{3704LOCK(mutexMsgProc);3705flagInterruptMsgProc = true;3706}3707condMsgProc.notify_all();3709(*m_interrupt_net)();3710g_socks5_interrupt();3712if (semOutbound) {3713for (int i=0; i<m_max_automatic_outbound; i++) {3714semOutbound->release();3715}3716}3718if (semAddnode) {3719for (int i=0; i<m_max_addnode; i++) {3720semAddnode->release();3721}3722}3724m_private_broadcast.m_sem_conn_max.release();3725m_private_broadcast.NumToOpenAdd(1); // Just unblock NumToOpenWait() to be able to continue with shutdown.3726}3728void CConnman::StopThreads()3729{3730if (threadPrivateBroadcast.joinable()) {3731threadPrivateBroadcast.join();3732}3733if (threadI2PAcceptIncoming.joinable()) {3734threadI2PAcceptIncoming.join();3735}3736if (threadMessageHandler.joinable())3737threadMessageHandler.join();3738if (threadOpenConnections.joinable())3739threadOpenConnections.join();3740if (threadOpenAddedConnections.joinable())3741threadOpenAddedConnections.join();3742if (threadDNSAddressSeed.joinable())3743threadDNSAddressSeed.join();3744if (threadSocketHandler.joinable())3745threadSocketHandler.join();3746}3748void CConnman::StopNodes()3749{3750AssertLockNotHeld(m_nodes_mutex);