[gnio/connection-factory] Re-imagining GSocketListener
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnio/connection-factory] Re-imagining GSocketListener
- Date: Sat, 9 May 2009 17:18:00 -0400 (EDT)
commit 0c236bb6a6437af2ae3fa8f60f109c228f36c02a
Author: Alexander Larsson <alexl redhat com>
Date: Sat May 9 22:28:42 2009 +0200
Re-imagining GSocketListener
We now support multiple sockets in each listener. This way we can
handle the ipv6+ipv4 linux vs non-linux issue nicely (you need 1 socket
on linux, 2 on other platforms).
We also remove the not very useful subclasses by pushing socket factory
to the base class and adding a helper function for the inet port case.
We also add support for listening and then accepting a socket, instead of
always getting a connection, as this may be useful in some cases.
examples/server.c is updated to work with the new APIs
---
examples/server.c | 17 ++-
gio/Makefile.am | 8 +-
gio/gnio.h | 2 -
gio/gsocket.c | 3 +-
gio/gsocketlistener.c | 476 +++++++++++++++++++++++++++++++++++++------------
gio/gsocketlistener.h | 37 +++-
gio/gtcplistener.c | 189 -------------------
gio/gtcplistener.h | 57 ------
gio/gunixlistener.c | 125 -------------
gio/gunixlistener.h | 57 ------
10 files changed, 405 insertions(+), 566 deletions(-)
diff --git a/examples/server.c b/examples/server.c
index 597b581..51d4566 100644
--- a/examples/server.c
+++ b/examples/server.c
@@ -44,6 +44,7 @@ main (int argc, char *argv[])
GSocketService *service;
GOptionContext *context;
GError *error = NULL;
+ GSocketListener *listener;
g_type_init ();
g_thread_init (NULL);
@@ -58,11 +59,17 @@ main (int argc, char *argv[])
service = g_threaded_socket_service_new ();
- {
- GSocketListener *tcp = g_tcp_listener_new (port);
- g_socket_service_add_listener (service, tcp);
- g_object_unref (tcp);
- }
+ listener = g_socket_listener_new ();
+ if (!g_socket_listener_add_inet_port (listener,
+ port,
+ &error))
+ {
+ g_printerr ("%s: %s\n", argv[0], error->message);
+ return 1;
+ }
+
+ g_socket_service_add_listener (service, listener);
+ g_object_unref (listener);
g_print ("Echo service listening on port %d\n", port);
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 672d3e4..ce38509 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -26,14 +26,12 @@ sources = \
gsocketoutputstream.h \
gsocketservice.c \
gtcpconnection.c \
- gtcplistener.c \
gthreadedsocketservice.c
if OS_UNIX
unix_sources = \
gunixconnection.c \
- gunixfdmessage.c \
- gunixlistener.c
+ gunixfdmessage.c
else
unix_sources =
endif
@@ -60,11 +58,9 @@ headers = \
gsocketlistener.h \
gsocketservice.h \
gtcpconnection.h \
- gtcplistener.h \
gthreadedsocketservice.h \
gunixfdmessage.h \
- gunixconnection.h \
- gunixlistener.h
+ gunixconnection.h
gioinclude_HEADERS = $(headers) gnioenums.h
diff --git a/gio/gnio.h b/gio/gnio.h
index 3bde0a3..239df7c 100644
--- a/gio/gnio.h
+++ b/gio/gnio.h
@@ -31,11 +31,9 @@
#include <gio/gsocketlistener.h>
#include <gio/gsocketservice.h>
#include <gio/gtcpconnection.h>
-#include <gio/gtcplistener.h>
#include <gio/gthreadedsocketservice.h>
#include <gio/gtls.h>
#include <gio/gunixconnection.h>
-#include <gio/gunixlistener.h>
#undef __GIO_GIO_H_INSIDE__
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 5f0cfc9..41dab8b 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -2231,7 +2231,8 @@ g_socket_create_source (GSocket *socket,
#ifdef G_OS_WIN32
source = winsock_source_new (socket, condition, cancellable);
#else
- source =_g_fd_source_new (socket->priv->fd, condition, cancellable);
+ source =_g_fd_source_new_with_object (G_OBJECT (socket), socket->priv->fd,
+ condition, cancellable);
#endif
return source;
}
diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c
index a0fe37b..2df057c 100644
--- a/gio/gsocketlistener.c
+++ b/gio/gsocketlistener.c
@@ -25,54 +25,41 @@
#include "gsocketlistener.h"
+#include "config.h"
#include <gio/gsimpleasyncresult.h>
#include <gio/gcancellable.h>
+#include <gio/gioerror.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
{
- GSocket *socket;
- GError *error;
-
- GSimpleAsyncResult *result;
- GCancellable *cancellable;
- gboolean from_mainloop;
+ GPtrArray *sockets;
+ GMainContext *main_context;
+ guint closed : 1;
};
static void
g_socket_listener_finalize (GObject *object)
{
- GSocketListener *server = G_SOCKET_LISTENER (object);
+ GSocketListener *listener = G_SOCKET_LISTENER (object);
- if (server->priv->socket)
- g_object_unref (server->priv->socket);
+ if (listener->priv->main_context)
+ g_main_context_unref (listener->priv->main_context);
- if (server->priv->error)
- g_error_free (server->priv->error);
+ if (!listener->priv->closed)
+ g_socket_listener_close (listener);
- /* the GSimpleAsyncResult maintains a ref to us.
- * if it's non-null, we have a serious problem...
- */
- g_assert (server->priv->cancellable == NULL);
- g_assert (server->priv->result == NULL);
+ g_ptr_array_free (listener->priv->sockets, TRUE);
G_OBJECT_CLASS (g_socket_listener_parent_class)
->finalize (object);
}
static void
-g_socket_listener_construct (GObject *object)
-{
- GSocketListener *listener = G_SOCKET_LISTENER (object);
- GSocketListenerClass *class = G_SOCKET_LISTENER_GET_CLASS (listener);
-
- listener->priv->socket = class->socket_factory (listener,
- &listener->priv->error);
-}
-
-static void
g_socket_listener_class_init (GSocketListenerClass *klass)
{
GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
@@ -80,160 +67,415 @@ g_socket_listener_class_init (GSocketListenerClass *klass)
g_type_class_add_private (klass, sizeof (GSocketListenerPrivate));
gobject_class->finalize = g_socket_listener_finalize;
- gobject_class->constructed = g_socket_listener_construct;
}
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);
}
-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,
+ GError **error)
+{
+ if (!check_listener (listener, error))
+ return FALSE;
+
+ /* TODO: Check that socket it is bound & not closed? */
+
+ g_ptr_array_add (listener->priv->sockets, socket);
+
+ return TRUE;
+}
+
+gboolean
+g_socket_listener_add_address (GSocketListener *listener,
+ GSocketAddress *address,
+ GSocketType type,
+ const char *protocol,
+ GError **error)
+{
+ GSocketFamily family;
GSocket *socket;
- GSocketConnection *connection;
- 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) ||
+ !g_socket_listen (socket, error) ||
+ !g_socket_listener_add_socket (listener, socket, error))
+ {
+ g_object_unref (socket);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+g_socket_listener_add_inet_port (GSocketListener *listener,
+ int port,
+ 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,
+ 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,
+ 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,
+ 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 TRUE;
+}
+
+GSocket *
+g_socket_listener_accept_socket (GSocketListener *listener,
+ GCancellable *cancellable,
+ GSocket **source,
+ GError **error)
+{
+ GSocket *accept_socket, *socket;
+
+ g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), NULL);
+
+ if (!check_listener (listener, error))
+ return NULL;
- 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)
+ *source = accept_socket;
+
+ return socket;
+}
+
+GSocketConnection *
+g_socket_listener_accept (GSocketListener *listener,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GSocketConnection *connection;
+ GSocket *socket;
+
+ socket = g_socket_listener_accept_socket (listener,
+ cancellable,
+ NULL,
+ error);
+ if (socket == NULL)
return NULL;
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;
- socket = g_socket_accept (listener->priv->socket, &error);
-
+ socket = g_socket_accept (accept_socket, &error);
if (socket)
- {
- GSocketConnection *connection;
-
- connection = g_socket_connection_factory_create_connection (socket);
-
- g_simple_async_result_set_op_res_gpointer (simple, connection,
- g_object_unref);
- g_object_unref (socket);
- }
+ {
+ g_simple_async_result_set_op_res_gpointer (data->simple, socket,
+ g_object_unref);
+ g_object_set_data_full (G_OBJECT (data->simple),
+ "accept-socket",
+ g_object_ref (accept_socket),
+ g_object_unref);
+ }
}
if (error)
{
- g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_set_from_error (data->simple, error);
g_error_free (error);
}
- if (listener->priv->cancellable)
- {
- g_object_unref (listener->priv->cancellable);
- listener->priv->cancellable = NULL;
- }
-
- if (listener->priv->from_mainloop)
- g_simple_async_result_complete (simple);
- else
- g_simple_async_result_complete_in_idle (simple);
-
- g_object_unref (simple);
+ g_simple_async_result_complete_in_idle (data->simple);
+ g_object_unref (data->simple);
+ free_sources (data->sources);
+ g_free (data);
return FALSE;
}
+
void
-g_socket_listener_accept_async (GSocketListener *listener,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+g_socket_listener_accept_socket_async (GSocketListener *listener,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- listener->priv->result =
- g_simple_async_result_new (G_OBJECT (listener), callback, user_data,
- g_socket_listener_accept_async);
-
- if (cancellable)
- g_object_ref (cancellable);
- listener->priv->cancellable = cancellable;
-
- if (!g_socket_condition_check (listener->priv->socket, G_IO_IN))
- {
- GSource *source;
-
- listener->priv->from_mainloop = TRUE;
- source = g_socket_create_source (listener->priv->socket,
- G_IO_IN, cancellable);
+ struct AcceptAsyncData *data;
+ GError *error = NULL;
- g_source_set_callback (source,
- (GSourceFunc) g_socket_listener_accept_ready,
- g_object_ref (listener), g_object_unref);
- g_source_attach (source, NULL);
- g_source_unref (source);
- }
- else
+ if (!check_listener (listener, &error))
{
- listener->priv->from_mainloop = FALSE;
- g_socket_listener_accept_ready (listener->priv->socket, G_IO_IN, listener);
+ g_simple_async_report_gerror_in_idle (G_OBJECT (listener),
+ callback, user_data,
+ error);
+ g_error_free (error);
+ return;
}
+
+ data = g_new0 (struct AcceptAsyncData, 1);
+ data->simple = g_simple_async_result_new (G_OBJECT (listener),
+ callback, user_data,
+ g_socket_listener_accept_socket_async);
+ data->cancellable = cancellable;
+ data->sources = add_sources (listener,
+ accept_ready,
+ data,
+ cancellable,
+ NULL);
}
-GSocketConnection *
-g_socket_listener_accept_finish (GSocketListener *server,
- GAsyncResult *result,
- GError **error)
+GSocket *
+g_socket_listener_accept_socket_finish (GSocketListener *listener,
+ GAsyncResult *result,
+ GSocket **source,
+ GError **error)
{
- GSocketConnection *connection;
+ GSocket *socket;
GSimpleAsyncResult *simple;
- g_return_val_if_fail (G_IS_SOCKET_LISTENER (server), FALSE);
+ g_return_val_if_fail (G_IS_SOCKET_LISTENER (listener), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_socket_listener_accept_async);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_socket_listener_accept_socket_async);
- connection = g_simple_async_result_get_op_res_gpointer (simple);
+ socket = g_simple_async_result_get_op_res_gpointer (simple);
- return g_object_ref (connection);
+ if (source)
+ *source = g_object_ref (g_object_get_data (G_OBJECT (simple), "accept-socket"));
+
+ return g_object_ref (socket);
}
void
-g_socket_listener_close (GSocketListener *server)
+g_socket_listener_accept_async (GSocketListener *listener,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_socket_listener_accept_socket_async (listener,
+ cancellable,
+ callback,
+ user_data);
+}
+
+GSocketConnection *
+g_socket_listener_accept_finish (GSocketListener *listener,
+ GAsyncResult *result,
+ GError **error)
{
- g_return_if_fail (G_IS_SOCKET_LISTENER (server));
+ GSocket *socket;
+ GSocketConnection *connection;
+
+ socket = g_socket_listener_accept_socket_finish (listener,
+ result,
+ NULL,
+ error);
+ if (socket == NULL)
+ return NULL;
+
+ connection = g_socket_connection_factory_create_connection (socket);
+ g_object_unref (socket);
+ return connection;
+}
+
+void
+g_socket_listener_close (GSocketListener *listener)
+{
+ GSocket *socket;
+ int i;
+
+ g_return_if_fail (G_IS_SOCKET_LISTENER (listener));
+
+ if (listener->priv->closed)
+ return;
+
+ for (i = 0; i < listener->priv->sockets->len; i++)
+ {
+ socket = listener->priv->sockets->pdata[i];
+ g_socket_close (socket, NULL);
+ }
+ listener->priv->closed = TRUE;
}
diff --git a/gio/gsocketlistener.h b/gio/gsocketlistener.h
index dfa1b1a..6278bab 100644
--- a/gio/gsocketlistener.h
+++ b/gio/gsocketlistener.h
@@ -46,8 +46,6 @@ struct _GSocketListenerClass
{
GObjectClass parent_class;
- GSocket * (* socket_factory) (GSocketListener *listener,
- GError **error);
gpointer padding[6];
};
@@ -59,23 +57,48 @@ struct _GSocketListener
GType g_socket_listener_get_type (void);
-GSocketListener * g_socket_listener_new (GSocketAddress *address,
+GSocketListener * g_socket_listener_new (void);
+
+gboolean g_socket_listener_add_socket (GSocketListener *listener,
+ GSocket *socket,
+ GError **error);
+gboolean g_socket_listener_add_address (GSocketListener *listener,
+ GSocketAddress *address,
+ GSocketType type,
+ const char *protocol,
+ GError **error);
+gboolean g_socket_listener_add_inet_port (GSocketListener *listener,
+ int port,
+ GError **error);
+
+GSocket * g_socket_listener_accept_socket (GSocketListener *listener,
+ GCancellable *cancellable,
+ GSocket **source,
GError **error);
+void g_socket_listener_accept_socket_async (GSocketListener *listener,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GSocket * g_socket_listener_accept_socket_finish (GSocketListener *listener,
+ GAsyncResult *result,
+ GSocket **source,
+ GError **error);
+
-GSocketConnection * g_socket_listener_accept (GSocketListener *server,
+GSocketConnection * g_socket_listener_accept (GSocketListener *listener,
GCancellable *cancellable,
GError **error);
-void g_socket_listener_accept_async (GSocketListener *server,
+void g_socket_listener_accept_async (GSocketListener *listener,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-GSocketConnection * g_socket_listener_accept_finish (GSocketListener *server,
+GSocketConnection * g_socket_listener_accept_finish (GSocketListener *listener,
GAsyncResult *result,
GError **error);
-void g_socket_listener_close (GSocketListener *server);
+void g_socket_listener_close (GSocketListener *listener);
G_END_DECLS
diff --git a/gio/gtcplistener.c b/gio/gtcplistener.c
deleted file mode 100644
index cc0ef93..0000000
--- a/gio/gtcplistener.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright © 2009 Codethink Limited
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * See the included COPYING file for more information.
- *
- * Authors: Ryan Lortie <desrt desrt ca>
- */
-
-#include "gtcplistener.h"
-
-#include <gio/ginetsocketaddress.h>
-#include <gio/ginetaddress.h>
-
-#include "gtcpconnection.h"
-
-enum
-{
- PROP_NONE,
- PROP_PORT,
- PROP_ADDRESS
-};
-
-struct _GTcpListenerPrivate
-{
- GInetAddress *address;
- guint16 port;
-};
-
-G_DEFINE_TYPE (GTcpListener, g_tcp_listener, G_TYPE_SOCKET_LISTENER);
-
-static GSocket *
-g_tcp_listener_socket_factory (GSocketListener *listener,
- GError **error)
-{
- GTcpListener *tcp_listener = G_TCP_LISTENER (listener);
- GSocketAddress *sockaddr;
- GInetAddress *address;
- GSocket *socket;
-
- if (tcp_listener->priv->address)
- /* address was explicitly given */
- {
- GSocketFamily family;
-
- family = g_inet_address_get_family (tcp_listener->priv->address);
- socket = g_socket_new (family, G_SOCKET_TYPE_STREAM, NULL, error);
- address = g_object_ref (tcp_listener->priv->address);
-
- if (family == G_SOCKET_FAMILY_IPV6)
- /* XXX do ipv6-only-socket ioctl */;
- }
-
- else
- {
- /* try to get a hybrid ipv6/ipv4 socket first */
- socket = g_socket_new (G_SOCKET_FAMILY_IPV6,
- G_SOCKET_TYPE_STREAM,
- NULL, NULL);
-
- if (socket != NULL)
- /* we can do ipv6, so bind to :: */
- address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
-
- else
- /* no ipv6. bind to 0.0.0.0 */
- {
- socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
- G_SOCKET_TYPE_STREAM,
- NULL, error);
- address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
- }
- }
-
- if (socket == NULL)
- return NULL;
-
- g_socket_set_reuse_address (socket, TRUE);
-
- sockaddr = g_inet_socket_address_new (address, tcp_listener->priv->port);
-
- if (!g_socket_bind (socket, sockaddr, error))
- {
- g_object_unref (socket);
- socket = NULL;
- goto err;
- }
-
- if (!g_socket_listen (socket, error))
- {
- g_object_unref (socket);
- socket = NULL;
- }
-
- err:
- g_object_unref (sockaddr);
- g_object_unref (address);
-
- return socket;
-}
-
-static void
-g_tcp_listener_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- GTcpListener *listener = G_TCP_LISTENER (object);
-
- switch (prop_id)
- {
- case PROP_PORT:
- g_assert (listener->priv->port == 0);
- listener->priv->port = g_value_get_uint (value);
- break;
-
- case PROP_ADDRESS:
- g_assert (listener->priv->address == NULL);
- listener->priv->address = g_value_dup_object (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-g_tcp_listener_get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- GTcpListener *listener = G_TCP_LISTENER (object);
-
- switch (prop_id)
- {
- case PROP_PORT:
- g_value_set_uint (value, listener->priv->port);
- break;
-
- case PROP_ADDRESS:
- g_value_set_object (value, listener->priv->address);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-g_tcp_listener_init (GTcpListener *listener)
-{
- listener->priv = G_TYPE_INSTANCE_GET_PRIVATE (listener,
- G_TYPE_TCP_LISTENER,
- GTcpListenerPrivate);
-}
-
-static void
-g_tcp_listener_class_init (GTcpListenerClass *class)
-{
- GSocketListenerClass *listener_class = G_SOCKET_LISTENER_CLASS (class);
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- g_type_class_add_private (class, sizeof (GTcpListenerPrivate));
-
- listener_class->socket_factory = g_tcp_listener_socket_factory;
- object_class->set_property = g_tcp_listener_set_property;
- object_class->get_property = g_tcp_listener_get_property;
-
- g_object_class_install_property (object_class, PROP_PORT,
- g_param_spec_uint ("port", "port number",
- "the TCP port number to bind (0 for any)",
- 0, G_MAXUINT16, 0, G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (object_class, PROP_ADDRESS,
- g_param_spec_object ("address", "IP address",
- "the local address to bind (NULL for all)",
- G_TYPE_INET_ADDRESS, G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-}
-
-GSocketListener *
-g_tcp_listener_new (guint16 port)
-{
- return g_object_new (G_TYPE_TCP_LISTENER, "port", port, NULL);
-}
diff --git a/gio/gtcplistener.h b/gio/gtcplistener.h
deleted file mode 100644
index 6404ce7..0000000
--- a/gio/gtcplistener.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright © 2009 Codethink Limited
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * See the included COPYING file for more information.
- *
- * Authors: Ryan Lortie <desrt desrt ca>
- */
-
-#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
-#error "Only <gio/gio.h> can be included directly."
-#endif
-
-#ifndef _gtcplistener_h_
-#define _gtcplistener_h_
-
-#include <gio/gsocketlistener.h>
-
-G_BEGIN_DECLS
-
-#define G_TYPE_TCP_LISTENER (g_tcp_listener_get_type ())
-#define G_TCP_LISTENER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
- G_TYPE_TCP_LISTENER, GTcpListener))
-#define G_TCP_LISTENER_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \
- G_TYPE_TCP_LISTENER, GTcpListenerClass))
-#define G_IS_TCP_LISTENER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
- G_TYPE_TCP_LISTENER))
-#define G_IS_TCP_LISTENER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \
- G_TYPE_TCP_LISTENER))
-#define G_TCP_LISTENER_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \
- G_TYPE_TCP_LISTENER, GTcpListenerClass))
-
-typedef struct _GTcpListenerPrivate GTcpListenerPrivate;
-typedef struct _GTcpListenerClass GTcpListenerClass;
-typedef struct _GTcpListener GTcpListener;
-
-struct _GTcpListenerClass
-{
- GSocketListenerClass parent_class;
-};
-
-struct _GTcpListener
-{
- GSocketListener parent_instance;
- GTcpListenerPrivate *priv;
-};
-
-GType g_tcp_listener_get_type (void);
-GSocketListener * g_tcp_listener_new (guint16 port);
-
-G_END_DECLS
-
-#endif /* _gtcplistener_h_ */
diff --git a/gio/gunixlistener.c b/gio/gunixlistener.c
deleted file mode 100644
index 92678d4..0000000
--- a/gio/gunixlistener.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright © 2009 Codethink Limited
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * See the included COPYING file for more information.
- *
- * Authors: Ryan Lortie <desrt desrt ca>
- */
-
-#include "gunixlistener.h"
-
-#include <gio/gunixsocketaddress.h>
-
-#include "gunixconnection.h"
-
-enum
-{
- PROP_NONE,
- PROP_PATH,
-};
-
-struct _GUnixListenerPrivate
-{
- gchar *path;
-};
-
-G_DEFINE_TYPE (GUnixListener, g_unix_listener, G_TYPE_SOCKET_LISTENER);
-
-static GSocket *
-g_unix_listener_socket_factory (GSocketListener *listener,
- GError **error)
-{
- GUnixListener *unix_listener = G_UNIX_LISTENER (listener);
- GSocketAddress *sockaddr;
- GSocket *socket;
-
- socket = g_socket_new (G_SOCKET_FAMILY_UNIX,
- G_SOCKET_TYPE_STREAM,
- NULL, error);
- if (socket == NULL)
- return NULL;
-
- sockaddr = g_unix_socket_address_new (unix_listener->priv->path);
-
- /* XXX fix */
- g_socket_bind (socket, sockaddr, NULL);
- g_socket_listen (socket, NULL);
-
- g_object_unref (sockaddr);
-
- return socket;
-}
-
-static void
-g_unix_listener_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- GUnixListener *listener = G_UNIX_LISTENER (object);
-
- switch (prop_id)
- {
- case PROP_PATH:
- g_assert (listener->priv->path == NULL);
- listener->priv->path = g_value_dup_string (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-g_unix_listener_get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- GUnixListener *listener = G_UNIX_LISTENER (object);
-
- switch (prop_id)
- {
- case PROP_PATH:
- g_value_set_string (value, listener->priv->path);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-g_unix_listener_init (GUnixListener *listener)
-{
- listener->priv = G_TYPE_INSTANCE_GET_PRIVATE (listener,
- G_TYPE_UNIX_LISTENER,
- GUnixListenerPrivate);
-}
-
-static void
-g_unix_listener_class_init (GUnixListenerClass *class)
-{
- GSocketListenerClass *listener_class = G_SOCKET_LISTENER_CLASS (class);
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- g_type_class_add_private (class, sizeof (GUnixListenerPrivate));
-
- listener_class->socket_factory = g_unix_listener_socket_factory;
- object_class->set_property = g_unix_listener_set_property;
- object_class->get_property = g_unix_listener_get_property;
-
- g_object_class_install_property (object_class, PROP_PATH,
- g_param_spec_string ("path", "socket path",
- "the filesystem path to bind to",
- NULL, G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-}
-
-GSocketListener *
-g_unix_listener_new (const gchar *path)
-{
- return g_object_new (G_TYPE_UNIX_LISTENER, "path", path, NULL);
-}
diff --git a/gio/gunixlistener.h b/gio/gunixlistener.h
deleted file mode 100644
index 819137b..0000000
--- a/gio/gunixlistener.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright © 2009 Codethink Limited
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * See the included COPYING file for more information.
- *
- * Authors: Ryan Lortie <desrt desrt ca>
- */
-
-#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
-#error "Only <gio/gio.h> can be included directly."
-#endif
-
-#ifndef _gunixlistener_h_
-#define _gunixlistener_h_
-
-#include <gio/gsocketlistener.h>
-
-G_BEGIN_DECLS
-
-#define G_TYPE_UNIX_LISTENER (g_unix_listener_get_type ())
-#define G_UNIX_LISTENER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
- G_TYPE_UNIX_LISTENER, GUnixListener))
-#define G_UNIX_LISTENER_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \
- G_TYPE_UNIX_LISTENER, GUnixListenerClass))
-#define G_IS_UNIX_LISTENER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
- G_TYPE_UNIX_LISTENER))
-#define G_IS_UNIX_LISTENER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \
- G_TYPE_UNIX_LISTENER))
-#define G_UNIX_LISTENER_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \
- G_TYPE_UNIX_LISTENER, GUnixListenerClass))
-
-typedef struct _GUnixListenerPrivate GUnixListenerPrivate;
-typedef struct _GUnixListenerClass GUnixListenerClass;
-typedef struct _GUnixListener GUnixListener;
-
-struct _GUnixListenerClass
-{
- GSocketListenerClass parent_class;
-};
-
-struct _GUnixListener
-{
- GSocketListener parent_instance;
- GUnixListenerPrivate *priv;
-};
-
-GType g_unix_listener_get_type (void);
-GSocketListener * g_unix_listener_new (const gchar *path);
-
-G_END_DECLS
-
-#endif /* _gunixlistener_h_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]