From: Samuel Cormier-Iijima Date: Sun, 2 Mar 2008 06:58:50 +0000 (-0500) Subject: It compiles! X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fgnio.git;a=commitdiff_plain;h=16c893bba43ba9f720ad26250ba8bbc8fd9ba96c It compiles! --- diff --git a/gnio/gsocket.c b/gnio/gsocket.c index ba6595b..1d54f1c 100644 --- a/gnio/gsocket.c +++ b/gnio/gsocket.c @@ -376,6 +376,30 @@ g_socket_get_reuse_address (GSocket *socket) return socket->priv->reuse_address; } +gboolean +g_socket_has_socket_error (GSocket *socket, + GError **error) +{ + gint sockerr; + gsize sockerr_size = sizeof (sockerr); + + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + + if (getsockopt (socket->priv->fd, SOL_SOCKET, SO_ERROR, (gpointer) &sockerr, &sockerr_size) < 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "could not get socket error: %s", g_strerror (errno)); + return TRUE; + } + + if (sockerr != 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (sockerr), "error connecting: %s", g_strerror (sockerr)); + return TRUE; + } + + return FALSE; +} + GSocketAddress * g_socket_get_local_address (GSocket *socket, GError **error) diff --git a/gnio/gsocket.h b/gnio/gsocket.h index 2a50583..ed2d4aa 100644 --- a/gnio/gsocket.h +++ b/gnio/gsocket.h @@ -91,6 +91,9 @@ void g_socket_set_reuse_address (GSocket *socket, gboolean g_socket_get_reuse_address (GSocket *socket); +gboolean g_socket_has_socket_error (GSocket *socket, + GError **error); + gboolean g_socket_bind (GSocket *socket, GSocketAddress *address, GError **error); diff --git a/gnio/gtcpclient.c b/gnio/gtcpclient.c index c46108c..c732a59 100644 --- a/gnio/gtcpclient.c +++ b/gnio/gtcpclient.c @@ -246,7 +246,7 @@ g_tcp_client_connect (GTcpClient *client, } else { - address = g_inet_socket_address_get_address (client->priv->address); + address = g_inet_socket_address_get_address (client->priv->address); } if (G_IS_INET4_ADDRESS (address)) @@ -276,19 +276,37 @@ typedef struct { GCancellable *cancellable; gpointer user_data; GTcpClient *client; - gchar address_buffer[256]; - gsize address_length; } ConnectData; -/* static gboolean connect_callback (ConnectData *data, GIOCondition condition, gint fd) { + GTcpClient *client; + GSimpleAsyncResult *result; + GError *error = NULL; + + client = data->client; + + if (condition & G_IO_OUT) + { + result = g_simple_async_result_new (G_OBJECT (client), data->callback, data->user_data, g_tcp_client_connect_async); + } + else if (condition & G_IO_ERR) + { + if (!g_socket_has_socket_error (client->priv->socket, &error)) + g_warning ("got G_IO_ERR but socket does not have error"); + + result = g_simple_async_result_new_from_error (G_OBJECT (client), data->callback, data->user_data, error); + } + + g_simple_async_result_complete (result); + + g_object_unref (result); + return FALSE; } -*/ void g_tcp_client_connect_async (GTcpClient *client, @@ -296,7 +314,73 @@ g_tcp_client_connect_async (GTcpClient *client, GAsyncReadyCallback callback, gpointer user_data) { + GInetAddress *address; + GSimpleAsyncResult *result; + GSource *source; + ConnectData *data; + GError *error = NULL; + + g_return_if_fail (G_IS_TCP_CLIENT (client)); + + if (!client->priv->address) + { + // we've been constructed with just hostname+port, resolve + // GResolver *resolver = g_resolver_new (); + return; + } + address = g_inet_socket_address_get_address (client->priv->address); + + if (G_IS_INET4_ADDRESS (address)) + client->priv->socket = g_socket_new (G_SOCKET_DOMAIN_INET, G_SOCKET_TYPE_STREAM, NULL, &error); + else if (G_IS_INET6_ADDRESS (address)) + client->priv->socket = g_socket_new (G_SOCKET_DOMAIN_INET6, G_SOCKET_TYPE_STREAM, NULL, &error); + else + { + g_simple_async_report_error_in_idle (G_OBJECT (client), callback, user_data, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported address domain"); + return; + } + + if (!client->priv->socket) + { + g_simple_async_report_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + g_socket_set_blocking (client->priv->socket, FALSE); + + if (!g_socket_connect (client->priv->socket, G_SOCKET_ADDRESS (client->priv->address), &error)) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) + { + // the connection is in progress + source = g_socket_create_source (client->priv->socket, G_IO_OUT | G_IO_ERR, cancellable); + + data = g_new (ConnectData, 1); + + data->client = client; + data->callback = callback; + data->cancellable = cancellable; + data->user_data = user_data; + + g_source_set_callback (source, (GSourceFunc) connect_callback, data, g_free); + + g_source_attach (source, NULL); + } + else + { + g_simple_async_report_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + } + } + else + { + // the connection is already completed + result = g_simple_async_result_new (G_OBJECT (client), callback, user_data, g_tcp_client_connect_async); + + g_simple_async_result_complete_in_idle (result); + + g_object_unref (result); + } } gboolean