[glib] Add an event signal to GSocketListener
- From: Paolo Borelli <pborelli src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Add an event signal to GSocketListener
- Date: Sat, 4 Apr 2015 19:26:27 +0000 (UTC)
commit b64e2956f6b9ae74f1fdcecb129bff7738817509
Author: Paolo Borelli <pborelli gnome org>
Date: Thu Oct 9 15:54:43 2014 +0200
Add an event signal to GSocketListener
This allows the caller to know when a socket has been bound so that
it can for instance set the SO_SENDBUF and SO_RECVBUF socket options
before listen is called
https://bugzilla.gnome.org/show_bug.cgi?id=738207
docs/reference/gio/gio-sections.txt | 1 +
gio/gioenums.h | 23 ++++++
gio/gsocketlistener.c | 138 +++++++++++++++++++++++++++++++----
gio/gsocketlistener.h | 5 +-
gio/tests/socket-listener.c | 65 ++++++++++++++++
5 files changed, 216 insertions(+), 16 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 39444f7..7936476 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -2225,6 +2225,7 @@ g_socket_control_message_get_type
<FILE>gsocketlistener</FILE>
<TITLE>GSocketListener</TITLE>
GSocketListener
+GSocketListenerEvent
g_socket_listener_new
g_socket_listener_add_socket
g_socket_listener_add_address
diff --git a/gio/gioenums.h b/gio/gioenums.h
index 9fd563d..55a70b1 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -1751,6 +1751,29 @@ typedef enum {
} GSocketClientEvent;
/**
+ * GSocketListenerEvent:
+ * @G_SOCKET_LISTENER_BINDING: The listener is about to bind a socket.
+ * @G_SOCKET_LISTENER_BOUND: The listener has bound a socket.
+ * @G_SOCKET_LISTENER_LISTENING: The listener is about to start
+ * listening on this socket.
+ * @G_SOCKET_LISTENER_LISTENED: The listener is now listening on
+ * this socket.
+ *
+ * Describes an event occurring on a #GSocketListener. See the
+ * #GSocketListener::event signal for more details.
+ *
+ * Additional values may be added to this type in the future.
+ *
+ * Since: 2.46
+ */
+typedef enum {
+ G_SOCKET_LISTENER_BINDING,
+ G_SOCKET_LISTENER_BOUND,
+ G_SOCKET_LISTENER_LISTENING,
+ G_SOCKET_LISTENER_LISTENED
+} GSocketListenerEvent;
+
+/**
* GTestDBusFlags:
* @G_TEST_DBUS_NONE: No flags.
*
diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c
index 7185745..8b60ea3 100644
--- a/gio/gsocketlistener.c
+++ b/gio/gsocketlistener.c
@@ -26,6 +26,7 @@
#include "config.h"
#include "gsocketlistener.h"
+#include <gio/gioenumtypes.h>
#include <gio/gtask.h>
#include <gio/gcancellable.h>
#include <gio/gsocketaddress.h>
@@ -61,6 +62,13 @@ enum
PROP_LISTEN_BACKLOG
};
+enum
+{
+ EVENT,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
static GQuark source_quark = 0;
@@ -131,7 +139,6 @@ g_socket_listener_set_property (GObject *object,
}
}
-
static void
g_socket_listener_class_init (GSocketListenerClass *klass)
{
@@ -149,6 +156,29 @@ g_socket_listener_class_init (GSocketListenerClass *klass)
10,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ /**
+ * GSocketListener::event:
+ * @listener: the #GSocketListener
+ * @event: the event that is occurring
+ * @socket: the #GSocket the event is occurring on
+ *
+ * Emitted when @listener's activity on @socket changes state.
+ * Note that when @listener is used to listen on both IPv4 and
+ * IPv6, a separate set of signals will be emitted for each, and
+ * the order they happen in is undefined.
+ *
+ * Since: 2.46
+ */
+ signals[EVENT] =
+ g_signal_new (I_("event"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GSocketListenerClass, event),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 2,
+ G_TYPE_SOCKET_LISTENER_EVENT,
+ G_TYPE_SOCKET);
+
source_quark = g_quark_from_static_string ("g-socket-listener-source");
}
@@ -306,13 +336,29 @@ g_socket_listener_add_address (GSocketListener *listener,
g_socket_set_listen_backlog (socket, listener->priv->listen_backlog);
- if (!g_socket_bind (socket, address, TRUE, error) ||
- !g_socket_listen (socket, error))
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BINDING, socket);
+
+ if (!g_socket_bind (socket, address, TRUE, error))
+ {
+ g_object_unref (socket);
+ return FALSE;
+ }
+
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BOUND, socket);
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENING, socket);
+
+ if (!g_socket_listen (socket, error))
{
g_object_unref (socket);
return FALSE;
}
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENED, socket);
+
local_address = NULL;
if (effective_address)
{
@@ -392,7 +438,6 @@ g_socket_listener_add_inet_port (GSocketListener *listener,
{
GInetAddress *inet_address;
GSocketAddress *address;
- gboolean result;
inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
address = g_inet_socket_address_new (inet_address, port);
@@ -400,18 +445,32 @@ g_socket_listener_add_inet_port (GSocketListener *listener,
g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog);
- result = g_socket_bind (socket6, address, TRUE, error) &&
- g_socket_listen (socket6, error);
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BINDING, socket6);
+
+ if (!g_socket_bind (socket6, address, TRUE, error))
+ {
+ g_object_unref (address);
+ g_object_unref (socket6);
+ return FALSE;
+ }
g_object_unref (address);
- if (!result)
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BOUND, socket6);
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENING, socket6);
+
+ if (!g_socket_listen (socket6, error))
{
g_object_unref (socket6);
-
return FALSE;
}
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENED, socket6);
+
if (source_object)
g_object_set_qdata_full (G_OBJECT (socket6), source_quark,
g_object_ref (source_object),
@@ -445,7 +504,6 @@ g_socket_listener_add_inet_port (GSocketListener *listener,
{
GInetAddress *inet_address;
GSocketAddress *address;
- gboolean result;
inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
address = g_inet_socket_address_new (inet_address, port);
@@ -454,21 +512,40 @@ g_socket_listener_add_inet_port (GSocketListener *listener,
g_socket_set_listen_backlog (socket4,
listener->priv->listen_backlog);
- result = g_socket_bind (socket4, address, TRUE, error) &&
- g_socket_listen (socket4, error);
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BINDING, socket4);
+
+ if (!g_socket_bind (socket4, address, TRUE, error))
+ {
+ g_object_unref (address);
+ g_object_unref (socket4);
+ if (socket6 != NULL)
+ g_object_unref (socket6);
+
+ return FALSE;
+ }
g_object_unref (address);
- if (!result)
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BOUND, socket4);
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENING, socket4);
+
+ if (!g_socket_listen (socket4, error))
{
g_object_unref (socket4);
-
if (socket6 != NULL)
g_object_unref (socket6);
return FALSE;
}
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENED, socket4);
+
+ g_object_unref (address);
+
if (source_object)
g_object_set_qdata_full (G_OBJECT (socket4), source_quark,
g_object_ref (source_object),
@@ -965,6 +1042,10 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV6);
address = g_inet_socket_address_new (inet_address, 0);
g_object_unref (inet_address);
+
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BINDING, socket6);
+
result = g_socket_bind (socket6, address, TRUE, error);
g_object_unref (address);
@@ -976,6 +1057,9 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
break;
}
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BOUND, socket6);
+
g_assert (G_IS_INET_SOCKET_ADDRESS (address));
candidate_port =
g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
@@ -1004,6 +1088,10 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
inet_address = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
address = g_inet_socket_address_new (inet_address, candidate_port);
g_object_unref (inet_address);
+
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BINDING, socket4);
+
/* a note on the 'error' clause below:
*
* if candidate_port is 0 then we report the error right away
@@ -1029,8 +1117,11 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
if (result)
/* got our candidate port successfully */
- break;
-
+ {
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BOUND, socket4);
+ break;
+ }
else
/* we failed to bind to the specified port. try again. */
{
@@ -1060,6 +1151,9 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
break;
}
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_BOUND, socket4);
+
g_assert (G_IS_INET_SOCKET_ADDRESS (address));
candidate_port =
g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (address));
@@ -1083,6 +1177,10 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
if (socket6 != NULL)
{
g_socket_set_listen_backlog (socket6, listener->priv->listen_backlog);
+
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENING, socket6);
+
if (!g_socket_listen (socket6, error))
{
g_object_unref (socket6);
@@ -1092,6 +1190,9 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
return 0;
}
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENED, socket6);
+
if (source_object)
g_object_set_qdata_full (G_OBJECT (socket6), source_quark,
g_object_ref (source_object),
@@ -1103,6 +1204,10 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
if (socket4 != NULL)
{
g_socket_set_listen_backlog (socket4, listener->priv->listen_backlog);
+
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENING, socket4);
+
if (!g_socket_listen (socket4, error))
{
g_object_unref (socket4);
@@ -1112,6 +1217,9 @@ g_socket_listener_add_any_inet_port (GSocketListener *listener,
return 0;
}
+ g_signal_emit (listener, signals[EVENT], 0,
+ G_SOCKET_LISTENER_LISTENED, socket4);
+
if (source_object)
g_object_set_qdata_full (G_OBJECT (socket4), source_quark,
g_object_ref (source_object),
diff --git a/gio/gsocketlistener.h b/gio/gsocketlistener.h
index 82d309a..abf064a 100644
--- a/gio/gsocketlistener.h
+++ b/gio/gsocketlistener.h
@@ -61,8 +61,11 @@ struct _GSocketListenerClass
void (* changed) (GSocketListener *listener);
+ void (* event) (GSocketListener *listener,
+ GSocketListenerEvent *event,
+ GSocket *socket);
+
/* Padding for future expansion */
- void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
diff --git a/gio/tests/socket-listener.c b/gio/tests/socket-listener.c
index 98e3396..5a58206 100644
--- a/gio/tests/socket-listener.c
+++ b/gio/tests/socket-listener.c
@@ -19,6 +19,70 @@
#include <gio/gio.h>
+static void
+event_cb (GSocketListener *listener,
+ GSocketListenerEvent event,
+ GSocket *socket,
+ gpointer data)
+{
+ static GSocketListenerEvent expected_event = G_SOCKET_LISTENER_BINDING;
+ gboolean *success = (gboolean *)data;
+
+ g_assert (G_IS_SOCKET_LISTENER (listener));
+ g_assert (G_IS_SOCKET (socket));
+ g_assert (event == expected_event);
+
+ switch (event)
+ {
+ case G_SOCKET_LISTENER_BINDING:
+ expected_event = G_SOCKET_LISTENER_BOUND;
+ break;
+ case G_SOCKET_LISTENER_BOUND:
+ expected_event = G_SOCKET_LISTENER_LISTENING;
+ break;
+ case G_SOCKET_LISTENER_LISTENING:
+ expected_event = G_SOCKET_LISTENER_LISTENED;
+ break;
+ case G_SOCKET_LISTENER_LISTENED:
+ *success = TRUE;
+ break;
+ }
+}
+
+static void
+test_event_signal (void)
+{
+ gboolean success = FALSE;
+ GInetAddress *iaddr;
+ GSocketAddress *saddr;
+ GSocketListener *listener;
+ GError *error = NULL;
+
+ iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
+ saddr = g_inet_socket_address_new (iaddr, 0);
+ g_object_unref (iaddr);
+
+ listener = g_socket_listener_new ();
+
+ g_signal_connect (listener, "event", G_CALLBACK (event_cb), &success);
+
+ g_socket_listener_add_address (listener,
+ saddr,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP,
+ NULL,
+ NULL,
+ &error);
+ g_assert_no_error (error);
+ g_object_unref (saddr);
+
+ do
+ g_main_context_iteration (NULL, TRUE);
+ while (!success);
+
+ g_object_unref (listener);
+}
+
GMutex mutex_712570;
GCond cond_712570;
volatile gboolean finalized;
@@ -160,6 +224,7 @@ main (int argc,
g_test_bug_base ("http://bugzilla.gnome.org/");
+ g_test_add_func ("/socket-listener/event-signal", test_event_signal);
g_test_add_func ("/socket-listener/threaded/712570", test_threaded_712570);
return g_test_run();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]