[gnio/connection-factory: 7/8] Merge branch 'master' into connection-factory
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnio/connection-factory: 7/8] Merge branch 'master' into connection-factory
- Date: Thu, 14 May 2009 13:21:08 -0400 (EDT)
commit dc6383ca0b55cdc0b9bcac056cd8a6608bb02c38
Merge: 9247ac0... b6d42bb...
Author: Alexander Larsson <alexl redhat com>
Date: Thu May 14 18:46:42 2009 +0200
Merge branch 'master' into connection-factory
Conflicts:
gio/Makefile.am
gio/gsocket.c
gio/gsocket.h
gio/gsocketclient.c
gio/gsocketlistener.c
gio/gtcpclient.c
gio/gtcplistener.c
gio/gunixclient.c
gio/gunixlistener.c
configure.ac | 49 +-
gio/Makefile.am | 16 +-
gio/gasyncinitable.c | 377 ------
gio/gasyncinitable.h | 120 --
gio/ginitable.c | 245 ----
gio/ginitable.h | 96 --
gio/giostream.c | 524 --------
gio/giostream.h | 113 --
gio/gnio.h | 4 -
gio/gnioerror.h | 41 -
gio/gsocket.c | 2973 -------------------------------------------
gio/gsocket.h | 256 ----
gio/gsocketclient.c | 5 +-
gio/gsocketcontrolmessage.c | 192 ---
gio/gsocketcontrolmessage.h | 90 --
gio/gsocketlistener.c | 5 +-
gio/gtls.h | 2 +-
gio/gunixfdmessage.c | 252 ----
gio/gunixfdmessage.h | 58 -
test/server.c | 5 +-
20 files changed, 9 insertions(+), 5414 deletions(-)
diff --cc gio/Makefile.am
index ce38509,cf2e468..bf4346f
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@@ -30,8 -27,9 +25,7 @@@ sources =
if OS_UNIX
unix_sources = \
- gunixconnection.c \
- gunixfdmessage.c
- gunixclient.c \
- gunixconnection.c \
- gunixlistener.c
++ gunixconnection.c
else
unix_sources =
endif
@@@ -45,22 -43,18 +39,14 @@@ endi
gioincludedir = $(includedir)/gnio/gio
headers = \
- giostream.h \
gnio.h \
- gnioconfig.h \
- gnioerror.h \
- gasyncinitable.h \
- ginitable.h \
- gsocket.h \
gsocketclient.h \
gsocketconnection.h \
- gsocketcontrolmessage.h \
gsocketlistener.h \
gsocketservice.h \
- gtcpclient.h \
gtcpconnection.h \
- gtcplistener.h \
gthreadedsocketservice.h \
- gunixfdmessage.h \
- gunixclient.h \
- gunixconnection.h \
- gunixlistener.h
+ gunixconnection.h
gioinclude_HEADERS = $(headers) gnioenums.h
diff --cc gio/gsocketclient.c
index a5060dd,7b270b8..40bf524
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@@ -37,62 -27,17 +37,63 @@@
#include <gio/gsimpleasyncresult.h>
#include <gio/gcancellable.h>
#include <gio/gioerror.h>
+#include <gio/gnetworkaddress.h>
- #include "gsocket.h"
+ #include <gio/gsocketaddress.h>
G_DEFINE_TYPE (GSocketClient, g_socket_client, G_TYPE_OBJECT);
+enum
+{
+ PROP_NONE,
+ PROP_FAMILY,
+ PROP_TYPE,
+ PROP_PROTOCOL,
+ PROP_LOCAL_ADDRESS
+};
+
+struct _GSocketClientPrivate
+{
+ GSocketFamily family;
+ GSocketType type;
+ char *protocol;
+ GSocketAddress *local_address;
+};
+
static GSocket *
-g_socket_client_real_socket_factory (GSocketClient *client,
- GSocketAddress *address,
- GError **error)
+create_socket (GSocketClient *client,
+ GSocketAddress *dest_address,
+ GError **error)
{
- return g_socket_new (g_socket_address_get_family (address),
- G_SOCKET_TYPE_STREAM, NULL, error);
+ GSocketFamily family;
+ GSocket *socket;
+
+ family = client->priv->family;
+ if (family == G_SOCKET_FAMILY_INVALID &&
+ client->priv->local_address != NULL)
+ family = g_socket_address_get_family (client->priv->local_address);
+ if (family == G_SOCKET_FAMILY_INVALID)
+ family = g_socket_address_get_family (dest_address);
+
+ socket = g_socket_new (family,
+ client->priv->type,
+ client->priv->protocol,
+ error);
+ if (socket == NULL)
+ return NULL;
+
+ if (client->priv->local_address)
+ {
+ if (!g_socket_bind (socket,
+ client->priv->local_address,
++ FALSE,
+ error))
+ {
+ g_object_unref (socket);
+ return NULL;
+ }
+ }
+
+ return socket;
}
static void
@@@ -526,17 -145,9 +527,17 @@@ g_socket_client_enumerator_callback (GO
GAsyncResult *result,
gpointer user_data);
+static void
+set_last_error (GSocketClientAsyncConnectData *data,
+ GError *error)
+{
+ g_clear_error (&data->last_error);
+ data->last_error = error;
+}
+
static gboolean
g_socket_client_socket_callback (GSocket *socket,
- GIOCondition condition,
+ GIOCondition condition,
GSocketClientAsyncConnectData *data)
{
GError *error = NULL;
diff --cc gio/gsocketlistener.c
index db964bd,e0ddf17..9ac7299
--- a/gio/gsocketlistener.c
+++ b/gio/gsocketlistener.c
@@@ -25,31 -25,19 +25,30 @@@
#include "gsocketlistener.h"
+#include "config.h"
#include <gio/gsimpleasyncresult.h>
#include <gio/gcancellable.h>
- #include <gio/gioerror.h>
++#include <gio/gsocketaddress.h>
+#include <gio/ginetaddress.h>
+#include <gio/ginetsocketaddress.h>
- #include "gsocket.h"
-G_DEFINE_ABSTRACT_TYPE (GSocketListener, g_socket_listener, G_TYPE_OBJECT);
+G_DEFINE_TYPE (GSocketListener, g_socket_listener, G_TYPE_OBJECT);
-struct _GSocketListenerPrivate
+enum
{
- GSocket *socket;
- GError *error;
+ PROP_0,
+ PROP_LISTEN_BACKLOG
+};
+
- GSimpleAsyncResult *result;
- GCancellable *cancellable;
- gboolean from_mainloop;
+static GQuark source_quark = 0;
+
+struct _GSocketListenerPrivate
+{
+ GPtrArray *sockets;
+ GMainContext *main_context;
+ int listen_backlog;
+ guint closed : 1;
};
static void
@@@ -131,303 -83,53 +130,303 @@@ g_socket_listener_class_init (GSocketLi
}
static void
-g_socket_listener_init (GSocketListener *server)
+g_socket_listener_init (GSocketListener *listener)
{
- server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server,
- G_TYPE_SOCKET_LISTENER,
- GSocketListenerPrivate);
+ listener->priv = G_TYPE_INSTANCE_GET_PRIVATE (listener,
+ G_TYPE_SOCKET_LISTENER,
+ GSocketListenerPrivate);
+ listener->priv->sockets =
+ g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+ listener->priv->listen_backlog = 10;
}
-GSocketConnection *
-g_socket_listener_accept (GSocketListener *listener,
- GCancellable *cancellable,
- GError **error)
+GSocketListener *
+g_socket_listener_new (void)
+{
+ return g_object_new (G_TYPE_SOCKET_LISTENER, NULL);
+}
+
+static gboolean
+check_listener (GSocketListener *listener,
+ GError **error)
+{
+ if (listener->priv->closed)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ _("Listener is already closed"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+g_socket_listener_add_socket (GSocketListener *listener,
+ GSocket *socket,
+ GObject *source_object,
+ GError **error)
+{
+ if (!check_listener (listener, error))
+ return FALSE;
+
+ /* TODO: Check that socket it is bound & not closed? */
+
+ if (g_socket_is_closed (socket))
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Added socket is closed"));
+ return FALSE;
+ }
+
+ g_ptr_array_add (listener->priv->sockets, socket);
+ g_socket_set_listen_backlog (socket, listener->priv->listen_backlog);
+
+ if (source_object)
+ g_object_set_qdata_full (G_OBJECT (socket), source_quark,
+ g_object_ref (source_object), g_object_unref);
+
+ return TRUE;
+}
+
+gboolean
+g_socket_listener_add_address (GSocketListener *listener,
+ GSocketAddress *address,
+ GSocketType type,
+ const char *protocol,
+ GObject *source_object,
+ GError **error)
{
+ GSocketFamily family;
GSocket *socket;
- g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), NULL);
+ if (!check_listener (listener, error))
+ return FALSE;
+
+ family = g_socket_address_get_family (address);
+ socket = g_socket_new (family, type, protocol, error);
+ if (socket == NULL)
+ return FALSE;
+
- if (!g_socket_bind (socket, address, error) ||
++ if (!g_socket_bind (socket, address, TRUE, error) ||
+ !g_socket_listen (socket, error) ||
+ !g_socket_listener_add_socket (listener, socket,
+ source_object,
+ error))
+ {
+ g_object_unref (socket);
+ return FALSE;
+ }
+
+ if (G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
+ G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);
+
+ return TRUE;
+}
+
+gboolean
+g_socket_listener_add_inet_port (GSocketListener *listener,
+ int port,
+ GObject *source_object,
+ GError **error)
+{
+ GSocketAddress *address4, *address6;
+ GInetAddress *inet_address;
+ gboolean res;
+
+ if (!check_listener (listener, error))
+ return FALSE;
+
+ inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
+ address4 = g_inet_socket_address_new (inet_address, port);
+ g_object_unref (inet_address);
+
+ inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
+ address6 = g_inet_socket_address_new (inet_address, port);
+ g_object_unref (inet_address);
+
+ if (!g_socket_listener_add_address (listener,
+ address6,
+ G_SOCKET_TYPE_STREAM,
+ NULL,
+ source_object,
+ NULL))
+ {
+ /* Failed, to create ipv6, socket, just use ipv4,
+ return any error */
+ res = g_socket_listener_add_address (listener,
+ address4,
+ G_SOCKET_TYPE_STREAM,
+ NULL,
+ source_object,
+ error);
+ }
+ else
+ {
+ /* Succeeded with ipv6, also try ipv4 in case its ipv6 only,
+ but ignore errors here */
+ res = TRUE;
+ g_socket_listener_add_address (listener,
+ address4,
+ G_SOCKET_TYPE_STREAM,
+ NULL,
+ source_object,
+ NULL);
+ }
+
+ g_object_unref (address4);
+ g_object_unref (address6);
+
+ return res;
+}
+
+static GList *
+add_sources (GSocketListener *listener,
+ GSocketSourceFunc callback,
+ gpointer callback_data,
+ GCancellable *cancellable,
+ GMainContext *context)
+{
+ GSocket *socket;
+ GSource *source;
+ GList *sources;
+ int i;
- if (listener->priv->error)
+ sources = NULL;
+ for (i = 0; i < listener->priv->sockets->len; i++)
{
- if (error)
- *error = g_error_copy (listener->priv->error);
+ socket = listener->priv->sockets->pdata[i];
+
+ source = g_socket_create_source (socket, G_IO_IN, cancellable);
+ g_source_set_callback (source,
+ (GSourceFunc) callback,
+ callback_data, NULL);
+ g_source_attach (source, context);
+
+ sources = g_list_prepend (sources, source);
+ }
+
+ return sources;
+}
+
+static void
+free_sources (GList *sources)
+{
+ GSource *source;
+ while (sources != NULL)
+ {
+ source = sources->data;
+ sources = g_list_delete_link (sources, sources);
+ g_source_destroy (source);
+ g_source_unref (source);
+ }
+}
+
+struct AcceptData {
+ GMainLoop *loop;
+ GSocket *socket;
+};
+
+static gboolean
+accept_callback (GSocket *socket,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ struct AcceptData *data = user_data;
+
+ data->socket = socket;
+ g_main_loop_quit (data->loop);
- return NULL;
+ return TRUE;
+}
+
+GSocket *
+g_socket_listener_accept_socket (GSocketListener *listener,
+ GCancellable *cancellable,
+ GObject **source_object,
+ GError **error)
+{
+ GSocket *accept_socket, *socket;
+
+ g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), NULL);
+
+ if (!check_listener (listener, error))
+ return NULL;
+
+ if (listener->priv->sockets->len == 1)
+ {
+ accept_socket = listener->priv->sockets->pdata[0];
+ if (!g_socket_condition_wait (accept_socket, G_IO_IN,
+ cancellable, error))
+ return NULL;
+ }
+ else
+ {
+ GList *sources;
+ struct AcceptData data;
+ GMainLoop *loop;
+
+ if (listener->priv->main_context == NULL)
+ listener->priv->main_context = g_main_context_new ();
+
+ loop = g_main_loop_new (listener->priv->main_context, FALSE);
+ data.loop = loop;
+ sources = add_sources (listener,
+ accept_callback,
+ &data,
+ cancellable,
+ listener->priv->main_context);
+ g_main_loop_run (loop);
+ accept_socket = data.socket;
+ free_sources (sources);
+ g_main_loop_unref (loop);
}
- if (!g_socket_condition_wait (listener->priv->socket, G_IO_IN,
- cancellable, error))
+ if (!(socket = g_socket_accept (accept_socket, error)))
return NULL;
- if (!(socket = g_socket_accept (listener->priv->socket, error)))
+ if (source_object)
+ *source_object = g_object_get_qdata (G_OBJECT (accept_socket), source_quark);
+
+ return socket;
+}
+
+GSocketConnection *
+g_socket_listener_accept (GSocketListener *listener,
+ GCancellable *cancellable,
+ GObject **source_object,
+ GError **error)
+{
+ GSocketConnection *connection;
+ GSocket *socket;
+
+ socket = g_socket_listener_accept_socket (listener,
+ cancellable,
+ source_object,
+ error);
+ if (socket == NULL)
return NULL;
- return G_SOCKET_LISTENER_GET_CLASS (listener)
- ->connection_factory (listener, socket);
+ connection = g_socket_connection_factory_create_connection (socket);
+ g_object_unref (socket);
+
+ return connection;
}
+struct AcceptAsyncData {
+ GSimpleAsyncResult *simple;
+ GCancellable *cancellable;
+ GList *sources;
+};
+
static gboolean
-g_socket_listener_accept_ready (GSocket *socket,
- GIOCondition condition,
- GSocketListener *listener)
+accept_ready (GSocket *accept_socket,
+ GIOCondition condition,
+ gpointer _data)
{
- GSimpleAsyncResult *simple;
+ struct AcceptAsyncData *data = _data;
GError *error = NULL;
- simple = listener->priv->result;
- listener->priv->result = NULL;
-
- if (!g_cancellable_set_error_if_cancelled (listener->priv->cancellable,
+ if (!g_cancellable_set_error_if_cancelled (data->cancellable,
&error))
{
GSocket *socket;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]