@ -2045,6 +2045,40 @@ static bool socks4_negotiate(struct pool *pool, int sockd, bool socks4a)
return true ;
return true ;
}
}
static void noblock_socket ( SOCKETTYPE fd )
{
# ifndef WIN32
int flags = fcntl ( fd , F_GETFL , 0 ) ;
fcntl ( fd , F_SETFL , O_NONBLOCK | flags ) ;
# else
u_long flags = 1 ;
ioctlsocket ( fd , FIONBIO , & flags ) ;
# endif
}
static void block_socket ( SOCKETTYPE fd )
{
# ifndef WIN32
int flags = fcntl ( fd , F_GETFL , 0 ) ;
fcntl ( fd , F_SETFL , flags & ~ O_NONBLOCK ) ;
# else
u_long flags = 0 ;
ioctlsocket ( fd , FIONBIO , & flags ) ;
# endif
}
static bool sock_connecting ( void )
{
# ifndef WIN32
return errno = = EINPROGRESS ;
# else
return WSAGetLastError ( ) = = WSAEWOULDBLOCK ;
# endif
}
static bool setup_stratum_socket ( struct pool * pool )
static bool setup_stratum_socket ( struct pool * pool )
{
{
struct addrinfo servinfobase , * servinfo , * hints , * p ;
struct addrinfo servinfobase , * servinfo , * hints , * p ;
@ -2096,11 +2130,41 @@ static bool setup_stratum_socket(struct pool *pool)
continue ;
continue ;
}
}
/* Iterate non blocking over entries returned by getaddrinfo
* to cope with round robin DNS entries , finding the first one
* we can connect to quickly . */
noblock_socket ( sockd ) ;
if ( connect ( sockd , p - > ai_addr , p - > ai_addrlen ) = = - 1 ) {
if ( connect ( sockd , p - > ai_addr , p - > ai_addrlen ) = = - 1 ) {
struct timeval tv_timeout = { 1 , 0 } ;
int selret ;
fd_set rw ;
if ( ! sock_connecting ( ) ) {
CLOSESOCKET ( sockd ) ;
applog ( LOG_DEBUG , " Failed sock connect " ) ;
continue ;
}
FD_ZERO ( & rw ) ;
FD_SET ( sockd , & rw ) ;
selret = select ( sockd + 1 , NULL , & rw , NULL , & tv_timeout ) ;
if ( selret > 0 & & FD_ISSET ( sockd , & rw ) ) {
socklen_t len ;
int err , n ;
len = sizeof ( err ) ;
n = getsockopt ( sockd , SOL_SOCKET , SO_ERROR , ( void * ) & err , & len ) ;
if ( ! n & & ! err ) {
applog ( LOG_DEBUG , " Succeeded delayed connect " ) ;
block_socket ( sockd ) ;
break ;
}
}
CLOSESOCKET ( sockd ) ;
CLOSESOCKET ( sockd ) ;
applog ( LOG_DEBUG , " Failed connect " ) ;
applog ( LOG_DEBUG , " Select timeout/f ailed connect" ) ;
continue ;
continue ;
}
}
applog ( LOG_WARNING , " Succeeded immediate connect " ) ;
block_socket ( sockd ) ;
break ;
break ;
}
}