mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
net: change ConnectSocketDirectly() to take a Sock argument
Change `ConnectSocketDirectly()` to take a `Sock` argument instead of a bare `SOCKET`. With this, use the `Sock`'s (possibly mocked) methods `Connect()`, `Wait()` and `GetSockOpt()` instead of calling the OS functions directly.
This commit is contained in:
parent
b5861100f8
commit
82d360b5a8
4 changed files with 27 additions and 40 deletions
|
@ -279,7 +279,7 @@ Sock Session::Hello() const
|
||||||
throw std::runtime_error("Cannot create socket");
|
throw std::runtime_error("Cannot create socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ConnectSocketDirectly(m_control_host, sock->Get(), nConnectTimeout, true)) {
|
if (!ConnectSocketDirectly(m_control_host, *sock, nConnectTimeout, true)) {
|
||||||
throw std::runtime_error(strprintf("Cannot connect to %s", m_control_host.ToString()));
|
throw std::runtime_error(strprintf("Cannot connect to %s", m_control_host.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -448,7 +448,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
connected = ConnectSocketDirectly(addrConnect, sock->Get(), nConnectTimeout,
|
connected = ConnectSocketDirectly(addrConnect, *sock, nConnectTimeout,
|
||||||
conn_type == ConnectionType::MANUAL);
|
conn_type == ConnectionType::MANUAL);
|
||||||
}
|
}
|
||||||
if (!proxyConnectionFailed) {
|
if (!proxyConnectionFailed) {
|
||||||
|
|
|
@ -537,12 +537,12 @@ static void LogConnectFailure(bool manual_connection, const char* fmt, const Arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection)
|
bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nTimeout, bool manual_connection)
|
||||||
{
|
{
|
||||||
// Create a sockaddr from the specified service.
|
// Create a sockaddr from the specified service.
|
||||||
struct sockaddr_storage sockaddr;
|
struct sockaddr_storage sockaddr;
|
||||||
socklen_t len = sizeof(sockaddr);
|
socklen_t len = sizeof(sockaddr);
|
||||||
if (hSocket == INVALID_SOCKET) {
|
if (sock.Get() == INVALID_SOCKET) {
|
||||||
LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
|
LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -552,8 +552,7 @@ bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to the addrConnect service on the hSocket socket.
|
// Connect to the addrConnect service on the hSocket socket.
|
||||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
|
if (sock.Connect(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {
|
||||||
{
|
|
||||||
int nErr = WSAGetLastError();
|
int nErr = WSAGetLastError();
|
||||||
// WSAEINVAL is here because some legacy version of winsock uses it
|
// WSAEINVAL is here because some legacy version of winsock uses it
|
||||||
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
|
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
|
||||||
|
@ -561,46 +560,34 @@ bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, i
|
||||||
// Connection didn't actually fail, but is being established
|
// Connection didn't actually fail, but is being established
|
||||||
// asynchronously. Thus, use async I/O api (select/poll)
|
// asynchronously. Thus, use async I/O api (select/poll)
|
||||||
// synchronously to check for successful connection with a timeout.
|
// synchronously to check for successful connection with a timeout.
|
||||||
#ifdef USE_POLL
|
const Sock::Event requested = Sock::RECV | Sock::SEND;
|
||||||
struct pollfd pollfd = {};
|
Sock::Event occurred;
|
||||||
pollfd.fd = hSocket;
|
if (!sock.Wait(std::chrono::milliseconds{nTimeout}, requested, &occurred)) {
|
||||||
pollfd.events = POLLIN | POLLOUT;
|
LogPrintf("wait for connect to %s failed: %s\n",
|
||||||
int nRet = poll(&pollfd, 1, nTimeout);
|
addrConnect.ToString(),
|
||||||
#else
|
NetworkErrorString(WSAGetLastError()));
|
||||||
struct timeval timeout = MillisToTimeval(nTimeout);
|
|
||||||
fd_set fdset;
|
|
||||||
FD_ZERO(&fdset);
|
|
||||||
FD_SET(hSocket, &fdset);
|
|
||||||
int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
|
|
||||||
#endif
|
|
||||||
// Upon successful completion, both select and poll return the total
|
|
||||||
// number of file descriptors that have been selected. A value of 0
|
|
||||||
// indicates that the call timed out and no file descriptors have
|
|
||||||
// been selected.
|
|
||||||
if (nRet == 0)
|
|
||||||
{
|
|
||||||
LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (occurred == 0) {
|
||||||
if (nRet == SOCKET_ERROR)
|
LogPrint(BCLog::NET, "connection attempt to %s timed out\n", addrConnect.ToString());
|
||||||
{
|
|
||||||
LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even if the select/poll was successful, the connect might not
|
// Even if the wait was successful, the connect might not
|
||||||
// have been successful. The reason for this failure is hidden away
|
// have been successful. The reason for this failure is hidden away
|
||||||
// in the SO_ERROR for the socket in modern systems. We read it into
|
// in the SO_ERROR for the socket in modern systems. We read it into
|
||||||
// nRet here.
|
// sockerr here.
|
||||||
socklen_t nRetSize = sizeof(nRet);
|
int sockerr;
|
||||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&nRet, &nRetSize) == SOCKET_ERROR)
|
socklen_t sockerr_len = sizeof(sockerr);
|
||||||
{
|
if (sock.GetSockOpt(SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&sockerr, &sockerr_len) ==
|
||||||
|
SOCKET_ERROR) {
|
||||||
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nRet != 0)
|
if (sockerr != 0) {
|
||||||
{
|
LogConnectFailure(manual_connection,
|
||||||
LogConnectFailure(manual_connection, "connect() to %s failed after select(): %s", addrConnect.ToString(), NetworkErrorString(nRet));
|
"connect() to %s failed after wait: %s",
|
||||||
|
addrConnect.ToString(),
|
||||||
|
NetworkErrorString(sockerr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,7 +655,7 @@ bool IsProxy(const CNetAddr &addr) {
|
||||||
bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed)
|
bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, int port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed)
|
||||||
{
|
{
|
||||||
// first connect to proxy server
|
// first connect to proxy server
|
||||||
if (!ConnectSocketDirectly(proxy.proxy, sock.Get(), nTimeout, true)) {
|
if (!ConnectSocketDirectly(proxy.proxy, sock, nTimeout, true)) {
|
||||||
outProxyConnectionFailed = true;
|
outProxyConnectionFailed = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ extern std::function<std::unique_ptr<Sock>(const CService&)> CreateSock;
|
||||||
* Try to connect to the specified service on the specified socket.
|
* Try to connect to the specified service on the specified socket.
|
||||||
*
|
*
|
||||||
* @param addrConnect The service to which to connect.
|
* @param addrConnect The service to which to connect.
|
||||||
* @param hSocket The socket on which to connect.
|
* @param sock The socket on which to connect.
|
||||||
* @param nTimeout Wait this many milliseconds for the connection to be
|
* @param nTimeout Wait this many milliseconds for the connection to be
|
||||||
* established.
|
* established.
|
||||||
* @param manual_connection Whether or not the connection was manually requested
|
* @param manual_connection Whether or not the connection was manually requested
|
||||||
|
@ -202,7 +202,7 @@ extern std::function<std::unique_ptr<Sock>(const CService&)> CreateSock;
|
||||||
*
|
*
|
||||||
* @returns Whether or not a connection was successfully made.
|
* @returns Whether or not a connection was successfully made.
|
||||||
*/
|
*/
|
||||||
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection);
|
bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nTimeout, bool manual_connection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a specified destination service through a SOCKS5 proxy by first
|
* Connect to a specified destination service through a SOCKS5 proxy by first
|
||||||
|
|
Loading…
Add table
Reference in a new issue