From 48aa363fffb042f947130762acc7cd3c787b11d9 Mon Sep 17 00:00:00 2001 From: Samuel Cormier-Iijima Date: Fri, 29 Feb 2008 05:04:24 -0500 Subject: [PATCH] Starting on TcpClient, some formatting fixes --- gnio/ginetaddress.c | 10 ++- gnio/ginetsocketaddress.c | 16 +++-- gnio/ginetsocketaddress.h | 3 +- gnio/gresolver.c | 4 +- gnio/gsocket.c | 10 ++- gnio/gtcpclient.c | 141 +++++++++++++++++++++++++++++++++++++- gnio/gtcpclient.h | 23 +++++-- 7 files changed, 190 insertions(+), 17 deletions(-) diff --git a/gnio/ginetaddress.c b/gnio/ginetaddress.c index fbf8c67..3890727 100644 --- a/gnio/ginetaddress.c +++ b/gnio/ginetaddress.c @@ -52,7 +52,10 @@ enum }; static void -g_inet_address_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +g_inet_address_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { GInetAddress *address = G_INET_ADDRESS (object); @@ -76,7 +79,10 @@ g_inet_address_get_property (GObject *object, guint prop_id, GValue *value, GPar } static void -g_inet_address_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +g_inet_address_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { GInetAddress *address G_GNUC_UNUSED = G_INET_ADDRESS (object); diff --git a/gnio/ginetsocketaddress.c b/gnio/ginetsocketaddress.c index f636162..040064a 100644 --- a/gnio/ginetsocketaddress.c +++ b/gnio/ginetsocketaddress.c @@ -67,7 +67,10 @@ g_inet_socket_address_dispose (GObject *object) } static void -g_inet_socket_address_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +g_inet_socket_address_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object); @@ -87,7 +90,10 @@ g_inet_socket_address_get_property (GObject *object, guint prop_id, GValue *valu } static void -g_inet_socket_address_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +g_inet_socket_address_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { GInetSocketAddress *address = G_INET_SOCKET_ADDRESS (object); @@ -124,7 +130,8 @@ g_inet_socket_address_native_size (GSocketAddress *address) } static gboolean -g_inet_socket_address_to_native (GSocketAddress *address, gpointer dest) +g_inet_socket_address_to_native (GSocketAddress *address, + gpointer dest) { GInetSocketAddress *addr; @@ -196,7 +203,8 @@ g_inet_socket_address_init (GInetSocketAddress *address) GInetSocketAddress * -g_inet_socket_address_new (GInetAddress *address, guint16 port) +g_inet_socket_address_new (GInetAddress *address, + guint16 port) { return G_INET_SOCKET_ADDRESS (g_object_new (G_TYPE_INET_SOCKET_ADDRESS, "address", address, "port", port, NULL)); } diff --git a/gnio/ginetsocketaddress.h b/gnio/ginetsocketaddress.h index 5982e55..fc44062 100644 --- a/gnio/ginetsocketaddress.h +++ b/gnio/ginetsocketaddress.h @@ -55,7 +55,8 @@ struct _GInetSocketAddressClass GType g_inet_socket_address_get_type (void) G_GNUC_CONST; -GInetSocketAddress * g_inet_socket_address_new (GInetAddress *address, guint16 port); +GInetSocketAddress * g_inet_socket_address_new (GInetAddress *address, + guint16 port); GInetAddress * g_inet_socket_address_get_address (GInetSocketAddress *sockaddr); diff --git a/gnio/gresolver.c b/gnio/gresolver.c index 8f76633..5a74b7c 100644 --- a/gnio/gresolver.c +++ b/gnio/gresolver.c @@ -56,7 +56,7 @@ G_LOCK_DEFINE (dnslock); #ifdef G_OS_WIN32 /* This is copied straight from giowin32.c, but its static there... */ -/* Is there another way to get this functionality? */ +/* TODO: is there another way to get this functionality? or maybe make this public? */ static char * winsock_error_message (int number) { @@ -406,7 +406,7 @@ g_resolver_init (GResolver *address) } typedef struct { - GList *list; + GList *list; const gchar *host; } ResolveListData; diff --git a/gnio/gsocket.c b/gnio/gsocket.c index 69a1b5c..605f92b 100644 --- a/gnio/gsocket.c +++ b/gnio/gsocket.c @@ -70,7 +70,10 @@ struct _GSocketPrivate }; static void -g_socket_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +g_socket_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { GSocket *socket = G_SOCKET (object); @@ -106,7 +109,10 @@ g_socket_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec } static void -g_socket_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +g_socket_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { GSocket *socket = G_SOCKET (object); diff --git a/gnio/gtcpclient.c b/gnio/gtcpclient.c index 599358e..ae8de6d 100644 --- a/gnio/gtcpclient.c +++ b/gnio/gtcpclient.c @@ -41,12 +41,13 @@ G_DEFINE_TYPE (GTcpClient, g_tcp_client, G_TYPE_OBJECT); enum { - PROP_0 + PROP_0, + PROP_ADDRESS }; struct _GTcpClientPrivate { - + GSocketAddress *address; }; static void @@ -56,6 +57,10 @@ g_tcp_client_get_property (GObject *object, guint prop_id, GValue *value, GParam switch (prop_id) { + case PROP_ADDRESS: + g_value_set_object (value, client->priv->address); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -102,6 +107,13 @@ g_tcp_client_class_init (GTcpClientClass *klass) gobject_class->dispose = g_tcp_client_dispose; gobject_class->set_property = g_tcp_client_set_property; gobject_class->get_property = g_tcp_client_get_property; + + g_object_class_install_property (gobject_class, PROP_ADDRESS, + g_param_spec_object ("address", + "address", + "the remote address the socket will connect to", + G_TYPE_SOCKET_ADDRESS, + G_TYPE_CONSTRUCT_ONLY | G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); } static void @@ -117,6 +129,131 @@ g_tcp_client_new (GInetSocketAddress *address, return NULL; } +gboolean +g_tcp_client_connect (GTcpClient *client, + GError **error) +{ + return FALSE; +} + +typedef struct { + GAsyncReadyCallback callback; + GCancellable *cancellable; + gpointer user_data; + GSocket *socket; + gchar address_buffer[256]; + gsize address_length; +} ConnectData; + +static gboolean +connect_callback (ConnectData *data, + GIOCondition condition, + gint fd) +{ + GSocket *socket; + GSimpleAsyncResult *result = NULL; + gint sockerr = 0; + gsize sockerr_size = 1; + + socket = data->socket; + + if (condition & G_IO_OUT) + { + result = g_simple_async_result_new (G_OBJECT (socket), data->callback, data->user_data, g_socket_connect_async); + } + else if (condition & G_IO_ERR) + { + if (getsockopt (fd, SOL_SOCKET, SO_ERROR, (gpointer) &sockerr, &sockerr_size) < 0) + g_warning ("getsockopt: %s", g_strerror (errno)); + + if (sockerr != 0) + result = g_simple_async_result_new_error (G_OBJECT (socket), data->callback, data->user_data, G_IO_ERROR, g_io_error_from_errno (sockerr), "error connecting: %s", g_strerror (sockerr)); + else + g_warning ("getsockopt SO_ERROR returned no error, with sockerr = %d", sockerr); + } + + g_simple_async_result_complete (result); + + g_object_unref (result); + + return FALSE; +} + +void +g_socket_connect_async (GTcpClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSource *source; + GSimpleAsyncResult *result; + ConnectData *data; + gint ret; + gchar buffer[256]; + gsize len; + + g_return_if_fail (G_IS_SOCKET (socket) && G_IS_SOCKET_ADDRESS (address)); + + if (g_socket_get_blocking (socket)) + g_socket_set_blocking (socket, FALSE); + + g_socket_address_to_native (address, buffer); + + len = g_socket_address_native_size (address); + + if ((ret = connect (socket->priv->fd, (struct sockaddr *) buffer, len)) < 0) + { + if (errno == EINPROGRESS) + { + source = _g_fd_source_new (socket->priv->fd, G_IO_OUT | G_IO_ERR, cancellable); + + data = g_new (ConnectData, 1); + + data->socket = socket; + data->callback = callback; + data->cancellable = cancellable; + data->user_data = user_data; + data->address_length = len; + memcpy (data->address_buffer, buffer, len); + + g_source_set_callback (source, (GSourceFunc) connect_callback, data, g_free); + + g_source_attach (source, NULL); + } + else + { + g_simple_async_report_error_in_idle (G_OBJECT (socket), callback, user_data, G_IO_ERROR, g_io_error_from_errno (errno), "error connecting: %s", g_strerror (errno)); + } + } + else + { + result = g_simple_async_result_new (G_OBJECT (socket), callback, user_data, g_socket_connect_async); + + g_simple_async_result_complete_in_idle (result); + + g_object_unref (result); + } +} + +gboolean +g_socket_connect_finish (GSocket *socket, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (G_IS_SOCKET (socket), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_socket_connect_async); + + return TRUE; +} + void g_tcp_client_close (GTcpClient *tcp_client) { diff --git a/gnio/gtcpclient.h b/gnio/gtcpclient.h index f461221..8a1bf7f 100644 --- a/gnio/gtcpclient.h +++ b/gnio/gtcpclient.h @@ -56,12 +56,27 @@ struct _GTcpClientClass GObjectClass parent_class; }; -GType g_tcp_client_get_type (void) G_GNUC_CONST; +GType g_tcp_client_get_type (void) G_GNUC_CONST; -GTcpClient * g_tcp_client_new (GInetSocketAddress *address, - GError **error); +GTcpClient * g_tcp_client_new (const gchar *hostname, + gushort port); -void g_tcp_client_close (GTcpClient *client); +GTcpClient * g_tcp_client_new_from_address (GInetSocketAddress *address); + +gboolean g_tcp_client_connect (GTcpClient *clientt, + GCancellable *cancellable, + GError **error); + +void g_tcp_client_connect_async (GTcpClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean g_tcp_client_connect_finish (GTcpClient *client, + GAsyncResult *result, + GError **error); + +void g_tcp_client_close (GTcpClient *client); G_END_DECLS -- 2.20.1