souphttp*: add ability to do HTTP session logging

This changeset adds the loggin infrastructure and
mods both souphttpsrc and souphttclientsink to use it.

https://bugzilla.gnome.org/show_bug.cgi?id=721764
This commit is contained in:
Reynaldo H. Verdejo Pinochet 2014-01-07 23:00:56 -03:00
parent 19a307930a
commit 4f42fff349
8 changed files with 192 additions and 22 deletions

View file

@ -1,6 +1,6 @@
plugin_LTLIBRARIES = libgstsouphttpsrc.la
libgstsouphttpsrc_la_SOURCES = gstsouphttpsrc.c gstsouphttpclientsink.c gstsoup.c
libgstsouphttpsrc_la_SOURCES = gstsouphttpsrc.c gstsouphttpclientsink.c gstsouputils.c gstsoup.c
libgstsouphttpsrc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
$(GST_CFLAGS) $(SOUP_CFLAGS) \
@ -10,4 +10,4 @@ libgstsouphttpsrc_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_API_VERSION
libgstsouphttpsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstsouphttpsrc_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
noinst_HEADERS = gstsouphttpsrc.h gstsouphttpclientsink.h
noinst_HEADERS = gstsouphttpsrc.h gstsouphttpclientsink.h gstsouputils.h

View file

@ -20,7 +20,9 @@
#include "gstsouphttpsrc.h"
#include "gstsouphttpclientsink.h"
#include "gstsouputils.h"
GST_DEBUG_CATEGORY (soup_utils_debug);
static gboolean
plugin_init (GstPlugin * plugin)
@ -36,6 +38,7 @@ plugin_init (GstPlugin * plugin)
GST_TYPE_SOUP_HTTP_SRC);
gst_element_register (plugin, "souphttpclientsink", GST_RANK_NONE,
GST_TYPE_SOUP_HTTP_CLIENT_SINK);
GST_DEBUG_CATEGORY_INIT (soup_utils_debug, "souputils", 0, "Soup utils");
return TRUE;
}

View file

