From 57d746ed3c0725b3d9b6a579c3e4a70e6dd19024 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Mon, 12 Dec 2016 21:06:21 +0900 Subject: [PATCH] souphttpsrc: add cookie jar Change-Id: I1912c1fa3903723f3487d0ec65daa57269b89519 --- ext/soup/gstsouphttpsrc.c | 217 +++++++++++++++++++++++++++++++++++++++- ext/soup/gstsouphttpsrc.h | 6 +- packaging/gst-plugins-good.spec | 3 +- 3 files changed, 218 insertions(+), 8 deletions(-) diff --git a/ext/soup/gstsouphttpsrc.c b/ext/soup/gstsouphttpsrc.c index d9ae2e7..df8daf1 100644 --- a/ext/soup/gstsouphttpsrc.c +++ b/ext/soup/gstsouphttpsrc.c @@ -492,7 +492,9 @@ gst_soup_http_src_init (GstSoupHTTPSrc * src) "The proxy in the http_proxy env var (\"%s\") cannot be parsed.", proxy); } - +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + src->cookie_jar = NULL; +#endif gst_base_src_set_automatic_eos (GST_BASE_SRC (src), FALSE); gst_soup_http_src_reset (src); @@ -593,8 +595,29 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id, break; } case PROP_COOKIES: +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + { + char **array; + SoupURI *base_uri; g_strfreev (src->cookies); src->cookies = g_strdupv (g_value_get_boxed (value)); + + if (src->cookie_jar && ((array = src->cookies) != NULL)) { + base_uri = soup_uri_new (src->location); + GST_INFO_OBJECT (src, "request to set cookies..."); + while (*array != NULL) { + soup_cookie_jar_add_cookie (src->cookie_jar, + soup_cookie_parse (*array++, base_uri)); + } + soup_uri_free (base_uri); + } else { + GST_INFO_OBJECT (src, "set cookies after session creation"); + } + } +#else + g_strfreev (src->cookies); + src->cookies = g_strdupv (g_value_get_boxed (value)); +#endif break; case PROP_IS_LIVE: gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); @@ -697,7 +720,26 @@ gst_soup_http_src_get_property (GObject * object, guint prop_id, } break; case PROP_COOKIES: - g_value_set_boxed (value, g_strdupv (src->cookies)); +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + { + GSList *cookie_list, *c; + gchar **cookies, **array; + + cookies = NULL; + if ((src->cookie_jar) && + ((cookie_list = soup_cookie_jar_all_cookies (src->cookie_jar)) != NULL)) { + cookies = g_new0 (gchar *, g_slist_length(cookie_list) + 1); + array = cookies; + for (c = cookie_list; c; c = c->next) { + *array++ = soup_cookie_to_set_cookie_header ((SoupCookie *)(c->data)); + } + soup_cookies_free (cookie_list); + } + g_value_set_boxed (value, cookies); + } +#else + g_value_set_boxed (value, g_strdupv (src->cookies)); +#endif break; case PROP_IS_LIVE: g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); @@ -795,7 +837,15 @@ gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src, guint64 offset, gint rc; soup_message_headers_remove (src->msg->request_headers, "Range"); +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION +/*[prasenjit.c]This changes are needed to enable Seekable Contents from server. +We have observed that , for few specific networks ( VODAFONE ) , without theabove headers , +Youtube is sending non-seekable contents to the Client. +*/ + if (offset >=0 || stop_offset != -1) { +#else if (offset || stop_offset != -1) { +#endif if (stop_offset != -1) { rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT, offset, stop_offset); @@ -840,6 +890,34 @@ _append_extra_header (GQuark field_id, const GValue * value, gpointer user_data) soup_message_headers_append (src->msg->request_headers, field_name, field_content); +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + if (!g_ascii_strcasecmp(field_name, "Cookie")) { + SoupURI *uri = NULL; + SoupCookie *cookie_parsed = NULL; + + if (strlen(field_content) > 0) { + gchar *tmp_field = NULL; + + uri = soup_uri_new (src->location); + + tmp_field = strtok (field_content, ";"); + + while (tmp_field != NULL) { + GST_DEBUG_OBJECT (src, "field_content = %s", tmp_field); + + cookie_parsed = soup_cookie_parse(tmp_field, uri); + GST_DEBUG_OBJECT (src, "cookie parsed = %p", cookie_parsed); + + if (src->cookie_jar) + soup_cookie_jar_add_cookie (src->cookie_jar, cookie_parsed); + + tmp_field = strtok (NULL, ";"); + } + soup_uri_free (uri); + } + } +#endif + g_free (field_content); return TRUE; @@ -950,6 +1028,28 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src) return FALSE; } +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + { + char **array = NULL; + SoupURI *base_uri; + SoupCookie *soup_cookie = NULL; + + soup_session_add_feature_by_type (src->session, SOUP_TYPE_COOKIE_JAR); + src->cookie_jar = SOUP_COOKIE_JAR (soup_session_get_feature (src->session, SOUP_TYPE_COOKIE_JAR)); + if ((array = src->cookies) != NULL) { + base_uri = soup_uri_new (src->location); + while (*array != NULL) { + soup_cookie = soup_cookie_parse (*array++, base_uri); + if (soup_cookie != NULL) { + GST_INFO_OBJECT (src, "adding cookies.."); + soup_cookie_jar_add_cookie (src->cookie_jar, soup_cookie); + } + } + soup_uri_free (base_uri); + } + } +#endif + g_signal_connect (src->session, "authenticate", G_CALLBACK (gst_soup_http_src_authenticate_cb), src); @@ -993,6 +1093,14 @@ gst_soup_http_src_session_close (GstSoupHTTPSrc * src) g_mutex_lock (&src->mutex); if (src->session) { +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION +//[prasenjit.c] When Playback is ongoing and Browser is moved to background ( Pressing Menu or Home Key ), The Session gets destroyed. +// But the cookie_jar property remains unfreed. This results in garbage pointer and causes crash. +// Removing the cookie_jar feature during close session of browser to handle the issue. + GST_DEBUG_OBJECT (src, "Removing Cookie Jar instance"); + soup_session_remove_feature_by_type(src->session, SOUP_TYPE_COOKIE_JAR); + src->cookie_jar = NULL; +#endif soup_session_abort (src->session); /* This unrefs the message. */ g_object_unref (src->session); src->session = NULL; @@ -1078,6 +1186,38 @@ insert_http_header (const gchar * name, const gchar * value, gpointer user_data) } } +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION +static void +gst_soup_http_src_headers_foreach (const gchar * name, const gchar * val, + gpointer src) +{ + GST_INFO_OBJECT (src, " %s: %s", name, val); + + if (g_ascii_strcasecmp (name, "Set-Cookie") == 0) + { + if (val) + { + gboolean bret = FALSE; + GstStructure *s = NULL; + GstSoupHTTPSrc * tmp = src; + SoupURI *uri; + + uri = soup_uri_new (tmp->location); + + /* post current bandwith & uri to application */ + s = gst_structure_new ("cookies", + "updated-cookie", G_TYPE_STRING, val, + "updated-url", G_TYPE_STRING, tmp->location, NULL); + bret = gst_element_post_message (GST_ELEMENT_CAST (src), gst_message_new_element (GST_OBJECT_CAST (src), s)); + soup_cookie_jar_set_cookie (tmp->cookie_jar, uri, val); + soup_uri_free (uri); + + GST_INFO_OBJECT (src, "request url [%s], posted cookies [%s] msg and returned = %d", tmp->location, val, bret); + } + } +} +#endif + static void gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src) { @@ -1091,7 +1231,10 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src) const gchar *accept_ranges; GST_INFO_OBJECT (src, "got headers"); - +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + soup_message_headers_foreach (msg->response_headers, + gst_soup_http_src_headers_foreach, src); +#endif if (msg->status_code == SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED && src->proxy_id && src->proxy_pw) return; @@ -1138,8 +1281,17 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src) /* Parse Content-Length. */ if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_CONTENT_LENGTH) { - newsize = src->request_position + - soup_message_headers_get_content_length (msg->response_headers); +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + if (msg->status_code == SOUP_STATUS_PARTIAL_CONTENT) { + newsize = src->request_position + + soup_message_headers_get_content_length (msg->response_headers); + } else { + newsize = soup_message_headers_get_content_length (msg->response_headers); + } +#else + newsize = src->request_position + + soup_message_headers_get_content_length (msg->response_headers); +#endif if (!src->have_size || (src->content_size != newsize)) { src->content_size = newsize; src->have_size = TRUE; @@ -1262,9 +1414,16 @@ gst_soup_http_src_got_headers_cb (SoupMessage * msg, GstSoupHTTPSrc * src) /* Handle HTTP errors. */ gst_soup_http_src_parse_status (msg, src); +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + /* Check if Range header was respected. */ + if (src->ret == GST_FLOW_CUSTOM_ERROR && + src->read_position && msg->status_code != SOUP_STATUS_PARTIAL_CONTENT && + (src->request_position < src->content_size)) { +#else /* Check if Range header was respected. */ if (src->ret == GST_FLOW_CUSTOM_ERROR && src->read_position && msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) { +#endif src->seekable = FALSE; GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (_("Server does not support seeking.")), @@ -1585,6 +1744,16 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src) /* 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 */ +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE && + ((src->have_body && !src->have_size) || + (src->have_size && src->request_position >= src->content_size))) { + GST_DEBUG_OBJECT (src, "Requested range out of limits and received full " + "body, returning EOS"); + src->ret = GST_FLOW_EOS; + return; + } +#else 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 " @@ -1592,6 +1761,7 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src) src->ret = GST_FLOW_EOS; return; } +#endif /* FIXME: reason_phrase is not translated and not suitable for user * error dialog according to libsoup documentation. @@ -1641,6 +1811,36 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method) soup_message_headers_append (src->msg->request_headers, "icy-metadata", "1"); } + +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION +/*[prasenjit.c]This changes are needed to enable Seekable Contents from server. +We have observed that , for few specific networks ( VODAFONE ) , without theabove headers , +Youtube is sending non-seekable contents to the Client. +*/ + soup_message_headers_append (src->msg->request_headers, "Accept-Ranges","bytes"); + + if (src->cookie_jar) { + GSList *cookie_list, *c; + gchar *header; + + SoupURI *uri = NULL; + SoupCookie *cookie; + uri = soup_uri_new (src->location); + + if ((cookie_list = soup_cookie_jar_all_cookies (src->cookie_jar)) != NULL) { + for (c = cookie_list; c; c = c->next) { + cookie = (SoupCookie *)c->data; + if (soup_cookie_applies_to_uri(cookie, uri)) { + header = soup_cookie_to_cookie_header (cookie); + soup_message_headers_append (src->msg->request_headers, "Cookie", header); + g_free (header); + } + } + } + soup_cookies_free (cookie_list); + soup_uri_free (uri); + } +#else if (src->cookies) { gchar **cookie; @@ -1649,6 +1849,8 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method) *cookie); } } +#endif + src->retry = FALSE; g_signal_connect (src->msg, "got_headers", @@ -1668,6 +1870,11 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method) gst_soup_http_src_add_extra_headers (src); +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + soup_message_headers_foreach (src->msg->request_headers, + gst_soup_http_src_headers_foreach, src); +#endif + return TRUE; } diff --git a/ext/soup/gstsouphttpsrc.h b/ext/soup/gstsouphttpsrc.h index ef9539c..bfb32e0 100644 --- a/ext/soup/gstsouphttpsrc.h +++ b/ext/soup/gstsouphttpsrc.h @@ -9,7 +9,7 @@ * 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 + * Library General Public License for more */ #ifndef __GST_SOUP_HTTP_SRC_H__ @@ -101,7 +101,9 @@ struct _GstSoupHTTPSrc { gchar *iradio_url; GstStructure *extra_headers; - +#ifdef TIZEN_FEATURE_SOUP_MODIFICATION + SoupCookieJar *cookie_jar; +#endif SoupLoggerLogLevel log_level;/* Soup HTTP session logger level */ gboolean compress; diff --git a/packaging/gst-plugins-good.spec b/packaging/gst-plugins-good.spec index f576af0..7c87180 100644 --- a/packaging/gst-plugins-good.spec +++ b/packaging/gst-plugins-good.spec @@ -75,7 +75,8 @@ export CFLAGS+=" -DTIZEN_FEATURE_V4L2SRC_MODIFICATION\ -DTIZEN_FEATURE_FLVDEMUX_MODIFICATION\ -DTIZEN_FEATURE_GST_UPSTREAM\ -DTIZEN_FEATURE_RTSP_MODIFICATION\ - -DTIZEN_FEATURE_GST_MUX_ENHANCEMENT" + -DTIZEN_FEATURE_GST_MUX_ENHANCEMENT\ + -DTIZEN_FEATURE_SOUP_MODIFICATION" %configure\ %if ! 0%{?ENABLE_AALIB} --disable-aalib\ -- 2.7.4