[PATCH] Switch over to use GIO for socket connections / DNS resolution
- From: "Daniel P. Berrange" <dan berrange com>
- To: gtk-vnc-list gnome org
- Subject: [PATCH] Switch over to use GIO for socket connections / DNS resolution
- Date: Wed, 14 Jul 2010 15:03:08 +0100
GIO provides GSocket and GResolver classes that can replace all
current use of POSIX sockets / DNS resolution APIs. This gives
cross platform portability for free, removing the need to use
gnulib for socket portability
* configure.ac: Check for GIO
* src/Makefile.am: Link to GIO
* src/vncconnection.c: Switch to using GSocket & friends
* src/vncdisplay.c: Remove winsock initialization code
---
configure.ac | 8 +-
src/Makefile.am | 2 +
src/vncconnection.c | 397 +++++++++++++++++++++++++--------------------------
src/vncdisplay.c | 53 -------
4 files changed, 204 insertions(+), 256 deletions(-)
diff --git a/configure.ac b/configure.ac
index 13fe807..7d074da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,6 +28,8 @@ dnl ****************************************************************************
GOBJECT_REQUIRED=2.10.0
AC_SUBST(GOBJECT_REQUIRED)
+GIO_REQUIRED=2.10.0
+AC_SUBST(GIO_REQUIRED)
GDK_PIXBUF_REQUIRED=2.10.0
AC_SUBST(GDK_PIXBUF_REQUIRED)
GNUTLS_REQUIRED=1.4.0
@@ -99,7 +101,7 @@ AC_SUBST([GTK_VNC_API_VERSION])
AM_CONDITIONAL([HAVE_GTK_2],[test "$with_gtk" = "2.0"])
AM_CONDITIONAL([HAVE_GTK_3],[test "$with_gtk" = "3.0"])
-AC_CHECK_HEADERS([pwd.h winsock2.h termios.h])
+AC_CHECK_HEADERS([pwd.h termios.h])
AC_ARG_WITH(python,
[ --with-python build python bindings],
@@ -158,6 +160,10 @@ PKG_CHECK_MODULES(GOBJECT, gobject-2.0 >= $GOBJECT_REQUIRED)
AC_SUBST(GOBJECT_CFLAGS)
AC_SUBST(GOBJECT_LIBS)
+PKG_CHECK_MODULES(GIO, gio-2.0 >= $GIO_REQUIRED)
+AC_SUBST(GIO_CFLAGS)
+AC_SUBST(GIO_LIBS)
+
PKG_CHECK_MODULES(GDK_PIXBUF, gdk-pixbuf-2.0 >= $GDK_PIXBUF_REQUIRED)
AC_SUBST(GDK_PIXBUF_CFLAGS)
AC_SUBST(GDK_PIXBUF_LIBS)
diff --git a/src/Makefile.am b/src/Makefile.am
index 0a94954..5c423c0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,7 @@ endif
libgvnc_1_0_la_LIBADD = \
@GOBJECT_LIBS@ \
+ @GIO_LIBS@ \
@GTHREAD_LIBS@ \
@GDK_PIXBUF_LIBS@ \
@GNUTLS_LIBS@ \
@@ -30,6 +31,7 @@ libgvnc_1_0_la_LIBADD = \
../gnulib/lib/libgnu.la
libgvnc_1_0_la_CFLAGS = \
@GOBJECT_CFLAGS@ \
+ @GIO_CFLAGS@ \
@GTHREAD_CFLAGS@ \
@GDK_PIXBUF_CFLAGS@ \
@GNUTLS_CFLAGS@ \
diff --git a/src/vncconnection.c b/src/vncconnection.c
index 027a7f1..3abec29 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -26,10 +26,6 @@
#include "vncmarshal.h"
#include "vncutil.h"
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
#include <string.h>
#include <unistd.h>
#include <stdio.h>
@@ -58,16 +54,8 @@
#include <zlib.h>
-#include "getaddrinfo.h"
#include "dh.h"
-/* AI_ADDRCONFIG is missing on some systems and gnulib won't provide it
- even if its emulated getaddrinfo() for us . */
-#ifndef AI_ADDRCONFIG
-# define AI_ADDRCONFIG 0
-#endif
-
-
struct wait_queue
{
gboolean waiting;
@@ -112,7 +100,7 @@ struct _VncConnectionPrivate
{
struct coroutine coroutine;
guint open_id;
- GIOChannel *channel;
+ GSocket *sock;
int fd;
char *host;
char *port;
@@ -228,7 +216,7 @@ static guint signals[VNC_LAST_SIGNAL] = { 0, 0, 0, 0,
#define niblo(a) ((a) & 0x0F)
/* Main loop helper functions */
-static gboolean g_io_wait_helper(GIOChannel *channel G_GNUC_UNUSED,
+static gboolean g_io_wait_helper(GSocket *sock G_GNUC_UNUSED,
GIOCondition cond,
gpointer data)
{
@@ -237,26 +225,33 @@ static gboolean g_io_wait_helper(GIOChannel *channel G_GNUC_UNUSED,
return FALSE;
}
-static GIOCondition g_io_wait(GIOChannel *channel, GIOCondition cond)
+static GIOCondition g_io_wait(GSocket *sock, GIOCondition cond)
{
GIOCondition *ret;
-
- g_io_add_watch(channel, cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL, g_io_wait_helper, coroutine_self());
+ GSource *src = g_socket_create_source(sock,
+ cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ NULL);
+ g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, coroutine_self(), NULL);
+ g_source_attach(src, NULL);
ret = coroutine_yield(NULL);
return *ret;
}
static GIOCondition g_io_wait_interruptable(struct wait_queue *wait,
- GIOChannel *channel,
+ GSocket *sock,
GIOCondition cond)
{
GIOCondition *ret;
gint id;
wait->context = coroutine_self();
- id = g_io_add_watch(channel, cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL, g_io_wait_helper, wait->context);
-
+ GSource *src = g_socket_create_source(sock,
+ cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ NULL);
+ g_source_set_callback(src, (GSourceFunc)g_io_wait_helper,
+ wait->context, NULL);
+ id = g_source_attach(src, NULL);
wait->waiting = TRUE;
ret = coroutine_yield(NULL);
wait->waiting = FALSE;
@@ -606,36 +601,46 @@ static int vnc_connection_read_wire(VncConnection *conn, void *data, size_t len)
{
VncConnectionPrivate *priv = conn->priv;
int ret;
+ gboolean blocking = FALSE;
reread:
if (priv->tls_session) {
ret = gnutls_read(priv->tls_session, data, len);
if (ret < 0) {
if (ret == GNUTLS_E_AGAIN)
- errno = EAGAIN;
- else
- errno = EIO;
+ blocking = TRUE;
ret = -1;
}
- } else
- ret = recv (priv->fd, data, len, 0);
+ } else {
+ GError *error = NULL;
+ ret = g_socket_receive(priv->sock,
+ data, len,
+ NULL, &error);
+ if (ret < 0) {
+ if (error) {
+ if (error->code == G_IO_ERROR_WOULD_BLOCK)
+ blocking = TRUE;
+ g_error_free(error);
+ } else {
+ VNC_DEBUG("Read error %s", error->message);
+ }
+ ret = -1;
+ }
+ }
if (ret == -1) {
- switch (errno) {
- case EWOULDBLOCK:
+ if (blocking) {
if (priv->wait_interruptable) {
if (!g_io_wait_interruptable(&priv->wait,
- priv->channel, G_IO_IN)) {
+ priv->sock, G_IO_IN)) {
//VNC_DEBUG("Read blocking interrupted %d", priv->has_error);
return -EAGAIN;
}
- } else
- g_io_wait(priv->channel, G_IO_IN);
- case EINTR:
+ } else {
+ g_io_wait(priv->sock, G_IO_IN);
+ }
goto reread;
-
- default:
- VNC_DEBUG("Closing the connection: vnc_connection_read() - errno=%d", errno);
+ } else {
priv->has_error = TRUE;
return -errno;
}
@@ -791,6 +796,7 @@ static void vnc_connection_flush_wire(VncConnection *conn,
//VNC_DEBUG("Flush write %p %d", data, datalen);
while (offset < datalen) {
int ret;
+ gboolean blocking = FALSE;
if (priv->tls_session) {
ret = gnutls_write(priv->tls_session,
@@ -798,22 +804,28 @@ static void vnc_connection_flush_wire(VncConnection *conn,
datalen-offset);
if (ret < 0) {
if (ret == GNUTLS_E_AGAIN)
- errno = EAGAIN;
- else
- errno = EIO;
+ blocking = TRUE;
ret = -1;
}
- } else
- ret = send (priv->fd,
- ptr+offset,
- datalen-offset, 0);
+ } else {
+ GError *error = NULL;
+ ret = g_socket_send(priv->sock,
+ ptr+offset,
+ datalen-offset,
+ NULL, &error);
+ if (ret < 0) {
+ if (error) {
+ if (error->code == G_IO_ERROR_WOULD_BLOCK)
+ blocking = TRUE;
+ g_error_free(error);
+ }
+ ret = -1;
+ }
+ }
if (ret == -1) {
- switch (errno) {
- case EWOULDBLOCK:
- g_io_wait(priv->channel, G_IO_OUT);
- case EINTR:
- continue;
- default:
+ if (blocking) {
+ g_io_wait(priv->sock, G_IO_OUT);
+ } else {
VNC_DEBUG("Closing the connection: vnc_connection_flush %d", errno);
priv->has_error = TRUE;
return;
@@ -920,12 +932,17 @@ static ssize_t vnc_connection_tls_push(gnutls_transport_ptr_t transport,
VncConnection *conn = transport;
VncConnectionPrivate *priv = conn->priv;
int ret;
+ GError *error = NULL;
- retry:
- ret = write(priv->fd, data, len);
+ ret = g_socket_send(priv->sock, data, len, NULL, &error);
if (ret < 0) {
- if (errno == EINTR)
- goto retry;
+ if (error) {
+ if (error->code == G_IO_ERROR_WOULD_BLOCK)
+ errno = EAGAIN; /* For gnutls compat */
+ else
+ VNC_DEBUG("Read error %s", error->message);
+ g_error_free(error);
+ }
return -1;
}
return ret;
@@ -938,12 +955,17 @@ static ssize_t vnc_connection_tls_pull(gnutls_transport_ptr_t transport,
VncConnection *conn = transport;
VncConnectionPrivate *priv = conn->priv;
int ret;
+ GError *error = NULL;
- retry:
- ret = read(priv->fd, data, len);
+ ret = g_socket_receive(priv->sock, data, len, NULL, &error);
if (ret < 0) {
- if (errno == EINTR)
- goto retry;
+ if (error) {
+ if (error->code == G_IO_ERROR_WOULD_BLOCK)
+ errno = EAGAIN; /* For gnutls compat */
+ else
+ VNC_DEBUG("Read error %s", error->message);
+ g_error_free(error);
+ }
return -1;
}
return ret;
@@ -996,7 +1018,7 @@ static guint16 vnc_connection_read_u16(VncConnection *conn)
{
guint16 value = 0;
vnc_connection_read(conn, &value, sizeof(value));
- return ntohs(value);
+ return g_ntohs(value);
}
/*
@@ -1006,7 +1028,7 @@ static guint32 vnc_connection_read_u32(VncConnection *conn)
{
guint32 value = 0;
vnc_connection_read(conn, &value, sizeof(value));
- return ntohl(value);
+ return g_ntohl(value);
}
/*
@@ -1016,7 +1038,7 @@ static gint32 vnc_connection_read_s32(VncConnection *conn)
{
gint32 value = 0;
vnc_connection_read(conn, &value, sizeof(value));
- return ntohl(value);
+ return g_ntohl(value);
}
/*
@@ -1032,7 +1054,7 @@ static void vnc_connection_write_u8(VncConnection *conn, guint8 value)
*/
static void vnc_connection_write_u16(VncConnection *conn, guint16 value)
{
- value = htons(value);
+ value = g_htons(value);
vnc_connection_write(conn, &value, sizeof(value));
}
@@ -1041,7 +1063,7 @@ static void vnc_connection_write_u16(VncConnection *conn, guint16 value)
*/
static void vnc_connection_write_u32(VncConnection *conn, guint32 value)
{
- value = htonl(value);
+ value = g_htonl(value);
vnc_connection_write(conn, &value, sizeof(value));
}
@@ -1380,7 +1402,7 @@ static void vnc_connection_buffered_write_u8(VncConnection *conn, guint8 value)
*/
static void vnc_connection_buffered_write_u16(VncConnection *conn, guint16 value)
{
- value = htons(value);
+ value = g_htons(value);
vnc_connection_buffered_write(conn, &value, 2);
}
@@ -1389,7 +1411,7 @@ static void vnc_connection_buffered_write_u16(VncConnection *conn, guint16 value
*/
static void vnc_connection_buffered_write_u32(VncConnection *conn, guint32 value)
{
- value = htonl(value);
+ value = g_htonl(value);
vnc_connection_buffered_write(conn, &value, 4);
}
@@ -1398,7 +1420,7 @@ static void vnc_connection_buffered_write_u32(VncConnection *conn, guint32 value
*/
static void vnc_connection_buffered_write_s32(VncConnection *conn, gint32 value)
{
- value = htonl(value);
+ value = g_htonl(value);
vnc_connection_buffered_write(conn, &value, 4);
}
@@ -3012,26 +3034,22 @@ static gboolean vnc_connection_perform_auth_mslogon(VncConnection *conn)
/*
* NB, keep in sync with similar method in qemud/remote.c
*/
-static char *vnc_connection_addr_to_string(struct sockaddr_storage *sa, socklen_t salen)
+static char *vnc_connection_addr_to_string(GSocketAddress *addr)
{
- char host[NI_MAXHOST], port[NI_MAXSERV];
- char *addr;
- int err;
+ GInetSocketAddress *iaddr = G_INET_SOCKET_ADDRESS(addr);
+ guint16 port;
+ GInetAddress *host;
+ gchar *hoststr;
+ gchar *ret;
- if ((err = getnameinfo((struct sockaddr *)sa, salen,
- host, sizeof(host),
- port, sizeof(port),
- NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
- VNC_DEBUG("Cannot resolve address %d: %s",
- err, gai_strerror(err));
- return NULL;
- }
+ host = g_inet_socket_address_get_address(iaddr);
+ port = g_inet_socket_address_get_port(iaddr);
+ hoststr = g_inet_address_to_string(host);
+
+ ret = g_strdup_printf("%s;%hu", hoststr, port);
+ g_free(hoststr);
- addr = g_malloc0(strlen(host) + 1 + strlen(port) + 1);
- strcpy(addr, host);
- strcat(addr, ";");
- strcat(addr, port);
- return addr;
+ return ret;
}
@@ -3144,8 +3162,6 @@ static gboolean vnc_connection_perform_auth_sasl(VncConnection *conn)
char *serverin = NULL;
unsigned int clientoutlen, serverinlen;
int err, complete;
- struct sockaddr_storage sa;
- socklen_t salen;
char *localAddr = NULL, *remoteAddr = NULL;
const void *val;
sasl_ssf_t ssf;
@@ -3160,6 +3176,7 @@ static gboolean vnc_connection_perform_auth_sasl(VncConnection *conn)
char *mechlist;
const char *mechname;
gboolean ret;
+ GSocketAddress *addr;
/* Sets up the SASL library as a whole */
err = sasl_client_init(NULL);
@@ -3171,31 +3188,26 @@ static gboolean vnc_connection_perform_auth_sasl(VncConnection *conn)
}
/* Get local address in form IPADDR:PORT */
- salen = sizeof(sa);
- if (getsockname(priv->fd, (struct sockaddr*)&sa, &salen) < 0) {
- VNC_DEBUG("failed to get sock address %d (%s)",
- errno, strerror(errno));
+ addr = g_socket_get_local_address(priv->sock, NULL);
+ if (!addr) {
+ VNC_DEBUG("failed to get local address");
goto error;
}
- if ((sa.ss_family == AF_INET ||
- sa.ss_family == AF_INET6) &&
- (localAddr = vnc_connection_addr_to_string(&sa, salen)) == NULL)
+ if ((g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV4 ||
+ g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV6) &&
+ (localAddr = vnc_connection_addr_to_string(addr)) == NULL)
goto error;
/* Get remote address in form IPADDR:PORT */
- salen = sizeof(sa);
- if (getpeername(priv->fd, (struct sockaddr*)&sa, &salen) < 0) {
- VNC_DEBUG("failed to get peer address %d (%s)",
- errno, strerror(errno));
- g_free(localAddr);
+ addr = g_socket_get_remote_address(priv->sock, NULL);
+ if (!addr) {
+ VNC_DEBUG("failed to get peer address");
goto error;
}
- if ((sa.ss_family == AF_INET ||
- sa.ss_family == AF_INET6) &&
- (remoteAddr = vnc_connection_addr_to_string(&sa, salen)) == NULL) {
- g_free(localAddr);
+ if ((g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV4 ||
+ g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV6) &&
+ (remoteAddr = vnc_connection_addr_to_string(addr)) == NULL)
goto error;
- }
VNC_DEBUG("Client SASL new host:'%s' local:'%s' remote:'%s'", priv->host, localAddr, remoteAddr);
@@ -3567,9 +3579,9 @@ static gboolean vnc_connection_start_tls(VncConnection *conn, int anonTLS)
if (!gnutls_error_is_fatal(ret)) {
VNC_DEBUG("Handshake was blocking");
if (!gnutls_record_get_direction(priv->tls_session))
- g_io_wait(priv->channel, G_IO_IN);
+ g_io_wait(priv->sock, G_IO_IN);
else
- g_io_wait(priv->channel, G_IO_OUT);
+ g_io_wait(priv->sock, G_IO_OUT);
goto retry;
}
VNC_DEBUG("Handshake failed %s", gnutls_strerror(ret));
@@ -4167,14 +4179,12 @@ static void vnc_connection_close(VncConnection *conn)
sasl_dispose (&priv->saslconn);
#endif
- if (priv->channel) {
- g_io_channel_unref(priv->channel);
- priv->channel = NULL;
+ if (priv->sock) {
+ g_object_unref(priv->sock);
+ priv->sock = NULL;
}
- if (priv->fd != -1) {
- close(priv->fd);
+ if (priv->fd != -1)
priv->fd = -1;
- }
if (priv->host) {
g_free(priv->host);
@@ -4239,7 +4249,9 @@ void vnc_connection_shutdown(VncConnection *conn)
priv->open_id = 0;
}
- close(priv->fd);
+ g_socket_close(priv->sock, NULL);
+ g_object_unref(priv->sock);
+ priv->sock = NULL;
priv->fd = -1;
priv->has_error = 1;
VNC_DEBUG("Waking up couroutine to shutdown gracefully");
@@ -4255,6 +4267,8 @@ gboolean vnc_connection_is_open(VncConnection *conn)
if (priv->fd != -1)
return TRUE;
+ if (priv->sock != NULL)
+ return TRUE;
if (priv->host)
return TRUE;
return FALSE;
@@ -4363,124 +4377,103 @@ static gboolean vnc_connection_initialize(VncConnection *conn)
return !vnc_connection_has_error(conn);
}
-static gboolean vnc_connection_set_nonblock(int fd)
+
+static gboolean vnc_connection_open_fd_internal(VncConnection *conn)
{
-#ifndef WIN32
- int flags;
- if ((flags = fcntl(fd, F_GETFL)) < 0) {
- VNC_DEBUG ("Failed to fcntl()");
- return FALSE;
- }
- flags |= O_NONBLOCK;
- if (fcntl(fd, F_SETFL, flags) < 0) {
- VNC_DEBUG ("Failed to fcntl()");
- return FALSE;
- }
+ VncConnectionPrivate *priv = conn->priv;
-#else /* WIN32 */
- unsigned long flag = 1;
+ VNC_DEBUG("Connecting to FD %d", priv->fd);
- /* This is actually Gnulib's replacement rpl_ioctl function.
- * We can't call ioctlsocket directly in any case.
- */
- if (ioctl (fd, FIONBIO, (void *) &flag) == -1) {
- VNC_DEBUG ("Failed to set nonblocking flag, winsock error = %d",
- WSAGetLastError ());
+ if (!(priv->sock = g_socket_new_from_fd(priv->fd, NULL))) {
+ VNC_DEBUG("Failed to open socket from fd %d", priv->fd);
return FALSE;
}
-#endif /* WIN32 */
- return TRUE;
+ g_socket_set_blocking(priv->sock, FALSE);
+
+ return !vnc_connection_has_error(conn);
}
-static gboolean vnc_connection_open_fd_internal(VncConnection *conn)
+static GSocket *vnc_connection_connect_socket(GSocketAddress *sockaddr,
+ GError **error)
{
- VncConnectionPrivate *priv = conn->priv;
+ GSocket *sock = g_socket_new(g_socket_address_get_family(sockaddr),
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ error);
- VNC_DEBUG("Connecting to FD %d", priv->fd);
-
- if (!vnc_connection_set_nonblock(priv->fd))
- return FALSE;
+ if (!sock)
+ return NULL;
- if (!(priv->channel =
-#ifdef WIN32
- g_io_channel_win32_new_socket(_get_osfhandle(priv->fd))
-#else
- g_io_channel_unix_new(priv->fd)
-#endif
- )) {
- VNC_DEBUG ("Failed to g_io_channel_unix_new()");
- return FALSE;
+ g_socket_set_blocking(sock, FALSE);
+ if (!g_socket_connect(sock, sockaddr, NULL, error)) {
+ if (*error && (*error)->code == G_IO_ERROR_PENDING) {
+ g_error_free(*error);
+ *error = NULL;
+ VNC_DEBUG("Socket pending");
+ g_io_wait(sock, G_IO_OUT|G_IO_ERR|G_IO_HUP);
+
+ if (!g_socket_check_connect_result(sock, error)) {
+ VNC_DEBUG("Failed to connect %s", (*error)->message);
+ g_object_unref(sock);
+ return NULL;
+ }
+ } else {
+ VNC_DEBUG("Socket error: %s", *error ? (*error)->message : "unknown");
+ g_object_unref(sock);
+ return NULL;
+ }
}
- return !vnc_connection_has_error(conn);
+ VNC_DEBUG("Finally connected");
+
+ return sock;
}
static gboolean vnc_connection_open_host_internal(VncConnection *conn)
{
VncConnectionPrivate *priv = conn->priv;
- struct addrinfo *ai, *runp, hints;
- int ret;
+ GSocketConnectable *addr;
+ GSocketAddressEnumerator *enumerator;
+ GSocketAddress *sockaddr;
+ GError *conn_error = NULL;
+ GSocket *sock = NULL;
+ int port = atoi(priv->port);
VNC_DEBUG("Resolving host %s %s", priv->host, priv->port);
- memset (&hints, '\0', sizeof (hints));
- hints.ai_flags = AI_ADDRCONFIG;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- if ((ret = getaddrinfo(priv->host, priv->port, &hints, &ai)) != 0) {
- VNC_DEBUG ("Failed to resolve hostname");
- return FALSE;
- }
+ addr = g_network_address_new(priv->host, port);
- runp = ai;
- while (runp != NULL) {
- int fd;
- GIOChannel *chan;
+ enumerator = g_socket_connectable_enumerate (addr);
+ g_object_unref (addr);
- if ((fd = socket(runp->ai_family, runp->ai_socktype,
- runp->ai_protocol)) < 0) {
- VNC_DEBUG ("Failed to socket()");
- break;
- }
-
- VNC_DEBUG("Trying socket %d", fd);
- if (!vnc_connection_set_nonblock(fd))
- break;
+ /* Try each sockaddr until we succeed. Record the first
+ * connection error, but not any further ones (since they'll probably
+ * be basically the same as the first).
+ */
+ while (!sock &&
+ (sockaddr = g_socket_address_enumerator_next(enumerator, NULL, &conn_error))) {
+ VNC_DEBUG("Trying one socket");
+ sock = vnc_connection_connect_socket(sockaddr, &conn_error);
+ g_object_unref(sockaddr);
+ }
+ g_object_unref(enumerator);
+ if (sock) {
+ /* We couldn't connect to the first address, but we succeeded
+ * in connecting to a later address.
+ */
+ if (conn_error)
+ g_error_free (conn_error);
+ priv->sock = sock;
+ return TRUE;
+ } else if (conn_error) {
+ /* Either the initial lookup failed, or else the caller
+ * cancelled us.
+ */
+ if (conn_error)
+ g_error_free (conn_error);
+ }
- if (!(chan =
-#ifdef WIN32
- g_io_channel_win32_new_socket(_get_osfhandle(fd))
-#else
- g_io_channel_unix_new(fd)
-#endif
- )) {
- close(fd);
- VNC_DEBUG ("Failed to g_io_channel_unix_new()");
- break;
- }
-
- reconnect:
- /* FIXME: Better handle EINPROGRESS/EISCONN return values,
- as explained in connect(2) man page */
- if ((connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) ||
- errno == EISCONN) {
- priv->channel = chan;
- priv->fd = fd;
- freeaddrinfo(ai);
- return !vnc_connection_has_error(conn);
- }
- if (errno == EINPROGRESS ||
- errno == EWOULDBLOCK) {
- g_io_wait(chan, G_IO_OUT|G_IO_ERR|G_IO_HUP);
- goto reconnect;
- }
- VNC_DEBUG ("Connect failed with errno = %d, try next addr", errno);
- close(fd);
- g_io_channel_unref(chan);
- runp = runp->ai_next;
- }
- freeaddrinfo (ai);
return FALSE;
}
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 175456a..a6b9467 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -40,13 +40,6 @@
#include <sys/stat.h>
#include <unistd.h>
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-
-static void winsock_startup (void);
-static void winsock_cleanup (void);
-
#define VNC_DISPLAY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), VNC_TYPE_DISPLAY, VncDisplayPrivate))
@@ -259,7 +252,6 @@ vnc_display_set_property (GObject *object,
GtkWidget *vnc_display_new(void)
{
- winsock_startup ();
return GTK_WIDGET(g_object_new(VNC_TYPE_DISPLAY, NULL));
}
@@ -1527,8 +1519,6 @@ static void vnc_display_finalize (GObject *obj)
vnc_display_keyval_free_entries();
G_OBJECT_CLASS (vnc_display_parent_class)->finalize (obj);
-
- winsock_cleanup();
}
static void vnc_display_class_init(VncDisplayClass *klass)
@@ -2224,49 +2214,6 @@ vnc_display_request_update(VncDisplay *obj)
vnc_connection_get_width(obj->priv->conn));
}
-#ifdef WIN32
-
-/* On Windows, we must call WSAStartup before using any sockets and we
- * must call WSACleanup afterwards. And we have to balance any calls
- * to WSAStartup with a corresponding call to WSACleanup.
- *
- * Note that Wine lets you do socket calls anyway, but real Windows
- * doesn't. (http://bugs.winehq.org/show_bug.cgi?id=11965)
- */
-
-static void
-winsock_startup (void)
-{
- WORD winsock_version, err;
- WSADATA winsock_data;
-
- /* http://msdn2.microsoft.com/en-us/library/ms742213.aspx */
- winsock_version = MAKEWORD (2, 2);
- err = WSAStartup (winsock_version, &winsock_data);
- if (err != 0)
- VNC_DEBUG ("ignored error %d from WSAStartup", err);
-}
-
-static void
-winsock_cleanup (void)
-{
- WSACleanup ();
-}
-
-#else /* !WIN32 */
-
-static void
-winsock_startup (void)
-{
-}
-
-static void
-winsock_cleanup (void)
-{
-}
-
-#endif /* !WIN32 */
-
/*
* Local variables:
* c-indent-level: 8
--
1.7.1.1
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]