From 6ab527e0c7a63c5ffd925120dcb8b8b6cbd6c6ca Mon Sep 17 00:00:00 2001 From: Samuel Cormier-Iijima Date: Sat, 1 Mar 2008 20:01:52 -0500 Subject: [PATCH] TcpClient seems to be working for sync connects, but connect() can block indefinitely. Maybe we can specify a timeout? --- gnio/ginet6address.h | 2 +- gnio/gnetworkinputstream.h | 1 - gnio/gresolver.c | 6 ++++ gnio/gresolver.h | 2 ++ gnio/gtcpclient.c | 60 +++++++++++++++++++++++++++++++++----- gnio/gtcpclient.h | 6 ++-- test/Makefile.am | 1 + test/test-tcp-client.c | 48 ++++++++++++++++++++++++++++++ 8 files changed, 114 insertions(+), 12 deletions(-) create mode 100644 test/test-tcp-client.c diff --git a/gnio/ginet6address.h b/gnio/ginet6address.h index ba791b6..d615426 100644 --- a/gnio/ginet6address.h +++ b/gnio/ginet6address.h @@ -25,7 +25,7 @@ #define G_INET6_ADDRESS_H #include -#include +#include G_BEGIN_DECLS diff --git a/gnio/gnetworkinputstream.h b/gnio/gnetworkinputstream.h index 06df919..fb51da5 100644 --- a/gnio/gnetworkinputstream.h +++ b/gnio/gnetworkinputstream.h @@ -58,4 +58,3 @@ GNetworkInputStream * g_network_input_stream_new (GSocket *socket); G_END_DECLS #endif /* G_NETWORK_INPUT_STREAM_H */ - diff --git a/gnio/gresolver.c b/gnio/gresolver.c index dac4a93..014be9a 100644 --- a/gnio/gresolver.c +++ b/gnio/gresolver.c @@ -405,6 +405,12 @@ g_resolver_init (GResolver *address) } +GResolver * +g_resolver_new () +{ + return G_RESOLVER (g_object_new (G_TYPE_RESOLVER, NULL)); +} + typedef struct { GList *list; const gchar *host; diff --git a/gnio/gresolver.h b/gnio/gresolver.h index fbc1ffb..9484511 100644 --- a/gnio/gresolver.h +++ b/gnio/gresolver.h @@ -53,6 +53,8 @@ struct _GResolverClass GType g_resolver_get_type (void) G_GNUC_CONST; +GResolver * g_resolver_new (void); + GInetAddress * g_resolver_resolve (GResolver *resolver, const char *host, GCancellable *cancellable, 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 { diff --git a/gnio/gtcpclient.h b/gnio/gtcpclient.h index f3a9cce..ff71d73 100644 --- a/gnio/gtcpclient.h +++ b/gnio/gtcpclient.h @@ -61,9 +61,9 @@ GTcpClient * g_tcp_client_new (const gchar *hostname, GTcpClient * g_tcp_client_new_from_address (GInetSocketAddress *address); -gboolean g_tcp_client_connect (GTcpClient *client, - GCancellable *cancellable, - GError **error); +gboolean g_tcp_client_connect (GTcpClient *client, + GCancellable *cancellable, + GError **error); void g_tcp_client_connect_async (GTcpClient *client, GCancellable *cancellable, diff --git a/test/Makefile.am b/test/Makefile.am index 9e32d5f..f450c7a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,6 +13,7 @@ noinst_PROGRAMS = \ test-stuff \ test-server \ test-client \ + test-tcp-client \ $(NULL) EXTRA_DIST = diff --git a/test/test-tcp-client.c b/test/test-tcp-client.c new file mode 100644 index 0000000..d9c7679 --- /dev/null +++ b/test/test-tcp-client.c @@ -0,0 +1,48 @@ +#include +#include + +GMainLoop *loop; + +/* +void +accept_callback (GSocket *socket, GAsyncResult *result, gpointer data) +{ + GError *error = NULL; + + if (!g_socket_connect_finish (socket, result, &error)) { + g_warning (error->message); + return; + } + + g_print ("successfully connected\n"); +} +*/ + +int main (int argc, char *argv[]) +{ + GTcpClient *client; + GError *error = NULL; + + g_thread_init (NULL); + + g_type_init (); + + loop = g_main_loop_new (NULL, FALSE); + + client = g_tcp_client_new ("localhost", 90); + + g_print ("connecting to www.google.com:80\n"); + + if (!g_tcp_client_connect (client, NULL, &error)) { + g_warning (error->message); + return; + } + + g_print ("connected!\n"); + + g_object_unref (G_OBJECT (client)); + +// g_main_loop_run (loop); + + return 0; +} -- 2.20.1