[gnio/connection-factory] Make GSocketService inherit from GSocketListener



commit 3e9586b11f3c033dec452fe07366a5404320bc65
Author: Alexander Larsson <alexl redhat com>
Date:   Sat May 9 23:15:38 2009 +0200

    Make GSocketService inherit from GSocketListener
---
 examples/server.c            |    7 +--
 gio/gsocketlistener.c        |   12 +++-
 gio/gsocketlistener.h        |    3 +
 gio/gsocketservice.c         |  131 ++++++++++++++++++++++--------------------
 gio/gsocketservice.h         |    9 +--
 gio/gthreadedsocketservice.c |   14 ++--
 gio/gthreadedsocketservice.h |    2 +-
 7 files changed, 92 insertions(+), 86 deletions(-)

diff --git a/examples/server.c b/examples/server.c
index 51d4566..0833788 100644
--- a/examples/server.c
+++ b/examples/server.c
@@ -44,7 +44,6 @@ main (int argc, char *argv[])
   GSocketService *service;
   GOptionContext *context;
   GError *error = NULL;
-  GSocketListener *listener;
 
   g_type_init ();
   g_thread_init (NULL);
@@ -59,8 +58,7 @@ main (int argc, char *argv[])
 
   service = g_threaded_socket_service_new ();
 
