mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 15:04:44 +01:00
netbase: refactor CreateSock() to accept sa_family_t
Also implement CService::GetSAFamily() to provide sa_family_t
This commit is contained in:
parent
adb3a3e51d
commit
bae86c8d31
9 changed files with 46 additions and 25 deletions
|
@ -32,6 +32,13 @@
|
||||||
#include <unistd.h> // IWYU pragma: export
|
#include <unistd.h> // IWYU pragma: export
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Windows does not have `sa_family_t` - it defines `sockaddr::sa_family` as `u_short`.
|
||||||
|
// Thus define `sa_family_t` on Windows too so that the rest of the code can use `sa_family_t`.
|
||||||
|
// See https://learn.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-sockaddr#syntax
|
||||||
|
#ifdef WIN32
|
||||||
|
typedef u_short sa_family_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
// We map Linux / BSD error functions and codes, to the equivalent
|
// We map Linux / BSD error functions and codes, to the equivalent
|
||||||
// Windows definitions, and use the WSA* names throughout our code.
|
// Windows definitions, and use the WSA* names throughout our code.
|
||||||
// Note that glibc defines EWOULDBLOCK as EAGAIN (see errno.h).
|
// Note that glibc defines EWOULDBLOCK as EAGAIN (see errno.h).
|
||||||
|
|
|
@ -326,7 +326,7 @@ Session::Reply Session::SendRequestAndGetReply(const Sock& sock,
|
||||||
|
|
||||||
std::unique_ptr<Sock> Session::Hello() const
|
std::unique_ptr<Sock> Session::Hello() const
|
||||||
{
|
{
|
||||||
auto sock = CreateSock(m_control_host);
|
auto sock = CreateSock(m_control_host.GetSAFamily());
|
||||||
|
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
throw std::runtime_error("Cannot create socket");
|
throw std::runtime_error("Cannot create socket");
|
||||||
|
|
|
@ -483,15 +483,16 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||||
addr_bind = CAddress{conn.me, NODE_NONE};
|
addr_bind = CAddress{conn.me, NODE_NONE};
|
||||||
}
|
}
|
||||||
} else if (use_proxy) {
|
} else if (use_proxy) {
|
||||||
sock = CreateSock(proxy.proxy);
|
sock = CreateSock(proxy.proxy.GetSAFamily());
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
LogPrintLevel(BCLog::PROXY, BCLog::Level::Debug, "Using proxy: %s to connect to %s:%s\n", proxy.proxy.ToStringAddrPort(), addrConnect.ToStringAddr(), addrConnect.GetPort());
|
||||||
connected = ConnectThroughProxy(proxy, addrConnect.ToStringAddr(), addrConnect.GetPort(),
|
connected = ConnectThroughProxy(proxy, addrConnect.ToStringAddr(), addrConnect.GetPort(),
|
||||||
*sock, nConnectTimeout, proxyConnectionFailed);
|
*sock, nConnectTimeout, proxyConnectionFailed);
|
||||||
} else {
|
} else {
|
||||||
// no proxy needed (none set for target network)
|
// no proxy needed (none set for target network)
|
||||||
sock = CreateSock(addrConnect);
|
sock = CreateSock(addrConnect.GetSAFamily());
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +505,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||||
addrman.Attempt(addrConnect, fCountFailure);
|
addrman.Attempt(addrConnect, fCountFailure);
|
||||||
}
|
}
|
||||||
} else if (pszDest && GetNameProxy(proxy)) {
|
} else if (pszDest && GetNameProxy(proxy)) {
|
||||||
sock = CreateSock(proxy.proxy);
|
sock = CreateSock(proxy.proxy.GetSAFamily());
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -2993,7 +2994,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Sock> sock = CreateSock(addrBind);
|
std::unique_ptr<Sock> sock = CreateSock(addrBind.GetSAFamily());
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
strError = strprintf(Untranslated("Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
|
strError = strprintf(Untranslated("Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
|
||||||
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
|
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
|
||||||
|
|
|
@ -818,6 +818,19 @@ bool CService::SetSockAddr(const struct sockaddr *paddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sa_family_t CService::GetSAFamily() const
|
||||||
|
{
|
||||||
|
switch (m_net) {
|
||||||
|
case NET_IPV4:
|
||||||
|
return AF_INET;
|
||||||
|
case NET_IPV6:
|
||||||
|
case NET_CJDNS:
|
||||||
|
return AF_INET6;
|
||||||
|
default:
|
||||||
|
return AF_UNSPEC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t CService::GetPort() const
|
uint16_t CService::GetPort() const
|
||||||
{
|
{
|
||||||
return port;
|
return port;
|
||||||
|
|
|
@ -540,6 +540,11 @@ public:
|
||||||
uint16_t GetPort() const;
|
uint16_t GetPort() const;
|
||||||
bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
|
bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
|
||||||
bool SetSockAddr(const struct sockaddr* paddr);
|
bool SetSockAddr(const struct sockaddr* paddr);
|
||||||
|
/**
|
||||||
|
* Get the address family
|
||||||
|
* @returns AF_UNSPEC if unspecified
|
||||||
|
*/
|
||||||
|
[[nodiscard]] sa_family_t GetSAFamily() const;
|
||||||
friend bool operator==(const CService& a, const CService& b);
|
friend bool operator==(const CService& a, const CService& b);
|
||||||
friend bool operator!=(const CService& a, const CService& b) { return !(a == b); }
|
friend bool operator!=(const CService& a, const CService& b) { return !(a == b); }
|
||||||
friend bool operator<(const CService& a, const CService& b);
|
friend bool operator<(const CService& a, const CService& b);
|
||||||
|
|
|
@ -444,18 +444,13 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Sock> CreateSockTCP(const CService& address_family)
|
std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family)
|
||||||
{
|
{
|
||||||
// Create a sockaddr from the specified service.
|
// Not IPv4 or IPv6
|
||||||
struct sockaddr_storage sockaddr;
|
if (address_family == AF_UNSPEC) return nullptr;
|
||||||
socklen_t len = sizeof(sockaddr);
|
|
||||||
if (!address_family.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
|
|
||||||
LogPrintf("Cannot create socket for %s: unsupported network\n", address_family.ToStringAddrPort());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a TCP socket in the address family of the specified service.
|
// Create a TCP socket in the address family of the specified service.
|
||||||
SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
|
SOCKET hSocket = socket(address_family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (hSocket == INVALID_SOCKET) {
|
if (hSocket == INVALID_SOCKET) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -493,7 +488,7 @@ std::unique_ptr<Sock> CreateSockTCP(const CService& address_family)
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<std::unique_ptr<Sock>(const CService&)> CreateSock = CreateSockTCP;
|
std::function<std::unique_ptr<Sock>(const sa_family_t&)> CreateSock = CreateSockOS;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
|
static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
|
||||||
|
|
|
@ -229,16 +229,16 @@ CService LookupNumeric(const std::string& name, uint16_t portDefault = 0, DNSLoo
|
||||||
CSubNet LookupSubNet(const std::string& subnet_str);
|
CSubNet LookupSubNet(const std::string& subnet_str);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a TCP socket in the given address family.
|
* Create a socket in the given address family.
|
||||||
* @param[in] address_family The socket is created in the same address family as this address.
|
* @param[in] address_family to use for the socket.
|
||||||
* @return pointer to the created Sock object or unique_ptr that owns nothing in case of failure
|
* @return pointer to the created Sock object or unique_ptr that owns nothing in case of failure
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<Sock> CreateSockTCP(const CService& address_family);
|
std::unique_ptr<Sock> CreateSockOS(sa_family_t address_family);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket factory. Defaults to `CreateSockTCP()`, but can be overridden by unit tests.
|
* Socket factory. Defaults to `CreateSockOS()`, but can be overridden by unit tests.
|
||||||
*/
|
*/
|
||||||
extern std::function<std::unique_ptr<Sock>(const CService&)> CreateSock;
|
extern std::function<std::unique_ptr<Sock>(const sa_family_t&)> CreateSock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to connect to the specified service on the specified socket.
|
* Try to connect to the specified service on the specified socket.
|
||||||
|
|
|
@ -81,7 +81,7 @@ static const TypeTestOneInput* g_test_one_input{nullptr};
|
||||||
void initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
// Terminate immediately if a fuzzing harness ever tries to create a TCP socket.
|
// Terminate immediately if a fuzzing harness ever tries to create a TCP socket.
|
||||||
CreateSock = [](const CService&) -> std::unique_ptr<Sock> { std::terminate(); };
|
CreateSock = [](const sa_family_t&) -> std::unique_ptr<Sock> { std::terminate(); };
|
||||||
|
|
||||||
// Terminate immediately if a fuzzing harness ever tries to perform a DNS lookup.
|
// Terminate immediately if a fuzzing harness ever tries to perform a DNS lookup.
|
||||||
g_dns_lookup = [](const std::string& name, bool allow_lookup) {
|
g_dns_lookup = [](const std::string& name, bool allow_lookup) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const BCLog::Level m_prev_log_level;
|
const BCLog::Level m_prev_log_level;
|
||||||
const std::function<std::unique_ptr<Sock>(const CService&)> m_create_sock_orig;
|
const std::function<std::unique_ptr<Sock>(const sa_family_t&)> m_create_sock_orig;
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(i2p_tests, EnvTestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(i2p_tests, EnvTestingSetup)
|
||||||
|
@ -46,7 +46,7 @@ BOOST_FIXTURE_TEST_SUITE(i2p_tests, EnvTestingSetup)
|
||||||
BOOST_AUTO_TEST_CASE(unlimited_recv)
|
BOOST_AUTO_TEST_CASE(unlimited_recv)
|
||||||
{
|
{
|
||||||
// Mock CreateSock() to create MockSock.
|
// Mock CreateSock() to create MockSock.
|
||||||
CreateSock = [](const CService&) {
|
CreateSock = [](const sa_family_t&) {
|
||||||
return std::make_unique<StaticContentsSock>(std::string(i2p::sam::MAX_MSG_SIZE + 1, 'a'));
|
return std::make_unique<StaticContentsSock>(std::string(i2p::sam::MAX_MSG_SIZE + 1, 'a'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(unlimited_recv)
|
||||||
BOOST_AUTO_TEST_CASE(listen_ok_accept_fail)
|
BOOST_AUTO_TEST_CASE(listen_ok_accept_fail)
|
||||||
{
|
{
|
||||||
size_t num_sockets{0};
|
size_t num_sockets{0};
|
||||||
CreateSock = [&num_sockets](const CService&) {
|
CreateSock = [&num_sockets](const sa_family_t&) {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
++num_sockets;
|
++num_sockets;
|
||||||
// First socket is the control socket for creating the session.
|
// First socket is the control socket for creating the session.
|
||||||
|
@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(damaged_private_key)
|
||||||
{
|
{
|
||||||
const auto CreateSockOrig = CreateSock;
|
const auto CreateSockOrig = CreateSock;
|
||||||
|
|
||||||
CreateSock = [](const CService&) {
|
CreateSock = [](const sa_family_t&) {
|
||||||
return std::make_unique<StaticContentsSock>("HELLO REPLY RESULT=OK VERSION=3.1\n"
|
return std::make_unique<StaticContentsSock>("HELLO REPLY RESULT=OK VERSION=3.1\n"
|
||||||
"SESSION STATUS RESULT=OK DESTINATION=\n");
|
"SESSION STATUS RESULT=OK DESTINATION=\n");
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue