[wing] namedpipelistener: handle multiple clients connecting to the same pipe
- From: Ignacio Casal Quinteiro <icq src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [wing] namedpipelistener: handle multiple clients connecting to the same pipe
- Date: Thu, 14 Jul 2016 11:37:37 +0000 (UTC)
commit d150f8a153eff37b04fd6a4b9f94a2061e8731f2
Author: Ignacio Casal Quinteiro <icq gnome org>
Date: Thu Jul 14 13:35:44 2016 +0200
namedpipelistener: handle multiple clients connecting to the same pipe
In the moment that we get a connection to the pipe we need to
create another so another client can connect to it otherwise
we were getting an error every time a second client was connecting
to the pipe or that the listener was trying to accept a pipe
the second time.
wing/wingnamedpipelistener.c | 147 +++++++++++++++++++++++++-----------------
1 files changed, 87 insertions(+), 60 deletions(-)
---
diff --git a/wing/wingnamedpipelistener.c b/wing/wingnamedpipelistener.c
index 103d7ff..4fe21a5 100644
--- a/wing/wingnamedpipelistener.c
+++ b/wing/wingnamedpipelistener.c
@@ -28,6 +28,7 @@
typedef struct
{
gchar *pipe_name;
+ gunichar2 *pipe_namew;
HANDLE handle;
OVERLAPPED overlapped;
GObject *source_object;
@@ -46,14 +47,14 @@ static GQuark source_quark = 0;
static PipeData *
pipe_data_new (const gchar *pipe_name,
- HANDLE handle,
GObject *source_object)
{
PipeData *data;
data = g_slice_new0 (PipeData);
data->pipe_name = g_strdup (pipe_name);
- data->handle = handle;
+ data->pipe_namew = g_utf8_to_utf16 (pipe_name, -1, NULL, NULL, NULL);
+ data->handle = INVALID_HANDLE_VALUE;
data->overlapped.hEvent = CreateEvent (NULL, /* default security attribute */
TRUE, /* manual-reset event */
TRUE, /* initial state = signaled */
@@ -68,6 +69,7 @@ static void
pipe_data_free (PipeData *data)
{
g_free (data->pipe_name);
+ g_free (data->pipe_namew);
if (data->handle != INVALID_HANDLE_VALUE)
CloseHandle (data->handle);
CloseHandle (data->overlapped.hEvent);
@@ -126,56 +128,25 @@ wing_named_pipe_listener_new (void)
return g_object_new (WING_TYPE_NAMED_PIPE_LISTENER, NULL);
}
-/**
- * wing_named_pipe_listener_add_named_pipe:
- * @listener: a #WingNamedPipeListener.
- * @pipe_name: a name for the pipe.
- * @source_object: (allow-none): Optional #GObject identifying this source
- * @error: #GError for error reporting, or %NULL to ignore.
- *
- * Adds @named_pipe to the set of named pipes that we try to accept clients
- * from.
- *
- * @source_object will be passed out in the various calls
- * to accept to identify this particular source, which is
- * useful if you're listening on multiple pipes and do
- * different things depending on what pipe is connected to.
- *
- * Returns: %TRUE on success, %FALSE on error.
- *
- * Since: 2.48
- */
-gboolean
-wing_named_pipe_listener_add_named_pipe (WingNamedPipeListener *listener,
- const gchar *pipe_name,
- GObject *source_object,
- GError **error)
+static gboolean
+create_pipe_from_pipe_data (PipeData *pipe_data,
+ GError **error)
{
- WingNamedPipeListenerPrivate *priv;
- gunichar2 *pipe_namew;
- PipeData *pipe_data;
- HANDLE handle;
-
- g_return_val_if_fail (WING_IS_NAMED_PIPE_LISTENER (listener), FALSE);
- g_return_val_if_fail (pipe_name != NULL, FALSE);
-
- priv = wing_named_pipe_listener_get_instance_private (listener);
-
- pipe_namew = g_utf8_to_utf16 (pipe_name, -1, NULL, NULL, NULL);
-
- handle = CreateNamedPipeW (pipe_namew,
- PIPE_ACCESS_DUPLEX |
- FILE_FLAG_OVERLAPPED,
- PIPE_TYPE_BYTE |
- PIPE_READMODE_BYTE |
- PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES,
- DEFAULT_PIPE_BUF_SIZE,
- DEFAULT_PIPE_BUF_SIZE,
- 0, NULL);
- g_free (pipe_namew);
-
- if (handle == INVALID_HANDLE_VALUE)
+ /* Set event as signaled */
+ SetEvent(pipe_data->overlapped.hEvent);
+
+ pipe_data->handle = CreateNamedPipeW (pipe_data->pipe_namew,
+ PIPE_ACCESS_DUPLEX |
+ FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE |
+ PIPE_READMODE_BYTE |
+ PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES,
+ DEFAULT_PIPE_BUF_SIZE,
+ DEFAULT_PIPE_BUF_SIZE,
+ 0, NULL);
+
+ if (pipe_data->handle == INVALID_HANDLE_VALUE)
{
int errsv = GetLastError ();
gchar *emsg = g_win32_error_message (errsv);
@@ -184,15 +155,13 @@ wing_named_pipe_listener_add_named_pipe (WingNamedPipeListener *listener,
G_IO_ERROR,
g_io_error_from_win32_error (errsv),
"Error creating named pipe '%s': %s",
- pipe_name, emsg);
+ pipe_data->pipe_name, emsg);
g_free (emsg);
return FALSE;
}
- pipe_data = pipe_data_new (pipe_name, handle, source_object);
-
- if (!ConnectNamedPipe (handle, &pipe_data->overlapped))
+ if (!ConnectNamedPipe (pipe_data->handle, &pipe_data->overlapped))
{
switch (GetLastError ())
{
@@ -209,15 +178,57 @@ wing_named_pipe_listener_add_named_pipe (WingNamedPipeListener *listener,
g_set_error (error,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Failed to connect named pipe '%s': %s",
- pipe_name, emsg);
+ pipe_data->pipe_name, emsg);
g_free (emsg);
- pipe_data_free (pipe_data);
return FALSE;
}
}
}
+ return TRUE;
+}
+
+/**
+ * wing_named_pipe_listener_add_named_pipe:
+ * @listener: a #WingNamedPipeListener.
+ * @pipe_name: a name for the pipe.
+ * @source_object: (allow-none): Optional #GObject identifying this source
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Adds @named_pipe to the set of named pipes that we try to accept clients
+ * from.
+ *
+ * @source_object will be passed out in the various calls
+ * to accept to identify this particular source, which is
+ * useful if you're listening on multiple pipes and do
+ * different things depending on what pipe is connected to.
+ *
+ * Returns: %TRUE on success, %FALSE on error.
+ *
+ * Since: 2.48
+ */
+gboolean
+wing_named_pipe_listener_add_named_pipe (WingNamedPipeListener *listener,
+ const gchar *pipe_name,
+ GObject *source_object,
+ GError **error)
+{
+ WingNamedPipeListenerPrivate *priv;
+ PipeData *pipe_data;
+
+ g_return_val_if_fail (WING_IS_NAMED_PIPE_LISTENER (listener), FALSE);
+ g_return_val_if_fail (pipe_name != NULL, FALSE);
+
+ priv = wing_named_pipe_listener_get_instance_private (listener);
+
+ pipe_data = pipe_data_new (pipe_name, source_object);
+ if (!create_pipe_from_pipe_data (pipe_data, error))
+ {
+ pipe_data_free (pipe_data);
+ return FALSE;
+ }
+
g_ptr_array_add (priv->named_pipes, pipe_data);
return TRUE;
@@ -265,6 +276,7 @@ connect_ready (HANDLE handle,
else
{
WingNamedPipeConnection *connection;
+ GError *error = NULL;
if (pipe_data->source_object != NULL)
g_object_set_qdata_full (G_OBJECT (task),
@@ -274,9 +286,17 @@ connect_ready (HANDLE handle,
connection = g_object_new (WING_TYPE_NAMED_PIPE_CONNECTION,
"handle", pipe_data->handle,
- "close-handle", FALSE,
+ "close-handle", TRUE,
NULL);
- g_task_return_pointer (task, connection, g_object_unref);
+
+ /* Put another pipe to listen so more clients can already connect */
+ if (!create_pipe_from_pipe_data (pipe_data, &error))
+ {
+ g_object_unref (connection);
+ g_task_return_error (task, error);
+ }
+ else
+ g_task_return_pointer (task, connection, g_object_unref);
}
g_object_unref (task);
@@ -469,11 +489,18 @@ wing_named_pipe_listener_accept (WingNamedPipeListener *listener,
{
connection = g_object_new (WING_TYPE_NAMED_PIPE_CONNECTION,
"handle", pipe_data->handle,
- "close-handle", FALSE,
+ "close-handle", TRUE,
NULL);
if (source_object)
*source_object = pipe_data->source_object;
+
+ /* Put another pipe to listen so more clients can already connect */
+ if (!create_pipe_from_pipe_data (pipe_data, error))
+ {
+ g_object_unref (connection);
+ connection = NULL;
+ }
}
return connection;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]