[network-manager-libreswan/th/vpn-plugin-debug-bgo766872: 22/22] WIP



commit aa668726ea90dab59287ffe3da8861a52049e685
Author: Thomas Haller <thaller redhat com>
Date:   Sun May 29 16:36:07 2016 +0200

    WIP

 src/nm-libreswan-service.c |  180 ++++++++++++++++++++++++++++++++++----------
 1 files changed, 141 insertions(+), 39 deletions(-)
---
diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c
index c75dd6a..54592f6 100644
--- a/src/nm-libreswan-service.c
+++ b/src/nm-libreswan-service.c
@@ -60,8 +60,9 @@
 # define DIST_VERSION VERSION
 #endif
 
-#define NM_TYPE_LIBRESWAN_PLUGIN (nm_libreswan_plugin_get_type ())
-#define NM_LIBRESWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LIBRESWAN_PLUGIN, 
NMLibreswanPlugin))
+#define NM_TYPE_LIBRESWAN_PLUGIN    (nm_libreswan_plugin_get_type ())
+#define NM_LIBRESWAN_PLUGIN(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LIBRESWAN_PLUGIN, 
NMLibreswanPlugin))
+#define NM_IS_LIBRESWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_LIBRESWAN_PLUGIN))
 
 typedef NMVpnServicePlugin NMLibreswanPlugin;
 typedef NMVpnServicePluginClass NMLibreswanPluginClass;
@@ -93,6 +94,8 @@ typedef enum {
 typedef struct {
        GIOChannel *channel;
        guint id;
+       guint flush_id;
+       GPid pid;
        GString *str;
        const char *detail;
 } Pipe;
@@ -123,8 +126,7 @@ typedef struct {
        GString *io_buf;
        char *password;
 
-       Pipe out;
-       Pipe err;
+       GSList *pipes;
 } NMLibreswanPluginPrivate;
 
 #define NM_LIBRESWAN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LIBRESWAN_PLUGIN, 
NMLibreswanPluginPrivate))
@@ -168,71 +170,174 @@ nm_utils_ip4_prefix_to_netmask (guint32 prefix)
 
 /****************************************************************/
 
-static gboolean pr_cb (GIOChannel *source, GIOCondition condition, gpointer user_data);
+static gboolean pipe_callback (GIOChannel *source, GIOCondition condition, gpointer user_data);
 
 static void
-pipe_cleanup (Pipe *pipe)
+pipe_free (Pipe *pipe)
 {
-       if (pipe->id) {
-               g_source_remove (pipe->id);
-               pipe->id = 0;
-       }
+       nm_clear_g_source (&pipe->id);
+       nm_clear_g_source (&pipe->flush_id);
        g_clear_pointer (&pipe->channel, g_io_channel_unref);
        if (pipe->str) {
                g_string_free (pipe->str, TRUE);
                pipe->str = NULL;
        }
+       g_slice_free (Pipe, pipe);
+}
+
+static void
+pipe_release (NMLibreswanPlugin *self, Pipe *pipe)
+{
+       NMLibreswanPluginPrivate *priv;
+       GSList *iter;
+
+       g_return_if_fail (NM_IS_LIBRESWAN_PLUGIN (self));
+       g_return_if_fail (pipe);
+
+       priv = NM_LIBRESWAN_PLUGIN_GET_PRIVATE (self);
+
+       for (iter = priv->pipes; iter; iter = iter->next) {
+               if (iter->data == pipe) {
+                       pipe_free (pipe);
+                       priv->pipes = g_slist_delete_link (priv->pipes, iter);
+                       return;
+               }
+       }
+       g_return_if_reached ();
+}
+
+static void
+pipe_release_all (NMLibreswanPlugin *self, GPid pid)
+{
+       NMLibreswanPluginPrivate *priv;
+       GSList *iter, *iter2;
+
+       g_return_if_fail (NM_IS_LIBRESWAN_PLUGIN (self));
+
+       priv = NM_LIBRESWAN_PLUGIN_GET_PRIVATE (self);
+
+       for (iter = priv->pipes; iter; ) {
+               Pipe *pipe = iter->data;
+
+               if (   pid != ((GPid) -1)
+                   && pid != pipe->pid) {
+                       iter = iter->next;
+                       continue;
+               }
+
+               pipe_free (pipe);
+               iter2 = iter;
+               iter = iter->next;
+               priv->pipes = g_slist_delete_link (priv->pipes, iter);
+       }
 }
 
 static void
-pipe_init (Pipe *pipe, int fd, const char *detail)
+pipe_start (NMLibreswanPlugin *self, GPid pid, int fd, const char *detail)
 {
-       g_assert (fd >= 0);
-       g_assert (detail);
-       g_assert (pipe);
+       NMLibreswanPluginPrivate *priv;
+       Pipe *pipe;
+
+       g_return_if_fail (NM_IS_LIBRESWAN_PLUGIN (self));
+       g_return_if_fail (fd > 0);
+       g_return_if_fail (pid > 0);
+       g_return_if_fail (detail);
+
+       if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+               _LOGD ("pipe[%ld,%s]: failure to set nonblocking: %s", (long) pid,
+                      detail, g_strerror (errno));
+       }
 
+       pipe = g_slice_new0 (Pipe);
        pipe->detail = detail;
+       pipe->pid = pid;
        pipe->str = g_string_sized_new (256);
        pipe->channel = g_io_channel_unix_new (fd);
        g_io_channel_set_encoding (pipe->channel, NULL, NULL);
        g_io_channel_set_buffered (pipe->channel, FALSE);
