net: add SetSocketNonBlocking() as OS independent wrapper

This commit is contained in:
Philip Kaufmann 2014-07-09 11:00:00 +02:00
parent e8d4cb8071
commit eaedb59e05
3 changed files with 47 additions and 44 deletions

View File

@ -501,14 +501,8 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
addrman.Attempt(addrConnect); addrman.Attempt(addrConnect);
// Set to non-blocking // Set to non-blocking
#ifdef WIN32 if (!SetSocketNonBlocking(hSocket, true))
u_long nOne = 1; LogPrintf("ConnectNode: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
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
// Add node // Add node
CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false); 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)); setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
#endif #endif
#ifdef WIN32
// Set to non-blocking, incoming connections will also inherit this // Set to non-blocking, incoming connections will also inherit this
if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR) if (!SetSocketNonBlocking(hListenSocket, true)) {
#else strError = strprintf("BindListenPort: Setting listening socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
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()));
LogPrintf("%s\n", strError); LogPrintf("%s\n", strError);
return false; return false;
} }

View File

@ -7,10 +7,6 @@
#include "bitcoin-config.h" #include "bitcoin-config.h"
#endif #endif
#ifdef HAVE_GETADDRINFO_A
#include <netdb.h>
#endif
#include "netbase.h" #include "netbase.h"
#include "hash.h" #include "hash.h"
@ -18,6 +14,10 @@
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"
#ifdef HAVE_GETADDRINFO_A
#include <netdb.h>
#endif
#ifndef WIN32 #ifndef WIN32
#if HAVE_INET_PTON #if HAVE_INET_PTON
#include <arpa/inet.h> #include <arpa/inet.h>
@ -331,22 +331,15 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (hSocket == INVALID_SOCKET) if (hSocket == INVALID_SOCKET)
return false; return false;
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
int set = 1; int set = 1;
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
#endif #endif
#ifdef WIN32 // Set to non-blocking
u_long fNonblock = 1; if (!SetSocketNonBlocking(hSocket, true))
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
#else
int fFlags = fcntl(hSocket, F_GETFL, 0);
if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
#endif
{
CloseSocket(hSocket);
return false;
}
if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) 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 // This is required when using SOCKS5 proxy!
// CNode::ConnectNode immediately turns the socket back to non-blocking // CNode::ConnectNode turns the socket back to non-blocking.
// but we'll turn it back to blocking just in case if (!SetSocketNonBlocking(hSocket, false))
#ifdef WIN32 return error("ConnectSocketDirectly: Setting socket to blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
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;
}
hSocketRet = hSocket; hSocketRet = hSocket;
return true; return true;
@ -1271,3 +1254,32 @@ bool CloseSocket(SOCKET& hSocket)
hSocket = INVALID_SOCKET; hSocket = INVALID_SOCKET;
return ret != SOCKET_ERROR; 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;
}

View File

@ -180,5 +180,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
std::string NetworkErrorString(int err); std::string NetworkErrorString(int err);
/** Close socket and set hSocket to INVALID_SOCKET */ /** Close socket and set hSocket to INVALID_SOCKET */
bool CloseSocket(SOCKET& hSocket); bool CloseSocket(SOCKET& hSocket);
/** Disable or enable blocking-mode for a socket */
bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking);
#endif #endif