diff -up vnc-4_1_2-unixsrc/common/network/Makefile.am.ipv6 vnc-4_1_2-unixsrc/common/network/Makefile.am --- vnc-4_1_2-unixsrc/common/network/Makefile.am.ipv6 2008-06-02 10:22:17.000000000 +0200 +++ vnc-4_1_2-unixsrc/common/network/Makefile.am 2008-06-02 10:52:56.000000000 +0200 @@ -1,5 +1,7 @@ noinst_LTLIBRARIES = libnetwork.la +libnetwork_la_CPPFLAGS = -DHAVE_GETADDRINFO + libnetwork_la_SOURCES = \ Socket.h \ TcpSocket.cxx \ diff -up vnc-4_1_2-unixsrc/common/network/TcpSocket.cxx.ipv6 vnc-4_1_2-unixsrc/common/network/TcpSocket.cxx --- vnc-4_1_2-unixsrc/common/network/TcpSocket.cxx.ipv6 2008-06-02 10:22:17.000000000 +0200 +++ vnc-4_1_2-unixsrc/common/network/TcpSocket.cxx 2008-06-02 10:49:04.000000000 +0200 @@ -109,50 +109,99 @@ TcpSocket::TcpSocket(int sock, bool clos TcpSocket::TcpSocket(const char *host, int port) : closeFd(true) { - int sock; +#define CAST_ADDR(x) (*((struct x *)&addr)) + int sock, err, family, result = -1; + size_t addrlen; + struct sockaddr_storage addr; +#ifdef HAVE_GETADDRINFO + struct addrinfo *ai, *current, hints; +#endif // - Create a socket initSockets(); - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) - throw SocketException("unable to create socket", errorNumber); -#ifndef WIN32 - // - By default, close the socket on exec() - fcntl(sock, F_SETFD, FD_CLOEXEC); -#endif +#ifdef HAVE_GETADDRINFO + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + if ((result = getaddrinfo(host, NULL, &hints, &ai)) != 0) { + throw Exception("unable to resolve host by name: %s", + gai_strerror(result)); + } + + for (current = ai; current != NULL; current = current->ai_next) { + family = current->ai_family; + if (family != AF_INET && family != AF_INET6) + continue; + + addrlen = current->ai_addrlen; + memcpy(&addr, current->ai_addr, addrlen); + + if (family == AF_INET) + CAST_ADDR(sockaddr_in).sin_port = htons(port); + else + CAST_ADDR(sockaddr_in6).sin6_port = htons(port); - // - Connect it to something +#else + family = AF_INET; + addrlen = sizeof(struct sockaddr_in); - // Try processing the host as an IP address - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(host); - addr.sin_port = htons(port); - if ((int)addr.sin_addr.s_addr == -1) { - // Host was not an IP address - try resolving as DNS name - struct hostent *hostinfo; - hostinfo = gethostbyname(host); - if (hostinfo && hostinfo->h_addr) { - addr.sin_addr.s_addr = ((struct in_addr *)hostinfo->h_addr)->s_addr; - } else { - int e = errorNumber; - closesocket(sock); - throw SocketException("unable to resolve host by name", e); + // Try processing the host as an IP address + memset(&addr, 0, addrlen); + CAST_ADDR(sockaddr_in).sin_family = AF_INET; + CAST_ADDR(sockaddr_in).sin_addr.s_addr = inet_addr(host); + CAST_ADDR(sockaddr_in).sin_port = htons(port); + if ((int)CAST_ADDR(sockaddr_in).sin_addr.s_addr == -1) { + // Host was not an IP address - try resolving as DNS name + struct hostent *hostinfo; + hostinfo = gethostbyname(host); + if (hostinfo && hostinfo->h_addr) { + CAST_ADDR(sockaddr_in).sin_addr.s_addr = + ((struct in_addr *)hostinfo->h_addr)->s_addr; + } else { + err = errorNumber; + throw SocketException("unable to resolve host by name", err); + } + } +#endif + sock = socket (family, SOCK_STREAM, 0); + if (sock == -1) { + err = errorNumber; +#ifdef HAVE_GETADDRINFO + freeaddrinfo(ai); +#endif + throw SocketException("unable to create socket", err); } - } - // Attempt to connect to the remote host - for (;;) { - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { - int e = errorNumber; - if (e == EINTR) - continue; + // Attempt to connect to the remote host + while ((result = connect(sock, (struct sockaddr *)&addr, addrlen)) == -1) { + err = errorNumber; + if (err == EINTR) + continue; closesocket(sock); - throw SocketException("unable to connect to host", e); - } else break; + break; + } +#ifdef HAVE_GETADDRINFO + if (result == 0) + break; + else + continue; } + freeaddrinfo(ai); +#endif + if (result == -1) + throw SocketException("unable connect to socket", err); + +#ifndef WIN32 + // - By default, close the socket on exec() + fcntl(sock, F_SETFD, FD_CLOEXEC); +#endif + // Disable Nagle's algorithm, to reduce latency enableNagles(sock, false); diff -up vnc-4_1_2-unixsrc/common/rdr/Exception.cxx.ipv6 vnc-4_1_2-unixsrc/common/rdr/Exception.cxx --- vnc-4_1_2-unixsrc/common/rdr/Exception.cxx.ipv6 2008-06-02 10:23:35.000000000 +0200 +++ vnc-4_1_2-unixsrc/common/rdr/Exception.cxx 2008-06-02 10:28:51.000000000 +0200 @@ -22,8 +22,23 @@ #include #endif +#include + using namespace rdr; +Exception::Exception(const char *format, ...) { + va_list ap; + int result; + + va_start(ap, format); + result = vsnprintf(str_, len, format, ap); + va_end(ap); + + /* XXX - ensure that string ends correctly */ + if (result > len) + str_[len - 1] = '\0'; +} + SystemException::SystemException(const char* s, int err_) : Exception(s), err(err_) { diff -up vnc-4_1_2-unixsrc/common/rdr/Exception.h.ipv6 vnc-4_1_2-unixsrc/common/rdr/Exception.h --- vnc-4_1_2-unixsrc/common/rdr/Exception.h.ipv6 2008-06-02 10:23:05.000000000 +0200 +++ vnc-4_1_2-unixsrc/common/rdr/Exception.h 2008-06-02 10:28:41.000000000 +0200 @@ -27,13 +27,7 @@ namespace rdr { struct Exception { enum { len = 256 }; char str_[len]; - Exception(const char* s=0) { - str_[0] = 0; - if (s) - strncat(str_, s, len-1); - else - strcat(str_, "Exception"); - } + Exception(const char *format, ...); virtual const char* str() const { return str_; } };