From eaedb59e0570558a528eac52f7fd89639911496e Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 9 Jul 2014 11:00:00 +0200 Subject: net: add SetSocketNonBlocking() as OS independent wrapper --- src/net.cpp | 19 ++++------------ src/netbase.cpp | 70 +++++++++++++++++++++++++++++++++------------------------ src/netbase.h | 2 ++ 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 441bde3e90..e0f0f14f2b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -501,14 +501,8 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) addrman.Attempt(addrConnect); // Set to non-blocking -#ifdef WIN32 - u_long nOne = 1; - if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) - LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %s\n", NetworkErrorString(WSAGetLastError())); -#else - if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) - LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %s\n", NetworkErrorString(errno)); -#endif + if (!SetSocketNonBlocking(hSocket, true)) + LogPrintf("ConnectNode: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); // Add node CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false); @@ -1642,14 +1636,9 @@ bool BindListenPort(const CService &addrBind, string& strError, bool fWhiteliste setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)); #endif -#ifdef WIN32 // Set to non-blocking, incoming connections will also inherit this - if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR) -#else - if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) -#endif - { - strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError())); + if (!SetSocketNonBlocking(hListenSocket, true)) { + strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); LogPrintf("%s\n", strError); return false; } diff --git a/src/netbase.cpp b/src/netbase.cpp index e9f3515456..af6d11f0e2 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -7,10 +7,6 @@ #include "bitcoin-config.h" #endif -#ifdef HAVE_GETADDRINFO_A -#include -#endif - #include "netbase.h" #include "hash.h" @@ -18,6 +14,10 @@ #include "uint256.h" #include "util.h" +#ifdef HAVE_GETADDRINFO_A +#include +#endif + #ifndef WIN32 #if HAVE_INET_PTON #include @@ -331,22 +331,15 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); if (hSocket == INVALID_SOCKET) return false; + #ifdef SO_NOSIGPIPE int set = 1; setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); #endif -#ifdef WIN32 - u_long fNonblock = 1; - if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) -#else - int fFlags = fcntl(hSocket, F_GETFL, 0); - if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1) -#endif - { - CloseSocket(hSocket); - return false; - } + // Set to non-blocking + if (!SetSocketNonBlocking(hSocket, true)) + return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { @@ -404,20 +397,10 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe } } - // this isn't even strictly necessary - // CNode::ConnectNode immediately turns the socket back to non-blocking - // but we'll turn it back to blocking just in case -#ifdef WIN32 - fNonblock = 0; - if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) -#else - fFlags = fcntl(hSocket, F_GETFL, 0); - if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) -#endif - { - CloseSocket(hSocket); - return false; - } + // This is required when using SOCKS5 proxy! + // CNode::ConnectNode turns the socket back to non-blocking. + if (!SetSocketNonBlocking(hSocket, false)) + return error("ConnectSocketDirectly: Setting socket to blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); hSocketRet = hSocket; return true; @@ -1271,3 +1254,32 @@ bool CloseSocket(SOCKET& hSocket) hSocket = INVALID_SOCKET; return ret != SOCKET_ERROR; } + +bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking) +{ + if (fNonBlocking) { +#ifdef WIN32 + u_long nOne = 1; + if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) { +#else + int fFlags = fcntl(hSocket, F_GETFL, 0); + if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) { +#endif + CloseSocket(hSocket); + return false; + } + } else { +#ifdef WIN32 + u_long nZero = 0; + if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) { +#else + int fFlags = fcntl(hSocket, F_GETFL, 0); + if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) { +#endif + CloseSocket(hSocket); + return false; + } + } + + return true; +} diff --git a/src/netbase.h b/src/netbase.h index 05221a5fde..7d83e35344 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -180,5 +180,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest std::string NetworkErrorString(int err); /** Close socket and set hSocket to INVALID_SOCKET */ bool CloseSocket(SOCKET& hSocket); +/** Disable or enable blocking-mode for a socket */ +bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking); #endif -- cgit v1.2.3