-  listener = g_socket_listener_new ();
-  if (!g_socket_listener_add_inet_port (listener,
+  if (!g_socket_listener_add_inet_port (G_SOCKET_LISTENER (service),
 					port,
 					&error))
     {
@@ -68,9 +66,6 @@ main (int argc, char *argv[])
       return 1;
     }
 
-  g_socket_service_add_listener (service, listener);
-  g_object_unref (listener);
-
   g_print ("Echo service listening on port %d\n", port);
 
   g_signal_connect (service, "run", G_CALLBACK (handler), NULL);
diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c
index 2df057c..8ebdc04 100644
--- a/gio/gsocketlistener.c
+++ b/gio/gsocketlistener.c
@@ -140,6 +140,9 @@ g_socket_listener_add_address (GSocketListener *listener,
       return FALSE;
     }
 
+  if (G_SOCKET_LISTENER_GET_CLASS (listener)->changed)
+    G_SOCKET_LISTENER_GET_CLASS (listener)->changed (listener);
+
   return TRUE;
 }
 
@@ -442,16 +445,17 @@ g_socket_listener_accept_async (GSocketListener     *listener,
 }
 
 GSocketConnection *
-g_socket_listener_accept_finish (GSocketListener  *listener,
-				 GAsyncResult   *result,
-				 GError        **error)
+g_socket_listener_accept_finish (GSocketListener *listener,
+				 GAsyncResult *result,
+				 GSocket **source,
+				 GError **error)
 {
   GSocket *socket;
   GSocketConnection *connection;
 
   socket = g_socket_listener_accept_socket_finish (listener,
 						   result,
-						   NULL,
+						   source,
 						   error);
   if (socket == NULL)
     return NULL;
diff --git a/gio/gsocketlistener.h b/gio/gsocketlistener.h
index 6278bab..c9f6e71 100644
--- a/gio/gsocketlistener.h
+++ b/gio/gsocketlistener.h
@@ -46,6 +46,8 @@ struct _GSocketListenerClass
 {
   GObjectClass parent_class;
 
+  void (* changed) (GSocketListener *listener);
+
   gpointer padding[6];
 };
 
@@ -96,6 +98,7 @@ void                    g_socket_listener_accept_async                  (GSocket
 
 GSocketConnection *     g_socket_listener_accept_finish                 (GSocketListener      *listener,
                                                                          GAsyncResult         *result,
+									 GSocket             **source,
                                                                          GError              **error);
 
 void                    g_socket_listener_close                         (GSocketListener      *listener);
diff --git a/gio/gsocketservice.c b/gio/gsocketservice.c
index 1610dee..36ea813 100644
--- a/gio/gsocketservice.c
+++ b/gio/gsocketservice.c
@@ -38,17 +38,28 @@
 #include "gsocketservice.h"
 
 #include "gnio-marshal.h"
+#include <gio/gio.h>
 #include "gsocketlistener.h"
 #include "gsocketconnection.h"
 
 static guint g_socket_service_incoming_signal;
 
-G_DEFINE_TYPE (GSocketService, g_socket_service, G_TYPE_OBJECT);
+G_DEFINE_TYPE (GSocketService, g_socket_service, G_TYPE_SOCKET_LISTENER);
+
+struct _GSocketServicePrivate
+{
+  GCancellable *cancellable;
+  gboolean active;
+};
+
+static void g_socket_service_ready (GObject      *object,
+				    GAsyncResult *result,
+				    gpointer      user_data);
 
 static gboolean
 g_socket_service_real_incoming (GSocketService    *service,
                                 GSocketConnection *connection,
-                                GSocketListener   *listener)
+                                GSocket           *source_socket)
 {
   return FALSE;
 }
@@ -56,29 +67,65 @@ g_socket_service_real_incoming (GSocketService    *service,
 static void
 g_socket_service_init (GSocketService *service)
 {
+  service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service,
+					       G_TYPE_SOCKET_SERVICE,
+					       GSocketServicePrivate);
+  service->priv->cancellable = g_cancellable_new ();
+}
+
+static void
+g_socket_service_finalize (GObject *object)
+{
+  GSocketService *service = G_SOCKET_SERVICE (object);
+
+  g_object_unref (service->priv->cancellable);
+
+  G_OBJECT_CLASS (g_socket_service_parent_class)
+    ->finalize (object);
 }
 
 static void
+g_socket_service_changed (GSocketListener   *listener)
+{
+  GSocketService  *service = G_SOCKET_SERVICE (listener);
+
+  if (service->priv->active)
+    g_cancellable_cancel (service->priv->cancellable);
+  else
+    g_socket_listener_accept_async (listener, service->priv->cancellable,
+				    g_socket_service_ready, NULL);
+  service->priv->active = TRUE;
+}
+
+static gboolean
 g_socket_service_incoming (GSocketService    *service,
                            GSocketConnection *connection,
-                           GSocketListener   *listener)
+                           GSocket           *source_socket)
 {
   gboolean result;
 
   g_signal_emit (service, g_socket_service_incoming_signal,
-                 0, connection, listener, &result);
+                 0, connection, source_socket, &result);
+  return result;
 }
 
 static void
 g_socket_service_class_init (GSocketServiceClass *class)
 {
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+  GSocketListenerClass *listener_class = G_SOCKET_LISTENER_CLASS (class);
+
+  g_type_class_add_private (class, sizeof (GSocketServicePrivate));
+
+  gobject_class->finalize = g_socket_service_finalize;
+  listener_class->changed = g_socket_service_changed;
   class->incoming = g_socket_service_real_incoming;
 
   /**
    * GSocketService::incoming:
    * @service: the #GSocketService.
    * @connection: a new #GSocketConnection object.
-   * @listener: the #GSocketListener whence @connection originated.
+   * @source_socket: the #GSocket whence @connection was accepted.
    * @returns: %TRUE if @connection has been handled.
    *
    * The ::incoming signal is emitted when a new incoming connection
@@ -93,7 +140,7 @@ g_socket_service_class_init (GSocketServiceClass *class)
                   G_STRUCT_OFFSET (GSocketServiceClass, incoming),
                   g_signal_accumulator_true_handled, NULL,
                   _gnio_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN,
-                  2, G_TYPE_SOCKET_CONNECTION, G_TYPE_SOCKET_LISTENER);
+                  2, G_TYPE_SOCKET_CONNECTION, G_TYPE_SOCKET);
 }
 
 static void
@@ -102,72 +149,32 @@ g_socket_service_ready (GObject      *object,
                         gpointer      user_data)
 {
   GSocketListener *listener = G_SOCKET_LISTENER (object);
-  GSocketService *service = user_data;
+  GSocketService *service = G_SOCKET_SERVICE (object);
   GSocketConnection *connection;
+  GSocket *source;
   GError *error = NULL;
 
-  connection = g_socket_listener_accept_finish (listener, result, &error);
+  connection = g_socket_listener_accept_finish (listener, result, &source, &error);
   if (error)
-    g_error ("fail: %s", error->message);
-  g_socket_service_incoming (service, connection, listener);
-  g_object_unref (connection);
+    {
+      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+	g_cancellable_reset (service->priv->cancellable);
+      else
+	g_warning ("fail: %s", error->message);
+      g_error_free (error);
+    }
+  else
+    {
+      g_socket_service_incoming (service, connection, source);
+      g_object_unref (connection);
+      g_object_unref (source);
+    }
 
   /* requeue */
   g_socket_listener_accept_async (listener, NULL,
                                   g_socket_service_ready, service);
 }
 
