[evolution-data-server] Enhance ESoupSession debug logging



commit 3764631f47159a1546abca14b9701220de67d070
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jul 2 13:37:46 2020 +0200

    Enhance ESoupSession debug logging
    
    It required specific code to have logged GInputStream data from a SoupRequest.
    It could be made transparent to the caller, thus avoid this special code.

 .../evolution-data-server-docs.sgml.in             |   1 +
 src/calendar/backends/http/e-cal-backend-http.c    |  16 --
 src/libedataserver/CMakeLists.txt                  |   2 +
 src/libedataserver/e-soup-logger.c                 | 201 +++++++++++++++++++++
 src/libedataserver/e-soup-logger.h                 |  32 ++++
 src/libedataserver/e-soup-session.c                |  10 +-
 src/libedataserver/e-webdav-session.c              |  21 ---
 src/libedataserver/libedataserver.h                |   1 +
 8 files changed, 241 insertions(+), 43 deletions(-)
---
diff --git a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in 
b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
index f1918ed9b..a3fb65e82 100644
--- a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
+++ b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
@@ -248,6 +248,7 @@
       <xi:include href="xml/e-operation-pool.xml"/>
       <xi:include href="xml/e-secret-store.xml"/>
       <xi:include href="xml/e-sexp.xml"/>
+      <xi:include href="xml/e-soup-logger.xml"/>
       <xi:include href="xml/e-soup-session.xml"/>
       <xi:include href="xml/e-soup-ssl-trust.xml"/>
       <xi:include href="xml/e-source-registry-watcher.xml"/>
diff --git a/src/calendar/backends/http/e-cal-backend-http.c b/src/calendar/backends/http/e-cal-backend-http.c
index 5f633a8ed..96ca1f340 100644
--- a/src/calendar/backends/http/e-cal-backend-http.c
+++ b/src/calendar/backends/http/e-cal-backend-http.c
@@ -256,17 +256,6 @@ ecb_http_connect_sync (ECalMetaBackend *meta_backend,
                success = input_stream != NULL;
 
                if (success && message && !SOUP_STATUS_IS_SUCCESSFUL (message->status_code) && 
message->status_code != SOUP_STATUS_NOT_MODIFIED) {
-                       if (input_stream && e_soup_session_get_log_level (cbhttp->priv->session) == 
SOUP_LOGGER_LOG_BODY) {
-                               gchar *response = ecb_http_read_stream_sync (input_stream, -1, cancellable, 
NULL);
-
-                               if (response) {
-                                       printf ("%s\n", response);
-                                       fflush (stdout);
-
-                                       g_free (response);
-                               }
-                       }
-
                        g_clear_object (&input_stream);
                        success = FALSE;
                }
@@ -460,11 +449,6 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
                return FALSE;
        }
 
