From 3d01d1daf3cbe21f17e64e19ff9f0949b6562b70 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@41a61cd8-c433-0410-bb1c-e256eeef9e11> Date: Tue, 27 Nov 2007 08:44:22 +0000 Subject: [PATCH] r1355@opsdev009 (orig r71477): mcslee | 2007-11-27 00:42:19 -0800 IPv6 tweaks for Thrift Summary: Need to pass hints including AI_ADDRCONFIG to getaddrinfo to make sure no IPv6 addresses come back on non-IPv6 enabled systems Reviewed By: mcslee Other Notes: Submitted by Paul Saab git-svn-id: http://svn.facebook.com/svnroot/thrift/trunk@696 41a61cd8-c433-0410-bb1c-e256eeef9e11 --- lib/cpp/src/server/TNonblockingServer.cpp | 2 +- lib/cpp/src/transport/TServerSocket.cpp | 22 ++++++------- lib/cpp/src/transport/TSocket.cpp | 54 +++++++++++++++---------------- lib/py/src/transport/TSocket.py | 6 ++-- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/lib/cpp/src/server/TNonblockingServer.cpp b/lib/cpp/src/server/TNonblockingServer.cpp index ad1fb65..7735ec2 100644 --- a/lib/cpp/src/server/TNonblockingServer.cpp +++ b/lib/cpp/src/server/TNonblockingServer.cpp @@ -557,7 +557,7 @@ void TNonblockingServer::listenSocket() { memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; sprintf(port, "%d", port_); // Wildcard address diff --git a/lib/cpp/src/transport/TServerSocket.cpp b/lib/cpp/src/transport/TServerSocket.cpp index ed86000..69d35bf 100644 --- a/lib/cpp/src/transport/TServerSocket.cpp +++ b/lib/cpp/src/transport/TServerSocket.cpp @@ -17,7 +17,7 @@ #include "TServerSocket.h" #include -namespace facebook { namespace thrift { namespace transport { +namespace facebook { namespace thrift { namespace transport { using namespace std; using boost::shared_ptr; @@ -81,7 +81,7 @@ void TServerSocket::listen() { memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; sprintf(port, "%d", port_); // Wildcard address @@ -98,7 +98,7 @@ void TServerSocket::listen() { if (res->ai_family == AF_INET6 || res->ai_next == NULL) break; } - + serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (serverSocket_ == -1) { GlobalOutput("TServerSocket::listen() socket"); @@ -153,7 +153,7 @@ void TServerSocket::listen() { } // prepare the port information - // we may want to try to bind more than once, since SO_REUSEADDR doesn't + // we may want to try to bind more than once, since SO_REUSEADDR doesn't // always seem to work. The client can configure the retry variables. int retries = 0; do { @@ -166,7 +166,7 @@ void TServerSocket::listen() { // free addrinfo freeaddrinfo(res0); - + // throw an error if we failed to bind properly if (retries > retryLimit_) { char errbuf[1024]; @@ -207,7 +207,7 @@ shared_ptr TServerSocket::acceptImpl() { if (ret < 0) { // error cases if (errno == EINTR && (numEintrs++ < maxEintrs)) { - // EINTR needs to be handled manually and we can tolerate + // EINTR needs to be handled manually and we can tolerate // a certain number continue; } @@ -215,7 +215,7 @@ shared_ptr TServerSocket::acceptImpl() { throw TTransportException(TTransportException::UNKNOWN); } else if (ret > 0) { // Check for an interrupt signal - if (intSock2_ >= 0 && FD_ISSET(intSock2_, &fds)) { + if (intSock2_ >= 0 && FD_ISSET(intSock2_, &fds)) { int8_t buf; if (-1 == recv(intSock2_, &buf, sizeof(int8_t), 0)) { GlobalOutput("TServerSocket::acceptImpl() interrupt receive"); @@ -228,7 +228,7 @@ shared_ptr TServerSocket::acceptImpl() { } } else { GlobalOutput("TServerSocket::acceptImpl() select 0"); - throw TTransportException(TTransportException::UNKNOWN); + throw TTransportException(TTransportException::UNKNOWN); } } @@ -237,7 +237,7 @@ shared_ptr TServerSocket::acceptImpl() { int clientSocket = ::accept(serverSocket_, (struct sockaddr *) &clientAddress, (socklen_t *) &size); - + if (clientSocket < 0) { int errno_copy = errno; GlobalOutput("TServerSocket::accept()"); @@ -256,7 +256,7 @@ shared_ptr TServerSocket::acceptImpl() { GlobalOutput("TServerSocket::select() fcntl SETFL"); throw TTransportException(TTransportException::UNKNOWN, "fcntl(F_SETFL)", errno_copy); } - + shared_ptr client(new TSocket(clientSocket)); if (sendTimeout_ > 0) { client->setSendTimeout(sendTimeout_); @@ -264,7 +264,7 @@ shared_ptr TServerSocket::acceptImpl() { if (recvTimeout_ > 0) { client->setRecvTimeout(recvTimeout_); } - + return client; } diff --git a/lib/cpp/src/transport/TSocket.cpp b/lib/cpp/src/transport/TSocket.cpp index 7da6d37..acf5288 100644 --- a/lib/cpp/src/transport/TSocket.cpp +++ b/lib/cpp/src/transport/TSocket.cpp @@ -20,7 +20,7 @@ #include "TSocket.h" #include "TTransportException.h" -namespace facebook { namespace thrift { namespace transport { +namespace facebook { namespace thrift { namespace transport { using namespace std; using namespace facebook::thrift::concurrency; @@ -37,7 +37,7 @@ uint32_t g_socket_syscalls = 0; // Mutex to protect syscalls to netdb static Monitor s_netdb_monitor; -TSocket::TSocket(string host, int port) : +TSocket::TSocket(string host, int port) : host_(host), port_(port), socket_(-1), @@ -52,7 +52,7 @@ TSocket::TSocket(string host, int port) : recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000); } -TSocket::TSocket() : +TSocket::TSocket() : host_(""), port_(0), socket_(-1), @@ -81,13 +81,13 @@ TSocket::TSocket(int socket) : recvTimeval_.tv_sec = (int)(recvTimeout_/1000); recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000); } - + TSocket::~TSocket() { close(); } -bool TSocket::isOpen() { - return (socket_ >= 0); +bool TSocket::isOpen() { + return (socket_ >= 0); } bool TSocket::peek() { @@ -135,7 +135,7 @@ void TSocket::openConnection(struct addrinfo *res) { setNoDelay(noDelay_); // Set the socket to be non blocking for connect if a timeout exists - int flags = fcntl(socket_, F_GETFL, 0); + int flags = fcntl(socket_, F_GETFL, 0); if (connTimeout_ > 0) { if (-1 == fcntl(socket_, F_SETFL, flags | O_NONBLOCK)) { throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed"); @@ -149,10 +149,10 @@ void TSocket::openConnection(struct addrinfo *res) { // Conn timeout struct timeval c = {(int)(connTimeout_/1000), (int)((connTimeout_%1000)*1000)}; - + // Connect the socket int ret = connect(socket_, res->ai_addr, res->ai_addrlen); - + if (ret == 0) { goto done; } @@ -221,9 +221,9 @@ void TSocket::open() { memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; sprintf(port, "%d", port_); - + { // Scope lock on host entry lookup Synchronized s(s_netdb_monitor); @@ -234,7 +234,7 @@ void TSocket::open() { close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for client socket."); } - + // Cycle through all the returned addresses until one // connects or push the exception up. for (res = res0; res; res = res->ai_next) { @@ -277,13 +277,13 @@ uint32_t TSocket::read(uint8_t* buf, uint32_t len) { // EAGAIN is taken to indicate an out of resources error. uint32_t eagainThresholdMicros = 0; if (recvTimeout_) { - // if a readTimeout is specified along with a max number of recv retries, then + // if a readTimeout is specified along with a max number of recv retries, then // the threshold will ensure that the read timeout is not exceeded even in the // case of resource errors eagainThresholdMicros = (recvTimeout_*1000)/ ((maxRecvRetries_>0) ? maxRecvRetries_ : 2); } - try_again: + try_again: // Read from the socket struct timeval begin; gettimeofday(&begin, NULL); @@ -295,7 +295,7 @@ uint32_t TSocket::read(uint8_t* buf, uint32_t len) { ++g_socket_syscalls; // Check for error on read - if (got < 0) { + if (got < 0) { if (errno == EAGAIN) { // check if this is the lack of resources or timeout case if (!eagainThresholdMicros || (readElapsedMicros < eagainThresholdMicros)) { @@ -303,21 +303,21 @@ uint32_t TSocket::read(uint8_t* buf, uint32_t len) { usleep(50); goto try_again; } else { - throw TTransportException(TTransportException::TIMED_OUT, + throw TTransportException(TTransportException::TIMED_OUT, "EAGAIN (unavailable resources)"); } } else { // infer that timeout has been hit - throw TTransportException(TTransportException::TIMED_OUT, + throw TTransportException(TTransportException::TIMED_OUT, "EAGAIN (timed out)"); } } - + // If interrupted, try again if (errno == EINTR && retries++ < maxRecvRetries_) { goto try_again; } - + // Now it's not a try again case, but a real probblez string errStr = "TSocket::read() " + getSocketInfo(); GlobalOutput(errStr.c_str()); @@ -326,29 +326,29 @@ uint32_t TSocket::read(uint8_t* buf, uint32_t len) { if (errno == ECONNRESET) { throw TTransportException(TTransportException::NOT_OPEN, "ECONNRESET"); } - + // This ish isn't open if (errno == ENOTCONN) { throw TTransportException(TTransportException::NOT_OPEN, "ENOTCONN"); } - + // Timed out! if (errno == ETIMEDOUT) { throw TTransportException(TTransportException::TIMED_OUT, "ETIMEDOUT"); } - + // Some other error, whatevz char buff[1024]; sprintf(buff, "ERROR errno: %d", errno); throw TTransportException(TTransportException::UNKNOWN, buff); } - + // The remote host has closed the socket if (got == 0) { close(); return 0; } - + // Pack data into string return got; } @@ -359,7 +359,7 @@ void TSocket::write(const uint8_t* buf, uint32_t len) { } uint32_t sent = 0; - + while (sent < len) { int flags = 0; @@ -385,7 +385,7 @@ void TSocket::write(const uint8_t* buf, uint32_t len) { GlobalOutput(errStr.c_str()); throw TTransportException(TTransportException::UNKNOWN, "send", errno_copy); } - + // Fail on blocked send if (b == 0) { throw TTransportException(TTransportException::NOT_OPEN, "Socket send returned 0."); @@ -466,7 +466,7 @@ void TSocket::setSendTimeout(int ms) { if (socket_ < 0) { return; } - + struct timeval s = {(int)(sendTimeout_/1000), (int)((sendTimeout_%1000)*1000)}; int ret = setsockopt(socket_, SOL_SOCKET, SO_SNDTIMEO, &s, sizeof(s)); diff --git a/lib/py/src/transport/TSocket.py b/lib/py/src/transport/TSocket.py index b2e08a1..0b44344 100644 --- a/lib/py/src/transport/TSocket.py +++ b/lib/py/src/transport/TSocket.py @@ -32,7 +32,7 @@ class TSocket(TTransportBase): def open(self): try: - res0 = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM) + res0 = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE | socket.AI_ADDRCONFIG) for res in res0: self.handle = socket.socket(res[0], res[1]) try: @@ -77,9 +77,9 @@ class TServerSocket(TServerTransportBase): def __init__(self, port): self.port = port self.handle = None - + def listen(self): - res0 = socket.getaddrinfo(None, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) + res0 = socket.getaddrinfo(None, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE | socket.AI_ADDRCONFIG) for res in res0: if res[0] is socket.AF_INET6 or res is res0[-1]: break -- 2.11.4.GIT