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:
parent
aa02096b8e
commit
163c47bdc0
|
@ -135,6 +135,8 @@ AC_PREREQ([2.59c], [], [AC_SUBST([htmldir], [m4_ifset([AC_PACKAGE_TARNAME],
|
||||||
|
|
||||||
XCB_CHECK_DOXYGEN()
|
XCB_CHECK_DOXYGEN()
|
||||||
|
|
||||||
|
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAVE_GETADDRINFO, 1, [getaddrinfo() function is available])], )
|
||||||
|
|
||||||
case $host_os in
|
case $host_os in
|
||||||
# darwin through Snow Leopard has poll() but can't be used to poll character devices.
|
# darwin through Snow Leopard has poll() but can't be used to poll character devices.
|
||||||
darwin@<:@789@:>@*|darwin10*) ;;
|
darwin@<:@789@:>@*|darwin10*) ;;
|
||||||
|
|
|
@ -30,6 +30,12 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.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
|
#ifdef _WIN32
|
||||||
#include "xcb_windefs.h"
|
#include "xcb_windefs.h"
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "xcb_windefs.h"
|
#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)
|
static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
#if HAVE_GETADDRINFO
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
char service[6]; /* "65535" with the trailing '\0' */
|
char service[6]; /* "65535" with the trailing '\0' */
|
||||||
struct addrinfo *results, *addr;
|
struct addrinfo *results, *addr;
|
||||||
char *bracket;
|
char *bracket;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
|
if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
|
||||||
#ifdef AF_INET6
|
#ifdef AF_INET6
|
||||||
|
@ -276,6 +291,7 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
|
||||||
if (*host == '\0')
|
if (*host == '\0')
|
||||||
host = "localhost";
|
host = "localhost";
|
||||||
|
|
||||||
|
#if HAVE_GETADDRINFO
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
#ifdef AI_NUMERICSERV
|
#ifdef AI_NUMERICSERV
|
||||||
hints.ai_flags |= 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)
|
for(addr = results; addr; addr = addr->ai_next)
|
||||||
{
|
{
|
||||||
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||||
if(fd >= 0) {
|
if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
|
||||||
int on = 1;
|
break;
|
||||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
|
close(fd);
|
||||||
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
|
fd = -1;
|
||||||
|
|
||||||
if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
|
|
||||||
break;
|
|
||||||
close(fd);
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
freeaddrinfo(results);
|
freeaddrinfo(results);
|
||||||
return fd;
|
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
|
#ifndef _WIN32
|
||||||
|
|
Loading…
Reference in New Issue