X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fgnio.git;a=blobdiff_plain;f=gnio%2Fgtcpclient.c;fp=gnio%2Fgtcpclient.c;h=1bb056f3725c24e70baab90936b819c3cb6ad0d0;hp=fc03627db8d52fd012a0a7d11fcbcdc238cd1041;hb=6ab527e0c7a63c5ffd925120dcb8b8b6cbd6c6ca;hpb=f88a5d4f15e0bbed0746dab6778631ce44b856d0 diff --git a/gnio/gtcpclient.c b/gnio/gtcpclient.c index fc03627..1bb056f 100644 --- a/gnio/gtcpclient.c +++ b/gnio/gtcpclient.c @@ -24,13 +24,11 @@ #include #include #include +#include #include #include -#include "gtcpclient.h" -#include "gasynchelper.h" - G_DEFINE_TYPE (GTcpClient, g_tcp_client, G_TYPE_OBJECT); enum @@ -46,6 +44,7 @@ struct _GTcpClientPrivate GInetSocketAddress *address; gchar *hostname; gushort port; + GSocket *socket; }; static void @@ -101,7 +100,9 @@ g_tcp_client_set_property (GObject *object, { case PROP_ADDRESS: // sink the address' floating reference - client->priv->address = G_INET_SOCKET_ADDRESS (g_object_ref_sink (g_value_get_object (value))); + client->priv->address = G_INET_SOCKET_ADDRESS (g_value_get_object (value)); + if (client->priv->address) + g_object_ref_sink (client->priv->address); break; case PROP_HOSTNAME: @@ -164,7 +165,7 @@ g_tcp_client_class_init (GTcpClientClass *klass) "hostname", "the hostname of the remote address the socket will connect to", NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); g_object_class_install_property (gobject_class, PROP_PORT, g_param_spec_uint ("port", @@ -173,7 +174,7 @@ g_tcp_client_class_init (GTcpClientClass *klass) 0, G_MAXUSHORT, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); } static void @@ -184,6 +185,7 @@ g_tcp_client_init (GTcpClient *client) client->priv->address = NULL; client->priv->hostname = NULL; client->priv->port = 0; + client->priv->socket = NULL; } GTcpClient * @@ -204,7 +206,51 @@ g_tcp_client_connect (GTcpClient *client, GCancellable *cancellable, GError **error) { - return FALSE; + GInetAddress *address; + + g_return_val_if_fail (G_IS_TCP_CLIENT (client), FALSE); + + if (!client->priv->address) + { + // we've been constructed with just hostname+port, resolve + GResolver *resolver = g_resolver_new (); + + address = g_resolver_resolve (resolver, client->priv->hostname, cancellable, error); + + if (!address) + return FALSE; + + client->priv->address = g_inet_socket_address_new (address, client->priv->port); + + g_object_unref (resolver); + + g_object_ref_sink (client->priv->address); + } + else + { + 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_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "unsupported address domain"); + return FALSE; + } + + if (!client->priv->socket) + return FALSE; + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return FALSE; + + if (!g_socket_connect (client->priv->socket, G_SOCKET_ADDRESS (client->priv->address), error)) + return FALSE; + + return TRUE; } typedef struct {