aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp151
1 files changed, 91 insertions, 60 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 865ce2ea97..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
@@ -484,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;
@@ -546,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)
@@ -563,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 {
@@ -626,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);
@@ -786,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);
@@ -924,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);
}
{
@@ -959,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;
}
@@ -975,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;
@@ -983,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;
@@ -1002,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);
}
@@ -1015,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());
@@ -1486,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()
@@ -1628,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());
}
}
@@ -1964,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)
{
@@ -1987,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;
@@ -2203,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) {
@@ -2225,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;
@@ -2258,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);
}
@@ -2332,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(); });
}
@@ -2701,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);
@@ -2727,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)