diff --git a/src/common/sockman.cpp b/src/common/sockman.cpp index 02fc425d28c..4ddbfcb8edf 100644 --- a/src/common/sockman.cpp +++ b/src/common/sockman.cpp @@ -226,6 +226,26 @@ std::unique_ptr SockMan::AcceptConnection(const Sock& listen_sock, CServic return sock; } +void SockMan::NewSockAccepted(std::unique_ptr&& sock, const CService& me, const CService& them) +{ + if (!sock->IsSelectable()) { + LogPrintf("connection from %s dropped: non-selectable socket\n", them.ToStringAddrPort()); + return; + } + + // According to the internet TCP_NODELAY is not carried into accepted sockets + // on all platforms. Set it again here just to be sure. + const int on{1}; + if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) { + LogDebug(BCLog::NET, "connection from %s: unable to set TCP_NODELAY, continuing anyway\n", + them.ToStringAddrPort()); + } + + const Id id{GetNewId()}; + + EventNewConnectionAccepted(id, std::move(sock), me, them); +} + SockMan::Id SockMan::GetNewId() { return m_next_id.fetch_add(1, std::memory_order_relaxed); @@ -276,7 +296,10 @@ void SockMan::ThreadI2PAccept() continue; } - EventNewConnectionAccepted(std::move(conn.sock), conn.me, conn.peer); + Assume(conn.me.IsI2P()); + Assume(conn.peer.IsI2P()); + + NewSockAccepted(std::move(conn.sock), conn.me, conn.peer); err_wait = err_wait_begin; } diff --git a/src/common/sockman.h b/src/common/sockman.h index 33d368630b3..f417987c3cc 100644 --- a/src/common/sockman.h +++ b/src/common/sockman.h @@ -137,6 +137,15 @@ public: */ std::unique_ptr AcceptConnection(const Sock& listen_sock, CService& addr); + /** + * After a new socket with a peer has been created, configure its flags, + * make a new connection id and call `EventNewConnectionAccepted()`. + * @param[in] sock The newly created socket. + * @param[in] me Address at our end of the connection. + * @param[in] them Address of the new peer. + */ + void NewSockAccepted(std::unique_ptr&& sock, const CService& me, const CService& them); + /** * Generate an id for a newly created connection. */ @@ -181,11 +190,13 @@ private: /** * Be notified when a new connection has been accepted. + * @param[in] id Id of the newly accepted connection. * @param[in] sock Connected socket to communicate with the peer. * @param[in] me The address and port at our side of the connection. * @param[in] them The address and port at the peer's side of the connection. */ - virtual void EventNewConnectionAccepted(std::unique_ptr&& sock, + virtual void EventNewConnectionAccepted(Id id, + std::unique_ptr&& sock, const CService& me, const CService& them) = 0; diff --git a/src/net.cpp b/src/net.cpp index e8a1a1301d1..06eaabbe9ba 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1712,10 +1712,14 @@ bool CConnman::AttemptToEvictConnection() return false; } -void CConnman::EventNewConnectionAccepted(std::unique_ptr&& sock, - const CService& addr_bind, - const CService& addr) +void CConnman::EventNewConnectionAccepted(SockMan::Id id, + std::unique_ptr&& sock, + const CService& me, + const CService& them) { + const CService addr_bind{MaybeFlipIPv6toCJDNS(me)}; + const CService addr{MaybeFlipIPv6toCJDNS(them)}; + int nInbound = 0; NetPermissionFlags permission_flags = NetPermissionFlags::None; @@ -1738,19 +1742,6 @@ void CConnman::EventNewConnectionAccepted(std::unique_ptr&& sock, return; } - if (!sock->IsSelectable()) { - LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToStringAddrPort()); - return; - } - - // According to the internet TCP_NODELAY is not carried into accepted sockets - // on all platforms. Set it again here just to be sure. - const int on{1}; - if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) { - LogDebug(BCLog::NET, "connection from %s: unable to set TCP_NODELAY, continuing anyway\n", - addr.ToStringAddrPort()); - } - // Don't accept connections from banned peers. bool banned = m_banman && m_banman->IsBanned(addr); if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && banned) @@ -1776,7 +1767,6 @@ void CConnman::EventNewConnectionAccepted(std::unique_ptr&& sock, } } - NodeId id = GetNewId(); uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end(); @@ -2278,10 +2268,7 @@ void CConnman::SocketHandlerListening(const Sock::EventsPerSock& events_per_sock auto sock_accepted{AcceptConnection(*sock, addr_accepted)}; if (sock_accepted) { - addr_accepted = MaybeFlipIPv6toCJDNS(addr_accepted); - const CService addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock))}; - - EventNewConnectionAccepted(std::move(sock_accepted), addr_bind, addr_accepted); + NewSockAccepted(std::move(sock_accepted), GetBindAddress(*sock), addr_accepted); } } } diff --git a/src/net.h b/src/net.h index ec5f1917491..5e935e2a226 100644 --- a/src/net.h +++ b/src/net.h @@ -1294,11 +1294,13 @@ private: /** * Create a `CNode` object and add it to the `m_nodes` member. + * @param[in] id Id of the newly accepted connection. * @param[in] sock Connected socket to communicate with the peer. * @param[in] me The address and port at our side of the connection. * @param[in] them The address and port at the peer's side of the connection. */ - virtual void EventNewConnectionAccepted(std::unique_ptr&& sock, + virtual void EventNewConnectionAccepted(SockMan::Id id, + std::unique_ptr&& sock, const CService& me, const CService& them) override;