Support IPv6 connections

fix #2522
This commit is contained in:
Florent Le Coz
2014-05-27 01:06:45 +02:00
parent 5507adbe94
commit 23e8e32f84
2 changed files with 18 additions and 7 deletions
+15 -5
View File
@@ -28,12 +28,11 @@ SocketHandler::SocketHandler(std::shared_ptr<Poller> poller):
connected(false), connected(false),
connecting(false) connecting(false)
{ {
this->init_socket();
} }
void SocketHandler::init_socket() void SocketHandler::init_socket(const struct addrinfo* rp)
{ {
if ((this->socket = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) if ((this->socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1)
throw std::runtime_error("Could not create socket"); throw std::runtime_error("Could not create socket");
int optval = 1; int optval = 1;
if (::setsockopt(this->socket, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) if (::setsockopt(this->socket, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1)
@@ -64,7 +63,7 @@ void SocketHandler::connect(const std::string& address, const std::string& port)
struct addrinfo hints; struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo)); memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = 0; hints.ai_flags = 0;
hints.ai_family = AF_INET; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0; hints.ai_protocol = 0;
@@ -99,10 +98,19 @@ void SocketHandler::connect(const std::string& address, const std::string& port)
addr_res->ai_addr = &this->ai_addr; addr_res->ai_addr = &this->ai_addr;
addr_res->ai_addrlen = this->ai_addrlen; addr_res->ai_addrlen = this->ai_addrlen;
} }
this->connecting = true;
for (struct addrinfo* rp = addr_res; rp; rp = rp->ai_next) for (struct addrinfo* rp = addr_res; rp; rp = rp->ai_next)
{ {
if (!this->connecting)
{
try {
this->init_socket(rp);
}
catch (const std::runtime_error& error) {
log_error("Failed to init socket: " << error.what());
break;
}
}
if (::connect(this->socket, rp->ai_addr, rp->ai_addrlen) == 0 if (::connect(this->socket, rp->ai_addr, rp->ai_addrlen) == 0
|| errno == EISCONN) || errno == EISCONN)
{ {
@@ -116,6 +124,8 @@ void SocketHandler::connect(const std::string& address, const std::string& port)
else if (errno == EINPROGRESS || errno == EALREADY) else if (errno == EINPROGRESS || errno == EALREADY)
{ // retry this process later, when the socket { // retry this process later, when the socket
// is ready to be written on. // is ready to be written on.
this->connecting = true;
this->poller->add_socket_handler(this);
this->poller->watch_send_events(this); this->poller->watch_send_events(this);
// Save the addrinfo structure, to use it on the next call // Save the addrinfo structure, to use it on the next call
this->ai_addrlen = rp->ai_addrlen; this->ai_addrlen = rp->ai_addrlen;
+3 -2
View File
@@ -26,9 +26,10 @@ public:
explicit SocketHandler(std::shared_ptr<Poller> poller); explicit SocketHandler(std::shared_ptr<Poller> poller);
virtual ~SocketHandler() {} virtual ~SocketHandler() {}
/** /**
* (re-)Initialize the socket * Initialize the socket with the parameters contained in the given
* addrinfo structure.
*/ */
void init_socket(); void init_socket(const struct addrinfo* rp);
/** /**
* Connect to the remote server, and call on_connected() if this succeeds * Connect to the remote server, and call on_connected() if this succeeds
*/ */