souphttpsrc: add support for keep-alive sessions

https://bugzilla.gnome.org/show_bug.cgi?id=699926
This commit is contained in:
Andoni Morales Alastruey 2013-02-28 12:20:52 +01:00 committed by Sebastian Dröge
parent 106bc2b17b
commit 4d80d3fad9
2 changed files with 90 additions and 37 deletions

View file

@ -108,17 +108,20 @@ enum
PROP_TIMEOUT,
PROP_EXTRA_HEADERS,
PROP_SOUP_LOG_LEVEL,
PROP_COMPRESS
PROP_COMPRESS,
PROP_KEEP_ALIVE
};
#define DEFAULT_USER_AGENT "GStreamer souphttpsrc "
#define DEFAULT_IRADIO_MODE TRUE
#define DEFAULT_SOUP_LOG_LEVEL SOUP_LOGGER_LOG_NONE
#define DEFAULT_COMPRESS FALSE
#define DEFAULT_KEEP_ALIVE FALSE
static void gst_soup_http_src_uri_handler_init (gpointer g_iface,
gpointer iface_data);
static void gst_soup_http_src_finalize (GObject * gobject);
static void gst_soup_http_src_dispose (GObject * gobject);
static void gst_soup_http_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
@ -191,6 +194,7 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
gobject_class->set_property = gst_soup_http_src_set_property;
gobject_class->get_property = gst_soup_http_src_get_property;
gobject_class->finalize = gst_soup_http_src_finalize;
gobject_class->dispose = gst_soup_http_src_dispose;
g_object_class_install_property (gobject_class,
PROP_LOCATION,
@ -248,6 +252,7 @@ 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:
*
@ -277,6 +282,20 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
"Allow compressed content encodings",
DEFAULT_COMPRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstSoupHTTPSrc::keep-alive:
*
* If set to %TRUE, souphttpsrc will keep alive connections when being
* set to READY state and only will close connections when connecting
* to a different server or when going to NULL state..
*
* Since: 1.4
*/
g_object_class_install_property (gobject_class, PROP_KEEP_ALIVE,
g_param_spec_boolean ("keep-alive", "keep-alive",
"Use HTTP persistent connections", DEFAULT_KEEP_ALIVE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&srctemplate));
@ -357,6 +376,18 @@ gst_soup_http_src_init (GstSoupHTTPSrc * src)
gst_soup_http_src_reset (src);
}
static void
gst_soup_http_src_dispose (GObject * gobject)
{
GstSoupHTTPSrc *src = GST_SOUP_HTTP_SRC (gobject);
GST_DEBUG_OBJECT (src, "dispose");
gst_soup_http_src_session_close (src);
G_OBJECT_CLASS (parent_class)->dispose (gobject);
}
static void
gst_soup_http_src_finalize (GObject * gobject)
{
@ -478,6 +509,9 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id,
case PROP_COMPRESS:
src->compress = g_value_get_boolean (value);
break;
case PROP_KEEP_ALIVE:
src->keep_alive = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -545,6 +579,9 @@ gst_soup_http_src_get_property (GObject * object, guint prop_id,
case PROP_COMPRESS:
g_value_set_boolean (value, src->compress);
break;
case PROP_KEEP_ALIVE:
g_value_set_boolean (value, src->keep_alive);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -707,9 +744,11 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
return FALSE;
}
src->context = g_main_context_new ();
if (!src->context)
src->context = g_main_context_new ();
src->loop = g_main_loop_new (src->context, TRUE);
if (!src->loop)
src->loop = g_main_loop_new (src->context, TRUE);
if (!src->loop) {
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
(NULL), ("Failed to start GMainLoop"));
@ -717,36 +756,43 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
return FALSE;
}
GST_DEBUG_OBJECT (src, "Creating session");
if (src->proxy == NULL) {
src->session =
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
src->context, SOUP_SESSION_USER_AGENT, src->user_agent,
SOUP_SESSION_TIMEOUT, src->timeout,
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
NULL);
} else {
src->session =
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
src->context, SOUP_SESSION_PROXY_URI, src->proxy,
SOUP_SESSION_TIMEOUT, src->timeout,
SOUP_SESSION_USER_AGENT, src->user_agent, NULL);
}
if (!src->session) {
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
(NULL), ("Failed to create async session"));
return FALSE;
GST_DEBUG_OBJECT (src, "Creating session");
if (src->proxy == NULL) {
src->session =
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
src->context, SOUP_SESSION_USER_AGENT, src->user_agent,
SOUP_SESSION_TIMEOUT, src->timeout,
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
NULL);
} else {
src->session =
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
src->context, SOUP_SESSION_PROXY_URI, src->proxy,
SOUP_SESSION_TIMEOUT, src->timeout,
SOUP_SESSION_USER_AGENT, src->user_agent, NULL);
}
if (!src->session) {
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
(NULL), ("Failed to create async session"));
return FALSE;
}
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));
} else {
GST_DEBUG_OBJECT (src, "Re-using session");
}
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));
if (src->compress)
soup_session_add_feature_by_type (src->session, SOUP_TYPE_CONTENT_DECODER);
else
soup_session_remove_feature_by_type (src->session,
SOUP_TYPE_CONTENT_DECODER);
return TRUE;
}
@ -760,6 +806,12 @@ gst_soup_http_src_session_close (GstSoupHTTPSrc * src)
src->session = NULL;
src->msg = NULL;
}
if (src->loop) {
g_main_loop_unref (src->loop);
g_main_context_unref (src->context);
src->loop = NULL;
src->context = NULL;
}
}
static void
@ -1263,8 +1315,10 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method)
return FALSE;
}
src->session_io_status = GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_IDLE;
soup_message_headers_append (src->msg->request_headers, "Connection",
"close");
if (!src->keep_alive) {
soup_message_headers_append (src->msg->request_headers, "Connection",
"close");
}
if (src->iradio_mode) {
soup_message_headers_append (src->msg->request_headers, "icy-metadata",
"1");
@ -1396,13 +1450,11 @@ gst_soup_http_src_stop (GstBaseSrc * bsrc)
src = GST_SOUP_HTTP_SRC (bsrc);
GST_DEBUG_OBJECT (src, "stop()");
gst_soup_http_src_session_close (src);
if (src->loop) {
g_main_loop_unref (src->loop);
g_main_context_unref (src->context);
src->loop = NULL;
src->context = NULL;
}
if (src->keep_alive)
gst_soup_http_src_cancel_message (src);
else
gst_soup_http_src_session_close (src);
if (src->extra_headers) {
gst_structure_free (src->extra_headers);
src->extra_headers = NULL;

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 */
gboolean keep_alive; /* Use keep-alive sessions */
/* Shoutcast/icecast metadata extraction handling. */
gboolean iradio_mode;