When new cookie values (with the same name as an existing cookie) are
returned in an HLS stream, the current implementation will append the
new cookie to the list of cookies. This causes FFMPEG to send multiple
cookie values for the same cookie and in some cases exceed the http
header size in some cases.

The patch attached resolves the issue.
-- 
"The mark of an immature man is that he wants to die nobly for a
cause, while the mark of the mature man is that he wants to live
humbly for one."   --W. Stekel
From ad65b070a7b49698e623f08365ec7e751d0bae08 Mon Sep 17 00:00:00 2001
From: Micah Galizia <micahgali...@gmail.com>
Date: Sun, 17 Aug 2014 20:50:02 +1000
Subject: [PATCH] Replace old cookies with new cookies of the same name

---
 libavformat/http.c | 86 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 73 insertions(+), 13 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 7480834..f1b9c34 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -444,6 +444,77 @@ static int parse_icy(HTTPContext *s, const char *tag, const char *p)
     return 0;
 }
 
+static int update_cookies(URLContext *h, char **cookies, char *new_cookie) {
+
+    int prefix, offset, suffix, new_cookie_len = strlen(new_cookie);
+    char *name, *cookie, *next;
+
+    // if the existing cookies are empty then just set it and forget it
+    if (!*cookies) {
+        if (!(*cookies = av_strdup(new_cookie)))
+            return AVERROR(ENOMEM);
+        return 0;
+    }
+
+    // get the new cookies name
+    if (!(cookie = av_strdup(new_cookie)))
+        return AVERROR(ENOMEM);
+
+    // if the new cookie format isnt valid just return (without error)
+    if (!(name = av_strtok(cookie, "=", &next))) {
+        av_log(h, AV_LOG_INFO, "Invalid new cookie format.");
+        return 0;
+    }
+
+    // copy the name and then free the copy of the cookies
+    name = av_asprintf("%s=", name);
+    av_free(cookie);
+
+    // find the offset and free the name (we don't need it anymore)
+    next = av_stristr(*cookies, name);
+    av_free(name);
+
+    // if no substring is found, just append
+    if (!next) {
+        cookie = av_asprintf("%s\n%s", *cookies, new_cookie);
+        av_free(*cookies);
+        *cookies = cookie;
+        return 0;
+    }
+
+    prefix = next - *cookies;
+
+    // no subsequent newline means this is the last cookie
+    if (!(next = av_stristr(next, "\n"))) {
+
+        // old and new cookie plus null terminate
+        if (!(cookie = av_malloc(prefix + new_cookie_len + 1)))
+            return AVERROR(ENOMEM);
+
+        strncpy(cookie, *cookies, prefix);
+        sprintf(&cookie[prefix], "%s", new_cookie);
+        av_free(*cookies);
+        *cookies = cookie;
+        return 0;
+    }
+
+    offset = next - *cookies;
+    suffix = strlen(*cookies) - offset;
+
+    if (!(cookie = av_malloc(prefix + suffix + new_cookie_len + 2)))
+        return AVERROR(ENOMEM);
+
+    // copy in the prefix, new cookie, and suffix if they exist
+    if (prefix) strncpy(cookie, *cookies, prefix);
+    sprintf(&cookie[prefix], "%s", new_cookie);
+    if (suffix) strncpy(&cookie[prefix + new_cookie_len], &((*cookies)[offset]), suffix);
+
+    av_free(*cookies);
+    *cookies = cookie;
+
+    return 0;
+}
+
 static int process_line(URLContext *h, char *line, int line_count,
                         int *new_location)
 {
@@ -515,19 +586,8 @@ static int process_line(URLContext *h, char *line, int line_count,
             av_free(s->mime_type);
             s->mime_type = av_strdup(p);
         } else if (!av_strcasecmp(tag, "Set-Cookie")) {
-            if (!s->cookies) {
-                if (!(s->cookies = av_strdup(p)))
-                    return AVERROR(ENOMEM);
-            } else {
-                char *tmp = s->cookies;
-                size_t str_size = strlen(tmp) + strlen(p) + 2;
-                if (!(s->cookies = av_malloc(str_size))) {
-                    s->cookies = tmp;
-                    return AVERROR(ENOMEM);
-                }
-                snprintf(s->cookies, str_size, "%s\n%s", tmp, p);
-                av_free(tmp);
-            }
+            update_cookies(h, &s->cookies, p);
+            av_log(h, AV_LOG_VERBOSE, "Cookies set to '%s'\n", s->cookies);
         } else if (!av_strcasecmp(tag, "Icy-MetaInt")) {
             s->icy_metaint = strtoll(p, NULL, 10);
         } else if (!av_strncasecmp(tag, "Icy-", 4)) {
-- 
1.9.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to