non blocking dns lookup
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "IXSocketConnect.h"
|
||||
#include "IXDNSLookup.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <basetsd.h>
|
||||
@ -47,10 +48,15 @@ namespace
|
||||
|
||||
namespace ix
|
||||
{
|
||||
//
|
||||
// This function can be cancelled every 50 ms
|
||||
// This is important so that we don't block the main UI thread when shutting down a connection which is
|
||||
// already trying to reconnect, and can be blocked waiting for ::connect to respond.
|
||||
//
|
||||
bool SocketConnect::connectToAddress(const struct addrinfo *address,
|
||||
int& sockfd,
|
||||
std::string& errMsg,
|
||||
CancellationRequest isCancellationRequested)
|
||||
const CancellationRequest& isCancellationRequested)
|
||||
{
|
||||
sockfd = -1;
|
||||
|
||||
@ -64,20 +70,17 @@ namespace ix
|
||||
}
|
||||
|
||||
// Set the socket to non blocking mode, so that slow responses cannot
|
||||
// block us for too long while we are trying to shut-down.
|
||||
// block us for too long
|
||||
SocketConnect::configure(fd);
|
||||
|
||||
if (::connect(fd, address->ai_addr, address->ai_addrlen) == -1
|
||||
&& errno != EINPROGRESS)
|
||||
{
|
||||
closeSocket(fd);
|
||||
sockfd = -1;
|
||||
errMsg = strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
// std::cout << "I WAS HERE A" << std::endl;
|
||||
|
||||
//
|
||||
// If during a connection attempt the request remains idle for longer
|
||||
// than the timeout interval, the request is considered to have timed
|
||||
@ -95,7 +98,6 @@ namespace ix
|
||||
if (isCancellationRequested())
|
||||
{
|
||||
closeSocket(fd);
|
||||
sockfd = -1;
|
||||
errMsg = "Cancelled";
|
||||
return false;
|
||||
}
|
||||
@ -115,7 +117,7 @@ namespace ix
|
||||
if (!FD_ISSET(fd, &wfds)) continue;
|
||||
|
||||
// Something was written to the socket
|
||||
int optval;
|
||||
int optval = -1;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
|
||||
// getsockopt() puts the errno value for connect into optval so 0
|
||||
@ -124,7 +126,6 @@ namespace ix
|
||||
optval != 0)
|
||||
{
|
||||
closeSocket(fd);
|
||||
sockfd = -1;
|
||||
errMsg = strerror(optval);
|
||||
return false;
|
||||
}
|
||||
@ -137,33 +138,22 @@ namespace ix
|
||||
}
|
||||
|
||||
closeSocket(fd);
|
||||
sockfd = -1;
|
||||
errMsg = strerror(errno);
|
||||
errMsg = "connect timed out after 60 seconds";
|
||||
return false;
|
||||
}
|
||||
|
||||
int SocketConnect::connect(const std::string& hostname,
|
||||
int port,
|
||||
std::string& errMsg,
|
||||
CancellationRequest isCancellationRequested)
|
||||
const CancellationRequest& isCancellationRequested)
|
||||
{
|
||||
//
|
||||
// First do DNS resolution
|
||||
//
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
std::string sport = std::to_string(port);
|
||||
|
||||
struct addrinfo *res = nullptr;
|
||||
int getaddrinfo_result = getaddrinfo(hostname.c_str(), sport.c_str(),
|
||||
&hints, &res);
|
||||
if (getaddrinfo_result)
|
||||
DNSLookup dnsLookup(hostname, port);
|
||||
struct addrinfo *res = dnsLookup.resolve(errMsg, isCancellationRequested);
|
||||
if (res == nullptr)
|
||||
{
|
||||
errMsg = gai_strerror(getaddrinfo_result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -183,15 +173,18 @@ namespace ix
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void SocketConnect::configure(int sockfd)
|
||||
{
|
||||
// 1. disable Nagle's algorithm
|
||||
int flag = 1;
|
||||
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(flag)); // Disable Nagle's algorithm
|
||||
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(flag));
|
||||
|
||||
// 2. make socket non blocking
|
||||
#ifdef _WIN32
|
||||
unsigned long nonblocking = 1;
|
||||
ioctlsocket(_sockfd, FIONBIO, &nonblocking);
|
||||
@ -199,6 +192,7 @@ namespace ix
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK); // make socket non blocking
|
||||
#endif
|
||||
|
||||
// 3. (apple) prevent SIGPIPE from being emitted when the remote end disconnect
|
||||
#ifdef SO_NOSIGPIPE
|
||||
int value = 1;
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE,
|
||||
|
Reference in New Issue
Block a user