From fe77b4a478b68d3be41e7ee1b3b122959f0fed2e Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 4 Feb 2014 12:38:04 -0500 Subject: [PATCH] Add CamelIMAPXLogger. This is a GConverter that just echos data to standard output if the I/O debugging setting is enabled ('CAMEL_DEBUG=imapx:io'). Attaches to the GInputStream and GOutputStream. --- camel/providers/imapx/Makefile.am | 2 + camel/providers/imapx/camel-imapx-logger.c | 217 +++++++++++++++++++++++++++++ camel/providers/imapx/camel-imapx-logger.h | 72 ++++++++++ camel/providers/imapx/camel-imapx-server.c | 80 +++++++---- docs/reference/camel/camel-docs.sgml | 1 + docs/reference/camel/camel-sections.txt | 19 +++ docs/reference/camel/camel.types | 2 + 7 files changed, 367 insertions(+), 26 deletions(-) create mode 100644 camel/providers/imapx/camel-imapx-logger.c create mode 100644 camel/providers/imapx/camel-imapx-logger.h diff --git a/camel/providers/imapx/Makefile.am b/camel/providers/imapx/Makefile.am index c4a6ab9..7bdfcab 100644 --- a/camel/providers/imapx/Makefile.am +++ b/camel/providers/imapx/Makefile.am @@ -27,6 +27,8 @@ libcamelimapx_la_SOURCES = \ camel-imapx-job.h \ camel-imapx-list-response.c \ camel-imapx-list-response.h \ + camel-imapx-logger.c \ + camel-imapx-logger.h \ camel-imapx-mailbox.c \ camel-imapx-mailbox.h \ camel-imapx-namespace.c \ diff --git a/camel/providers/imapx/camel-imapx-logger.c b/camel/providers/imapx/camel-imapx-logger.c new file mode 100644 index 0000000..e317c52 --- /dev/null +++ b/camel/providers/imapx/camel-imapx-logger.c @@ -0,0 +1,217 @@ +/* + * camel-imapx-logger.c + * + * 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 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 . + * + */ + +/** + * SECTION: camel-imapx-logger + * @include: camel-imapx-logger.h + * @short_description: Log input/output streams + * + * #CamelIMAPXLogger is a simple #GConverter that just echos data to standard + * output if the I/O debugging setting is enabled ('CAMEL_DEBUG=imapx:io'). + * Attaches to the #GInputStream and #GOutputStream. + **/ + +#include "camel-imapx-logger.h" + +#include + +#include "camel-imapx-utils.h" + +#define CAMEL_IMAPX_LOGGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), CAMEL_TYPE_IMAPX_LOGGER, CamelIMAPXLoggerPrivate)) + +struct _CamelIMAPXLoggerPrivate { + gchar prefix; +}; + +enum { + PROP_0, + PROP_PREFIX +}; + +/* Forward Declarations */ +static void camel_imapx_logger_interface_init + (GConverterIface *interface); + +G_DEFINE_TYPE_WITH_CODE ( + CamelIMAPXLogger, + camel_imapx_logger, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE ( + G_TYPE_CONVERTER, + camel_imapx_logger_interface_init)) + +static void +imapx_logger_set_prefix (CamelIMAPXLogger *logger, + gchar prefix) +{ + logger->priv->prefix = prefix; +} + +static void +imapx_logger_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREFIX: + imapx_logger_set_prefix ( + CAMEL_IMAPX_LOGGER (object), + g_value_get_schar (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +imapx_logger_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREFIX: + g_value_set_schar ( + value, + camel_imapx_logger_get_prefix ( + CAMEL_IMAPX_LOGGER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static GConverterResult +imapx_logger_convert (GConverter *converter, + gconstpointer inbuf, + gsize inbuf_size, + gpointer outbuf, + gsize outbuf_size, + GConverterFlags flags, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + CamelIMAPXLoggerPrivate *priv; + GConverterResult result; + gsize min_size; + + priv = CAMEL_IMAPX_LOGGER_GET_PRIVATE (converter); + + min_size = MIN (inbuf_size, outbuf_size); + + memcpy (outbuf, inbuf, min_size); + *bytes_read = *bytes_written = min_size; + + camel_imapx_debug ( + io, priv->prefix, "I/O: '%.*s'\n", + (gint) min_size, (gchar *) outbuf); + + 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 +imapx_logger_reset (GConverter *converter) +{ + /* Nothing to do. */ +} + +static void +camel_imapx_logger_class_init (CamelIMAPXLoggerClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (CamelIMAPXLoggerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = imapx_logger_set_property; + object_class->get_property = imapx_logger_get_property; + + g_object_class_install_property ( + object_class, + PROP_PREFIX, + g_param_spec_char ( + "prefix", + "Prefix", + "Output prefix to distinguish connections", + 0x20, 0x7F, '*', + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +camel_imapx_logger_interface_init (GConverterIface *interface) +{ + interface->convert = imapx_logger_convert; + interface->reset = imapx_logger_reset; +} + +static void +camel_imapx_logger_init (CamelIMAPXLogger *logger) +{ + logger->priv = CAMEL_IMAPX_LOGGER_GET_PRIVATE (logger); +} + +/** + * camel_imapx_logger_new: + * @prefix: a prefix character + * + * Creates a new #CamelIMAPXLogger. Each output line generated by the + * logger will have a prefix string that includes the @prefix character + * to distinguish it from other active loggers. + * + * Returns: a #CamelIMAPXLogger + * + * Since: 3.12 + **/ +GConverter * +camel_imapx_logger_new (gchar prefix) +{ + return g_object_new ( + CAMEL_TYPE_IMAPX_LOGGER, + "prefix", prefix, NULL); +} + +/** + * camel_imapx_logger_get_prefix: + * @logger: a #CamelIMAPXLogger + * + * Returns the prefix character passed to camel_imapx_logger_new(). + * + * Returns: the prefix character + * + * Since: 3.12 + **/ +gchar +camel_imapx_logger_get_prefix (CamelIMAPXLogger *logger) +{ + g_return_val_if_fail (CAMEL_IS_IMAPX_LOGGER (logger), NULL); + + return logger->priv->prefix; +} + diff --git a/camel/providers/imapx/camel-imapx-logger.h b/camel/providers/imapx/camel-imapx-logger.h new file mode 100644 index 0000000..d92d1c9 --- /dev/null +++ b/camel/providers/imapx/camel-imapx-logger.h @@ -0,0 +1,72 @@ +/* + * camel-imapx-logger.h + * + * 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 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 . + * + */ + +#ifndef CAMEL_IMAPX_LOGGER_H +#define CAMEL_IMAPX_LOGGER_H + +#include + +/* Standard GObject macros */ +#define CAMEL_TYPE_IMAPX_LOGGER \ + (camel_imapx_logger_get_type ()) +#define CAMEL_IMAPX_LOGGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), CAMEL_TYPE_IMAPX_LOGGER, CamelIMAPXLogger)) +#define CAMEL_IMAPX_LOGGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), CAMEL_TYPE_IMAPX_LOGGER, CamelIMAPXLoggerClass)) +#define CAMEL_IS_IMAPX_LOGGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), CAMEL_TYPE_IMAPX_LOGGER)) +#define CAMEL_IS_IMAPX_LOGGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), CAMEL_TYPE_IMAPX_LOGGER)) +#define CAMEL_IMAPX_LOGGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), CAMEL_TYPE_IMAPX_LOGGER, CamelIMAPXLoggerClass)) + +G_BEGIN_DECLS + +typedef struct _CamelIMAPXLogger CamelIMAPXLogger; +typedef struct _CamelIMAPXLoggerClass CamelIMAPXLoggerClass; +typedef struct _CamelIMAPXLoggerPrivate CamelIMAPXLoggerPrivate; + +/** + * CamelIMAPXLogger: + * + * Contains only private data that should be read and manipulated using the + * functions below. + * + * Since: 3.12 + **/ +struct _CamelIMAPXLogger { + GObject parent; + CamelIMAPXLoggerPrivate *priv; +}; + +struct _CamelIMAPXLoggerClass { + GObjectClass parent_class; +}; + +GType camel_imapx_logger_get_type (void) G_GNUC_CONST; +GConverter * camel_imapx_logger_new (gchar prefix); +gchar camel_imapx_logger_get_prefix (CamelIMAPXLogger *logger); + +G_END_DECLS + +#endif /* CAMEL_IMAPX_LOGGER_H */ + diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c index c548950..275542a 100644 --- a/camel/providers/imapx/camel-imapx-server.c +++ b/camel/providers/imapx/camel-imapx-server.c @@ -41,6 +41,7 @@ #include "camel-imapx-command.h" #include "camel-imapx-folder.h" #include "camel-imapx-job.h" +#include "camel-imapx-logger.h" #include "camel-imapx-settings.h" #include "camel-imapx-store.h" #include "camel-imapx-stream.h" @@ -4218,6 +4219,54 @@ imapx_maybe_select (CamelIMAPXServer *is, camel_imapx_command_unref (ic); } +static void +imapx_server_set_streams (CamelIMAPXServer *is, + GInputStream *input_stream, + GOutputStream *output_stream) +{ + GConverter *logger; + + /* Wrapper the streams for debugging output. */ + + if (input_stream != NULL) { + logger = camel_imapx_logger_new (is->tagprefix); + input_stream = g_converter_input_stream_new ( + input_stream, logger); + g_clear_object (&logger); + } + + if (output_stream != NULL) { + logger = camel_imapx_logger_new (is->tagprefix); + output_stream = g_converter_output_stream_new ( + output_stream, logger); + g_clear_object (&logger); + } + + g_mutex_lock (&is->priv->stream_lock); + + /* Don't close the base streams so STARTTLS works correctly. */ + + if (G_IS_FILTER_INPUT_STREAM (is->priv->input_stream)) { + g_filter_input_stream_set_close_base_stream ( + G_FILTER_INPUT_STREAM (is->priv->input_stream), + FALSE); + } + + if (G_IS_FILTER_OUTPUT_STREAM (is->priv->output_stream)) { + g_filter_output_stream_set_close_base_stream ( + G_FILTER_OUTPUT_STREAM (is->priv->output_stream), + FALSE); + } + + g_clear_object (&is->priv->input_stream); + is->priv->input_stream = input_stream; + + g_clear_object (&is->priv->output_stream); + is->priv->output_stream = output_stream; + + g_mutex_unlock (&is->priv->stream_lock); +} + static gboolean connect_to_server_process (CamelIMAPXServer *is, const gchar *cmd, @@ -4356,20 +4405,14 @@ connect_to_server_process (CamelIMAPXServer *is, GOutputStream *output_stream; g_mutex_lock (&is->priv->stream_lock); - g_warn_if_fail (is->priv->subprocess == NULL); - g_warn_if_fail (is->priv->input_stream == NULL); - g_warn_if_fail (is->priv->output_stream == NULL); - is->priv->subprocess = g_object_ref (subprocess); + g_mutex_unlock (&is->priv->stream_lock); input_stream = g_subprocess_get_stdout_pipe (subprocess); - is->priv->input_stream = g_object_ref (input_stream); - output_stream = g_subprocess_get_stdin_pipe (subprocess); - is->priv->output_stream = g_object_ref (output_stream); - g_mutex_unlock (&is->priv->stream_lock); + imapx_server_set_streams (is, input_stream, output_stream); g_object_unref (subprocess); } @@ -4446,18 +4489,10 @@ imapx_connect_to_server (CamelIMAPXServer *is, GInputStream *input_stream; GOutputStream *output_stream; - g_mutex_lock (&is->priv->stream_lock); - - g_warn_if_fail (is->priv->input_stream == NULL); - g_warn_if_fail (is->priv->output_stream == NULL); - input_stream = g_io_stream_get_input_stream (base_stream); - is->priv->input_stream = g_object_ref (input_stream); - output_stream = g_io_stream_get_output_stream (base_stream); - is->priv->output_stream = g_object_ref (output_stream); - g_mutex_unlock (&is->priv->stream_lock); + imapx_server_set_streams (is, input_stream, output_stream); stream = camel_stream_new (base_stream); g_object_unref (base_stream); @@ -4607,20 +4642,13 @@ imapx_connect_to_server (CamelIMAPXServer *is, GInputStream *input_stream; GOutputStream *output_stream; - g_mutex_lock (&is->priv->stream_lock); - - g_clear_object (&is->priv->input_stream); - g_clear_object (&is->priv->output_stream); - input_stream = g_io_stream_get_input_stream (tls_stream); - is->priv->input_stream = g_object_ref (input_stream); - output_stream = g_io_stream_get_output_stream (tls_stream); - is->priv->output_stream = g_object_ref (output_stream); - g_mutex_unlock (&is->priv->stream_lock); + imapx_server_set_streams ( + is, input_stream, output_stream); camel_stream_set_base_stream (stream, tls_stream); g_object_unref (tls_stream); diff --git a/docs/reference/camel/camel-docs.sgml b/docs/reference/camel/camel-docs.sgml index 080442a..7079437 100644 --- a/docs/reference/camel/camel-docs.sgml +++ b/docs/reference/camel/camel-docs.sgml @@ -224,6 +224,7 @@ + diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt index 7e665e1..f5907ae 100644 --- a/docs/reference/camel/camel-sections.txt +++ b/docs/reference/camel/camel-sections.txt @@ -3448,6 +3448,25 @@ CamelIMAPXListResponsePrivate
+camel-imapx-logger +CamelIMAPXLogger +CamelIMAPXLogger +camel_imapx_logger_new +camel_imapx_logger_get_prefix + +CAMEL_IMAPX_LOGGER +CAMEL_IS_IMAPX_LOGGER +CAMEL_TYPE_IMAPX_LOGGER +CAMEL_IMAPX_LOGGER_CLASS +CAMEL_IS_IMAPX_LOGGER_CLASS +CAMEL_IMAPX_LOGGER_GET_CLASS +CamelIMAPXLoggerClass +camel_imapx_logger_get_type + +CamelIMAPXLoggerPrivate +
+ +
camel-imapx-mailbox CamelIMAPXMailbox CamelIMAPXMailbox diff --git a/docs/reference/camel/camel.types b/docs/reference/camel/camel.types index 96afd67..7c9dd93 100644 --- a/docs/reference/camel/camel.types +++ b/docs/reference/camel/camel.types @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -164,6 +165,7 @@ camel_spool_summary_get_type camel_imapx_folder_get_type camel_imapx_list_response_get_type +camel_imapx_logger_get_type camel_imapx_mailbox_get_type camel_imapx_namespace_get_type camel_imapx_namespace_response_get_type -- 2.7.4