@ -41,6 +41,7 @@
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#include "gstsouphttpclientsink.h"
#include "gstsouputils.h"
#include <gst/glib-compat-private.h>
@ -93,10 +94,12 @@ enum
PROP_PROXY_ID,
PROP_PROXY_PW,
PROP_COOKIES,
PROP_SESSION
PROP_SESSION,
PROP_SOUP_LOG_LEVEL
};
#define DEFAULT_USER_AGENT "GStreamer souphttpclientsink "
#define DEFAULT_SOUP_LOG_LEVEL SOUP_LOGGER_LOG_NONE
/* pad templates */
@ -168,6 +171,19 @@ gst_soup_http_client_sink_class_init (GstSoupHttpClientSinkClass * klass)
g_object_class_install_property (gobject_class, PROP_COOKIES,
g_param_spec_boxed ("cookies", "Cookies", "HTTP request cookies",
G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstSoupHttpClientSink::http-log-level:
*
* If set and > 0, captures and dumps HTTP session data as
* log messages if log level >= GST_LEVEL_TRACE
*
* Since: 1.4
*/
g_object_class_install_property (gobject_class, PROP_SOUP_LOG_LEVEL,
g_param_spec_enum ("http-log-level", "HTTP log level",
"Set log level for soup's HTTP session log",
SOUP_TYPE_LOGGER_LOG_LEVEL, DEFAULT_SOUP_LOG_LEVEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_soup_http_client_sink_sink_template));
@ -214,6 +230,7 @@ gst_soup_http_client_sink_init (GstSoupHttpClientSink * souphttpsink)
souphttpsink->proxy_pw = NULL;
souphttpsink->prop_session = NULL;
souphttpsink->timeout = 1;
souphttpsink->log_level = DEFAULT_SOUP_LOG_LEVEL;
proxy = g_getenv ("http_proxy");
if (proxy && !gst_soup_http_client_sink_set_proxy (souphttpsink, proxy)) {
GST_WARNING_OBJECT (souphttpsink,
@ -316,6 +333,9 @@ gst_soup_http_client_sink_set_property (GObject * object, guint property_id,
g_strfreev (souphttpsink->cookies);
souphttpsink->cookies = g_strdupv (g_value_get_boxed (value));
break;
case PROP_SOUP_LOG_LEVEL:
souphttpsink->log_level = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -368,6 +388,9 @@ gst_soup_http_client_sink_get_property (GObject * object, guint property_id,
case PROP_COOKIES:
g_value_set_boxed (value, g_strdupv (souphttpsink->cookies));
break;
case PROP_SOUP_LOG_LEVEL:
g_value_set_enum (value, souphttpsink->log_level);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -514,13 +537,14 @@ gst_soup_http_client_sink_start (GstBaseSink * sink)
souphttpsink->user_agent, SOUP_SESSION_TIMEOUT, souphttpsink->timeout,
NULL);
//soup_session_add_feature (souphttpsink->session,
// SOUP_SESSION_FEATURE (soup_logger_new (SOUP_LOGGER_LOG_BODY, 100)));
g_signal_connect (souphttpsink->session, "authenticate",
G_CALLBACK (authenticate), souphttpsink);
}
/* Set up logging */
gst_soup_util_log_setup (souphttpsink->session, souphttpsink->log_level,
GST_ELEMENT (souphttpsink));
return TRUE;
}

View file

@ -66,7 +66,7 @@ struct _GstSoupHttpClientSink
char *user_agent;
gboolean automatic_redirect;
gchar **cookies;
SoupLoggerLogLevel log_level;
};
struct _GstSoupHttpClientSinkClass

View file

@ -79,6 +79,7 @@
#include <gst/gst-i18n-plugin.h>
#include <libsoup/soup.h>
#include "gstsouphttpsrc.h"
#include "gstsouputils.h"
#include <gst/tag/tag.h>
@ -105,11 +106,13 @@ enum
PROP_COOKIES,
PROP_IRADIO_MODE,
PROP_TIMEOUT,
PROP_EXTRA_HEADERS
PROP_EXTRA_HEADERS,
PROP_SOUP_LOG_LEVEL
};
#define DEFAULT_USER_AGENT "GStreamer souphttpsrc "
#define DEFAULT_IRADIO_MODE TRUE
#define DEFAULT_SOUP_LOG_LEVEL SOUP_LOGGER_LOG_NONE
static void gst_soup_http_src_uri_handler_init (gpointer g_iface,
gpointer iface_data);
@ -243,6 +246,19 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
"Enable internet radio mode (ask server to send shoutcast/icecast "
"metadata interleaved with the actual stream data)",
DEFAULT_IRADIO_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstSoupHTTPSrc::http-log-level:
*
* If set and > 0, captures and dumps HTTP session data as
* log messages if log level >= GST_LEVEL_TRACE
*
* Since: 1.4
*/
g_object_class_install_property (gobject_class, PROP_SOUP_LOG_LEVEL,
g_param_spec_enum ("http-log-level", "HTTP log level",
"Set log level for soup's HTTP session log",
SOUP_TYPE_LOGGER_LOG_LEVEL, DEFAULT_SOUP_LOG_LEVEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&srctemplate));
@ -313,6 +329,7 @@ gst_soup_http_src_init (GstSoupHTTPSrc * src)
src->context = NULL;
src->session = NULL;
src->msg = NULL;
src->log_level = DEFAULT_SOUP_LOG_LEVEL;
proxy = g_getenv ("http_proxy");
if (proxy && !gst_soup_http_src_set_proxy (src, proxy)) {
GST_WARNING_OBJECT (src,
@ -438,6 +455,9 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id,
src->extra_headers = s ? gst_structure_copy (s) : NULL;
break;
}
case PROP_SOUP_LOG_LEVEL:
src->log_level = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -499,6 +519,9 @@ gst_soup_http_src_get_property (GObject * object, guint prop_id,
case PROP_EXTRA_HEADERS:
gst_value_set_structure (value, src->extra_headers);
break;
case PROP_SOUP_LOG_LEVEL:
g_value_set_enum (value, src->log_level);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -695,6 +718,10 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
g_signal_connect (src->session, "authenticate",
G_CALLBACK (gst_soup_http_src_authenticate_cb), src);
/* Set up logging */
gst_soup_util_log_setup (src->session, src->log_level, GST_ELEMENT (src));
return TRUE;
}
@ -725,13 +752,6 @@ gst_soup_http_src_authenticate_cb (SoupSession * session, SoupMessage * msg,
}
}
static void
gst_soup_http_src_headers_foreach (const gchar * name, const gchar * val,
gpointer src)
{
GST_DEBUG_OBJECT (src, " %s: %s", name, val);
}
static void
gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
{
@ -741,9 +761,7 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src)
guint64 newsize;
GHashTable *params = NULL;
GST_DEBUG_OBJECT (src, "got headers:");
soup_message_headers_foreach (msg->response_headers,
gst_soup_http_src_headers_foreach, src);
GST_INFO_OBJECT (src, "got headers");
if (msg->status_code == SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED &&
src->proxy_id && src->proxy_pw)
@ -1251,10 +1269,6 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method)
gst_soup_http_src_add_extra_headers (src);
GST_DEBUG_OBJECT (src, "request headers:");
soup_message_headers_foreach (src->msg->request_headers,
gst_soup_http_src_headers_foreach, src);
return TRUE;
}

