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.
3252// Receive messages3253bool fMoreNodeWork{m_msgproc->ProcessMessages(*pnode, flagInterruptMsgProc)};3254fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);3255if (flagInterruptMsgProc)3256return;3257// Send messages3258m_msgproc->SendMessages(*pnode);3260if (flagInterruptMsgProc)3261return;3262}3263}3265WAIT_LOCK(mutexMsgProc, lock);3266if (!fMoreWork) {3267condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this]() EXCLUSIVE_LOCKS_REQUIRED(mutexMsgProc) { return fMsgProcWake; });3268}3269fMsgProcWake = false;3270}3271}3273void CConnman::ThreadI2PAcceptIncoming()3274{3275AssertLockNotHeld(m_nodes_mutex);3277static constexpr auto err_wait_begin = 1s;3278static constexpr auto err_wait_cap = 5min;3279auto err_wait = err_wait_begin;3281bool advertising_listen_addr = false;3282i2p::Connection conn;3284auto SleepOnFailure = [&]() {3285m_interrupt_net->sleep_for(err_wait);3286if (err_wait < err_wait_cap) {3287err_wait += 1s;3288}3289};3291while (!m_interrupt_net->interrupted()) {3293if (!m_i2p_sam_session->Listen(conn)) {3294if (advertising_listen_addr && conn.me.IsValid()) {3295RemoveLocal(conn.me);3296advertising_listen_addr = false;3297}3298SleepOnFailure();3299continue;3300}3302if (!advertising_listen_addr) {3303AddLocal(conn.me, LOCAL_MANUAL);3304advertising_listen_addr = true;3305}3307if (!m_i2p_sam_session->Accept(conn)) {3308SleepOnFailure();3309continue;3310}3312CreateNodeFromAcceptedSocket(std::move(conn.sock), NetPermissionFlags::None, conn.me, conn.peer);3314err_wait = err_wait_begin;3315}3316}3318void CConnman::ThreadPrivateBroadcast()3319{3320AssertLockNotHeld(m_nodes_mutex);3321AssertLockNotHeld(m_unused_i2p_sessions_mutex);3323size_t addrman_num_bad_addresses{0};3324while (!m_interrupt_net->interrupted()) {3326if (!fNetworkActive) {3327m_interrupt_net->sleep_for(5s);3328continue;3329}3331CountingSemaphoreGrant<> conn_max_grant{m_private_broadcast.m_sem_conn_max}; // Would block if too many are opened.3333m_private_broadcast.NumToOpenWait();3335if (m_interrupt_net->interrupted()) {3336break;3337}3339std::optional<Proxy> proxy;3340const std::optional<Network> net{m_private_broadcast.PickNetwork(proxy)};3341if (!net.has_value()) {3342LogWarning("Unable to open -privatebroadcast connections: neither Tor nor I2P is reachable");3343m_interrupt_net->sleep_for(5s);3344continue;3345}3347const auto [addr, _] = addrman.get().Select(/*new_only=*/false, {net.value()});3349if (!addr.IsValid() || IsLocal(addr)) {3350++addrman_num_bad_addresses;3351if (addrman_num_bad_addresses > 100) {3352LogDebug(BCLog::PRIVBROADCAST, "Connections needed but addrman keeps returning bad addresses, will retry");3353m_interrupt_net->sleep_for(500ms);3354}3355continue;3356}3357addrman_num_bad_addresses = 0;3359auto target_str{addr.ToStringAddrPort()};3360if (proxy.has_value()) {3361target_str += " through the proxy at " + proxy->ToString();3362}3364const bool use_v2transport(addr.nServices & GetLocalServices() & NODE_P2P_V2);3366if (OpenNetworkConnection(addr,3367/*fCountFailure=*/true,3368std::move(conn_max_grant),3369/*pszDest=*/nullptr,3370ConnectionType::PRIVATE_BROADCAST,3371use_v2transport,3372proxy)) {3373const size_t remaining{m_private_broadcast.NumToOpenSub(1)};3374LogDebug(BCLog::PRIVBROADCAST, "Socket connected to %s; remaining connections to open: %d", target_str, remaining);3375} else {3376const size_t remaining{m_private_broadcast.NumToOpen()};3377if (remaining == 0) {3378LogDebug(BCLog::PRIVBROADCAST, "Failed to connect to %s, will not retry, no more connections needed", target_str);3379} else {3380LogDebug(BCLog::PRIVBROADCAST, "Failed to connect to %s, will retry to a different address; remaining connections to open: %d", target_str, remaining);3381m_interrupt_net->sleep_for(100ms); // Prevent busy loop if OpenNetworkConnection() fails fast repeatedly.3382}3383}3384}3385}3387bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError, NetPermissionFlags permissions)3388{3389int nOne = 1;3391// Create socket for listening for incoming connections3392struct sockaddr_storage sockaddr;3393socklen_t len = sizeof(sockaddr);3394if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))3395{3396strError = Untranslated(strprintf("Bind address family for %s not supported", addrBind.ToStringAddrPort()));3397LogError("%s\n", strError.original);3398return false;3399}3401std::unique_ptr<Sock> sock = CreateSock(addrBind.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP);3402if (!sock) {3403strError = Untranslated(strprintf("Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError())));3404LogError("%s\n", strError.original);3405return false;3406}3408// Allow binding if the port is still in TIME_WAIT state after3409// the program was closed and restarted.3410if (sock->SetSockOpt(SOL_SOCKET, SO_REUSEADDR, &nOne, sizeof(int)) == SOCKET_ERROR) {3411strError = Untranslated(strprintf("Error setting SO_REUSEADDR on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError())));3412LogInfo("%s\n", strError.original);3413}3415// some systems don't have IPV6_V6ONLY but are always v6only; others do have the option3416// and enable it by default or not. Try to enable it, if possible.3417if (addrBind.IsIPv6()) {3418#ifdef IPV6_V6ONLY3419if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_V6ONLY, &nOne, sizeof(int)) == SOCKET_ERROR) {3420strError = Untranslated(strprintf("Error setting IPV6_V6ONLY on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError())));3421LogInfo("%s\n", strError.original);3422}3423#endif3424#ifdef WIN323425int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;3426if (sock->SetSockOpt(IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, &nProtLevel, sizeof(int)) == SOCKET_ERROR) {3427strError = Untranslated(strprintf("Error setting IPV6_PROTECTION_LEVEL on socket: %s, continuing anyway", NetworkErrorString(WSAGetLastError())));3428LogInfo("%s\n", strError.original);3429}3430#endif3431}3433if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {3434int nErr = WSAGetLastError();3435if (nErr == WSAEADDRINUSE)3436strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToStringAddrPort(), CLIENT_NAME);3437else3438strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToStringAddrPort(), NetworkErrorString(nErr));3439LogError("%s\n", strError.original);3440return false;3441}3442LogInfo("Bound to %s\n", addrBind.ToStringAddrPort());3444// Listen for incoming connections3445if (sock->Listen(SOMAXCONN) == SOCKET_ERROR)3446{3447strError = strprintf(_("Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));3448LogError("%s\n", strError.original);3449return false;3450}3452vhListenSocket.emplace_back(std::move(sock), permissions);3453return true;3454}3456void Discover()3457{3458if (!fDiscover)3459return;3461for (const CNetAddr &addr: GetLocalAddresses()) {3462if (AddLocal(addr, LOCAL_IF) && fLogIPs) {3463LogInfo("%s: %s\n", __func__, addr.ToStringAddr());3464}3465}3466}3468void CConnman::SetNetworkActive(bool active)3469{3470LogInfo("%s: %s\n", __func__, active);3472if (fNetworkActive == active) {3473return;3474}3476fNetworkActive = active;3478if (m_client_interface) {3479m_client_interface->NotifyNetworkActiveChanged(fNetworkActive);3480}3481}3483CConnman::CConnman(uint64_t nSeed0In,3484uint64_t nSeed1In,3485AddrMan& addrman_in,3486const NetGroupManager& netgroupman,3487const CChainParams& params,3488bool network_active,3489std::shared_ptr<CThreadInterrupt> interrupt_net)3490: addrman(addrman_in)3491, m_netgroupman{netgroupman}3492, nSeed0(nSeed0In)3493, nSeed1(nSeed1In)3494, m_interrupt_net{interrupt_net}3495, m_params(params)3496{3497SetTryNewOutboundPeer(false);3499Options connOptions;3500Init(connOptions);