-       pipe->id = g_io_add_watch (pipe->channel, G_IO_IN | G_IO_ERR | G_IO_HUP, pr_cb, pipe);
+       pipe->id = g_io_add_watch (pipe->channel, G_IO_IN | G_IO_ERR | G_IO_HUP, pipe_callback, pipe);
+
+       priv = NM_LIBRESWAN_PLUGIN_GET_PRIVATE (self);
+       priv->pipes = g_slist_prepend (priv->pipes, pipe);
 }
 
 static gboolean
-pr_cb (GIOChannel *source, GIOCondition condition, gpointer user_data)
+pipe_callback (GIOChannel *source, GIOCondition condition, gpointer user_data)
 {
        Pipe *pipe = user_data;
        char buf[200];
        gsize bytes_read = 0;
        char *nl;
+       gboolean invalid = FALSE;
+
+       g_return_val_if_fail (pipe && NM_IS_LIBRESWAN_PLUGIN (pipe->self), G_SOURCE_REMOVE);
+
+       nm_clear_g_source (&pipe->flush_id);
 
        if (condition & (G_IO_ERR | G_IO_HUP)) {
-               _LOGD ("PTY(%s) pipe error!", pipe->detail);
+               _LOGD ("pipe[%ld,%s] pipe error!", (long) pipe->pid, pipe->detail);
                pipe->id = 0;
+               pipe_release (priv->self, pipe);
                return G_SOURCE_REMOVE;
        }
-       g_assert (condition & G_IO_IN);
 
-       while (   (g_io_channel_read_chars (source,
-                                           buf,
-                                           sizeof (buf) - 1,
-                                           &bytes_read,
-                                           NULL) == G_IO_STATUS_NORMAL)
-              && bytes_read
-              && pipe->str->len < 500)
+       g_return_val_if_fail (condition & G_IO_IN, G_SOURCE_REMOVE);
+
+       while (TRUE) {
+               GIOStatus st;
+               GError *local = NULL;
+
+               st = g_io_channel_read_chars (source,
+                                             buf,
+                                             sizeof (buf) - 1,
+                                             &bytes_read,
+                                             &local);
+               if (local) {
+                       if (pipe->str->len)
+                               _LOGD ("pipe[%ld,%s]: %s", (long) pipe->pid, pipe->detail, pipe->str);
+                       _LOGD ("pipe[%ld,%s] pipe read error: %s", (long) pipe->pid, pipe->detail,
+                              local->message);
+                       pipe->id = 0;
+                       pipe_release (priv->self, pipe);
+                       g_error_free (local);
+                       return G_SOURCE_REMOVE;
+               }
+
+               if (st == G_IO_STATUS_AGAIN)
+                       return G_SOURCE_CONTINUE;
+
+               if (st != G_IO_STATUS_NORMAL) {
+                       if (pipe->str->len)
+                               _LOGD ("pipe[%ld,%s]: %s", (long) pipe->pid, pipe->detail, pipe->str);
+                       _LOGD ("pipe[%ld,%s] pipe read error", (long) pipe->pid, pipe->detail);
+                       pipe->id = 0;
+                       pipe_release (priv->self, pipe);
+                       g_error_free (local);
+                       return G_SOURCE_REMOVE;
+               }
+
+               if (!bytes_read)
+                       continue;
+
                g_string_append_len (pipe->str, buf, bytes_read);
 
-       /* Print each complete line and remove it from the buffer */
-       while (pipe->str->len) {
                nl = strpbrk (pipe->str->str, "\n\r");
-               if (!nl)
-                       break;
-               *nl = 0;  /* Don't print the linebreak */
-               if (pipe->str->str[0])
-                       _LOGD ("PTY(%s): %s", pipe->detail, pipe->str->str);
-               g_string_erase (pipe->str, 0, (nl - pipe->str->str) + 1);
-       }
+               if (!nl) {
+                       /* there is no new-line, */
+               }
+               if (
+
+                       /* Print each complete line and remove it from the buffer */
+                       while (pipe->str->len) {
+                               nl = strpbrk (pipe->str->str, "\n\r");
+                               if (!nl)
+                                       break;
+                               *nl = 0;  /* Don't print the linebreak */
+                               if (pipe->str->str[0])
+                                       _LOGD ("PTY(%s): %s", pipe->detail, pipe->str->str);
+                               g_string_erase (pipe->str, 0, (nl - pipe->str->str) + 1);
+                       }
+               }
 
        return G_SOURCE_CONTINUE;
 }
@@ -494,9 +599,6 @@ connect_cleanup (NMLibreswanPlugin *self)
                priv->io_buf = NULL;
        }
 
-       pipe_cleanup (&priv->out);
-       pipe_cleanup (&priv->err);
-
        if (priv->password) {
                memset (priv->password, 0, strlen (priv->password));
                g_free (priv->password);
@@ -1664,8 +1766,8 @@ connect_step (NMLibreswanPlugin *self, GError **error)
                g_io_channel_set_buffered (priv->channel, FALSE);
                priv->io_id = g_io_add_watch (priv->channel, G_IO_IN | G_IO_ERR | G_IO_HUP, io_cb, self);
 
-               pipe_init (&priv->out, up_stdout, "OUT");
-               pipe_init (&priv->err, up_stderr, "ERR");
+               pipe_start (self, priv->pid, up_stdout, "OUT");
+               pipe_start (self, priv->pid, up_stderr, "ERR");
                return TRUE;
 
        case CONNECT_STEP_LAST:


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