From 08b3eba2ce5f8beafb2b8cb8fc8b08c9676adf5f Mon Sep 17 00:00:00 2001 From: Samuel Cormier-Iijima Date: Sat, 1 Mar 2008 23:08:12 -0500 Subject: [PATCH] Starting the NetworkStreams. HTTP to www.google.com works with the sync API calls. --- gnio/gnetworkinputstream.c | 105 +++++++++++++++++++++++++++++++++++- gnio/gnetworkinputstream.h | 9 +++- gnio/gnetworkoutputstream.c | 105 +++++++++++++++++++++++++++++++++++- gnio/gnetworkoutputstream.h | 7 ++- gnio/gsocket.c | 6 ++- gnio/gsocket.h | 2 +- gnio/gtcpclient.c | 20 +++++++ test/test-stuff.c | 6 +-- test/test-tcp-client.c | 26 ++++++++- 9 files changed, 272 insertions(+), 14 deletions(-) diff --git a/gnio/gnetworkinputstream.c b/gnio/gnetworkinputstream.c index a7bdbb6..48ecf8c 100644 --- a/gnio/gnetworkinputstream.c +++ b/gnio/gnetworkinputstream.c @@ -25,18 +25,119 @@ #include #include +#include "gsocket.h" #include "gnetworkinputstream.h" G_DEFINE_TYPE (GNetworkInputStream, g_network_input_stream, G_TYPE_INPUT_STREAM); +enum +{ + PROP_0, + PROP_SOCKET +}; + +struct _GNetworkInputStreamPrivate +{ + GSocket *socket; +}; + +static void +g_network_input_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GNetworkInputStream *stream = G_NETWORK_INPUT_STREAM (object); + + switch (prop_id) + { + case PROP_SOCKET: + g_value_set_object (value, stream->priv->socket); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_network_input_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GNetworkInputStream *stream = G_NETWORK_INPUT_STREAM (object); + + switch (prop_id) + { + case PROP_SOCKET: + stream->priv->socket = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_network_input_stream_finalize (GObject *object) +{ + if (G_OBJECT_CLASS (g_network_input_stream_parent_class)->finalize) + (*G_OBJECT_CLASS (g_network_input_stream_parent_class)->finalize) (object); +} + +static void +g_network_input_stream_dispose (GObject *object) +{ + if (G_OBJECT_CLASS (g_network_input_stream_parent_class)->dispose) + (*G_OBJECT_CLASS (g_network_input_stream_parent_class)->dispose) (object); +} + +static gssize +g_network_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + GNetworkInputStream *input_stream = G_NETWORK_INPUT_STREAM (stream); + + return g_socket_receive (input_stream->priv->socket, (gchar *) buffer, count, error); +} + static void g_network_input_stream_class_init (GNetworkInputStreamClass *klass) { - GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GInputStreamClass *ginputstream_class = G_INPUT_STREAM_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GNetworkInputStreamPrivate)); + + gobject_class->finalize = g_network_input_stream_finalize; + gobject_class->dispose = g_network_input_stream_dispose; + gobject_class->get_property = g_network_input_stream_get_property; + gobject_class->set_property = g_network_input_stream_set_property; + + ginputstream_class->read_fn = g_network_input_stream_read; + + g_object_class_install_property (gobject_class, PROP_SOCKET, + g_param_spec_object ("socket", + "socket", + "the socket that this stream wraps", + G_TYPE_SOCKET, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); } static void -g_network_input_stream_init (GNetworkInputStream *address) +g_network_input_stream_init (GNetworkInputStream *stream) { + stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, G_TYPE_NETWORK_INPUT_STREAM, GNetworkInputStreamPrivate); + + stream->priv->socket = NULL; +} +GNetworkInputStream * +_g_network_input_stream_new (GSocket *socket) +{ + return G_NETWORK_INPUT_STREAM (g_object_new (G_TYPE_NETWORK_INPUT_STREAM, "socket", socket, NULL)); } diff --git a/gnio/gnetworkinputstream.h b/gnio/gnetworkinputstream.h index 9d6d42e..db44e86 100644 --- a/gnio/gnetworkinputstream.h +++ b/gnio/gnetworkinputstream.h @@ -27,9 +27,11 @@ #include #include +#include + G_BEGIN_DECLS -#define G_TYPE_NETWORK_INPUT_STREAM (g_socket_get_type ()) +#define G_TYPE_NETWORK_INPUT_STREAM (g_network_input_stream_get_type ()) #define G_NETWORK_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_NETWORK_INPUT_STREAM, GNetworkInputStream)) #define G_NETWORK_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_NETWORK_INPUT_STREAM, GNetworkInputStreamClass)) #define G_IS_NETWORK_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_NETWORK_INPUT_STREAM)) @@ -38,10 +40,13 @@ G_BEGIN_DECLS typedef struct _GNetworkInputStream GNetworkInputStream; typedef struct _GNetworkInputStreamClass GNetworkInputStreamClass; +typedef struct _GNetworkInputStreamPrivate GNetworkInputStreamPrivate; struct _GNetworkInputStream { GInputStream parent; + + GNetworkInputStreamPrivate *priv; }; struct _GNetworkInputStreamClass @@ -51,7 +56,7 @@ struct _GNetworkInputStreamClass GType g_network_input_stream_get_type (void) G_GNUC_CONST; -GNetworkInputStream * g_network_input_stream_new (void); +GNetworkInputStream * _g_network_input_stream_new (GSocket *socket); G_END_DECLS diff --git a/gnio/gnetworkoutputstream.c b/gnio/gnetworkoutputstream.c index c32a470..b7e9ea6 100644 --- a/gnio/gnetworkoutputstream.c +++ b/gnio/gnetworkoutputstream.c @@ -25,18 +25,119 @@ #include #include +#include "gsocket.h" #include "gnetworkoutputstream.h" G_DEFINE_TYPE (GNetworkOutputStream, g_network_output_stream, G_TYPE_OUTPUT_STREAM); +enum +{ + PROP_0, + PROP_SOCKET +}; + +struct _GNetworkOutputStreamPrivate +{ + GSocket *socket; +}; + +static void +g_network_output_stream_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GNetworkOutputStream *stream = G_NETWORK_OUTPUT_STREAM (object); + + switch (prop_id) + { + case PROP_SOCKET: + g_value_set_object (value, stream->priv->socket); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_network_output_stream_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GNetworkOutputStream *stream = G_NETWORK_OUTPUT_STREAM (object); + + switch (prop_id) + { + case PROP_SOCKET: + stream->priv->socket = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_network_output_stream_finalize (GObject *object) +{ + if (G_OBJECT_CLASS (g_network_output_stream_parent_class)->finalize) + (*G_OBJECT_CLASS (g_network_output_stream_parent_class)->finalize) (object); +} + +static void +g_network_output_stream_dispose (GObject *object) +{ + if (G_OBJECT_CLASS (g_network_output_stream_parent_class)->dispose) + (*G_OBJECT_CLASS (g_network_output_stream_parent_class)->dispose) (object); +} + +static gssize +g_network_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + GNetworkOutputStream *output_stream = G_NETWORK_OUTPUT_STREAM (stream); + + return g_socket_send (output_stream->priv->socket, (const gchar *) buffer, count, error); +} + static void g_network_output_stream_class_init (GNetworkOutputStreamClass *klass) { - GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GOutputStreamClass *goutputstream_class = G_OUTPUT_STREAM_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GNetworkOutputStreamPrivate)); + + gobject_class->finalize = g_network_output_stream_finalize; + gobject_class->dispose = g_network_output_stream_dispose; + gobject_class->get_property = g_network_output_stream_get_property; + gobject_class->set_property = g_network_output_stream_set_property; + + goutputstream_class->write_fn = g_network_output_stream_write; + + g_object_class_install_property (gobject_class, PROP_SOCKET, + g_param_spec_object ("socket", + "socket", + "the socket that this stream wraps", + G_TYPE_SOCKET, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); } static void -g_network_output_stream_init (GNetworkOutputStream *address) +g_network_output_stream_init (GNetworkOutputStream *stream) { + stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, G_TYPE_NETWORK_OUTPUT_STREAM, GNetworkOutputStreamPrivate); + + stream->priv->socket = NULL; +} +GNetworkOutputStream * +_g_network_output_stream_new (GSocket *socket) +{ + return G_NETWORK_OUTPUT_STREAM (g_object_new (G_TYPE_NETWORK_OUTPUT_STREAM, "socket", socket, NULL)); } diff --git a/gnio/gnetworkoutputstream.h b/gnio/gnetworkoutputstream.h index 84615e8..02d2146 100644 --- a/gnio/gnetworkoutputstream.h +++ b/gnio/gnetworkoutputstream.h @@ -29,7 +29,7 @@ G_BEGIN_DECLS -#define G_TYPE_NETWORK_OUTPUT_STREAM (g_socket_get_type ()) +#define G_TYPE_NETWORK_OUTPUT_STREAM (g_network_output_stream_get_type ()) #define G_NETWORK_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_NETWORK_OUTPUT_STREAM, GNetworkOutputStream)) #define G_NETWORK_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_NETWORK_OUTPUT_STREAM, GNetworkOutputStreamClass)) #define G_IS_NETWORK_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_NETWORK_OUTPUT_STREAM)) @@ -38,10 +38,13 @@ G_BEGIN_DECLS typedef struct _GNetworkOutputStream GNetworkOutputStream; typedef struct _GNetworkOutputStreamClass GNetworkOutputStreamClass; +typedef struct _GNetworkOutputStreamPrivate GNetworkOutputStreamPrivate; struct _GNetworkOutputStream { GOutputStream parent; + + GNetworkOutputStreamPrivate *priv; }; struct _GNetworkOutputStreamClass @@ -51,7 +54,7 @@ struct _GNetworkOutputStreamClass GType g_network_output_stream_get_type (void) G_GNUC_CONST; -GNetworkOutputStream * g_network_output_stream_new (void); +GNetworkOutputStream * _g_network_output_stream_new (GSocket *socket); G_END_DECLS diff --git a/gnio/gsocket.c b/gnio/gsocket.c index 605f92b..ba6595b 100644 --- a/gnio/gsocket.c +++ b/gnio/gsocket.c @@ -340,6 +340,8 @@ g_socket_set_blocking (GSocket *socket, g_warning ("Error setting socket status flags: %s", g_strerror (errno)); socket->priv->blocking = blocking; + + g_object_notify (G_OBJECT (socket), "blocking"); } gboolean @@ -362,6 +364,8 @@ g_socket_set_reuse_address (GSocket *socket, g_warning ("error setting reuse address: %s", g_strerror (errno)); socket->priv->reuse_address = reuse; + + g_object_notify (G_OBJECT (socket), "reuse-address"); } gboolean @@ -517,7 +521,7 @@ g_socket_receive (GSocket *socket, gssize g_socket_send (GSocket *socket, - gchar *buffer, + const gchar *buffer, gsize size, GError **error) { diff --git a/gnio/gsocket.h b/gnio/gsocket.h index d28244c..2a50583 100644 --- a/gnio/gsocket.h +++ b/gnio/gsocket.h @@ -111,7 +111,7 @@ gssize g_socket_receive (GSocket *socket, GError **error); gssize g_socket_send (GSocket *socket, - gchar *buffer, + const gchar *buffer, gsize size, GError **error); diff --git a/gnio/gtcpclient.c b/gnio/gtcpclient.c index 1bb056f..c46108c 100644 --- a/gnio/gtcpclient.c +++ b/gnio/gtcpclient.c @@ -201,6 +201,24 @@ g_tcp_client_new_from_address (GInetSocketAddress *address) return G_TCP_CLIENT (g_object_new (G_TYPE_TCP_CLIENT, "address", address, NULL)); } +GNetworkInputStream * +g_tcp_client_get_input_stream (GTcpClient *client) +{ + if (!client->priv->socket) + return NULL; + + return _g_network_input_stream_new (client->priv->socket); +} + +GNetworkOutputStream * +g_tcp_client_get_output_stream (GTcpClient *client) +{ + if (!client->priv->socket) + return NULL; + + return _g_network_output_stream_new (client->priv->socket); +} + gboolean g_tcp_client_connect (GTcpClient *client, GCancellable *cancellable, @@ -262,6 +280,7 @@ typedef struct { gsize address_length; } ConnectData; +/* static gboolean connect_callback (ConnectData *data, GIOCondition condition, @@ -269,6 +288,7 @@ connect_callback (ConnectData *data, { return FALSE; } +*/ void g_tcp_client_connect_async (GTcpClient *client, diff --git a/test/test-stuff.c b/test/test-stuff.c index 4209e86..791748e 100644 --- a/test/test-stuff.c +++ b/test/test-stuff.c @@ -11,9 +11,9 @@ GMainLoop *loop; -void print_address (GInetAddress *address, gpointer data); +static void print_address (GInetAddress *address, gpointer data); -void +static void print_address (GInetAddress *address, gpointer data) { gchar *string = g_inet_address_to_string (G_INET_ADDRESS (address)); @@ -23,7 +23,7 @@ print_address (GInetAddress *address, gpointer data) g_free (string); } -void +static void resolve_callback (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; diff --git a/test/test-tcp-client.c b/test/test-tcp-client.c index f13aae8..467d172 100644 --- a/test/test-tcp-client.c +++ b/test/test-tcp-client.c @@ -21,7 +21,11 @@ accept_callback (GSocket *socket, GAsyncResult *result, gpointer data) int main (int argc, char *argv[]) { GTcpClient *client; + GInputStream *input; + GOutputStream *output; GError *error = NULL; + gchar buffer[512] = {0}; + gssize count; g_thread_init (NULL); @@ -29,7 +33,7 @@ int main (int argc, char *argv[]) loop = g_main_loop_new (NULL, FALSE); - client = g_tcp_client_new ("localhost", 90); + client = g_tcp_client_new ("www.google.com", 80); g_print ("connecting to www.google.com:80\n"); @@ -40,6 +44,26 @@ int main (int argc, char *argv[]) g_print ("connected!\n"); + output = G_OUTPUT_STREAM (g_tcp_client_get_output_stream (client)); + + input = G_INPUT_STREAM (g_tcp_client_get_input_stream (client)); + + g_print ("writing...\n"); + + if ((count = g_output_stream_write (output, "GET / HTTP/1.0\r\n\r\n", 19, NULL, &error)) < 0) { + g_warning (error->message); + return 1; + } + + g_print ("wrote %d bytes\n", count); + + if ((count = g_input_stream_read (input, buffer, 512, NULL, &error)) < 0) { + g_warning (error->message); + return 1; + } + + g_print ("read %d bytes: %s\n", count, buffer); + g_object_unref (G_OBJECT (client)); // g_main_loop_run (loop); -- 2.20.1