-       if (e_soup_session_get_log_level (cbhttp->priv->session) == SOUP_LOGGER_LOG_BODY) {
-               printf ("%s\n", icalstring);
-               fflush (stdout);
-       }
-
        /* Skip the UTF-8 marker at the beginning of the string */
        if (((guchar) icalstring[0]) == 0xEF &&
            ((guchar) icalstring[1]) == 0xBB &&
diff --git a/src/libedataserver/CMakeLists.txt b/src/libedataserver/CMakeLists.txt
index 17be15469..fa86153d9 100644
--- a/src/libedataserver/CMakeLists.txt
+++ b/src/libedataserver/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SOURCES
        e-secret-store.c
        e-sexp.c
        e-soup-auth-bearer.c
+       e-soup-logger.c
        e-soup-session.c
        e-soup-ssl-trust.c
        e-source.c
@@ -163,6 +164,7 @@ set(HEADERS
        e-secret-store.h
        e-sexp.h
        e-soup-auth-bearer.h
+       e-soup-logger.h
        e-soup-session.h
        e-soup-ssl-trust.h
        e-source.h
diff --git a/src/libedataserver/e-soup-logger.c b/src/libedataserver/e-soup-logger.c
new file mode 100644
index 000000000..bcb099821
--- /dev/null
+++ b/src/libedataserver/e-soup-logger.c
@@ -0,0 +1,201 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2020 Red Hat (www.redhat.com)
+ *
+ * This library 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.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <stdio.h>
+#include <libsoup/soup.h>
+
+#include "e-soup-logger.h"
+
+/* Standard GObject macros */
+#define E_TYPE_SOUP_LOGGER \
+       (e_soup_logger_get_type ())
+#define E_SOUP_LOGGER(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_SOUP_LOGGER, EO365SoupLogger))
+#define E_SOUP_LOGGER_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_SOUP_LOGGER, EO365SoupLoggerClass))
+#define E_IS_SOUP_LOGGER(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_SOUP_LOGGER))
+#define E_IS_SOUP_LOGGER_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_SOUP_LOGGER))
+#define E_SOUP_LOGGER_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_SOUP_LOGGER))
+
+G_BEGIN_DECLS
+
+typedef struct _EO365SoupLogger EO365SoupLogger;
+typedef struct _EO365SoupLoggerClass EO365SoupLoggerClass;
+
+struct _EO365SoupLogger {
+       GObject parent;
+
+       GByteArray *data;
+};
+
+struct _EO365SoupLoggerClass {
+       GObjectClass parent_class;
+};
+
+GType          e_soup_logger_get_type  (void) G_GNUC_CONST;
+
+static void    e_soup_logger_converter_interface_init
+                                               (GConverterIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EO365SoupLogger, e_soup_logger, G_TYPE_OBJECT,
+       G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER, e_soup_logger_converter_interface_init))
+
+static GConverterResult
+e_soup_logger_convert (GConverter *converter,
+                      gconstpointer inbuf,
+                      gsize inbuf_size,
+                      gpointer outbuf,
+                      gsize outbuf_size,
+                      GConverterFlags flags,
+                      gsize *bytes_read,
+                      gsize *bytes_written,
+                      GError **error)
+{
+       EO365SoupLogger *logger = E_SOUP_LOGGER (converter);
+       GConverterResult result;
+       gsize min_size;
+
+       min_size = MIN (inbuf_size, outbuf_size);
+
+       if (inbuf && min_size)
+               memcpy (outbuf, inbuf, min_size);
+       *bytes_read = *bytes_written = min_size;
+
+       if (!logger->data)
+               logger->data = g_byte_array_sized_new (10240);
+
+       g_byte_array_append (logger->data, (const guint8 *) outbuf, (guint) min_size);
+
+       if ((flags & G_CONVERTER_INPUT_AT_END) != 0)
+               result = G_CONVERTER_FINISHED;
+       else if ((flags & G_CONVERTER_FLUSH) != 0)
+               result = G_CONVERTER_FLUSHED;
+       else
+               result = G_CONVERTER_CONVERTED;
+
+       return result;
+}
+
+static void
+e_soup_logger_reset (GConverter *converter)
+{
+       /* Nothing to do. */
+}
+
+static void
+e_soup_logger_print_data (EO365SoupLogger *logger)
+{
+       if (logger->data) {
+               fwrite (logger->data->data, 1, logger->data->len, stdout);
+               fwrite ("\n\n", 1, 2, stdout);
+
+               g_byte_array_free (logger->data, TRUE);
+               logger->data = NULL;
+       }
+
+       fflush (stdout);
+}
+
+static void
+e_soup_logger_message_finished_cb (SoupMessage *msg,
+                                       gpointer user_data)
+{
+       EO365SoupLogger *logger = user_data;
+
+       g_return_if_fail (E_IS_SOUP_LOGGER (logger));
+
+       e_soup_logger_print_data (logger);
+}
+
+static void
+o365_soup_logger_finalize (GObject *object)
+{
+       EO365SoupLogger *logger = E_SOUP_LOGGER (object);
+
+       e_soup_logger_print_data (logger);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_soup_logger_parent_class)->finalize (object);
+}
+
+static void
+e_soup_logger_class_init (EO365SoupLoggerClass *class)
+{
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->finalize = o365_soup_logger_finalize;
+}
+
+static void
+e_soup_logger_converter_interface_init (GConverterIface *iface)
+{
+       iface->convert = e_soup_logger_convert;
+       iface->reset = e_soup_logger_reset;
+}
+
+static void
+e_soup_logger_init (EO365SoupLogger *logger)
+{
+}
+
+/**
+ * e_soup_logger_attach:
+ * @message: a #SoupMessage
+ * @input_stream: (transfer full): a #GInputStream, associated with the @message
+ *
+ * Remembers what had been read from the @input_stream and prints it
+ * to stdout when the @message is finished. The function assumes
+ * ownership of the @input_stream.
+ *
+ * Returns: (transfer full): a new input stream, to be used instead of the @input_stream.
+ *    It should be freed with g_object_unref(), when no longer needed.
+ *
+ * Since: 3.38
+ **/
+GInputStream *
+e_soup_logger_attach (SoupMessage *message,
+                     GInputStream *input_stream)
+{
+       GConverter *logger;
+       GInputStream *filter_stream;
+
+       g_return_val_if_fail (SOUP_IS_MESSAGE (message), input_stream);
+       g_return_val_if_fail (G_IS_INPUT_STREAM (input_stream), input_stream);
+
+       logger = g_object_new (E_TYPE_SOUP_LOGGER, NULL);
+
+       filter_stream = g_converter_input_stream_new (input_stream, logger);
+       g_object_set_data_full (G_OBJECT (message), "ESoupLogger", logger, g_object_unref);
+
+       g_signal_connect_object (message, "finished",
+               G_CALLBACK (e_soup_logger_message_finished_cb), logger, G_CONNECT_AFTER);
+
+       g_object_unref (input_stream);
+
+       return filter_stream;
+}
diff --git a/src/libedataserver/e-soup-logger.h b/src/libedataserver/e-soup-logger.h
new file mode 100644
index 000000000..06a1758b1
--- /dev/null
+++ b/src/libedataserver/e-soup-logger.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2020 Red Hat (www.redhat.com)
+ *
+ * This library 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.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__LIBEDATASERVER_H_INSIDE__) && !defined (LIBEDATASERVER_COMPILATION)
+#error "Only <libedataserver/libedateserver.h> should be included directly."
+#endif
+
+#ifndef E_SOUP_LOGGER_H
+#define E_SOUP_LOGGER_H
+
+#include <libsoup/soup.h>
+
+GInputStream * e_soup_logger_attach    (SoupMessage *message,
+                                        GInputStream *input_stream);
+
+G_END_DECLS
+
+#endif /* E_SOUP_LOGGER_H */
diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c
index a06bfb15e..9ce03bee3 100644
--- a/src/libedataserver/e-soup-session.c
+++ b/src/libedataserver/e-soup-session.c
@@ -31,6 +31,7 @@
 
 #include "e-oauth2-services.h"
 #include "e-soup-auth-bearer.h"
