Support pre-IPv6 systems (without getaddrinfo)
[profile/ivi/libxcb.git] / src / xcb_util.c
index 1bde7b7..fcb11f0 100644 (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 (_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;
 
-            if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
+        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;
     }
-    freeaddrinfo(results);
-    return fd;
+#endif
 }
 
 #ifndef _WIN32