Support pre-IPv6 systems (without getaddrinfo)

Some of these systems (eg. Interix on XP) are still in use.

Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Peter Harris <pharris@opentext.com>
This commit is contained in:
Markus Duft 2011-08-24 10:49:06 -04:00 committed by Peter Harris
parent aa02096b8e
commit 163c47bdc0
3 changed files with 57 additions and 10 deletions

View File

@ -135,6 +135,8 @@ AC_PREREQ([2.59c], [], [AC_SUBST([htmldir], [m4_ifset([AC_PACKAGE_TARNAME],
XCB_CHECK_DOXYGEN()
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAVE_GETADDRINFO, 1, [getaddrinfo() function is available])], )
case $host_os in
# darwin through Snow Leopard has poll() but can't be used to poll character devices.
darwin@<:@789@:>@*|darwin10*) ;;

View File

@ -30,6 +30,12 @@
#include <sys/param.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#ifdef __INTERIX
/* _don't_ ask. interix has INADDR_LOOPBACK in here. */
#include <rpc/types.h>
#endif
#ifdef _WIN32
#include "xcb_windefs.h"

View File

@ -34,6 +34,7 @@
#include <stddef.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#ifdef _WIN32
#include "xcb_windefs.h"
@ -258,13 +259,27 @@ static int _xcb_socket(int family, int type, int proto)
}
static int _xcb_do_connect(int fd, const struct sockaddr* addr, int addrlen) {
int on = 1;
if(fd < 0)
return -1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
return connect(fd, addr, addrlen);
}
static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port)
{
int fd = -1;
#if HAVE_GETADDRINFO
struct addrinfo hints;
char service[6]; /* "65535" with the trailing '\0' */
struct addrinfo *results, *addr;
char *bracket;
#endif
if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
#ifdef AF_INET6
@ -276,6 +291,7 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
if (*host == '\0')
host = "localhost";
#if HAVE_GETADDRINFO
memset(&hints, 0, sizeof(hints));
#ifdef AI_NUMERICSERV
hints.ai_flags |= AI_NUMERICSERV;
@ -302,19 +318,42 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
for(addr = results; addr; addr = addr->ai_next)
{
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(fd >= 0) {
int on = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
break;
close(fd);
fd = -1;
}
if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
break;
close(fd);
fd = -1;
}
freeaddrinfo(results);
return fd;
#else
{
struct hostent* _h;
struct sockaddr_in _s;
struct in_addr ** _c;
if((_h = gethostbyname(host)) == NULL)
return -1;
_c = (struct in_addr**)_h->h_addr_list;
fd = -1;
while(*_c) {
_s.sin_family = AF_INET;
_s.sin_port = htons(port);
_s.sin_addr = *(*_c);
fd = _xcb_socket(_s.sin_family, SOCK_STREAM, 0);
if(_xcb_do_connect(fd, (struct sockaddr*)&_s, sizeof(_s)) >= 0)
break;
close(fd);
fd = -1;
++_c;
}
return fd;
}
#endif
}
#ifndef _WIN32