GInet6Address *
g_inet6_address_new_any (void)
{
- return NULL;
+ guint8 bytes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ return g_inet6_address_from_bytes (bytes);
}
}
else if (G_IS_INET6_ADDRESS (addr->priv->address))
{
- return FALSE;
+ struct sockaddr_in6 *sock = (struct sockaddr_in6 *) dest;
+ memset (sock, 0, sizeof (sock));
+ sock->sin6_family = AF_INET6;
+ sock->sin6_port = g_htons (addr->priv->port);
+ memcpy (&(sock->sin6_addr.s6_addr), g_inet6_address_to_bytes (G_INET6_ADDRESS (addr->priv->address)), sizeof (sock->sin6_addr));
+ return TRUE;
}
else
return FALSE;
#include <glib.h>
#include <gio/gio.h>
+#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));
}
#include <glib-object.h>
#include <gio/gio.h>
+#include <gnio/gsocket.h>
+
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))
typedef struct _GNetworkInputStream GNetworkInputStream;
typedef struct _GNetworkInputStreamClass GNetworkInputStreamClass;
+typedef struct _GNetworkInputStreamPrivate GNetworkInputStreamPrivate;
struct _GNetworkInputStream
{
GInputStream parent;
+
+ GNetworkInputStreamPrivate *priv;
};
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
#include <glib.h>
#include <gio/gio.h>
+#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));
}
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))
typedef struct _GNetworkOutputStream GNetworkOutputStream;
typedef struct _GNetworkOutputStreamClass GNetworkOutputStreamClass;
+typedef struct _GNetworkOutputStreamPrivate GNetworkOutputStreamPrivate;
struct _GNetworkOutputStream
{
GOutputStream parent;
+
+ GNetworkOutputStreamPrivate *priv;
};
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
#include <config.h>
#include <glib.h>
#include <gio/gio.h>
-#include <gnio/gnio.h>
#include "gasynchelper.h"
-#include "gnioenumtypes.h"
#include <string.h>
#ifndef G_OS_WIN32
g_warning ("Error setting socket status flags: %s", g_strerror (errno));
socket->priv->blocking = blocking;
+
+ g_object_notify (G_OBJECT (socket), "blocking");
}
gboolean
g_warning ("error setting reuse address: %s", g_strerror (errno));
socket->priv->reuse_address = reuse;
+
+ g_object_notify (G_OBJECT (socket), "reuse-address");
}
gboolean
return socket->priv->reuse_address;
}
+gboolean
+g_socket_has_socket_error (GSocket *socket,
+ GError **error)
+{
+ gint sockerr;
+ guint32 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)
{
gchar buffer[256];
- gsize len = 256;
+ guint32 len = 256;
g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
GError **error)
{
gchar buffer[256];
- gsize len = 256;
+ guint32 len = 256;
g_return_val_if_fail (G_IS_SOCKET (socket), NULL);
gssize
g_socket_send (GSocket *socket,
- gchar *buffer,
+ const gchar *buffer,
gsize size,
GError **error)
{
{
g_return_val_if_fail (G_IS_SOCKET (socket) && (cancellable == NULL || G_IS_CANCELLABLE (cancellable)), NULL);
- return _g_fd_source_new (socket->priv->fd, G_IO_IN | G_IO_HUP | G_IO_ERR, cancellable);
+ return _g_fd_source_new (socket->priv->fd, condition, cancellable);
}
gboolean g_socket_get_reuse_address (GSocket *socket);
-gboolean g_socket_has_error (GSocket *socket,
+gboolean g_socket_has_socket_error (GSocket *socket,
GError **error);
gboolean g_socket_bind (GSocket *socket,
GError **error);
gssize g_socket_send (GSocket *socket,
- gchar *buffer,
+ const gchar *buffer,
gsize size,
GError **error);
#include "gsocketaddress.h"
#include "ginetsocketaddress.h"
#include "ginet4address.h"
+#include "ginet6address.h"
G_DEFINE_ABSTRACT_TYPE (GSocketAddress, g_socket_address, G_TYPE_INITIALLY_UNOWNED);
return G_SOCKET_ADDRESS (g_inet_socket_address_new (G_INET_ADDRESS (g_inet4_address_from_bytes ((guint8 *) &(addr->sin_addr))), g_ntohs (addr->sin_port)));
}
- // TODO: handle AF_INET6 and AF_UNIX
+
+ if (family == AF_INET6)
+ {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *) native;
+
+ return G_SOCKET_ADDRESS (g_inet_socket_address_new (G_INET_ADDRESS (g_inet6_address_from_bytes ((guint8 *) &(addr->sin6_addr))), g_ntohs (addr->sin6_port)));
+ }
+
+ // TODO: handle AF_UNIX
return NULL;
}
PROP_0,
PROP_ADDRESS,
PROP_HOSTNAME,
- PROP_PORT
+ PROP_PORT,
+ PROP_INPUT_STREAM,
+ PROP_OUTPUT_STREAM
};
struct _GTcpClientPrivate
{
- GInetSocketAddress *address;
- gchar *hostname;
- gushort port;
- GSocket *socket;
+ GInetSocketAddress *address;
+ gchar *hostname;
+ gushort port;
+ GSocket *socket;
+ GNetworkInputStream *input;
+ GNetworkOutputStream *output;
};
static void
g_value_set_uint (value, client->priv->port);
break;
+ case PROP_INPUT_STREAM:
+ g_value_set_object (value, g_tcp_client_get_input_stream (client));
+ break;
+
+ case PROP_OUTPUT_STREAM:
+ g_value_set_object (value, g_tcp_client_get_output_stream (client));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
G_MAXUSHORT,
0,
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_INPUT_STREAM,
+ g_param_spec_object ("input-stream",
+ "input stream",
+ "the GNetworkInputStream for reading from this socket",
+ G_TYPE_NETWORK_INPUT_STREAM,
+ G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
+
+ g_object_class_install_property (gobject_class, PROP_OUTPUT_STREAM,
+ g_param_spec_object ("output-stream",
+ "output stream",
+ "the GNetworkOutputStream for writing to this socket",
+ G_TYPE_NETWORK_OUTPUT_STREAM,
+ G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
}
static void
client->priv->hostname = NULL;
client->priv->port = 0;
client->priv->socket = NULL;
+ client->priv->input = NULL;
+ client->priv->output = NULL;
}
GTcpClient *
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;
+
+ if (client->priv->input)
+ return client->priv->input;
+
+ // TODO: should we set g_object_notify here, or just create both these streams earlier?
+
+ return (client->priv->input = _g_network_input_stream_new (client->priv->socket));
+}
+
+GNetworkOutputStream *
+g_tcp_client_get_output_stream (GTcpClient *client)
+{
+ if (!client->priv->socket)
+ return NULL;
+
+ if (client->priv->output)
+ return client->priv->output;
+
+ // TODO: should we set g_object_notify here, or just create both these streams earlier?
+
+ return (client->priv->output = _g_network_output_stream_new (client->priv->socket));
+}
+
gboolean
g_tcp_client_connect (GTcpClient *client,
GCancellable *cancellable,
}
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))
GCancellable *cancellable;
gpointer user_data;
GTcpClient *client;
- gchar address_buffer[256];
- gsize address_length;
} ConnectData;
static gboolean
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 (!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;
}
+static void
+resolve_callback (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ConnectData *data = (ConnectData *) user_data;
+ GInetAddress *address;
+ GSimpleAsyncResult *error_result;
+ GError *error = NULL;
+
+ address = g_resolver_resolve_finish (G_RESOLVER (source), result, &error);
+
+ g_object_unref (G_RESOLVER (source));
+
+ if (!address)
+ {
+ error_result = g_simple_async_result_new_from_error (G_OBJECT (data->client), data->callback, data->user_data, error);
+
+ g_simple_async_result_complete (error_result);
+
+ g_object_unref (error_result);
+ }
+ else
+ {
+ data->client->priv->address = g_inet_socket_address_new (address, data->client->priv->port);
+
+ g_object_ref_sink (data->client->priv->address);
+
+ // at this point, the address has been resolved, so connect_async again
+ g_tcp_client_connect_async (data->client, data->cancellable, data->callback, data->user_data);
+ }
+
+ g_free (data);
+}
+
void
g_tcp_client_connect_async (GTcpClient *client,
GCancellable *cancellable,
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 ();
+
+ data = g_new (ConnectData, 1);
+
+ data->client = client;
+ data->callback = callback;
+ data->cancellable = cancellable;
+ data->user_data = user_data;
+
+ g_resolver_resolve_async (resolver, client->priv->hostname, cancellable, resolve_callback, data);
+
+ 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 | G_IO_HUP, 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
if (size == 0)
break;
- g_print ("received %d bytes of data: %s\n", size, buffer);
+ g_print ("received %" G_GSSIZE_FORMAT " bytes of data: %s\n", size, buffer);
if ((size = g_socket_send (new_socket, buffer, size, &error)) < 0) {
g_error (error->message);
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));
g_free (string);
}
-void
+static void
resolve_callback (GObject *source, GAsyncResult *result, gpointer data)
{
GError *error = NULL;
GMainLoop *loop;
-/*
-void
-accept_callback (GSocket *socket, GAsyncResult *result, gpointer data)
+static void
+connect_callback (GObject *source, GAsyncResult *result, gpointer data)
{
+ GTcpClient *client = G_TCP_CLIENT (source);
+ GInputStream *input;
+ GOutputStream *output;
+ gchar buffer[512] = {0};
+ gssize count;
GError *error = NULL;
- if (!g_socket_connect_finish (socket, result, &error)) {
+ if (!g_tcp_client_connect_finish (client, result, &error)) {
g_warning (error->message);
return;
}
g_print ("successfully 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;
+ }
+
+ g_print ("wrote %" G_GSSIZE_FORMAT " bytes\n", count);
+
+ if ((count = g_input_stream_read (input, buffer, 512, NULL, &error)) < 0) {
+ g_warning (error->message);
+ return;
+ }
+
+ g_print ("read %" G_GSSIZE_FORMAT " bytes: %s\n", count, buffer);
}
-*/
int main (int argc, char *argv[])
{
GTcpClient *client;
- GError *error = NULL;
g_thread_init (NULL);
loop = g_main_loop_new (NULL, FALSE);
- client = g_tcp_client_new ("localhost", 90);
+ client = g_tcp_client_new ("localhost", 31882);
g_print ("connecting to www.google.com:80\n");
+ g_tcp_client_connect_async (client, NULL, connect_callback, NULL);
+
+ g_print ("connecting seems to have begun\n");
+/*
if (!g_tcp_client_connect (client, NULL, &error)) {
g_warning (error->message);
return 1;
g_print ("connected!\n");
g_object_unref (G_OBJECT (client));
+*/
-// g_main_loop_run (loop);
+ g_main_loop_run (loop);
return 0;
}
+