From 0ac79d03981e823a1922e7e1f58af7f3b02dca7d Mon Sep 17 00:00:00 2001
From: Philip de Nier <philipn@rd.bbc.co.uk>
Date: Wed, 7 Dec 2016 15:09:09 +0000
Subject: [PATCH] http: allow content range to set filesize
Set filesize to Content-Length if present and Transfer-Encoding is
not chunked. Otherwise set to Content-Range instance length if present.
Solves issue where filesize is set to unknown when using byte range
requests in combination with chunked transfers.
Fixes issue #6007
---
libavformat/http.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
@@ -63,6 +63,7 @@ typedef struct HTTPContext {
int http_code;
/* Used if "Transfer-Encoding: chunked" otherwise -1. */
uint64_t chunksize;
+ uint64_t content_len, content_range_len;
uint64_t off, end_off, filesize;
char *location;
HTTPAuthState auth_state;
@@ -618,9 +619,9 @@ static void parse_content_range(URLContext *h, const char *p)
p += 6;
s->off = strtoull(p, NULL, 10);
if ((slash = strchr(p, '/')) && strlen(slash) > 0)
- s->filesize = strtoull(slash + 1, NULL, 10);
+ s->content_range_len = strtoull(slash + 1, NULL, 10);
}
- if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
+ if (s->seekable == -1 && (!s->is_akamai || s->content_range_len != 2147483647))
h->is_streamed = 0; /* we _can_ in fact seek */
}
@@ -810,7 +811,7 @@ static int process_line(URLContext *h, char *line, int line_count,
*new_location = 1;
} else if (!av_strcasecmp(tag, "Content-Length") &&
s->filesize == UINT64_MAX) {
- s->filesize = strtoull(p, NULL, 10);
+ s->content_len = strtoull(p, NULL, 10);
} else if (!av_strcasecmp(tag, "Content-Range")) {
parse_content_range(h, p);
} else if (!av_strcasecmp(tag, "Accept-Ranges") &&
@@ -819,7 +820,6 @@ static int process_line(URLContext *h, char *line, int line_count,
h->is_streamed = 0;
} else if (!av_strcasecmp(tag, "Transfer-Encoding") &&
!av_strncasecmp(p, "chunked", 7)) {
- s->filesize = UINT64_MAX;
s->chunksize = 0;
} else if (!av_strcasecmp(tag, "WWW-Authenticate")) {
ff_http_auth_handle_header(&s->auth_state, tag, p);
@@ -974,6 +974,8 @@ static int http_read_header(URLContext *h, int *new_location)
int err = 0;
s->chunksize = UINT64_MAX;
+ s->content_range_len = UINT64_MAX;
+ s->content_len = UINT64_MAX;
for (;;) {
if ((err = http_get_line(s, line, sizeof(line))) < 0)
@@ -989,6 +991,13 @@ static int http_read_header(URLContext *h, int *new_location)
s->line_count++;
}
+ if (s->filesize == UINT64_MAX) {
+ if (s->chunksize == UINT64_MAX && s->content_len != UINT64_MAX)
+ s->filesize = s->content_len;
+ else if (s->content_range_len != UINT64_MAX)
+ s->filesize = s->content_range_len;
+ }
+
if (s->seekable == -1 && s->is_mediagateway && s->filesize == 2000000000)
h->is_streamed = 1; /* we can in fact _not_ seek */
--
1.9.1