From 856c07ea0084bf249103c2b58dc61f151c3d7c98 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 7 Oct 2013 14:27:21 -0300 Subject: [PATCH] souphttpsrc: do not emit EOS when connection drops If the pipeline is stalled for too long, souphttpsrc will block and stop fetching data from the network. This can cause the connection to drop and souphttpsrc would handle it as an EOS. This patch makes it persist and try to fetch more data until the end of the content length or until receiving an error that it is beyong limits in case the content is unknown. https://bugzilla.gnome.org/show_bug.cgi?id=683536 --- ext/soup/gstsouphttpsrc.c | 30 +++++++++++++++++++++++++----- ext/soup/gstsouphttpsrc.h | 5 +++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/ext/soup/gstsouphttpsrc.c b/ext/soup/gstsouphttpsrc.c index aa2d0ad3fc..80f9eb0329 100644 --- a/ext/soup/gstsouphttpsrc.c +++ b/ext/soup/gstsouphttpsrc.c @@ -281,6 +281,7 @@ gst_soup_http_src_reset (GstSoupHTTPSrc * src) src->request_position = 0; src->stop_position = -1; src->content_size = 0; + src->have_body = FALSE; gst_caps_replace (&src->src_caps, NULL); g_free (src->iradio_name); @@ -892,7 +893,7 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src) * don't output any data (such as an error html page), and return * GST_FLOW_ERROR from the create function instead of having * got_chunk_cb overwrite src->ret with FLOW_OK again. */ - if (src->ret == GST_FLOW_ERROR) { + if (src->ret == GST_FLOW_ERROR || src->ret == GST_FLOW_EOS) { gst_soup_http_src_session_pause_message (src); if (src->loop) @@ -916,9 +917,14 @@ gst_soup_http_src_got_body_cb (SoupMessage * msg, GstSoupHTTPSrc * src) } GST_DEBUG_OBJECT (src, "got body"); src->ret = GST_FLOW_EOS; - if (src->loop) - g_main_loop_quit (src->loop); - gst_soup_http_src_session_pause_message (src); + src->have_body = TRUE; + + /* no need to interrupt the message here, we do it on the + * finished_cb anyway if needed. And getting the body might mean + * that the connection was hang up before finished. This happens when + * the pipeline is stalled for too long (long pauses during playback). + * Best to let it continue from here and pause because it reached the + * final bytes based on content_size or received an out of range error */ } /* Finished. Signal EOS. */ @@ -936,7 +942,8 @@ gst_soup_http_src_finished_cb (SoupMessage * msg, GstSoupHTTPSrc * src) * that occurred in the QUEUEING state; i.e. before the connection setup * was complete. Do nothing */ } else if (src->session_io_status == - GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING && src->read_position > 0) { + GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING && src->read_position > 0 && + (!src->have_size || src->read_position < src->content_size)) { /* The server disconnected while streaming. Reconnect and seeking to the * last location. */ src->retry = TRUE; @@ -1047,6 +1054,7 @@ gst_soup_http_src_got_chunk_cb (SoupMessage * msg, SoupBuffer * chunk, GST_DEBUG_OBJECT (src, "got chunk, but not for current message"); return; } + src->have_body = FALSE; if (G_UNLIKELY (src->session_io_status != GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_RUNNING)) { /* Probably a redirect. */ @@ -1164,6 +1172,18 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src) SOUP_STATUS_IS_REDIRECTION (msg->status_code) || SOUP_STATUS_IS_SERVER_ERROR (msg->status_code)) { /* Report HTTP error. */ + + /* when content_size is unknown and we have just finished receiving + * a body message, requests that go beyond the content limits will result + * in an error. Here we convert those to EOS */ + if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE && + src->have_body && src->have_size) { + GST_DEBUG_OBJECT (src, "Requested range out of limits and received full " + "body, returning EOS"); + src->ret = GST_FLOW_EOS; + return; + } + /* FIXME: reason_phrase is not translated and not suitable for user * error dialog according to libsoup documentation. * FIXME: error code (OPEN_READ vs. READ) should depend on http status? */ diff --git a/ext/soup/gstsouphttpsrc.h b/ext/soup/gstsouphttpsrc.h index 594dfaa250..8ebd2b612d 100644 --- a/ext/soup/gstsouphttpsrc.h +++ b/ext/soup/gstsouphttpsrc.h @@ -78,6 +78,11 @@ struct _GstSoupHTTPSrc { Range. */ guint64 request_position; /* Seek to this position. */ guint64 stop_position; /* Stop at this position. */ + gboolean have_body; /* Indicates if it has just been signaled the + * end of the message body. This is used to + * decide if an out of range request should be + * handled as an error or EOS when the content + * size is unknown */ /* Shoutcast/icecast metadata extraction handling. */ gboolean iradio_mode;