+#include "e-soup-logger.h"
 #include "e-soup-ssl-trust.h"
 #include "e-source-authentication.h"
 #include "e-source-webdav.h"
@@ -1065,6 +1066,9 @@ e_soup_session_send_request_sync (ESoupSession *session,
                if (input_stream) {
                        message = soup_request_http_get_message (request);
 
+                       if (message && e_soup_session_get_log_level (session) == SOUP_LOGGER_LOG_BODY)
+                               input_stream = e_soup_logger_attach (message, input_stream);
+
                        if (message && SOUP_STATUS_IS_REDIRECTION (message->status_code)) {
                                /* libsoup uses 20, but the constant is not in any public header */
                                if (resend_count >= 30) {
@@ -1180,12 +1184,6 @@ e_soup_session_send_request_simple_sync (ESoupSession *session,
        g_free (buffer);
        g_object_unref (input_stream);
 
-       if (bytes->len > 0 && e_soup_session_get_log_level (session) == SOUP_LOGGER_LOG_BODY) {
-               fwrite (bytes->data, 1, bytes->len, stdout);
-               fprintf (stdout, "\n");
-               fflush (stdout);
-       }
-
        if (success)
                success = e_soup_session_check_result (session, request, bytes->data, bytes->len, error);
 
diff --git a/src/libedataserver/e-webdav-session.c b/src/libedataserver/e-webdav-session.c
index f254a84fb..1af7c2a3c 100644
--- a/src/libedataserver/e-webdav-session.c
+++ b/src/libedataserver/e-webdav-session.c
@@ -2100,7 +2100,6 @@ e_webdav_session_get_sync (EWebDAVSession *webdav,
        success = input_stream != NULL;
 
        if (success) {
-               SoupLoggerLogLevel log_level = e_soup_session_get_log_level (E_SOUP_SESSION (webdav));
                gpointer buffer;
                gsize nread = 0, nwritten;
                gboolean first_chunk = TRUE;
@@ -2109,11 +2108,6 @@ e_webdav_session_get_sync (EWebDAVSession *webdav,
 
                while (success = g_input_stream_read_all (input_stream, buffer, BUFFER_SIZE, &nread, 
cancellable, error),
                       success && nread > 0) {
-                       if (log_level == SOUP_LOGGER_LOG_BODY) {
-                               fwrite (buffer, 1, nread, stdout);
-                               fflush (stdout);
-                       }
-
                        if (first_chunk) {
                                GByteArray tmp_bytes;
 
@@ -2134,9 +2128,6 @@ e_webdav_session_get_sync (EWebDAVSession *webdav,
 
                if (success && first_chunk) {
                        success = !e_webdav_session_replace_with_detailed_error_internal (webdav, request, 
NULL, FALSE, _("Failed to read resource"), error, TRUE, TRUE);
-               } else if (success && !first_chunk && log_level == SOUP_LOGGER_LOG_BODY) {
-                       fprintf (stdout, "\n");
-                       fflush (stdout);
                }
 
                g_free (buffer);
@@ -2222,7 +2213,6 @@ e_webdav_session_get_data_sync (EWebDAVSession *webdav,
 
 typedef struct _ChunkWriteData {
        SoupSession *session;
-       SoupLoggerLogLevel log_level;
        GInputStream *stream;
        goffset read_from;
        gboolean wrote_any;
@@ -2252,11 +2242,6 @@ e_webdav_session_write_next_chunk (SoupMessage *message,
        } else {
                cwd->wrote_any = TRUE;
                soup_message_body_append (message->request_body, SOUP_MEMORY_TEMPORARY, cwd->buffer, nread);
-
-               if (cwd->log_level == SOUP_LOGGER_LOG_BODY) {
-                       fwrite (cwd->buffer, 1, nread, stdout);
-                       fflush (stdout);
-               }
        }
 }
 
@@ -2418,7 +2403,6 @@ e_webdav_session_put_sync (EWebDAVSession *webdav,
        }
 
        cwd.session = SOUP_SESSION (webdav);
-       cwd.log_level = e_soup_session_get_log_level (E_SOUP_SESSION (webdav));
        cwd.stream = stream;
        cwd.read_from = 0;
        cwd.wrote_any = FALSE;
@@ -2450,11 +2434,6 @@ e_webdav_session_put_sync (EWebDAVSession *webdav,
        success = !e_webdav_session_replace_with_detailed_error_internal (webdav, request, bytes, FALSE, 
_("Failed to put data"), error, TRUE, TRUE) &&
                bytes != NULL;
 
-       if (cwd.wrote_any && cwd.log_level == SOUP_LOGGER_LOG_BODY) {
-               fprintf (stdout, "\n");
-               fflush (stdout);
-       }
-
        if (cwd.error) {
                g_clear_error (error);
                g_propagate_error (error, cwd.error);
diff --git a/src/libedataserver/libedataserver.h b/src/libedataserver/libedataserver.h
index 6f872098a..cee5b6054 100644
--- a/src/libedataserver/libedataserver.h
+++ b/src/libedataserver/libedataserver.h
@@ -48,6 +48,7 @@
 #include <libedataserver/e-secret-store.h>
 #include <libedataserver/e-sexp.h>
 #include <libedataserver/e-soup-auth-bearer.h>
+#include <libedataserver/e-soup-logger.h>
 #include <libedataserver/e-soup-session.h>
 #include <libedataserver/e-soup-ssl-trust.h>
 #include <libedataserver/e-source-address-book.h>


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