Go to the documentation of this file.
25 #include "config_components.h"
58 #define BUFFER_SIZE (MAX_URL_SIZE + HTTP_HEADERS_SIZE)
59 #define MAX_REDIRECTS 8
60 #define MAX_CACHED_REDIRECTS 32
63 #define MAX_DATE_LEN 19
64 #define WHITESPACES " \n\t\r"
165 z_stream inflate_stream;
166 uint8_t *inflate_buffer;
184 #define OFFSET(x) offsetof(HTTPContext, x)
185 #define D AV_OPT_FLAG_DECODING_PARAM
186 #define E AV_OPT_FLAG_ENCODING_PARAM
187 #define DEFAULT_USER_AGENT "Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION)
190 {
"seekable",
"control seekability of connection",
OFFSET(seekable),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1,
D },
191 {
"chunked_post",
"use chunked transfer-encoding for posts",
OFFSET(chunked_post),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
E },
197 {
"multiple_requests",
"use persistent connections",
OFFSET(multiple_requests),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1,
D |
E },
199 {
"initial_request_size",
"size (in bytes) of initial requests made during probing / header parsing",
OFFSET(initial_request_size),
AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
D },
203 {
"cookies",
"set cookies to be sent in applicable future requests, use newline delimited Set-Cookie HTTP field value syntax",
OFFSET(cookies),
AV_OPT_TYPE_STRING, { .str =
NULL }, 0, 0,
D },
209 {
"none",
"No auth method set, autodetect", 0,
AV_OPT_TYPE_CONST, { .i64 =
HTTP_AUTH_NONE }, 0, 0,
D |
E, .unit =
"auth_type"},
211 {
"send_expect_100",
"Force sending an Expect: 100-continue header for POST",
OFFSET(send_expect_100),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1,
E },
214 {
"end_offset",
"try to limit the request to bytes preceding this offset",
OFFSET(end_off),
AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
D },
215 {
"method",
"Override the HTTP method or set the expected HTTP method from a client",
OFFSET(method),
AV_OPT_TYPE_STRING, { .str =
NULL }, 0, 0,
D |
E },
216 {
"reconnect",
"auto reconnect after disconnect before EOF",
OFFSET(reconnect),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
D },
217 {
"reconnect_at_eof",
"auto reconnect at EOF",
OFFSET(reconnect_at_eof),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
D },
218 {
"reconnect_on_network_error",
"auto reconnect in case of tcp/tls error during connect",
OFFSET(reconnect_on_network_error),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
D },
219 {
"reconnect_on_http_error",
"list of http status codes to reconnect on",
OFFSET(reconnect_on_http_error),
AV_OPT_TYPE_STRING, { .str =
NULL }, 0, 0,
D },
220 {
"reconnect_streamed",
"auto reconnect streamed / non seekable streams",
OFFSET(reconnect_streamed),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
D },
221 {
"reconnect_delay_max",
"max reconnect delay in seconds after which to give up",
OFFSET(reconnect_delay_max),
AV_OPT_TYPE_INT, { .i64 = 120 }, 0, UINT_MAX/1000/1000,
D },
222 {
"reconnect_max_retries",
"the max number of times to retry a connection",
OFFSET(reconnect_max_retries),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX,
D },
223 {
"reconnect_delay_total_max",
"max total reconnect delay in seconds after which to give up",
OFFSET(reconnect_delay_total_max),
AV_OPT_TYPE_INT, { .i64 = 256 }, 0, UINT_MAX/1000/1000,
D },
224 {
"respect_retry_after",
"respect the Retry-After header when retrying connections",
OFFSET(respect_retry_after),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D },
227 {
"reply_code",
"The http status code to return to a client",
OFFSET(reply_code),
AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599,
E},
228 {
"short_seek_size",
"Threshold to favor readahead over seek.",
OFFSET(short_seek_size),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
D },
234 const char *hoststr,
const char *auth,
235 const char *proxyauth);
251 const char *path, *proxy_path, *lower_proto =
"tcp", *local_path;
252 char *env_http_proxy, *env_no_proxy;
254 char hostname[1024], hoststr[1024], proto[10], tmp_host[1024];
255 char auth[1024], proxyauth[1024] =
"";
258 int port, use_proxy, err = 0;
262 hostname,
sizeof(hostname), &port,
263 path1,
sizeof(path1),
s->location);
265 av_strlcpy(tmp_host, hostname,
sizeof(tmp_host));
269 if (strchr(tmp_host,
':'))
270 tmp_host[strcspn(tmp_host,
"%")] =
'\0';
274 proxy_path =
s->http_proxy ?
s->http_proxy : env_http_proxy;
281 if (
h->protocol_whitelist &&
av_match_list(proto,
h->protocol_whitelist,
',') <= 0) {
282 av_log(
h,
AV_LOG_ERROR,
"Protocol '%s' not on whitelist '%s'!\n", proto,
h->protocol_whitelist);
286 if (
h->protocol_blacklist &&
av_match_list(proto,
h->protocol_blacklist,
',') > 0) {
291 if (!strcmp(proto,
"https")) {
302 }
else if (strcmp(proto,
"http")) {
310 hashmark = strchr(path1,
'#');
314 if (path1[0] ==
'\0') {
316 }
else if (path1[0] ==
'?') {
317 snprintf(sanitized_path,
sizeof(sanitized_path),
"/%s", path1);
318 path = sanitized_path;
330 hostname,
sizeof(hostname), &port,
NULL, 0, proxy_path);
339 h->protocol_whitelist,
h->protocol_blacklist,
h);
345 h, path, local_path, hoststr, auth, proxyauth);
350 const char *status_group;
360 status_group =
"4xx";
364 status_group =
"5xx";
368 return s->reconnect_on_network_error;
371 if (!
s->reconnect_on_http_error)
374 if (
av_match_list(status_group,
s->reconnect_on_http_error,
',') > 0)
377 snprintf(http_code,
sizeof(http_code),
"%d",
s->http_code);
379 return av_match_list(http_code,
s->reconnect_on_http_error,
',') > 0;
393 delim = strchr(re->
value,
';');
399 if (time(
NULL) > expiry) {
428 int ret, conn_attempts = 1, auth_attempts = 0, redirects = 0;
429 int reconnect_delay = 0;
430 int reconnect_delay_total = 0;
438 if (redirects++ >=
s->max_redirects)
452 cur_auth_type =
s->auth_state.auth_type;
453 cur_proxy_auth_type =
s->auth_state.auth_type;
459 reconnect_delay >
s->reconnect_delay_max ||
460 (
s->reconnect_max_retries >= 0 && conn_attempts >
s->reconnect_max_retries) ||
461 reconnect_delay_total >
s->reconnect_delay_total_max)
465 if (
s->respect_retry_after &&
s->retry_after > 0) {
466 reconnect_delay =
s->retry_after;
467 if (reconnect_delay >
s->reconnect_delay_max)
474 s->willclose ?
"reconnect" :
"retry", off, reconnect_delay);
478 reconnect_delay_total += reconnect_delay;
479 reconnect_delay = 1 + 2 * reconnect_delay;
491 if (
s->http_code == 401) {
499 if (
s->http_code == 407) {
500 if ((cur_proxy_auth_type ==
HTTP_AUTH_NONE ||
s->proxy_auth_state.stale) &&
501 s->proxy_auth_state.auth_type !=
HTTP_AUTH_NONE && auth_attempts < 4) {
507 if ((
s->http_code == 301 ||
s->http_code == 302 ||
508 s->http_code == 303 ||
s->http_code == 307 ||
s->http_code == 308) &&
512 if (redirects++ >=
s->max_redirects)
516 s->expires = (
s->http_code == 301 ||
s->http_code == 308) ? INT64_MAX : -1;
524 s->location =
s->new_location;
525 s->new_location =
NULL;
530 memset(&
s->auth_state, 0,
sizeof(
s->auth_state));
554 char hostname1[1024], hostname2[1024], proto1[10], proto2[10];
558 !(!strcmp(
h->prot->name,
"http") ||
559 !strcmp(
h->prot->name,
"https")))
563 hostname1,
sizeof(hostname1), &port1,
564 NULL, 0,
s->location);
566 hostname2,
sizeof(hostname2), &port2,
568 if (strcmp(proto1, proto2) != 0) {
569 av_log(
h,
AV_LOG_INFO,
"Cannot reuse HTTP connection for different protocol %s vs %s\n",
573 if (port1 != port2 || strncmp(hostname1, hostname2,
sizeof(hostname2)) != 0) {
574 av_log(
h,
AV_LOG_INFO,
"Cannot reuse HTTP connection for different host: %s:%d != %s:%d\n",
581 if (!
s->end_chunked_post) {
590 s->end_chunked_post = 0;
594 s->icy_data_read = 0;
618 return s->new_location;
623 int ret,
body = 0, reply_code, message_len;
624 const char *reply_text, *content_type;
627 content_type =
"text/plain";
631 switch (status_code) {
635 reply_text =
"Bad Request";
640 reply_text =
"Forbidden";
645 reply_text =
"Not Found";
650 reply_text =
"Too Many Requests";
655 content_type =
s->content_type ?
s->content_type :
"application/octet-stream";
660 reply_text =
"Internal server error";
668 "HTTP/1.1 %03d %s\r\n"
669 "Content-Type: %s\r\n"
670 "Content-Length: %zu\r\n"
677 strlen(reply_text) + 6,
678 s->headers ?
s->headers :
"",
684 "HTTP/1.1 %03d %s\r\n"
685 "Content-Type: %s\r\n"
686 "Transfer-Encoding: chunked\r\n"
692 s->headers ?
s->headers :
"");
746 char hostname[1024], proto[10];
748 const char *lower_proto =
"tcp";
750 av_url_split(proto,
sizeof(proto),
NULL, 0, hostname,
sizeof(hostname), &port,
752 if (!strcmp(proto,
"https"))
754 ff_url_join(lower_url,
sizeof(lower_url), lower_proto,
NULL, hostname, port,
760 h->protocol_whitelist,
h->protocol_blacklist,
h
780 if(
s->seekable == 1 )
785 s->initial_requests =
s->seekable != 0 &&
s->initial_request_size > 0;
786 s->filesize = UINT64_MAX;
800 int len = strlen(
s->headers);
801 if (
len < 2 || strcmp(
"\r\n",
s->headers +
len - 2)) {
803 "No trailing CRLF found in HTTP header. Adding it.\n");
807 s->headers[
len] =
'\r';
808 s->headers[
len + 1] =
'\n';
809 s->headers[
len + 2] =
'\0';
839 cc = (*c)->priv_data;
855 if (
s->buf_ptr >=
s->buf_end) {
859 }
else if (
len == 0) {
862 s->buf_ptr =
s->buffer;
863 s->buf_end =
s->buffer +
len;
866 return *
s->buf_ptr++;
881 if (q >
line && q[-1] ==
'\r')
887 if ((q -
line) < line_size - 1)
898 if (http_code >= 400 && http_code < 600 &&
900 (http_code != 407 ||
s->proxy_auth_state.auth_type !=
HTTP_AUTH_NONE)) {
914 s->new_location =
av_strdup(redirected_location);
915 if (!
s->new_location)
924 const char *slash, *end;
926 if (!strncmp(
p,
"bytes ", 6)) {
928 s->off = strtoull(
p,
NULL, 10);
929 if ((end = strchr(
p,
'-')) && strlen(end) > 0)
930 s->range_end = strtoull(end + 1,
NULL, 10) + 1;
931 if ((slash = strchr(
p,
'/')) && strlen(slash) > 0)
932 s->filesize_from_content_range = strtoull(slash + 1,
NULL, 10);
934 if (
s->seekable == -1 && (!
s->is_akamai ||
s->filesize != 2147483647))
946 inflateEnd(&
s->inflate_stream);
947 if (inflateInit2(&
s->inflate_stream, 32 + 15) != Z_OK) {
949 s->inflate_stream.msg);
952 if (zlibCompileFlags() & (1 << 17)) {
954 "Your zlib was compiled without gzip support.\n");
959 "Compressed (%s) content, need zlib with gzip support\n",
p);
974 int len = 4 + strlen(
p) + strlen(
tag);
975 int is_first = !
s->icy_metadata_headers;
980 if (
s->icy_metadata_headers)
981 len += strlen(
s->icy_metadata_headers);
987 *
s->icy_metadata_headers =
'\0';
1001 for (
i = 0, j = 0; date_str[
i] !=
'\0' && j < date_buf_len;
i++) {
1002 if ((date_str[
i] >=
'0' && date_str[
i] <=
'9') ||
1003 (date_str[
i] >=
'A' && date_str[
i] <=
'Z') ||
1004 (date_str[
i] >=
'a' && date_str[
i] <=
'z')) {
1005 date_buf[j] = date_str[
i];
1013 while ((*date < '0' || *date >
'9') && *date !=
'\0')
1021 char *param, *next_param, *cstr, *back;
1022 char *saveptr =
NULL;
1031 back = &cstr[strlen(cstr)-1];
1040 while ((param =
av_strtok(next_param,
";", &saveptr))) {
1069 if (!cookie_entry || !cookie_entry->
value) {
1076 struct tm new_tm = {0};
1088 if (e2 && e2->
value) {
1092 if (e2 && e2->
value) {
1093 struct tm old_tm = {0};
1110 if (!(eql = strchr(
p,
'=')))
return AVERROR(EINVAL);
1130 if (*cookies)
av_free(*cookies);
1132 if (!*cookies)
return AVERROR(ENOMEM);
1182 char *
tag, *
p, *end, *method, *resource, *
version;
1186 if (
line[0] ==
'\0') {
1192 if (line_count == 0) {
1193 if (
s->is_connected_server) {
1204 av_log(
h,
AV_LOG_ERROR,
"Received and expected HTTP method do not match. (%s expected, %s received)\n",
1213 "(%s autodetected %s received)\n", auto_method, method);
1248 while (*
p !=
'/' && *
p !=
'\0')
1258 s->http_code = strtol(
p, &end, 10);
1262 *parsed_http_code = 1;
1268 while (*
p !=
'\0' && *
p !=
':')
1282 s->filesize == UINT64_MAX) {
1283 s->filesize = strtoull(
p,
NULL, 10);
1287 !strncmp(
p,
"bytes", 5) &&
1288 s->seekable == -1) {
1292 s->filesize = UINT64_MAX;
1307 s->is_mediagateway = 1;
1316 s->icy_metaint = strtoull(
p,
NULL, 10);
1335 s->retry_after = (
unsigned int)
FFMAX(0,
diff);
1337 s->retry_after = strtoul(
p,
NULL, 10);
1358 char *cookie, *set_cookies, *next;
1359 char *saveptr =
NULL;
1372 while ((cookie =
av_strtok(next,
"\n", &saveptr)) && !
ret) {
1387 if (!cookie_entry || !cookie_entry->
value)
1392 struct tm tm_buf = {0};
1402 int domain_offset = strlen(domain) - strlen(e->
value);
1403 if (domain_offset < 0)
1420 char *
tmp = *cookies;
1448 int err = 0, http_err = 0;
1452 s->chunksize = UINT64_MAX;
1453 s->filesize_from_content_range = UINT64_MAX;
1456 int parsed_http_code = 0;
1468 if (parsed_http_code) {
1486 if (
s->filesize_from_content_range != UINT64_MAX)
1487 s->filesize =
s->filesize_from_content_range;
1489 if (
s->seekable == -1 &&
s->is_mediagateway &&
s->filesize == 2000000000)
1493 s->initial_requests = 0;
1511 #define NEEDS_ESCAPE(ch) \
1512 ((ch) <= ' ' || (ch) >= '\x7f' || \
1513 (ch) == '"' || (ch) == '%' || (ch) == '<' || (ch) == '>' || (ch) == '\\' || \
1514 (ch) == '^' || (ch) == '`' || (ch) == '{' || (ch) == '}' || (ch) == '|')
1518 while (*path && q - buf <
sizeof(buf) - 4) {
1524 q +=
snprintf(q, 4,
"%%%02X", (uint8_t)*path++);
1536 if (
s->initial_requests)
1537 return s->initial_request_size;
1538 return s->request_size;
1542 const char *hoststr,
const char *auth,
1543 const char *proxyauth)
1548 char *authstr =
NULL, *proxyauthstr =
NULL;
1549 uint64_t off =
s->off;
1551 int send_expect_100 = 0;
1563 s->chunked_post = 0;
1569 method = post ?
"POST" :
"GET";
1572 local_path, method);
1574 local_path, method);
1576 if (post && !
s->post_data) {
1577 if (
s->send_expect_100 != -1) {
1578 send_expect_100 =
s->send_expect_100;
1580 send_expect_100 = 0;
1585 if (auth && *auth &&
1587 s->http_code != 401)
1588 send_expect_100 = 1;
1596 if (post &&
s->chunked_post)
1597 av_bprintf(&request,
"Transfer-Encoding: chunked\r\n");
1600 av_bprintf(&request,
"User-Agent: %s\r\n",
s->user_agent);
1604 av_bprintf(&request,
"Referer: %s\r\n",
s->referer);
1611 int is_partial_request = 0;
1612 if (!
has_header(
s->headers,
"\r\nRange: ") && !post && (
s->off > 0 ||
s->end_off ||
s->seekable != 0)) {
1613 av_bprintf(&request,
"Range: bytes=%"PRIu64
"-",
s->off);
1615 if (req_size &&
s->seekable != 0) {
1616 uint64_t target_off =
s->off + req_size;
1617 if (target_off < s->off)
1618 target_off = UINT64_MAX;
1620 target_off =
FFMIN(target_off,
s->end_off);
1621 if (target_off != UINT64_MAX) {
1622 av_bprintf(&request,
"%"PRId64, target_off - 1);
1623 is_partial_request = 1;
1625 }
else if (
s->end_off)
1629 if (send_expect_100 && !
has_header(
s->headers,
"\r\nExpect: "))
1630 av_bprintf(&request,
"Expect: 100-continue\r\n");
1632 if (!
has_header(
s->headers,
"\r\nConnection: ")) {
1633 keep_alive =
s->multiple_requests > 0;
1634 if (
s->multiple_requests < 0 && is_partial_request)
1636 av_bprintf(&request,
"Connection: %s\r\n", keep_alive ?
"keep-alive" :
"close");
1640 av_bprintf(&request,
"Host: %s\r\n", hoststr);
1641 if (!
has_header(
s->headers,
"\r\nContent-Length: ") &&
s->post_data)
1642 av_bprintf(&request,
"Content-Length: %d\r\n",
s->post_datalen);
1644 if (!
has_header(
s->headers,
"\r\nContent-Type: ") &&
s->content_type)
1645 av_bprintf(&request,
"Content-Type: %s\r\n",
s->content_type);
1646 if (!
has_header(
s->headers,
"\r\nCookie: ") &&
s->cookies) {
1647 char *cookies =
NULL;
1648 if (!
get_cookies(
s, &cookies, path, hoststr) && cookies) {
1649 av_bprintf(&request,
"Cookie: %s\r\n", cookies);
1653 if (!
has_header(
s->headers,
"\r\nIcy-MetaData: ") &&
s->icy)
1663 av_bprintf(&request,
"Proxy-%s", proxyauthstr);
1674 if ((err =
ffurl_write(
s->hd, request.str, request.len)) < 0)
1678 if ((err =
ffurl_write(
s->hd,
s->post_data,
s->post_datalen)) < 0)
1682 s->buf_ptr =
s->buffer;
1683 s->buf_end =
s->buffer;
1686 s->icy_data_read = 0;
1687 s->filesize = UINT64_MAX;
1689 s->willclose = !keep_alive;
1690 s->end_chunked_post = 0;
1695 if (post && !
s->post_data && !send_expect_100) {
1712 s->sum_latency += latency;
1713 s->max_latency =
FFMAX(
s->max_latency, latency);
1715 if (
s->new_location)
1718 if (off !=
s->off) {
1720 "Unexpected offset: expected %"PRIu64
", got %"PRIu64
"\n",
1741 if (
s->chunksize != UINT64_MAX) {
1745 if (!
s->chunksize) {
1754 s->chunksize = strtoull(
line,
NULL, 16);
1757 "Chunked encoding data size: %"PRIu64
"\n",
1760 if (!
s->chunksize &&
s->multiple_requests) {
1765 else if (!
s->chunksize) {
1770 else if (
s->chunksize == UINT64_MAX) {
1780 len =
s->buf_end -
s->buf_ptr;
1784 memcpy(buf,
s->buf_ptr,
len);
1787 uint64_t file_end =
s->end_off ?
s->end_off :
s->filesize;
1788 uint64_t target_end =
s->range_end ?
s->range_end : file_end;
1789 if ((!
s->willclose ||
s->chunksize == UINT64_MAX) &&
s->off >= file_end)
1791 if (
s->off == target_end && target_end < file_end)
1795 (!
s->willclose ||
s->chunksize == UINT64_MAX) &&
s->off < target_end) {
1797 "Stream ends prematurely at %"PRIu64
", should be %"PRIu64
"\n",
1805 if (
s->chunksize > 0 &&
s->chunksize != UINT64_MAX) {
1807 s->chunksize -=
len;
1814 #define DECOMPRESS_BUF_SIZE (256 * 1024)
1815 static int http_buf_read_compressed(
URLContext *
h, uint8_t *buf,
int size)
1820 if (!
s->inflate_buffer) {
1821 s->inflate_buffer =
av_malloc(DECOMPRESS_BUF_SIZE);
1822 if (!
s->inflate_buffer)
1826 if (
s->inflate_stream.avail_in == 0) {
1830 s->inflate_stream.next_in =
s->inflate_buffer;
1831 s->inflate_stream.avail_in =
read;
1834 s->inflate_stream.avail_out =
size;
1835 s->inflate_stream.next_out = buf;
1838 if (
ret != Z_OK &&
ret != Z_STREAM_END)
1840 ret,
s->inflate_stream.msg);
1842 return size -
s->inflate_stream.avail_out;
1853 int reconnect_delay = 0;
1854 int reconnect_delay_total = 0;
1855 int conn_attempts = 1;
1860 if (
s->end_chunked_post && !
s->end_header) {
1868 return http_buf_read_compressed(
h, buf,
size);
1873 while (read_ret < 0) {
1874 uint64_t target =
h->is_streamed ? 0 :
s->off;
1875 bool is_premature =
s->filesize > 0 &&
s->off <
s->filesize;
1879 else if (read_ret ==
AVERROR(EAGAIN)) {
1884 s->initial_requests = 0;
1891 if (
h->is_streamed && !
s->reconnect_streamed)
1894 if (!(
s->reconnect && is_premature) &&
1902 if (reconnect_delay >
s->reconnect_delay_max || (
s->reconnect_max_retries >= 0 && conn_attempts >
s->reconnect_max_retries) ||
1903 reconnect_delay_total >
s->reconnect_delay_total_max)
1906 av_log(
h,
AV_LOG_WARNING,
"Will %s at %"PRIu64
" in %d second(s), error=%s.\n",
s->willclose ?
"reconnect" :
"retry",
1909 if (err !=
AVERROR(ETIMEDOUT))
1911 reconnect_delay_total += reconnect_delay;
1912 reconnect_delay = 1 + 2*reconnect_delay;
1915 if (seek_ret >= 0 && seek_ret != target) {
1954 end = strstr(
val,
"';");
1975 if (
s->icy_metaint <
s->icy_data_read)
1977 remaining =
s->icy_metaint -
s->icy_data_read;
1989 char data[255 * 16 + 1];
2000 s->icy_data_read = 0;
2001 remaining =
s->icy_metaint;
2011 if (
s->icy_metaint > 0) {
2019 s->icy_data_read +=
size;
2028 char crlf[] =
"\r\n";
2031 if (!
s->chunked_post) {
2053 char footer[] =
"0\r\n\r\n";
2068 if (read_ret < 0 && read_ret !=
AVERROR(EAGAIN)) {
2073 s->end_chunked_post = 1;
2085 inflateEnd(&
s->inflate_stream);
2089 if (
s->hd && !
s->end_chunked_post)
2101 av_log(
h,
AV_LOG_DEBUG,
"Statistics: %d connection%s, %d request%s, %d retr%s, %d reconnection%s, %d redirect%s\n",
2102 s->nb_connections,
s->nb_connections == 1 ?
"" :
"s",
2103 s->nb_requests,
s->nb_requests == 1 ?
"" :
"s",
2104 s->nb_retries,
s->nb_retries == 1 ?
"y" :
"ies",
2105 s->nb_reconnects,
s->nb_reconnects == 1 ?
"" :
"s",
2106 s->nb_redirects,
s->nb_redirects == 1 ?
"" :
"s");
2108 if (
s->nb_requests > 0) {
2110 1e-3 *
s->sum_latency /
s->nb_requests,
2111 1e-3 *
s->max_latency);
2120 uint64_t old_off =
s->off;
2122 int old_buf_size,
ret;
2124 uint8_t discard[4096];
2127 return s->filesize == UINT64_MAX ?
AVERROR(ENOSYS) :
s->filesize;
2128 else if ((
s->filesize == UINT64_MAX && whence == SEEK_END))
2131 if (whence == SEEK_CUR)
2133 else if (whence == SEEK_END)
2135 else if (whence != SEEK_SET)
2139 if (!force_reconnect && off ==
s->off)
2143 if (
s->off &&
h->is_streamed)
2147 if (
s->end_off ||
s->filesize != UINT64_MAX) {
2148 uint64_t end_pos =
s->end_off ?
s->end_off :
s->filesize;
2149 if (
s->off >= end_pos)
2154 if (strcmp(
s->uri,
s->location)) {
2160 s->location = new_uri;
2164 old_buf_size =
s->buf_end -
s->buf_ptr;
2165 memcpy(old_buf,
s->buf_ptr, old_buf_size);
2169 uint64_t old_read_pos = old_off + old_buf_size;
2170 if (
s->hd && !
s->willclose &&
s->range_end && short_seek > 0 &&
2171 old_read_pos + short_seek >=
s->range_end)
2173 uint64_t remaining =
s->range_end - old_read_pos;
2178 "%"PRIu64
" remaining byte(s)\n",
s->off, remaining);
2206 memcpy(
s->buffer, old_buf, old_buf_size);
2207 s->buf_ptr =
s->buffer;
2208 s->buf_end =
s->buffer + old_buf_size;
2236 if (
s->short_seek_size >= 1)
2237 return s->short_seek_size;
2241 #define HTTP_CLASS(flavor) \
2242 static const AVClass flavor ## _context_class = { \
2243 .class_name = # flavor, \
2244 .item_name = av_default_item_name, \
2245 .option = http_options, \
2246 .version = LIBAVUTIL_VERSION_INT, \
2249 #if CONFIG_HTTP_PROTOCOL
2265 .priv_data_class = &http_context_class,
2267 .default_whitelist =
"http,https,tls,rtp,tcp,udp,crypto,httpproxy,data"
2271 #if CONFIG_HTTPS_PROTOCOL
2285 .priv_data_class = &https_context_class,
2287 .default_whitelist =
"http,https,tls,rtp,tcp,udp,crypto,httpproxy"
2291 #if CONFIG_HTTPPROXY_PROTOCOL
2303 char hostname[1024], hoststr[1024];
2304 char auth[1024], pathbuf[1024], *path;
2305 char lower_url[100];
2306 int port,
ret = 0, auth_attempts = 0;
2310 if(
s->seekable == 1 )
2315 av_url_split(
NULL, 0, auth,
sizeof(auth), hostname,
sizeof(hostname), &port,
2316 pathbuf,
sizeof(pathbuf), uri);
2322 ff_url_join(lower_url,
sizeof(lower_url),
"tcp",
NULL, hostname, port,
2326 &
h->interrupt_callback,
NULL,
2327 h->protocol_whitelist,
h->protocol_blacklist,
h);
2334 "CONNECT %s HTTP/1.1\r\n"
2336 "Connection: close\r\n"
2341 authstr ?
"Proxy-" :
"", authstr ? authstr :
"");
2347 s->buf_ptr =
s->buffer;
2348 s->buf_end =
s->buffer;
2350 s->filesize = UINT64_MAX;
2351 cur_auth_type =
s->proxy_auth_state.auth_type;
2367 if (
s->http_code == 407 &&
2369 s->proxy_auth_state.auth_type !=
HTTP_AUTH_NONE && auth_attempts < 2) {
2374 if (
s->http_code < 400)
2379 http_proxy_close(
h);
2383 static int http_proxy_write(
URLContext *
h,
const uint8_t *buf,
int size)
2390 .
name =
"httpproxy",
2391 .url_open = http_proxy_open,
2393 .url_write = http_proxy_write,
2394 .url_close = http_proxy_close,
static char * redirect_cache_get(HTTPContext *s)
static void error(const char *err)
@ HTTP_AUTH_BASIC
HTTP 1.0 Basic auth from RFC 1945 (also in RFC 2617)
static av_const int av_isxdigit(int c)
Locale-independent conversion of ASCII isxdigit.
#define AV_LOG_WARNING
Something somehow does not look correct.
static int http_open_cnx(URLContext *h, AVDictionary **options)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
static int http_write_reply(URLContext *h, int status_code)
#define URL_PROTOCOL_FLAG_NETWORK
#define AVERROR_HTTP_OTHER_4XX
static int parse_icy(HTTPContext *s, const char *tag, const char *p)
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
#define AVERROR_EOF
End of file.
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
uint64_t initial_request_size
static void bprint_escaped_path(AVBPrint *bp, const char *path)
Escape unsafe characters in path in order to pass them safely to the HTTP request.
static int http_listen(URLContext *h, const char *uri, int flags, AVDictionary **options)
char * av_asprintf(const char *fmt,...)
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
int seekable
Control seekability, 0 = disable, 1 = enable, -1 = probe.
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
static int http_read(URLContext *h, uint8_t *buf, int size)
static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
static void parse_cache_control(HTTPContext *s, const char *p)
#define AVERROR_HTTP_SERVER_ERROR
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
#define AV_LOG_VERBOSE
Detailed information.
static void freeenv_utf8(char *var)
static int http_get_line(HTTPContext *s, char *line, int line_size)
int ffurl_close(URLContext *h)
AVDictionary * chained_options
static int parse_location(HTTPContext *s, const char *p)
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
char * ff_http_auth_create_response(HTTPAuthState *state, const char *auth, const char *path, const char *method)
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
const URLProtocol ff_httpproxy_protocol
#define AVERROR_HTTP_UNAUTHORIZED
static int get_cookies(HTTPContext *s, char **cookies, const char *path, const char *domain)
Create a string containing cookie values for use as a HTTP cookie header field value for a particular...
@ AV_OPT_TYPE_BINARY
Underlying C type is a uint8_t* that is either NULL or points to an array allocated with the av_mallo...
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
Init a print buffer using a pre-existing buffer.
int ffurl_get_short_seek(void *urlcontext)
Return the current short seek threshold value for this URL.
static int check_http_code(URLContext *h, int http_code, const char *end)
#define DEFAULT_USER_AGENT
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
static int cookie_string(AVDictionary *dict, char **cookies)
static int has_header(const char *str, const char *header)
static int redirect_cache_set(HTTPContext *s, const char *source, const char *dest, int64_t expiry)
static double val(void *priv, double ch)
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define AVERROR_HTTP_NOT_FOUND
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
char * cookies
holds newline ( ) delimited Set-Cookie header field values (without the "Set-Cookie: " field name)
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
@ AV_OPT_TYPE_INT64
Underlying C type is int64_t.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define AVIO_FLAG_WRITE
write-only
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
FFmpeg currently uses a custom build this text attempts to document some of its obscure features and options Makefile the full command issued by make and its output will be shown on the screen DESTDIR Destination directory for the install useful to prepare packages or install FFmpeg in cross environments GEN Set to ‘1’ to generate the missing or mismatched references Makefile builds all the libraries and the executables fate Run the fate test note that you must have installed it fate list List all fate regression test targets fate list failing List the fate tests that failed the last time they were executed fate clear reports Remove the test reports from previous test libraries and programs examples Build all examples located in doc examples checkheaders Check headers dependencies alltools Build all tools in tools directory config Reconfigure the project with the current configuration tools target_dec_< decoder > _fuzzer Build fuzzer to fuzz the specified decoder tools target_bsf_< filter > _fuzzer Build fuzzer to fuzz the specified bitstream filter Useful standard make this is useful to reduce unneeded rebuilding when changing headers
int reconnect_on_network_error
int av_stristart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str independent of case.
static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, const char *value)
static int parse_content_encoding(URLContext *h, const char *p)
static void handle_http_errors(URLContext *h, int error)
unsigned char buffer[BUFFER_SIZE]
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
int ffurl_accept(URLContext *s, URLContext **c)
Accept an URLContext c on an URLContext s.
static AVDictionary * opts
static int http_read_stream_all(URLContext *h, uint8_t *buf, int size)
Describe the class of an AVClass context structure.
static int http_get_short_seek(URLContext *h)
int av_match_list(const char *name, const char *list, char separator)
Check if a name is in a list.
int multiple_requests
A flag which indicates if we use persistent connections.
void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
Initialize the authentication state based on another HTTP URLContext.
@ AV_OPT_TYPE_DICT
Underlying C type is AVDictionary*.
int ff_http_do_new_request2(URLContext *h, const char *uri, AVDictionary **opts)
Send a new HTTP request, reusing the old connection.
HTTPAuthState proxy_auth_state
static char * getenv_utf8(const char *varname)
#define AVERROR_HTTP_TOO_MANY_REQUESTS
static int http_buf_read(URLContext *h, uint8_t *buf, int size)
static int http_shutdown(URLContext *h, int flags)
static int process_line(URLContext *h, char *line, int line_count, int *parsed_http_code)
static void parse_content_range(URLContext *h, const char *p)
#define AVERROR_HTTP_BAD_REQUEST
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
HTTP Authentication state structure.
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a source
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i http
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
uint64_t filesize_from_content_range
int reconnect_max_retries
static int parse_http_date(const char *date_str, struct tm *buf)
#define i(width, name, range_min, range_max)
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
static void parse_expires(HTTPContext *s, const char *p)
static const AVOption http_options[]
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
int reconnect_delay_total_max
static int http_write(URLContext *h, const uint8_t *buf, int size)
static const uint8_t header[24]
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
char * icy_metadata_packet
const URLProtocol ff_http_protocol
#define AV_LOG_INFO
Standard information.
static void update_metadata(URLContext *h, char *data)
#define AV_OPT_FLAG_READONLY
The option may not be set through the AVOptions API, only read.
int ffurl_alloc(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb)
Create a URLContext for accessing to the resource indicated by url, but do not initiate the connectio...
static int http_should_reconnect(HTTPContext *s, int err)
static int http_handshake(URLContext *c)
@ HTTP_AUTH_NONE
No authentication specified.
static int http_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
static int http_connect(URLContext *h, const char *path, const char *local_path, const char *hoststr, const char *auth, const char *proxyauth)
This document is work in progress *What is CVSS *The Common Vulnerability Scoring industry standard framework used to measure and communicate the severity of software ranging from to *Why we need this Document *It is important that FFmpeg CVEs have consistent and correct not only for the obvious reason that one can recognize the severity of an issue at first glance But also as these numbers form the basis of rewards paid in bug bounty systems Inconsistent CVSS could lead to unfair payouts *What is this Document FFmpeg had no guideline about CVSS This document describes how to select the CVSS for a FFmpeg related CVE It currently only covers the Base Score *What is the CVSS Base Score *AV Attack High PR Privileges Required S High I High *Things people have set incorrectly *Below are general guidelines and in specific cases other things may apply Attack Vector Quote from https
int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb)
Waits for up to 'timeout' microseconds.
static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
static int64_t http_seek(URLContext *h, int64_t off, int whence)
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
static int http_close(URLContext *h)
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
HandshakeState handshake_step
static uint64_t request_size(URLContext *h)
const URLProtocol ff_https_protocol
const char * ff_http_get_new_location(URLContext *h)
AVIOInterruptCB interrupt_callback
void av_bprintf(AVBPrint *buf, const char *fmt,...)
AVDictionary * cookie_dict
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
@ AV_OPT_TYPE_INT
Underlying C type is int.
static int http_read_header(URLContext *h)
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
#define AVERROR_HTTP_FORBIDDEN
#define HTTP_CLASS(flavor)
static void body(uint32_t ABCD[4], const uint8_t *src, size_t nblocks)
static int http_get_file_handle(URLContext *h)
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
int64_t av_gettime(void)
Get the current time in microseconds.
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
HTTPAuthType
Authentication types, ordered from weakest to strongest.
#define AVIO_FLAG_READ
read-only
static int ff_http_averror(int status_code, int default_averror)
int ffurl_handshake(URLContext *c)
Perform one step of the protocol handshake to accept a new client.
int ff_make_absolute_url(char *buf, int size, const char *base, const char *rel)
Convert a relative url into an absolute url, given a base url.
#define AV_OPT_FLAG_EXPORT
The option is intended for exporting values to the caller.
#define MAX_CACHED_REDIRECTS
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
static int http_getc(HTTPContext *s)
static int http_accept(URLContext *s, URLContext **c)
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
char * icy_metadata_headers
int av_opt_set_dict(void *obj, AVDictionary **options)
Set all the options from a given dictionary on an object.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
AVDictionary * redirect_cache
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
static int store_icy(URLContext *h, int size)
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common like for each output line the vertical scaler pulls lines from a ring buffer When the ring buffer does not contain the wanted line
static uint32_t BS_FUNC() read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that's been allocated with av_malloc() or another memory allocation function.
char * reconnect_on_http_error
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.