diff options
Diffstat (limited to 'src/net.cpp')
-rw-r--r-- | src/net.cpp | 162 |
1 files changed, 96 insertions, 66 deletions
diff --git a/src/net.cpp b/src/net.cpp index c4aaac4986..3c28b9eddf 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -91,13 +91,12 @@ static constexpr auto FEELER_SLEEP_WINDOW{1s}; /** Used to pass flags to the Bind() function */ enum BindFlags { BF_NONE = 0, - BF_EXPLICIT = (1U << 0), - BF_REPORT_ERROR = (1U << 1), + BF_REPORT_ERROR = (1U << 0), /** * Do not call AddLocal() for our special addresses, e.g., for incoming * Tor connections, to prevent gossiping them over the network. */ - BF_DONT_ADVERTISE = (1U << 2), + BF_DONT_ADVERTISE = (1U << 1), }; // The set of sockets cannot be modified while waiting @@ -208,12 +207,11 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn) // one by discovery. CService GetLocalAddress(const CNetAddr& addrPeer) { - CService ret{CNetAddr(), GetListenPort()}; CService addr; if (GetLocal(addr, &addrPeer)) { - ret = CService{addr}; + return addr; } - return ret; + return CService{CNetAddr(), GetListenPort()}; } static int GetnScore(const CService& addr) @@ -454,7 +452,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "trying connection %s lastseen=%.1fhrs\n", pszDest ? pszDest : addrConnect.ToString(), - Ticks<HoursDouble>(pszDest ? 0h : AdjustedTime() - addrConnect.nTime)); + Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.nTime)); // Resolve const uint16_t default_port{pszDest != nullptr ? Params().GetDefaultPort(pszDest) : @@ -485,18 +483,27 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo Proxy proxy; CAddress addr_bind; assert(!addr_bind.IsValid()); + std::unique_ptr<i2p::sam::Session> i2p_transient_session; if (addrConnect.IsValid()) { + const bool use_proxy{GetProxy(addrConnect.GetNetwork(), proxy)}; bool proxyConnectionFailed = false; - if (addrConnect.GetNetwork() == NET_I2P && m_i2p_sam_session.get() != nullptr) { + if (addrConnect.GetNetwork() == NET_I2P && use_proxy) { i2p::Connection conn; - if (m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed)) { - connected = true; + + if (m_i2p_sam_session) { + connected = m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed); + } else { + i2p_transient_session = std::make_unique<i2p::sam::Session>(proxy.proxy, &interruptNet); + connected = i2p_transient_session->Connect(addrConnect, conn, proxyConnectionFailed); + } + + if (connected) { sock = std::move(conn.sock); addr_bind = CAddress{conn.me, NODE_NONE}; } - } else if (GetProxy(addrConnect.GetNetwork(), proxy)) { + } else if (use_proxy) { sock = CreateSock(proxy.proxy); if (!sock) { return nullptr; @@ -547,7 +554,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo addr_bind, pszDest ? pszDest : "", conn_type, - /*inbound_onion=*/false); + /*inbound_onion=*/false, + CNodeOptions{ .i2p_sam_session = std::move(i2p_transient_session) }); pnode->AddRef(); // We're making a new connection, harvest entropy from the time (and our peer count) @@ -564,6 +572,7 @@ void CNode::CloseSocketDisconnect() LogPrint(BCLog::NET, "disconnecting peer=%d\n", id); m_sock.reset(); } + m_i2p_sam_session.reset(); } void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const { @@ -627,7 +636,7 @@ void CNode::CopyStats(CNodeStats& stats) X(mapRecvBytesPerMsgType); X(nRecvBytes); } - X(m_permissionFlags); + X(m_permission_flags); X(m_last_ping_time); X(m_min_ping_time); @@ -787,7 +796,8 @@ CNetMessage V1TransportDeserializer::GetMessage(const std::chrono::microseconds return msg; } -void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) { +void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) const +{ // create dbl-sha256 checksum uint256 hash = Hash(msg.data); @@ -925,27 +935,27 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock)), NODE_NONE}; - NetPermissionFlags permissionFlags = NetPermissionFlags::None; - hListenSocket.AddSocketPermissionFlags(permissionFlags); + NetPermissionFlags permission_flags = NetPermissionFlags::None; + hListenSocket.AddSocketPermissionFlags(permission_flags); - CreateNodeFromAcceptedSocket(std::move(sock), permissionFlags, addr_bind, addr); + CreateNodeFromAcceptedSocket(std::move(sock), permission_flags, addr_bind, addr); } void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, - NetPermissionFlags permissionFlags, + NetPermissionFlags permission_flags, const CAddress& addr_bind, const CAddress& addr) { int nInbound = 0; int nMaxInbound = nMaxConnections - m_max_outbound; - AddWhitelistPermissionFlags(permissionFlags, addr); - if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::Implicit)) { - NetPermissions::ClearFlag(permissionFlags, NetPermissionFlags::Implicit); - if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::ForceRelay); - if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::Relay); - NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::Mempool); - NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::NoBan); + AddWhitelistPermissionFlags(permission_flags, addr); + if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::Implicit)) { + NetPermissions::ClearFlag(permission_flags, NetPermissionFlags::Implicit); + if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::ForceRelay); + if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Relay); + NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Mempool); + NetPermissions::AddFlag(permission_flags, NetPermissionFlags::NoBan); } { @@ -960,8 +970,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, return; } - if (!IsSelectableSocket(sock->Get())) - { + if (!sock->IsSelectable()) { LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString()); return; } @@ -976,7 +985,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, // Don't accept connections from banned peers. bool banned = m_banman && m_banman->IsBanned(addr); - if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::NoBan) && banned) + if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && banned) { LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString()); return; @@ -984,7 +993,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, // Only accept connections from discouraged peers if our inbound slots aren't (almost) full. bool discouraged = m_banman && m_banman->IsDiscouraged(addr); - if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged) + if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged) { LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToString()); return; @@ -1003,7 +1012,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); ServiceFlags nodeServices = nLocalServices; - if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::BloomFilter)) { + if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::BloomFilter)) { nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM); } @@ -1016,10 +1025,12 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, addr_bind, /*addrNameIn=*/"", ConnectionType::INBOUND, - inbound_onion); + inbound_onion, + CNodeOptions{ + .permission_flags = permission_flags, + .prefer_evict = discouraged, + }); pnode->AddRef(); - pnode->m_permissionFlags = permissionFlags; - pnode->m_prefer_evict = discouraged; m_msgproc->InitializeNode(*pnode, nodeServices); LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString()); @@ -1487,12 +1498,12 @@ void CConnman::ThreadDNSAddressSeed() void CConnman::DumpAddresses() { - int64_t nStart = GetTimeMillis(); + const auto start{SteadyClock::now()}; DumpPeerAddresses(::gArgs, addrman); LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n", - addrman.size(), GetTimeMillis() - nStart); + addrman.size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start)); } void CConnman::ProcessAddrFetch() @@ -1629,15 +1640,28 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect) LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex); if (m_addr_fetches.empty() && m_added_nodes.empty()) { add_fixed_seeds_now = true; - LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n"); + LogPrintf("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet), -addnode is not provided and all -seednode(s) attempted\n"); } } if (add_fixed_seeds_now) { + std::vector<CAddress> seed_addrs{ConvertSeeds(Params().FixedSeeds())}; + // We will not make outgoing connections to peers that are unreachable + // (e.g. because of -onlynet configuration). + // Therefore, we do not add them to addrman in the first place. + // Note that if you change -onlynet setting from one network to another, + // peers.dat will contain only peers of unreachable networks and + // manual intervention will be needed (either delete peers.dat after + // configuration change or manually add some reachable peer using addnode), + // see <https://github.com/bitcoin/bitcoin/issues/26035> for details. + seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(), + [](const CAddress& addr) { return !IsReachable(addr); }), + seed_addrs.end()); CNetAddr local; local.SetInternal("fixedseeds"); - addrman.Add(ConvertSeeds(Params().FixedSeeds()), local); + addrman.Add(seed_addrs, local); add_fixed_seeds = false; + LogPrintf("Added %d fixed seeds from reachable networks.\n", seed_addrs.size()); } } @@ -1735,7 +1759,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect) addrman.ResolveCollisions(); - const auto nANow{AdjustedTime()}; + const auto current_time{NodeClock::now()}; int nTries = 0; while (!interruptNet) { @@ -1798,7 +1822,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect) continue; // only consider very recently tried nodes after 30 failed attempts - if (nANow - addr_last_try < 10min && nTries < 30) { + if (current_time - addr_last_try < 10min && nTries < 30) { continue; } @@ -1965,8 +1989,12 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai } } +Mutex NetEventsInterface::g_msgproc_mutex; + void CConnman::ThreadMessageHandler() { + LOCK(NetEventsInterface::g_msgproc_mutex); + SetSyscallSandboxPolicy(SyscallSandboxPolicy::MESSAGE_HANDLER); while (!flagInterruptMsgProc) { @@ -1988,10 +2016,7 @@ void CConnman::ThreadMessageHandler() if (flagInterruptMsgProc) return; // Send messages - { - LOCK(pnode->cs_sendProcessing); - m_msgproc->SendMessages(pnode); - } + m_msgproc->SendMessages(pnode); if (flagInterruptMsgProc) return; @@ -2204,9 +2229,6 @@ bool CConnman::Bind(const CService& addr_, unsigned int flags, NetPermissionFlag { const CService addr{MaybeFlipIPv6toCJDNS(addr_)}; - if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) { - return false; - } bilingual_str strError; if (!BindListenPort(addr, strError, permissions)) { if ((flags & BF_REPORT_ERROR) && m_client_interface) { @@ -2226,13 +2248,13 @@ bool CConnman::InitBinds(const Options& options) { bool fBound = false; for (const auto& addrBind : options.vBinds) { - fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR), NetPermissionFlags::None); + fBound |= Bind(addrBind, BF_REPORT_ERROR, NetPermissionFlags::None); } for (const auto& addrBind : options.vWhiteBinds) { - fBound |= Bind(addrBind.m_service, (BF_EXPLICIT | BF_REPORT_ERROR), addrBind.m_flags); + fBound |= Bind(addrBind.m_service, BF_REPORT_ERROR, addrBind.m_flags); } for (const auto& addr_bind : options.onion_binds) { - fBound |= Bind(addr_bind, BF_EXPLICIT | BF_DONT_ADVERTISE, NetPermissionFlags::None); + fBound |= Bind(addr_bind, BF_DONT_ADVERTISE, NetPermissionFlags::None); } if (options.bind_on_any) { struct in_addr inaddr_any; @@ -2259,7 +2281,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) } Proxy i2p_sam; - if (GetProxy(NET_I2P, i2p_sam)) { + if (GetProxy(NET_I2P, i2p_sam) && connOptions.m_i2p_accept_incoming) { m_i2p_sam_session = std::make_unique<i2p::sam::Session>(gArgs.GetDataDirNet() / "i2p_private_key", i2p_sam.proxy, &interruptNet); } @@ -2333,7 +2355,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) // Process messages threadMessageHandler = std::thread(&util::TraceThread, "msghand", [this] { ThreadMessageHandler(); }); - if (connOptions.m_i2p_accept_incoming && m_i2p_sam_session.get() != nullptr) { + if (m_i2p_sam_session) { threadI2PAcceptIncoming = std::thread(&util::TraceThread, "i2paccept", [this] { ThreadI2PAcceptIncoming(); }); } @@ -2702,20 +2724,31 @@ ServiceFlags CConnman::GetLocalServices() const unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } -CNode::CNode(NodeId idIn, std::shared_ptr<Sock> sock, const CAddress& addrIn, - uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, - const CAddress& addrBindIn, const std::string& addrNameIn, - ConnectionType conn_type_in, bool inbound_onion) - : m_sock{sock}, +CNode::CNode(NodeId idIn, + std::shared_ptr<Sock> sock, + const CAddress& addrIn, + uint64_t nKeyedNetGroupIn, + uint64_t nLocalHostNonceIn, + const CAddress& addrBindIn, + const std::string& addrNameIn, + ConnectionType conn_type_in, + bool inbound_onion, + CNodeOptions&& node_opts) + : m_deserializer{std::make_unique<V1TransportDeserializer>(V1TransportDeserializer(Params(), idIn, SER_NETWORK, INIT_PROTO_VERSION))}, + m_serializer{std::make_unique<V1TransportSerializer>(V1TransportSerializer())}, + m_permission_flags{node_opts.permission_flags}, + m_sock{sock}, m_connected{GetTime<std::chrono::seconds>()}, - addr(addrIn), - addrBind(addrBindIn), + addr{addrIn}, + addrBind{addrBindIn}, m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn}, - m_inbound_onion(inbound_onion), - nKeyedNetGroup(nKeyedNetGroupIn), - id(idIn), - nLocalHostNonce(nLocalHostNonceIn), - m_conn_type(conn_type_in) + m_inbound_onion{inbound_onion}, + m_prefer_evict{node_opts.prefer_evict}, + nKeyedNetGroup{nKeyedNetGroupIn}, + id{idIn}, + nLocalHostNonce{nLocalHostNonceIn}, + m_conn_type{conn_type_in}, + m_i2p_sam_session{std::move(node_opts.i2p_sam_session)} { if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND); @@ -2728,9 +2761,6 @@ CNode::CNode(NodeId idIn, std::shared_ptr<Sock> sock, const CAddress& addrIn, } else { LogPrint(BCLog::NET, "Added connection peer=%d\n", id); } - - m_deserializer = std::make_unique<V1TransportDeserializer>(V1TransportDeserializer(Params(), id, SER_NETWORK, INIT_PROTO_VERSION)); - m_serializer = std::make_unique<V1TransportSerializer>(V1TransportSerializer()); } bool CConnman::NodeFullyConnected(const CNode* pnode) |