-/**
- * g_socket_service_add_listener:
- * @service: a #GSocketService.
- * @listener: a newly created #GSocketListener.
- *
- * Adds a #GSocketListener to @service.
- *
- * A #GSocketService must have at least one #GSocketListener in order
- * to listen for incoming connections.  Any number of listeners may be
- * added and connections are accepted from all of them.
- *
- * This call forms a mutual reference between @service and @listener
- * and keeps both alive.  You can drop your own references to each of
- * them and connections will continue to be accepted.
- *
- * If you want to destroy a service, call g_socket_service_destroy()
- * on it.  This is equivalent to removing all of the listeners.
- **/
-void
-g_socket_service_add_listener (GSocketService  *service,
-                               GSocketListener *listener)
-{
-  g_return_if_fail (G_IS_SOCKET_SERVICE (service));
-  g_return_if_fail (G_IS_SOCKET_LISTENER (listener));
-
-  g_socket_listener_accept_async (listener,
-                                  NULL, //g_object_ref (service->cancellable),
-                                  g_socket_service_ready,
-                                  g_object_ref (service));
-}
-
-/**
- * g_socket_service_destroy:
- * @service: a #GSocketService.
- *
- * Requests cancellation of all accept requests on the listeners
- * associated with @service.  It is likely that one or more mainloop
- * visits will be required before all requests are fully cancelled.
- *
- * If @service held the only reference on a given listener then that
- * listener will be freed and its associated socket will be closed.
- * If other references are held, then listener may be used elsewhere.
- *
- * This call does not drop the caller's reference on @service.  You
- * will need to do that yourself with g_object_unref().
- **/
-void
-g_socket_service_destroy (GSocketService *service)
-{
-  g_assert_not_reached ();
-}
 
 /**
  * g_socket_service_new:
diff --git a/gio/gsocketservice.h b/gio/gsocketservice.h
index 3eb97fd..cae3eef 100644
--- a/gio/gsocketservice.h
+++ b/gio/gsocketservice.h
@@ -40,26 +40,23 @@ typedef struct _GSocketService                              GSocketService;
 
 struct _GSocketServiceClass
 {
-  GObjectClass parent_class;
+  GSocketListenerClass parent_class;
 
   gboolean (* incoming) (GSocketService    *service,
                          GSocketConnection *connection,
-                         GSocketListener   *listener);
+			 GSocket           *source_socket);
   gpointer padding[6];
 };
 
 struct _GSocketService
 {
-  GObject parent_instance;
+  GSocketListener parent_instance;
   GSocketServicePrivate *priv;
 };
 
 GType                   g_socket_service_get_type                       (void);
 
 GSocketService *        g_socket_service_new                            (void);
-void                    g_socket_service_add_listener                   (GSocketService  *service,
-                                                                         GSocketListener *listener);
-void                    g_socket_service_destroy                        (GSocketService  *service);
 
 G_END_DECLS
 
diff --git a/gio/gthreadedsocketservice.c b/gio/gthreadedsocketservice.c
index 0d97712..bc85d1b 100644
--- a/gio/gthreadedsocketservice.c
+++ b/gio/gthreadedsocketservice.c
@@ -42,7 +42,7 @@ typedef struct
 {
   GThreadedSocketService *service;
   GSocketConnection *connection;
-  GSocketListener *listener;
+  GSocket *source_socket;
 } GThreadedSocketServiceData;
 
 static gpointer
@@ -52,27 +52,27 @@ g_threaded_socket_service_func (gpointer user_data)
   gboolean result;
 
   g_signal_emit (data->service, g_threaded_socket_service_run_signal,
-                 0, data->connection, data->listener, &result);
+                 0, data->connection, data->source_socket, &result);
 
   g_object_unref (data->service);
   g_object_unref (data->connection);
-  g_object_unref (data->listener);
+  g_object_unref (data->source_socket);
   g_slice_free (GThreadedSocketServiceData, data);
-  
+
   return NULL;
 }
 
 static gboolean
 g_threaded_socket_service_incoming (GSocketService    *service,
                                     GSocketConnection *connection,
-                                    GSocketListener   *listener)
+                                    GSocket           *source_socket)
 {
   GThreadedSocketServiceData *data;
 
   data = g_slice_new (GThreadedSocketServiceData);
   data->service = g_object_ref (service);
   data->connection = g_object_ref (connection);
-  data->listener = g_object_ref (listener);
+  data->source_socket = g_object_ref (source_socket);
 
   g_thread_create (g_threaded_socket_service_func, data, FALSE, NULL);
   return FALSE;
@@ -109,7 +109,7 @@ g_threaded_socket_service_class_init (GThreadedSocketServiceClass *class)
                   G_STRUCT_OFFSET (GThreadedSocketServiceClass, run),
                   g_signal_accumulator_true_handled, NULL,
                   _gnio_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN,
-                  2, G_TYPE_SOCKET_CONNECTION, G_TYPE_SOCKET_LISTENER);
+                  2, G_TYPE_SOCKET_CONNECTION, G_TYPE_SOCKET);
 }
 
 /**
diff --git a/gio/gthreadedsocketservice.h b/gio/gthreadedsocketservice.h
index d7b92da..d0fe165 100644
--- a/gio/gthreadedsocketservice.h
+++ b/gio/gthreadedsocketservice.h
@@ -47,7 +47,7 @@ struct _GThreadedSocketServiceClass
 
   gboolean (* run) (GThreadedSocketService *service,
                     GSocketConnection      *connection,
-                    GSocketListener        *listener);
+                    GSocket                *source_socket);
 };
 
 struct _GThreadedSocketService



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]