View file

@ -83,6 +83,7 @@ struct _GstSoupHTTPSrc {
* decide if an out of range request should be
* handled as an error or EOS when the content
* size is unknown */
SoupLoggerLogLevel log_level;/* Soup HTTP session logger level */
/* Shoutcast/icecast metadata extraction handling. */
gboolean iradio_mode;

97
ext/soup/gstsouputils.c Normal file
View file

@ -0,0 +1,97 @@
/* GStreamer
*
* Copyright (C) 2014 Samsung Electronics. All rights reserved.
* @Author: Reynaldo H. Verdejo Pinochet <r.verdejo@sisa.samsung.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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
* Library General Public License for more
*/
#include <glib.h>
#include <gst/gst.h>
#include <libsoup/soup.h>
#include "gstsouputils.h"
/**
* Soup logger funcs
*/
GST_DEBUG_CATEGORY_EXTERN (soup_utils_debug);
#define GST_CAT_DEFAULT soup_utils_debug
static inline gchar
gst_soup_util_log_make_level_tag (SoupLoggerLogLevel level)
{
gchar c;
if (G_UNLIKELY (level > 9))
return '?';
switch (level) {
case SOUP_LOGGER_LOG_MINIMAL:
c = 'M';
break;
case SOUP_LOGGER_LOG_HEADERS:
c = 'H';
break;
case SOUP_LOGGER_LOG_BODY:
c = 'B';
break;
default:
/* Unknown level. If this is hit libsoup likely added a new
* log level to SoupLoggerLogLevel and it should be added
* as a case */
c = level + '0';
break;
}
return c;
}
static void
gst_soup_util_log_printer_cb (SoupLogger G_GNUC_UNUSED * logger,
SoupLoggerLogLevel level, char direction, const char *data,
gpointer user_data)
{
gchar c;
c = gst_soup_util_log_make_level_tag (level);
GST_TRACE_OBJECT (GST_ELEMENT (user_data), "HTTP_SESSION(%c): %c %s", c,
direction, data);
}
void
gst_soup_util_log_setup (SoupSession * session, SoupLoggerLogLevel level,
GstElement * element)
{
SoupLogger *logger;
if (!level) {
GST_INFO_OBJECT (element, "Not attaching a logger with level 0");
return;
}
g_assert (session && element);
if (gst_debug_category_get_threshold (GST_CAT_DEFAULT)
< GST_LEVEL_TRACE) {
GST_INFO_OBJECT (element, "Not setting up HTTP session logger. "
"Need at least GST_LEVEL_TRACE");
return;
}
/* Create a new logger and set body_size_limit to -1 (no limit) */
logger = soup_logger_new (level, -1);
soup_logger_set_printer (logger, gst_soup_util_log_printer_cb,
gst_object_ref (element), (GDestroyNotify) gst_object_unref);
/* Attach logger to session */
soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
g_object_unref (logger);
}

31
ext/soup/gstsouputils.h Normal file
View file

@ -0,0 +1,31 @@
/* GStreamer
*
* Copyright (C) 2014 Samsung Electronics. All rights reserved.
* @Author: Reynaldo H. Verdejo Pinochet <r.verdejo@sisa.samsung.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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
* Library General Public License for more
*/
#ifndef __GST_SOUP_UTILS_H__
#define __GST_SOUP_UTILS_H__
#include <glib.h>
#include <gst/gst.h>
#include <libsoup/soup.h>
G_BEGIN_DECLS
void gst_soup_util_log_setup (SoupSession * session, SoupLoggerLogLevel level,
GstElement * element);
G_END_DECLS
#endif