FFmpeg
http.c
Go to the documentation of this file.
1 /*
2  * HTTP protocol for ffmpeg client
3  * Copyright (c) 2000, 2001 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "config.h"
23 
24 #if CONFIG_ZLIB
25 #include <zlib.h>
26 #endif /* CONFIG_ZLIB */
27 
28 #include "libavutil/avassert.h"
29 #include "libavutil/avstring.h"
30 #include "libavutil/bprint.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/time.h"
33 #include "libavutil/parseutils.h"
34 
35 #include "avformat.h"
36 #include "http.h"
37 #include "httpauth.h"
38 #include "internal.h"
39 #include "network.h"
40 #include "os_support.h"
41 #include "url.h"
42 
43 /* XXX: POST protocol is not completely implemented because ffmpeg uses
44  * only a subset of it. */
45 
46 /* The IO buffer size is unrelated to the max URL size in itself, but needs
47  * to be large enough to fit the full request headers (including long
48  * path names). */
49 #define BUFFER_SIZE MAX_URL_SIZE
50 #define MAX_REDIRECTS 8
51 #define HTTP_SINGLE 1
52 #define HTTP_MUTLI 2
53 #define MAX_EXPIRY 19
54 #define WHITESPACES " \n\t\r"
55 typedef enum {
61 
62 typedef struct HTTPContext {
63  const AVClass *class;
65  unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end;
67  int http_code;
68  /* Used if "Transfer-Encoding: chunked" otherwise -1. */
69  uint64_t chunksize;
70  int chunkend;
71  uint64_t off, end_off, filesize;
72  char *location;
75  char *http_proxy;
76  char *headers;
77  char *mime_type;
78  char *http_version;
79  char *user_agent;
80  char *referer;
81 #if FF_API_HTTP_USER_AGENT
82  char *user_agent_deprecated;
83 #endif
84  char *content_type;
85  /* Set if the server correctly handles Connection: close and will close
86  * the connection after feeding us the content. */
87  int willclose;
88  int seekable; /**< Control seekability, 0 = disable, 1 = enable, -1 = probe. */
90  /* A flag which indicates if the end of chunked encoding has been sent. */
92  /* A flag which indicates we have finished to read POST reply. */
94  /* A flag which indicates if we use persistent connections. */
98  int is_akamai;
100  char *cookies; ///< holds newline (\n) delimited Set-Cookie header field values (without the "Set-Cookie: " field name)
101  /* A dictionary containing cookies keyed by cookie name */
103  int icy;
104  /* how much data was read since the last ICY metadata packet */
105  uint64_t icy_data_read;
106  /* after how many bytes of read data a new metadata packet will be found */
107  uint64_t icy_metaint;
111 #if CONFIG_ZLIB
112  int compressed;
113  z_stream inflate_stream;
114  uint8_t *inflate_buffer;
115 #endif /* CONFIG_ZLIB */
117  /* -1 = try to send if applicable, 0 = always disabled, 1 = always enabled */
119  char *method;
124  int listen;
125  char *resource;
130 } HTTPContext;
131 
132 #define OFFSET(x) offsetof(HTTPContext, x)
133 #define D AV_OPT_FLAG_DECODING_PARAM
134 #define E AV_OPT_FLAG_ENCODING_PARAM
135 #define DEFAULT_USER_AGENT "Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION)
136 
137 static const AVOption options[] = {
138  { "seekable", "control seekability of connection", OFFSET(seekable), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, D },
139  { "chunked_post", "use chunked transfer-encoding for posts", OFFSET(chunked_post), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
140  { "http_proxy", "set HTTP proxy to tunnel through", OFFSET(http_proxy), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
141  { "headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
142  { "content_type", "set a specific content type for the POST messages", OFFSET(content_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
143  { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D },
144  { "referer", "override referer header", OFFSET(referer), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D },
145 #if FF_API_HTTP_USER_AGENT
146  { "user-agent", "use the \"user_agent\" option instead", OFFSET(user_agent_deprecated), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D|AV_OPT_FLAG_DEPRECATED },
147 #endif
148  { "multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D | E },
149  { "post_data", "set custom HTTP post data", OFFSET(post_data), AV_OPT_TYPE_BINARY, .flags = D | E },
150  { "mime_type", "export the MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
151  { "http_version", "export the http response version", OFFSET(http_version), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
152  { "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 },
153  { "icy", "request ICY metadata", OFFSET(icy), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, D },
154  { "icy_metadata_headers", "return ICY metadata headers", OFFSET(icy_metadata_headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT },
155  { "icy_metadata_packet", "return current ICY metadata packet", OFFSET(icy_metadata_packet), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT },
156  { "metadata", "metadata read from the bitstream", OFFSET(metadata), AV_OPT_TYPE_DICT, {0}, 0, 0, AV_OPT_FLAG_EXPORT },
157  { "auth_type", "HTTP authentication type", OFFSET(auth_state.auth_type), AV_OPT_TYPE_INT, { .i64 = HTTP_AUTH_NONE }, HTTP_AUTH_NONE, HTTP_AUTH_BASIC, D | E, "auth_type"},
158  { "none", "No auth method set, autodetect", 0, AV_OPT_TYPE_CONST, { .i64 = HTTP_AUTH_NONE }, 0, 0, D | E, "auth_type"},
159  { "basic", "HTTP basic authentication", 0, AV_OPT_TYPE_CONST, { .i64 = HTTP_AUTH_BASIC }, 0, 0, D | E, "auth_type"},
160  { "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 },
161  { "location", "The actual location of the data received", OFFSET(location), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
162  { "offset", "initial byte offset", OFFSET(off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D },
163  { "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 },
164  { "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 },
165  { "reconnect", "auto reconnect after disconnect before EOF", OFFSET(reconnect), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
166  { "reconnect_at_eof", "auto reconnect at EOF", OFFSET(reconnect_at_eof), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
167  { "reconnect_streamed", "auto reconnect streamed / non seekable streams", OFFSET(reconnect_streamed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
168  { "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 },
169  { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E },
170  { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
171  { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E},
172  { NULL }
173 };
174 
175 static int http_connect(URLContext *h, const char *path, const char *local_path,
176  const char *hoststr, const char *auth,
177  const char *proxyauth, int *new_location);
178 static int http_read_header(URLContext *h, int *new_location);
179 static int http_shutdown(URLContext *h, int flags);
180 
182 {
183  memcpy(&((HTTPContext *)dest->priv_data)->auth_state,
184  &((HTTPContext *)src->priv_data)->auth_state,
185  sizeof(HTTPAuthState));
186  memcpy(&((HTTPContext *)dest->priv_data)->proxy_auth_state,
187  &((HTTPContext *)src->priv_data)->proxy_auth_state,
188  sizeof(HTTPAuthState));
189 }
190 
192 {
193  const char *path, *proxy_path, *lower_proto = "tcp", *local_path;
194  char *hashmark;
195  char hostname[1024], hoststr[1024], proto[10];
196  char auth[1024], proxyauth[1024] = "";
197  char path1[MAX_URL_SIZE], sanitized_path[MAX_URL_SIZE];
198  char buf[1024], urlbuf[MAX_URL_SIZE];
199  int port, use_proxy, err, location_changed = 0;
200  HTTPContext *s = h->priv_data;
201 
202  av_url_split(proto, sizeof(proto), auth, sizeof(auth),
203  hostname, sizeof(hostname), &port,
204  path1, sizeof(path1), s->location);
205  ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
206 
207  proxy_path = s->http_proxy ? s->http_proxy : getenv("http_proxy");
208  use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), hostname) &&
209  proxy_path && av_strstart(proxy_path, "http://", NULL);
210 
211  if (!strcmp(proto, "https")) {
212  lower_proto = "tls";
213  use_proxy = 0;
214  if (port < 0)
215  port = 443;
216  }
217  if (port < 0)
218  port = 80;
219 
220  hashmark = strchr(path1, '#');
221  if (hashmark)
222  *hashmark = '\0';
223 
224  if (path1[0] == '\0') {
225  path = "/";
226  } else if (path1[0] == '?') {
227  snprintf(sanitized_path, sizeof(sanitized_path), "/%s", path1);
228  path = sanitized_path;
229  } else {
230  path = path1;
231  }
232  local_path = path;
233  if (use_proxy) {
234  /* Reassemble the request URL without auth string - we don't
235  * want to leak the auth to the proxy. */
236  ff_url_join(urlbuf, sizeof(urlbuf), proto, NULL, hostname, port, "%s",
237  path1);
238  path = urlbuf;
239  av_url_split(NULL, 0, proxyauth, sizeof(proxyauth),
240  hostname, sizeof(hostname), &port, NULL, 0, proxy_path);
241  }
242 
243  ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL);
244 
245  if (!s->hd) {
247  &h->interrupt_callback, options,
249  if (err < 0)
250  return err;
251  }
252 
253  err = http_connect(h, path, local_path, hoststr,
254  auth, proxyauth, &location_changed);
255  if (err < 0)
256  return err;
257 
258  return location_changed;
259 }
260 
261 /* return non zero if error */
262 static int http_open_cnx(URLContext *h, AVDictionary **options)
263 {
264  HTTPAuthType cur_auth_type, cur_proxy_auth_type;
265  HTTPContext *s = h->priv_data;
266  int location_changed, attempts = 0, redirects = 0;
267 redo:
268  av_dict_copy(options, s->chained_options, 0);
269 
270  cur_auth_type = s->auth_state.auth_type;
271  cur_proxy_auth_type = s->auth_state.auth_type;
272 
273  location_changed = http_open_cnx_internal(h, options);
274  if (location_changed < 0)
275  goto fail;
276 
277  attempts++;
278  if (s->http_code == 401) {
279  if ((cur_auth_type == HTTP_AUTH_NONE || s->auth_state.stale) &&
280  s->auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) {
281  ffurl_closep(&s->hd);
282  goto redo;
283  } else
284  goto fail;
285  }
286  if (s->http_code == 407) {
287  if ((cur_proxy_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
288  s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) {
289  ffurl_closep(&s->hd);
290  goto redo;
291  } else
292  goto fail;
293  }
294  if ((s->http_code == 301 || s->http_code == 302 ||
295  s->http_code == 303 || s->http_code == 307) &&
296  location_changed == 1) {
297  /* url moved, get next */
298  ffurl_closep(&s->hd);
299  if (redirects++ >= MAX_REDIRECTS)
300  return AVERROR(EIO);
301  /* Restart the authentication process with the new target, which
302  * might use a different auth mechanism. */
303  memset(&s->auth_state, 0, sizeof(s->auth_state));
304  attempts = 0;
305  location_changed = 0;
306  goto redo;
307  }
308  return 0;
309 
310 fail:
311  if (s->hd)
312  ffurl_closep(&s->hd);
313  if (location_changed < 0)
314  return location_changed;
315  return ff_http_averror(s->http_code, AVERROR(EIO));
316 }
318 {
319  int ret = 0;
320  HTTPContext *s = h->priv_data;
321 
322  /* flush the receive buffer when it is write only mode */
323  char buf[1024];
324  int read_ret;
325  read_ret = ffurl_read(s->hd, buf, sizeof(buf));
326  if (read_ret < 0) {
327  ret = read_ret;
328  }
329 
330  return ret;
331 }
332 
333 int ff_http_do_new_request(URLContext *h, const char *uri) {
334  return ff_http_do_new_request2(h, uri, NULL);
335 }
336 
338 {
339  HTTPContext *s = h->priv_data;
340  AVDictionary *options = NULL;
341  int ret;
342  char hostname1[1024], hostname2[1024], proto1[10], proto2[10];
343  int port1, port2;
344 
345  if (!h->prot ||
346  !(!strcmp(h->prot->name, "http") ||
347  !strcmp(h->prot->name, "https")))
348  return AVERROR(EINVAL);
349 
350  av_url_split(proto1, sizeof(proto1), NULL, 0,
351  hostname1, sizeof(hostname1), &port1,
352  NULL, 0, s->location);
353  av_url_split(proto2, sizeof(proto2), NULL, 0,
354  hostname2, sizeof(hostname2), &port2,
355  NULL, 0, uri);
356  if (port1 != port2 || strncmp(hostname1, hostname2, sizeof(hostname2)) != 0) {
357  av_log(h, AV_LOG_ERROR, "Cannot reuse HTTP connection for different host: %s:%d != %s:%d\n",
358  hostname1, port1,
359  hostname2, port2
360  );
361  return AVERROR(EINVAL);
362  }
363 
364  if (!s->end_chunked_post) {
365  ret = http_shutdown(h, h->flags);
366  if (ret < 0)
367  return ret;
368  }
369 
370  if (s->willclose)
371  return AVERROR_EOF;
372 
373  s->end_chunked_post = 0;
374  s->chunkend = 0;
375  s->off = 0;
376  s->icy_data_read = 0;
377  av_free(s->location);
378  s->location = av_strdup(uri);
379  if (!s->location)
380  return AVERROR(ENOMEM);
381 
382  if ((ret = av_opt_set_dict(s, opts)) < 0)
383  return ret;
384 
385  av_log(s, AV_LOG_INFO, "Opening \'%s\' for %s\n", uri, h->flags & AVIO_FLAG_WRITE ? "writing" : "reading");
386  ret = http_open_cnx(h, &options);
387  av_dict_free(&options);
388  return ret;
389 }
390 
391 int ff_http_averror(int status_code, int default_averror)
392 {
393  switch (status_code) {
394  case 400: return AVERROR_HTTP_BAD_REQUEST;
395  case 401: return AVERROR_HTTP_UNAUTHORIZED;
396  case 403: return AVERROR_HTTP_FORBIDDEN;
397  case 404: return AVERROR_HTTP_NOT_FOUND;
398  default: break;
399  }
400  if (status_code >= 400 && status_code <= 499)
401  return AVERROR_HTTP_OTHER_4XX;
402  else if (status_code >= 500)
404  else
405  return default_averror;
406 }
407 
408 static int http_write_reply(URLContext* h, int status_code)
409 {
410  int ret, body = 0, reply_code, message_len;
411  const char *reply_text, *content_type;
412  HTTPContext *s = h->priv_data;
413  char message[BUFFER_SIZE];
414  content_type = "text/plain";
415 
416  if (status_code < 0)
417  body = 1;
418  switch (status_code) {
420  case 400:
421  reply_code = 400;
422  reply_text = "Bad Request";
423  break;
425  case 403:
426  reply_code = 403;
427  reply_text = "Forbidden";
428  break;
430  case 404:
431  reply_code = 404;
432  reply_text = "Not Found";
433  break;
434  case 200:
435  reply_code = 200;
436  reply_text = "OK";
437  content_type = s->content_type ? s->content_type : "application/octet-stream";
438  break;
440  case 500:
441  reply_code = 500;
442  reply_text = "Internal server error";
443  break;
444  default:
445  return AVERROR(EINVAL);
446  }
447  if (body) {
448  s->chunked_post = 0;
449  message_len = snprintf(message, sizeof(message),
450  "HTTP/1.1 %03d %s\r\n"
451  "Content-Type: %s\r\n"
452  "Content-Length: %"SIZE_SPECIFIER"\r\n"
453  "%s"
454  "\r\n"
455  "%03d %s\r\n",
456  reply_code,
457  reply_text,
458  content_type,
459  strlen(reply_text) + 6, // 3 digit status code + space + \r\n
460  s->headers ? s->headers : "",
461  reply_code,
462  reply_text);
463  } else {
464  s->chunked_post = 1;
465  message_len = snprintf(message, sizeof(message),
466  "HTTP/1.1 %03d %s\r\n"
467  "Content-Type: %s\r\n"
468  "Transfer-Encoding: chunked\r\n"
469  "%s"
470  "\r\n",
471  reply_code,
472  reply_text,
473  content_type,
474  s->headers ? s->headers : "");
475  }
476  av_log(h, AV_LOG_TRACE, "HTTP reply header: \n%s----\n", message);
477  if ((ret = ffurl_write(s->hd, message, message_len)) < 0)
478  return ret;
479  return 0;
480 }
481 
482 static void handle_http_errors(URLContext *h, int error)
483 {
484  av_assert0(error < 0);
485  http_write_reply(h, error);
486 }
487 
489 {
490  int ret, err, new_location;
491  HTTPContext *ch = c->priv_data;
492  URLContext *cl = ch->hd;
493  switch (ch->handshake_step) {
494  case LOWER_PROTO:
495  av_log(c, AV_LOG_TRACE, "Lower protocol\n");
496  if ((ret = ffurl_handshake(cl)) > 0)
497  return 2 + ret;
498  if (ret < 0)
499  return ret;
501  ch->is_connected_server = 1;
502  return 2;
503  case READ_HEADERS:
504  av_log(c, AV_LOG_TRACE, "Read headers\n");
505  if ((err = http_read_header(c, &new_location)) < 0) {
506  handle_http_errors(c, err);
507  return err;
508  }
510  return 1;
511  case WRITE_REPLY_HEADERS:
512  av_log(c, AV_LOG_TRACE, "Reply code: %d\n", ch->reply_code);
513  if ((err = http_write_reply(c, ch->reply_code)) < 0)
514  return err;
515  ch->handshake_step = FINISH;
516  return 1;
517  case FINISH:
518  return 0;
519  }
520  // this should never be reached.
521  return AVERROR(EINVAL);
522 }
523 
524 static int http_listen(URLContext *h, const char *uri, int flags,
525  AVDictionary **options) {
526  HTTPContext *s = h->priv_data;
527  int ret;
528  char hostname[1024], proto[10];
529  char lower_url[100];
530  const char *lower_proto = "tcp";
531  int port;
532  av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
533  NULL, 0, uri);
534  if (!strcmp(proto, "https"))
535  lower_proto = "tls";
536  ff_url_join(lower_url, sizeof(lower_url), lower_proto, NULL, hostname, port,
537  NULL);
538  if ((ret = av_dict_set_int(options, "listen", s->listen, 0)) < 0)
539  goto fail;
540  if ((ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
541  &h->interrupt_callback, options,
543  )) < 0)
544  goto fail;
546  if (s->listen == HTTP_SINGLE) { /* single client */
547  s->reply_code = 200;
548  while ((ret = http_handshake(h)) > 0);
549  }
550 fail:
552  return ret;
553 }
554 
555 static int http_open(URLContext *h, const char *uri, int flags,
556  AVDictionary **options)
557 {
558  HTTPContext *s = h->priv_data;
559  int ret;
560 
561  if( s->seekable == 1 )
562  h->is_streamed = 0;
563  else
564  h->is_streamed = 1;
565 
566  s->filesize = UINT64_MAX;
567  s->location = av_strdup(uri);
568  if (!s->location)
569  return AVERROR(ENOMEM);
570  if (options)
571  av_dict_copy(&s->chained_options, *options, 0);
572 
573  if (s->headers) {
574  int len = strlen(s->headers);
575  if (len < 2 || strcmp("\r\n", s->headers + len - 2)) {
577  "No trailing CRLF found in HTTP header. Adding it.\n");
578  ret = av_reallocp(&s->headers, len + 3);
579  if (ret < 0)
580  return ret;
581  s->headers[len] = '\r';
582  s->headers[len + 1] = '\n';
583  s->headers[len + 2] = '\0';
584  }
585  }
586 
587  if (s->listen) {
588  return http_listen(h, uri, flags, options);
589  }
590  ret = http_open_cnx(h, options);
591  if (ret < 0)
593  return ret;
594 }
595 
597 {
598  int ret;
599  HTTPContext *sc = s->priv_data;
600  HTTPContext *cc;
601  URLContext *sl = sc->hd;
602  URLContext *cl = NULL;
603 
604  av_assert0(sc->listen);
605  if ((ret = ffurl_alloc(c, s->filename, s->flags, &sl->interrupt_callback)) < 0)
606  goto fail;
607  cc = (*c)->priv_data;
608  if ((ret = ffurl_accept(sl, &cl)) < 0)
609  goto fail;
610  cc->hd = cl;
611  cc->is_multi_client = 1;
612  return 0;
613 fail:
614  if (c) {
615  ffurl_closep(c);
616  }
617  return ret;
618 }
619 
620 static int http_getc(HTTPContext *s)
621 {
622  int len;
623  if (s->buf_ptr >= s->buf_end) {
624  len = ffurl_read(s->hd, s->buffer, BUFFER_SIZE);
625  if (len < 0) {
626  return len;
627  } else if (len == 0) {
628  return AVERROR_EOF;
629  } else {
630  s->buf_ptr = s->buffer;
631  s->buf_end = s->buffer + len;
632  }
633  }
634  return *s->buf_ptr++;
635 }
636 
637 static int http_get_line(HTTPContext *s, char *line, int line_size)
638 {
639  int ch;
640  char *q;
641 
642  q = line;
643  for (;;) {
644  ch = http_getc(s);
645  if (ch < 0)
646  return ch;
647  if (ch == '\n') {
648  /* process line */
649  if (q > line && q[-1] == '\r')
650  q--;
651  *q = '\0';
652 
653  return 0;
654  } else {
655  if ((q - line) < line_size - 1)
656  *q++ = ch;
657  }
658  }
659 }
660 
661 static int check_http_code(URLContext *h, int http_code, const char *end)
662 {
663  HTTPContext *s = h->priv_data;
664  /* error codes are 4xx and 5xx, but regard 401 as a success, so we
665  * don't abort until all headers have been parsed. */
666  if (http_code >= 400 && http_code < 600 &&
667  (http_code != 401 || s->auth_state.auth_type != HTTP_AUTH_NONE) &&
668  (http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) {
669  end += strspn(end, SPACE_CHARS);
670  av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", http_code, end);
671  return ff_http_averror(http_code, AVERROR(EIO));
672  }
673  return 0;
674 }
675 
676 static int parse_location(HTTPContext *s, const char *p)
677 {
678  char redirected_location[MAX_URL_SIZE], *new_loc;
679  ff_make_absolute_url(redirected_location, sizeof(redirected_location),
680  s->location, p);
681  new_loc = av_strdup(redirected_location);
682  if (!new_loc)
683  return AVERROR(ENOMEM);
684  av_free(s->location);
685  s->location = new_loc;
686  return 0;
687 }
688 
689 /* "bytes $from-$to/$document_size" */
690 static void parse_content_range(URLContext *h, const char *p)
691 {
692  HTTPContext *s = h->priv_data;
693  const char *slash;
694 
695  if (!strncmp(p, "bytes ", 6)) {
696  p += 6;
697  s->off = strtoull(p, NULL, 10);
698  if ((slash = strchr(p, '/')) && strlen(slash) > 0)
699  s->filesize = strtoull(slash + 1, NULL, 10);
700  }
701  if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
702  h->is_streamed = 0; /* we _can_ in fact seek */
703 }
704 
705 static int parse_content_encoding(URLContext *h, const char *p)
706 {
707  if (!av_strncasecmp(p, "gzip", 4) ||
708  !av_strncasecmp(p, "deflate", 7)) {
709 #if CONFIG_ZLIB
710  HTTPContext *s = h->priv_data;
711 
712  s->compressed = 1;
713  inflateEnd(&s->inflate_stream);
714  if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) {
715  av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n",
716  s->inflate_stream.msg);
717  return AVERROR(ENOSYS);
718  }
719  if (zlibCompileFlags() & (1 << 17)) {
721  "Your zlib was compiled without gzip support.\n");
722  return AVERROR(ENOSYS);
723  }
724 #else
726  "Compressed (%s) content, need zlib with gzip support\n", p);
727  return AVERROR(ENOSYS);
728 #endif /* CONFIG_ZLIB */
729  } else if (!av_strncasecmp(p, "identity", 8)) {
730  // The normal, no-encoding case (although servers shouldn't include
731  // the header at all if this is the case).
732  } else {
733  av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p);
734  }
735  return 0;
736 }
737 
738 // Concat all Icy- header lines
739 static int parse_icy(HTTPContext *s, const char *tag, const char *p)
740 {
741  int len = 4 + strlen(p) + strlen(tag);
742  int is_first = !s->icy_metadata_headers;
743  int ret;
744 
745  av_dict_set(&s->metadata, tag, p, 0);
746 
747  if (s->icy_metadata_headers)
748  len += strlen(s->icy_metadata_headers);
749 
750  if ((ret = av_reallocp(&s->icy_metadata_headers, len)) < 0)
751  return ret;
752 
753  if (is_first)
754  *s->icy_metadata_headers = '\0';
755 
756  av_strlcatf(s->icy_metadata_headers, len, "%s: %s\n", tag, p);
757 
758  return 0;
759 }
760 
761 static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
762 {
763  char exp_buf[MAX_EXPIRY];
764  int i, j, exp_buf_len = MAX_EXPIRY-1;
765  char *expiry;
766 
767  // strip off any punctuation or whitespace
768  for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
769  if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
770  (exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
771  (exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
772  exp_buf[j] = exp_str[i];
773  j++;
774  }
775  }
776  exp_buf[j] = '\0';
777  expiry = exp_buf;
778 
779  // move the string beyond the day of week
780  while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
781  expiry++;
782 
783  return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : AVERROR(EINVAL);
784 }
785 
786 static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
787 {
788  char *param, *next_param, *cstr, *back;
789 
790  if (!set_cookie[0])
791  return 0;
792 
793  if (!(cstr = av_strdup(set_cookie)))
794  return AVERROR(EINVAL);
795 
796  // strip any trailing whitespace
797  back = &cstr[strlen(cstr)-1];
798  while (strchr(WHITESPACES, *back)) {
799  *back='\0';
800  if (back == cstr)
801  break;
802  back--;
803  }
804 
805  next_param = cstr;
806  while ((param = av_strtok(next_param, ";", &next_param))) {
807  char *name, *value;
808  param += strspn(param, WHITESPACES);
809  if ((name = av_strtok(param, "=", &value))) {
810  if (av_dict_set(dict, name, value, 0) < 0) {
811  av_free(cstr);
812  return -1;
813  }
814  }
815  }
816 
817  av_free(cstr);
818  return 0;
819 }
820 
821 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
822 {
823  AVDictionary *new_params = NULL;
824  AVDictionaryEntry *e, *cookie_entry;
825  char *eql, *name;
826 
827  // ensure the cookie is parsable
828  if (parse_set_cookie(p, &new_params))
829  return -1;
830 
831  // if there is no cookie value there is nothing to parse
832  cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
833  if (!cookie_entry || !cookie_entry->value) {
834  av_dict_free(&new_params);
835  return -1;
836  }
837 
838  // ensure the cookie is not expired or older than an existing value
839  if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
840  struct tm new_tm = {0};
841  if (!parse_set_cookie_expiry_time(e->value, &new_tm)) {
842  AVDictionaryEntry *e2;
843 
844  // if the cookie has already expired ignore it
845  if (av_timegm(&new_tm) < av_gettime() / 1000000) {
846  av_dict_free(&new_params);
847  return 0;
848  }
849 
850  // only replace an older cookie with the same name
851  e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
852  if (e2 && e2->value) {
853  AVDictionary *old_params = NULL;
854  if (!parse_set_cookie(p, &old_params)) {
855  e2 = av_dict_get(old_params, "expires", NULL, 0);
856  if (e2 && e2->value) {
857  struct tm old_tm = {0};
858  if (!parse_set_cookie_expiry_time(e->value, &old_tm)) {
859  if (av_timegm(&new_tm) < av_timegm(&old_tm)) {
860  av_dict_free(&new_params);
861  av_dict_free(&old_params);
862  return -1;
863  }
864  }
865  }
866  }
867  av_dict_free(&old_params);
868  }
869  }
870  }
871  av_dict_free(&new_params);
872 
873  // duplicate the cookie name (dict will dupe the value)
874  if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
875  if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
876 
877  // add the cookie to the dictionary
878  av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
879 
880  return 0;
881 }
882 
883 static int cookie_string(AVDictionary *dict, char **cookies)
884 {
885  AVDictionaryEntry *e = NULL;
886  int len = 1;
887 
888  // determine how much memory is needed for the cookies string
889  while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))
890  len += strlen(e->key) + strlen(e->value) + 1;
891 
892  // reallocate the cookies
893  e = NULL;
894  if (*cookies) av_free(*cookies);
895  *cookies = av_malloc(len);
896  if (!*cookies) return AVERROR(ENOMEM);
897  *cookies[0] = '\0';
898 
899  // write out the cookies
900  while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))
901  av_strlcatf(*cookies, len, "%s%s\n", e->key, e->value);
902 
903  return 0;
904 }
905 
906 static int process_line(URLContext *h, char *line, int line_count,
907  int *new_location)
908 {
909  HTTPContext *s = h->priv_data;
910  const char *auto_method = h->flags & AVIO_FLAG_READ ? "POST" : "GET";
911  char *tag, *p, *end, *method, *resource, *version;
912  int ret;
913 
914  /* end of header */
915  if (line[0] == '\0') {
916  s->end_header = 1;
917  return 0;
918  }
919 
920  p = line;
921  if (line_count == 0) {
922  if (s->is_connected_server) {
923  // HTTP method
924  method = p;
925  while (*p && !av_isspace(*p))
926  p++;
927  *(p++) = '\0';
928  av_log(h, AV_LOG_TRACE, "Received method: %s\n", method);
929  if (s->method) {
930  if (av_strcasecmp(s->method, method)) {
931  av_log(h, AV_LOG_ERROR, "Received and expected HTTP method do not match. (%s expected, %s received)\n",
932  s->method, method);
933  return ff_http_averror(400, AVERROR(EIO));
934  }
935  } else {
936  // use autodetected HTTP method to expect
937  av_log(h, AV_LOG_TRACE, "Autodetected %s HTTP method\n", auto_method);
938  if (av_strcasecmp(auto_method, method)) {
939  av_log(h, AV_LOG_ERROR, "Received and autodetected HTTP method did not match "
940  "(%s autodetected %s received)\n", auto_method, method);
941  return ff_http_averror(400, AVERROR(EIO));
942  }
943  if (!(s->method = av_strdup(method)))
944  return AVERROR(ENOMEM);
945  }
946 
947  // HTTP resource
948  while (av_isspace(*p))
949  p++;
950  resource = p;
951  while (*p && !av_isspace(*p))
952  p++;
953  *(p++) = '\0';
954  av_log(h, AV_LOG_TRACE, "Requested resource: %s\n", resource);
955  if (!(s->resource = av_strdup(resource)))
956  return AVERROR(ENOMEM);
957 
958  // HTTP version
959  while (av_isspace(*p))
960  p++;
961  version = p;
962  while (*p && !av_isspace(*p))
963  p++;
964  *p = '\0';
965  if (av_strncasecmp(version, "HTTP/", 5)) {
966  av_log(h, AV_LOG_ERROR, "Malformed HTTP version string.\n");
967  return ff_http_averror(400, AVERROR(EIO));
968  }
969  av_log(h, AV_LOG_TRACE, "HTTP version string: %s\n", version);
970  } else {
971  if (av_strncasecmp(p, "HTTP/1.0", 8) == 0)
972  s->willclose = 1;
973  while (*p != '/' && *p != '\0')
974  p++;
975  while (*p == '/')
976  p++;
977  av_freep(&s->http_version);
978  s->http_version = av_strndup(p, 3);
979  while (!av_isspace(*p) && *p != '\0')
980  p++;
981  while (av_isspace(*p))
982  p++;
983  s->http_code = strtol(p, &end, 10);
984 
985  av_log(h, AV_LOG_TRACE, "http_code=%d\n", s->http_code);
986 
987  if ((ret = check_http_code(h, s->http_code, end)) < 0)
988  return ret;
989  }
990  } else {
991  while (*p != '\0' && *p != ':')
992  p++;
993  if (*p != ':')
994  return 1;
995 
996  *p = '\0';
997  tag = line;
998  p++;
999  while (av_isspace(*p))
1000  p++;
1001  if (!av_strcasecmp(tag, "Location")) {
1002  if ((ret = parse_location(s, p)) < 0)
1003  return ret;
1004  *new_location = 1;
1005  } else if (!av_strcasecmp(tag, "Content-Length") &&
1006  s->filesize == UINT64_MAX) {
1007  s->filesize = strtoull(p, NULL, 10);
1008  } else if (!av_strcasecmp(tag, "Content-Range")) {
1009  parse_content_range(h, p);
1010  } else if (!av_strcasecmp(tag, "Accept-Ranges") &&
1011  !strncmp(p, "bytes", 5) &&
1012  s->seekable == -1) {
1013  h->is_streamed = 0;
1014  } else if (!av_strcasecmp(tag, "Transfer-Encoding") &&
1015  !av_strncasecmp(p, "chunked", 7)) {
1016  s->filesize = UINT64_MAX;
1017  s->chunksize = 0;
1018  } else if (!av_strcasecmp(tag, "WWW-Authenticate")) {
1020  } else if (!av_strcasecmp(tag, "Authentication-Info")) {
1022  } else if (!av_strcasecmp(tag, "Proxy-Authenticate")) {
1024  } else if (!av_strcasecmp(tag, "Connection")) {
1025  if (!strcmp(p, "close"))
1026  s->willclose = 1;
1027  } else if (!av_strcasecmp(tag, "Server")) {
1028  if (!av_strcasecmp(p, "AkamaiGHost")) {
1029  s->is_akamai = 1;
1030  } else if (!av_strncasecmp(p, "MediaGateway", 12)) {
1031  s->is_mediagateway = 1;
1032  }
1033  } else if (!av_strcasecmp(tag, "Content-Type")) {
1034  av_free(s->mime_type);
1035  s->mime_type = av_strdup(p);
1036  } else if (!av_strcasecmp(tag, "Set-Cookie")) {
1037  if (parse_cookie(s, p, &s->cookie_dict))
1038  av_log(h, AV_LOG_WARNING, "Unable to parse '%s'\n", p);
1039  } else if (!av_strcasecmp(tag, "Icy-MetaInt")) {
1040  s->icy_metaint = strtoull(p, NULL, 10);
1041  } else if (!av_strncasecmp(tag, "Icy-", 4)) {
1042  if ((ret = parse_icy(s, tag, p)) < 0)
1043  return ret;
1044  } else if (!av_strcasecmp(tag, "Content-Encoding")) {
1045  if ((ret = parse_content_encoding(h, p)) < 0)
1046  return ret;
1047  }
1048  }
1049  return 1;
1050 }
1051 
1052 /**
1053  * Create a string containing cookie values for use as a HTTP cookie header
1054  * field value for a particular path and domain from the cookie values stored in
1055  * the HTTP protocol context. The cookie string is stored in *cookies, and may
1056  * be NULL if there are no valid cookies.
1057  *
1058  * @return a negative value if an error condition occurred, 0 otherwise
1059  */
1060 static int get_cookies(HTTPContext *s, char **cookies, const char *path,
1061  const char *domain)
1062 {
1063  // cookie strings will look like Set-Cookie header field values. Multiple
1064  // Set-Cookie fields will result in multiple values delimited by a newline
1065  int ret = 0;
1066  char *cookie, *set_cookies, *next;
1067 
1068  // destroy any cookies in the dictionary.
1070 
1071  if (!s->cookies)
1072  return 0;
1073 
1074  next = set_cookies = av_strdup(s->cookies);
1075  if (!next)
1076  return AVERROR(ENOMEM);
1077 
1078  *cookies = NULL;
1079  while ((cookie = av_strtok(next, "\n", &next)) && !ret) {
1080  AVDictionary *cookie_params = NULL;
1081  AVDictionaryEntry *cookie_entry, *e;
1082 
1083  // store the cookie in a dict in case it is updated in the response
1084  if (parse_cookie(s, cookie, &s->cookie_dict))
1085  av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
1086 
1087  // continue on to the next cookie if this one cannot be parsed
1088  if (parse_set_cookie(cookie, &cookie_params))
1089  goto skip_cookie;
1090 
1091  // if the cookie has no value, skip it
1092  cookie_entry = av_dict_get(cookie_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
1093  if (!cookie_entry || !cookie_entry->value)
1094  goto skip_cookie;
1095 
1096  // if the cookie has expired, don't add it
1097  if ((e = av_dict_get(cookie_params, "expires", NULL, 0)) && e->value) {
1098  struct tm tm_buf = {0};
1099  if (!parse_set_cookie_expiry_time(e->value, &tm_buf)) {
1100  if (av_timegm(&tm_buf) < av_gettime() / 1000000)
1101  goto skip_cookie;
1102  }
1103  }
1104 
1105  // if no domain in the cookie assume it appied to this request
1106  if ((e = av_dict_get(cookie_params, "domain", NULL, 0)) && e->value) {
1107  // find the offset comparison is on the min domain (b.com, not a.b.com)
1108  int domain_offset = strlen(domain) - strlen(e->value);
1109  if (domain_offset < 0)
1110  goto skip_cookie;
1111 
1112  // match the cookie domain
1113  if (av_strcasecmp(&domain[domain_offset], e->value))
1114  goto skip_cookie;
1115  }
1116 
1117  // ensure this cookie matches the path
1118  e = av_dict_get(cookie_params, "path", NULL, 0);
1119  if (!e || av_strncasecmp(path, e->value, strlen(e->value)))
1120  goto skip_cookie;
1121 
1122  // cookie parameters match, so copy the value
1123  if (!*cookies) {
1124  *cookies = av_asprintf("%s=%s", cookie_entry->key, cookie_entry->value);
1125  } else {
1126  char *tmp = *cookies;
1127  *cookies = av_asprintf("%s; %s=%s", tmp, cookie_entry->key, cookie_entry->value);
1128  av_free(tmp);
1129  }
1130  if (!*cookies)
1131  ret = AVERROR(ENOMEM);
1132 
1133  skip_cookie:
1134  av_dict_free(&cookie_params);
1135  }
1136 
1137  av_free(set_cookies);
1138 
1139  return ret;
1140 }
1141 
1142 static inline int has_header(const char *str, const char *header)
1143 {
1144  /* header + 2 to skip over CRLF prefix. (make sure you have one!) */
1145  if (!str)
1146  return 0;
1147  return av_stristart(str, header + 2, NULL) || av_stristr(str, header);
1148 }
1149 
1150 static int http_read_header(URLContext *h, int *new_location)
1151 {
1152  HTTPContext *s = h->priv_data;
1153  char line[MAX_URL_SIZE];
1154  int err = 0;
1155 
1156  s->chunksize = UINT64_MAX;
1157 
1158  for (;;) {
1159  if ((err = http_get_line(s, line, sizeof(line))) < 0)
1160  return err;
1161 
1162  av_log(h, AV_LOG_TRACE, "header='%s'\n", line);
1163 
1164  err = process_line(h, line, s->line_count, new_location);
1165  if (err < 0)
1166  return err;
1167  if (err == 0)
1168  break;
1169  s->line_count++;
1170  }
1171 
1172  if (s->seekable == -1 && s->is_mediagateway && s->filesize == 2000000000)
1173  h->is_streamed = 1; /* we can in fact _not_ seek */
1174 
1175  // add any new cookies into the existing cookie string
1178 
1179  return err;
1180 }
1181 
1182 /**
1183  * Escape unsafe characters in path in order to pass them safely to the HTTP
1184  * request. Insipred by the algorithm in GNU wget:
1185  * - escape "%" characters not followed by two hex digits
1186  * - escape all "unsafe" characters except which are also "reserved"
1187  * - pass through everything else
1188  */
1189 static void bprint_escaped_path(AVBPrint *bp, const char *path)
1190 {
1191 #define NEEDS_ESCAPE(ch) \
1192  ((ch) <= ' ' || (ch) >= '\x7f' || \
1193  (ch) == '"' || (ch) == '%' || (ch) == '<' || (ch) == '>' || (ch) == '\\' || \
1194  (ch) == '^' || (ch) == '`' || (ch) == '{' || (ch) == '}' || (ch) == '|')
1195  while (*path) {
1196  char buf[1024];
1197  char *q = buf;
1198  while (*path && q - buf < sizeof(buf) - 4) {
1199  if (path[0] == '%' && av_isxdigit(path[1]) && av_isxdigit(path[2])) {
1200  *q++ = *path++;
1201  *q++ = *path++;
1202  *q++ = *path++;
1203  } else if (NEEDS_ESCAPE(*path)) {
1204  q += snprintf(q, 4, "%%%02X", (uint8_t)*path++);
1205  } else {
1206  *q++ = *path++;
1207  }
1208  }
1209  av_bprint_append_data(bp, buf, q - buf);
1210  }
1211 }
1212 
1213 static int http_connect(URLContext *h, const char *path, const char *local_path,
1214  const char *hoststr, const char *auth,
1215  const char *proxyauth, int *new_location)
1216 {
1217  HTTPContext *s = h->priv_data;
1218  int post, err;
1219  AVBPrint request;
1220  char *authstr = NULL, *proxyauthstr = NULL;
1221  uint64_t off = s->off;
1222  const char *method;
1223  int send_expect_100 = 0;
1224 
1225  av_bprint_init_for_buffer(&request, s->buffer, sizeof(s->buffer));
1226 
1227  /* send http header */
1228  post = h->flags & AVIO_FLAG_WRITE;
1229 
1230  if (s->post_data) {
1231  /* force POST method and disable chunked encoding when
1232  * custom HTTP post data is set */
1233  post = 1;
1234  s->chunked_post = 0;
1235  }
1236 
1237  if (s->method)
1238  method = s->method;
1239  else
1240  method = post ? "POST" : "GET";
1241 
1242  authstr = ff_http_auth_create_response(&s->auth_state, auth,
1243  local_path, method);
1244  proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth,
1245  local_path, method);
1246 
1247  if (post && !s->post_data) {
1248  if (s->send_expect_100 != -1) {
1249  send_expect_100 = s->send_expect_100;
1250  } else {
1251  send_expect_100 = 0;
1252  /* The user has supplied authentication but we don't know the auth type,
1253  * send Expect: 100-continue to get the 401 response including the
1254  * WWW-Authenticate header, or an 100 continue if no auth actually
1255  * is needed. */
1256  if (auth && *auth &&
1258  s->http_code != 401)
1259  send_expect_100 = 1;
1260  }
1261  }
1262 
1263 #if FF_API_HTTP_USER_AGENT
1264  if (strcmp(s->user_agent_deprecated, DEFAULT_USER_AGENT)) {
1265  s->user_agent = av_strdup(s->user_agent_deprecated);
1266  }
1267 #endif
1268 
1269  av_bprintf(&request, "%s ", method);
1270  bprint_escaped_path(&request, path);
1271  av_bprintf(&request, " HTTP/1.1\r\n");
1272 
1273  if (post && s->chunked_post)
1274  av_bprintf(&request, "Transfer-Encoding: chunked\r\n");
1275  /* set default headers if needed */
1276  if (!has_header(s->headers, "\r\nUser-Agent: "))
1277  av_bprintf(&request, "User-Agent: %s\r\n", s->user_agent);
1278  if (s->referer) {
1279  /* set default headers if needed */
1280  if (!has_header(s->headers, "\r\nReferer: "))
1281  av_bprintf(&request, "Referer: %s\r\n", s->referer);
1282  }
1283  if (!has_header(s->headers, "\r\nAccept: "))
1284  av_bprintf(&request, "Accept: */*\r\n");
1285  // Note: we send this on purpose even when s->off is 0 when we're probing,
1286  // since it allows us to detect more reliably if a (non-conforming)
1287  // server supports seeking by analysing the reply headers.
1288  if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) {
1289  av_bprintf(&request, "Range: bytes=%"PRIu64"-", s->off);
1290  if (s->end_off)
1291  av_bprintf(&request, "%"PRId64, s->end_off - 1);
1292  av_bprintf(&request, "\r\n");
1293  }
1294  if (send_expect_100 && !has_header(s->headers, "\r\nExpect: "))
1295  av_bprintf(&request, "Expect: 100-continue\r\n");
1296 
1297  if (!has_header(s->headers, "\r\nConnection: "))
1298  av_bprintf(&request, "Connection: %s\r\n", s->multiple_requests ? "keep-alive" : "close");
1299 
1300  if (!has_header(s->headers, "\r\nHost: "))
1301  av_bprintf(&request, "Host: %s\r\n", hoststr);
1302  if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data)
1303  av_bprintf(&request, "Content-Length: %d\r\n", s->post_datalen);
1304 
1305  if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type)
1306  av_bprintf(&request, "Content-Type: %s\r\n", s->content_type);
1307  if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) {
1308  char *cookies = NULL;
1309  if (!get_cookies(s, &cookies, path, hoststr) && cookies) {
1310  av_bprintf(&request, "Cookie: %s\r\n", cookies);
1311  av_free(cookies);
1312  }
1313  }
1314  if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy)
1315  av_bprintf(&request, "Icy-MetaData: 1\r\n");
1316 
1317  /* now add in custom headers */
1318  if (s->headers)
1319  av_bprintf(&request, "%s", s->headers);
1320 
1321  if (authstr)
1322  av_bprintf(&request, "%s", authstr);
1323  if (proxyauthstr)
1324  av_bprintf(&request, "Proxy-%s", proxyauthstr);
1325  av_bprintf(&request, "\r\n");
1326 
1327  av_log(h, AV_LOG_DEBUG, "request: %s\n", request.str);
1328 
1329  if (!av_bprint_is_complete(&request)) {
1330  av_log(h, AV_LOG_ERROR, "overlong headers\n");
1331  err = AVERROR(EINVAL);
1332  goto done;
1333  }
1334 
1335  if ((err = ffurl_write(s->hd, request.str, request.len)) < 0)
1336  goto done;
1337 
1338  if (s->post_data)
1339  if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0)
1340  goto done;
1341 
1342  /* init input buffer */
1343  s->buf_ptr = s->buffer;
1344  s->buf_end = s->buffer;
1345  s->line_count = 0;
1346  s->off = 0;
1347  s->icy_data_read = 0;
1348  s->filesize = UINT64_MAX;
1349  s->willclose = 0;
1350  s->end_chunked_post = 0;
1351  s->end_header = 0;
1352 #if CONFIG_ZLIB
1353  s->compressed = 0;
1354 #endif
1355  if (post && !s->post_data && !send_expect_100) {
1356  /* Pretend that it did work. We didn't read any header yet, since
1357  * we've still to send the POST data, but the code calling this
1358  * function will check http_code after we return. */
1359  s->http_code = 200;
1360  err = 0;
1361  goto done;
1362  }
1363 
1364  /* wait for header */
1365  err = http_read_header(h, new_location);
1366  if (err < 0)
1367  goto done;
1368 
1369  if (*new_location)
1370  s->off = off;
1371 
1372  err = (off == s->off) ? 0 : -1;
1373 done:
1374  av_freep(&authstr);
1375  av_freep(&proxyauthstr);
1376  return err;
1377 }
1378 
1379 static int http_buf_read(URLContext *h, uint8_t *buf, int size)
1380 {
1381  HTTPContext *s = h->priv_data;
1382  int len;
1383 
1384  if (s->chunksize != UINT64_MAX) {
1385  if (s->chunkend) {
1386  return AVERROR_EOF;
1387  }
1388  if (!s->chunksize) {
1389  char line[32];
1390  int err;
1391 
1392  do {
1393  if ((err = http_get_line(s, line, sizeof(line))) < 0)
1394  return err;
1395  } while (!*line); /* skip CR LF from last chunk */
1396 
1397  s->chunksize = strtoull(line, NULL, 16);
1398 
1399  av_log(h, AV_LOG_TRACE,
1400  "Chunked encoding data size: %"PRIu64"\n",
1401  s->chunksize);
1402 
1403  if (!s->chunksize && s->multiple_requests) {
1404  http_get_line(s, line, sizeof(line)); // read empty chunk
1405  s->chunkend = 1;
1406  return 0;
1407  }
1408  else if (!s->chunksize) {
1409  av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n");
1410  ffurl_closep(&s->hd);
1411  return 0;
1412  }
1413  else if (s->chunksize == UINT64_MAX) {
1414  av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n",
1415  s->chunksize);
1416  return AVERROR(EINVAL);
1417  }
1418  }
1419  size = FFMIN(size, s->chunksize);
1420  }
1421 
1422  /* read bytes from input buffer first */
1423  len = s->buf_end - s->buf_ptr;
1424  if (len > 0) {
1425  if (len > size)
1426  len = size;
1427  memcpy(buf, s->buf_ptr, len);
1428  s->buf_ptr += len;
1429  } else {
1430  uint64_t target_end = s->end_off ? s->end_off : s->filesize;
1431  if ((!s->willclose || s->chunksize == UINT64_MAX) && s->off >= target_end)
1432  return AVERROR_EOF;
1433  len = ffurl_read(s->hd, buf, size);
1434  if (!len && (!s->willclose || s->chunksize == UINT64_MAX) && s->off < target_end) {
1435  av_log(h, AV_LOG_ERROR,
1436  "Stream ends prematurely at %"PRIu64", should be %"PRIu64"\n",
1437  s->off, target_end
1438  );
1439  return AVERROR(EIO);
1440  }
1441  }
1442  if (len > 0) {
1443  s->off += len;
1444  if (s->chunksize > 0 && s->chunksize != UINT64_MAX) {
1445  av_assert0(s->chunksize >= len);
1446  s->chunksize -= len;
1447  }
1448  }
1449  return len;
1450 }
1451 
1452 #if CONFIG_ZLIB
1453 #define DECOMPRESS_BUF_SIZE (256 * 1024)
1454 static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size)
1455 {
1456  HTTPContext *s = h->priv_data;
1457  int ret;
1458 
1459  if (!s->inflate_buffer) {
1460  s->inflate_buffer = av_malloc(DECOMPRESS_BUF_SIZE);
1461  if (!s->inflate_buffer)
1462  return AVERROR(ENOMEM);
1463  }
1464 
1465  if (s->inflate_stream.avail_in == 0) {
1466  int read = http_buf_read(h, s->inflate_buffer, DECOMPRESS_BUF_SIZE);
1467  if (read <= 0)
1468  return read;
1469  s->inflate_stream.next_in = s->inflate_buffer;
1470  s->inflate_stream.avail_in = read;
1471  }
1472 
1473  s->inflate_stream.avail_out = size;
1474  s->inflate_stream.next_out = buf;
1475 
1476  ret = inflate(&s->inflate_stream, Z_SYNC_FLUSH);
1477  if (ret != Z_OK && ret != Z_STREAM_END)
1478  av_log(h, AV_LOG_WARNING, "inflate return value: %d, %s\n",
1479  ret, s->inflate_stream.msg);
1480 
1481  return size - s->inflate_stream.avail_out;
1482 }
1483 #endif /* CONFIG_ZLIB */
1484 
1485 static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect);
1486 
1487 static int http_read_stream(URLContext *h, uint8_t *buf, int size)
1488 {
1489  HTTPContext *s = h->priv_data;
1490  int err, new_location, read_ret;
1491  int64_t seek_ret;
1492  int reconnect_delay = 0;
1493 
1494  if (!s->hd)
1495  return AVERROR_EOF;
1496 
1497  if (s->end_chunked_post && !s->end_header) {
1498  err = http_read_header(h, &new_location);
1499  if (err < 0)
1500  return err;
1501  }
1502 
1503 #if CONFIG_ZLIB
1504  if (s->compressed)
1505  return http_buf_read_compressed(h, buf, size);
1506 #endif /* CONFIG_ZLIB */
1507  read_ret = http_buf_read(h, buf, size);
1508  while (read_ret < 0) {
1509  uint64_t target = h->is_streamed ? 0 : s->off;
1510 
1511  if (read_ret == AVERROR_EXIT)
1512  break;
1513 
1514  if (h->is_streamed && !s->reconnect_streamed)
1515  break;
1516 
1517  if (!(s->reconnect && s->filesize > 0 && s->off < s->filesize) &&
1518  !(s->reconnect_at_eof && read_ret == AVERROR_EOF))
1519  break;
1520 
1521  if (reconnect_delay > s->reconnect_delay_max)
1522  return AVERROR(EIO);
1523 
1524  av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s), error=%s.\n", s->off, reconnect_delay, av_err2str(read_ret));
1525  err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback);
1526  if (err != AVERROR(ETIMEDOUT))
1527  return err;
1528  reconnect_delay = 1 + 2*reconnect_delay;
1529  seek_ret = http_seek_internal(h, target, SEEK_SET, 1);
1530  if (seek_ret >= 0 && seek_ret != target) {
1531  av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target);
1532  return read_ret;
1533  }
1534 
1535  read_ret = http_buf_read(h, buf, size);
1536  }
1537 
1538  return read_ret;
1539 }
1540 
1541 // Like http_read_stream(), but no short reads.
1542 // Assumes partial reads are an error.
1543 static int http_read_stream_all(URLContext *h, uint8_t *buf, int size)
1544 {
1545  int pos = 0;
1546  while (pos < size) {
1547  int len = http_read_stream(h, buf + pos, size - pos);
1548  if (len < 0)
1549  return len;
1550  pos += len;
1551  }
1552  return pos;
1553 }
1554 
1555 static void update_metadata(URLContext *h, char *data)
1556 {
1557  char *key;
1558  char *val;
1559  char *end;
1560  char *next = data;
1561  HTTPContext *s = h->priv_data;
1562 
1563  while (*next) {
1564  key = next;
1565  val = strstr(key, "='");
1566  if (!val)
1567  break;
1568  end = strstr(val, "';");
1569  if (!end)
1570  break;
1571 
1572  *val = '\0';
1573  *end = '\0';
1574  val += 2;
1575 
1576  av_dict_set(&s->metadata, key, val, 0);
1577  av_log(h, AV_LOG_VERBOSE, "Metadata update for %s: %s\n", key, val);
1578 
1579  next = end + 2;
1580  }
1581 }
1582 
1583 static int store_icy(URLContext *h, int size)
1584 {
1585  HTTPContext *s = h->priv_data;
1586  /* until next metadata packet */
1587  uint64_t remaining;
1588 
1589  if (s->icy_metaint < s->icy_data_read)
1590  return AVERROR_INVALIDDATA;
1591  remaining = s->icy_metaint - s->icy_data_read;
1592 
1593  if (!remaining) {
1594  /* The metadata packet is variable sized. It has a 1 byte header
1595  * which sets the length of the packet (divided by 16). If it's 0,
1596  * the metadata doesn't change. After the packet, icy_metaint bytes
1597  * of normal data follows. */
1598  uint8_t ch;
1599  int len = http_read_stream_all(h, &ch, 1);
1600  if (len < 0)
1601  return len;
1602  if (ch > 0) {
1603  char data[255 * 16 + 1];
1604  int ret;
1605  len = ch * 16;
1606  ret = http_read_stream_all(h, data, len);
1607  if (ret < 0)
1608  return ret;
1609  data[len + 1] = 0;
1610  if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
1611  return ret;
1612  update_metadata(h, data);
1613  }
1614  s->icy_data_read = 0;
1615  remaining = s->icy_metaint;
1616  }
1617 
1618  return FFMIN(size, remaining);
1619 }
1620 
1621 static int http_read(URLContext *h, uint8_t *buf, int size)
1622 {
1623  HTTPContext *s = h->priv_data;
1624 
1625  if (s->icy_metaint > 0) {
1626  size = store_icy(h, size);
1627  if (size < 0)
1628  return size;
1629  }
1630 
1631  size = http_read_stream(h, buf, size);
1632  if (size > 0)
1633  s->icy_data_read += size;
1634  return size;
1635 }
1636 
1637 /* used only when posting data */
1638 static int http_write(URLContext *h, const uint8_t *buf, int size)
1639 {
1640  char temp[11] = ""; /* 32-bit hex + CRLF + nul */
1641  int ret;
1642  char crlf[] = "\r\n";
1643  HTTPContext *s = h->priv_data;
1644 
1645  if (!s->chunked_post) {
1646  /* non-chunked data is sent without any special encoding */
1647  return ffurl_write(s->hd, buf, size);
1648  }
1649 
1650  /* silently ignore zero-size data since chunk encoding that would
1651  * signal EOF */
1652  if (size > 0) {
1653  /* upload data using chunked encoding */
1654  snprintf(temp, sizeof(temp), "%x\r\n", size);
1655 
1656  if ((ret = ffurl_write(s->hd, temp, strlen(temp))) < 0 ||
1657  (ret = ffurl_write(s->hd, buf, size)) < 0 ||
1658  (ret = ffurl_write(s->hd, crlf, sizeof(crlf) - 1)) < 0)
1659  return ret;
1660  }
1661  return size;
1662 }
1663 
1664 static int http_shutdown(URLContext *h, int flags)
1665 {
1666  int ret = 0;
1667  char footer[] = "0\r\n\r\n";
1668  HTTPContext *s = h->priv_data;
1669 
1670  /* signal end of chunked encoding if used */
1671  if (((flags & AVIO_FLAG_WRITE) && s->chunked_post) ||
1672  ((flags & AVIO_FLAG_READ) && s->chunked_post && s->listen)) {
1673  ret = ffurl_write(s->hd, footer, sizeof(footer) - 1);
1674  ret = ret > 0 ? 0 : ret;
1675  /* flush the receive buffer when it is write only mode */
1676  if (!(flags & AVIO_FLAG_READ)) {
1677  char buf[1024];
1678  int read_ret;
1679  s->hd->flags |= AVIO_FLAG_NONBLOCK;
1680  read_ret = ffurl_read(s->hd, buf, sizeof(buf));
1681  s->hd->flags &= ~AVIO_FLAG_NONBLOCK;
1682  if (read_ret < 0 && read_ret != AVERROR(EAGAIN)) {
1683  av_log(h, AV_LOG_ERROR, "URL read error: %s\n", av_err2str(read_ret));
1684  ret = read_ret;
1685  }
1686  }
1687  s->end_chunked_post = 1;
1688  }
1689 
1690  return ret;
1691 }
1692 
1693 static int http_close(URLContext *h)
1694 {
1695  int ret = 0;
1696  HTTPContext *s = h->priv_data;
1697 
1698 #if CONFIG_ZLIB
1699  inflateEnd(&s->inflate_stream);
1700  av_freep(&s->inflate_buffer);
1701 #endif /* CONFIG_ZLIB */
1702 
1703  if (s->hd && !s->end_chunked_post)
1704  /* Close the write direction by sending the end of chunked encoding. */
1705  ret = http_shutdown(h, h->flags);
1706 
1707  if (s->hd)
1708  ffurl_closep(&s->hd);
1710  return ret;
1711 }
1712 
1713 static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
1714 {
1715  HTTPContext *s = h->priv_data;
1716  URLContext *old_hd = s->hd;
1717  uint64_t old_off = s->off;
1718  uint8_t old_buf[BUFFER_SIZE];
1719  int old_buf_size, ret;
1720  AVDictionary *options = NULL;
1721 
1722  if (whence == AVSEEK_SIZE)
1723  return s->filesize;
1724  else if (!force_reconnect &&
1725  ((whence == SEEK_CUR && off == 0) ||
1726  (whence == SEEK_SET && off == s->off)))
1727  return s->off;
1728  else if ((s->filesize == UINT64_MAX && whence == SEEK_END))
1729  return AVERROR(ENOSYS);
1730 
1731  if (whence == SEEK_CUR)
1732  off += s->off;
1733  else if (whence == SEEK_END)
1734  off += s->filesize;
1735  else if (whence != SEEK_SET)
1736  return AVERROR(EINVAL);
1737  if (off < 0)
1738  return AVERROR(EINVAL);
1739  s->off = off;
1740 
1741  if (s->off && h->is_streamed)
1742  return AVERROR(ENOSYS);
1743 
1744  /* do not try to make a new connection if seeking past the end of the file */
1745  if (s->end_off || s->filesize != UINT64_MAX) {
1746  uint64_t end_pos = s->end_off ? s->end_off : s->filesize;
1747  if (s->off >= end_pos)
1748  return s->off;
1749  }
1750 
1751  /* we save the old context in case the seek fails */
1752  old_buf_size = s->buf_end - s->buf_ptr;
1753  memcpy(old_buf, s->buf_ptr, old_buf_size);
1754  s->hd = NULL;
1755 
1756  /* if it fails, continue on old connection */
1757  if ((ret = http_open_cnx(h, &options)) < 0) {
1758  av_dict_free(&options);
1759  memcpy(s->buffer, old_buf, old_buf_size);
1760  s->buf_ptr = s->buffer;
1761  s->buf_end = s->buffer + old_buf_size;
1762  s->hd = old_hd;
1763  s->off = old_off;
1764  return ret;
1765  }
1766  av_dict_free(&options);
1767  ffurl_close(old_hd);
1768  return off;
1769 }
1770 
1771 static int64_t http_seek(URLContext *h, int64_t off, int whence)
1772 {
1773  return http_seek_internal(h, off, whence, 0);
1774 }
1775 
1777 {
1778  HTTPContext *s = h->priv_data;
1779  return ffurl_get_file_handle(s->hd);
1780 }
1781 
1783 {
1784  HTTPContext *s = h->priv_data;
1785  return ffurl_get_short_seek(s->hd);
1786 }
1787 
1788 #define HTTP_CLASS(flavor) \
1789 static const AVClass flavor ## _context_class = { \
1790  .class_name = # flavor, \
1791  .item_name = av_default_item_name, \
1792  .option = options, \
1793  .version = LIBAVUTIL_VERSION_INT, \
1794 }
1795 
1796 #if CONFIG_HTTP_PROTOCOL
1797 HTTP_CLASS(http);
1798 
1799 const URLProtocol ff_http_protocol = {
1800  .name = "http",
1801  .url_open2 = http_open,
1802  .url_accept = http_accept,
1803  .url_handshake = http_handshake,
1804  .url_read = http_read,
1805  .url_write = http_write,
1806  .url_seek = http_seek,
1807  .url_close = http_close,
1808  .url_get_file_handle = http_get_file_handle,
1809  .url_get_short_seek = http_get_short_seek,
1810  .url_shutdown = http_shutdown,
1811  .priv_data_size = sizeof(HTTPContext),
1812  .priv_data_class = &http_context_class,
1814  .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy,data"
1815 };
1816 #endif /* CONFIG_HTTP_PROTOCOL */
1817 
1818 #if CONFIG_HTTPS_PROTOCOL
1819 HTTP_CLASS(https);
1820 
1822  .name = "https",
1823  .url_open2 = http_open,
1824  .url_read = http_read,
1825  .url_write = http_write,
1826  .url_seek = http_seek,
1827  .url_close = http_close,
1828  .url_get_file_handle = http_get_file_handle,
1829  .url_get_short_seek = http_get_short_seek,
1830  .url_shutdown = http_shutdown,
1831  .priv_data_size = sizeof(HTTPContext),
1832  .priv_data_class = &https_context_class,
1834  .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy"
1835 };
1836 #endif /* CONFIG_HTTPS_PROTOCOL */
1837 
1838 #if CONFIG_HTTPPROXY_PROTOCOL
1839 static int http_proxy_close(URLContext *h)
1840 {
1841  HTTPContext *s = h->priv_data;
1842  if (s->hd)
1843  ffurl_closep(&s->hd);
1844  return 0;
1845 }
1846 
1847 static int http_proxy_open(URLContext *h, const char *uri, int flags)
1848 {
1849  HTTPContext *s = h->priv_data;
1850  char hostname[1024], hoststr[1024];
1851  char auth[1024], pathbuf[1024], *path;
1852  char lower_url[100];
1853  int port, ret = 0, attempts = 0;
1854  HTTPAuthType cur_auth_type;
1855  char *authstr;
1856  int new_loc;
1857 
1858  if( s->seekable == 1 )
1859  h->is_streamed = 0;
1860  else
1861  h->is_streamed = 1;
1862 
1863  av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
1864  pathbuf, sizeof(pathbuf), uri);
1865  ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
1866  path = pathbuf;
1867  if (*path == '/')
1868  path++;
1869 
1870  ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port,
1871  NULL);
1872 redo:
1873  ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
1874  &h->interrupt_callback, NULL,
1876  if (ret < 0)
1877  return ret;
1878 
1879  authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth,
1880  path, "CONNECT");
1881  snprintf(s->buffer, sizeof(s->buffer),
1882  "CONNECT %s HTTP/1.1\r\n"
1883  "Host: %s\r\n"
1884  "Connection: close\r\n"
1885  "%s%s"
1886  "\r\n",
1887  path,
1888  hoststr,
1889  authstr ? "Proxy-" : "", authstr ? authstr : "");
1890  av_freep(&authstr);
1891 
1892  if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
1893  goto fail;
1894 
1895  s->buf_ptr = s->buffer;
1896  s->buf_end = s->buffer;
1897  s->line_count = 0;
1898  s->filesize = UINT64_MAX;
1899  cur_auth_type = s->proxy_auth_state.auth_type;
1900 
1901  /* Note: This uses buffering, potentially reading more than the
1902  * HTTP header. If tunneling a protocol where the server starts
1903  * the conversation, we might buffer part of that here, too.
1904  * Reading that requires using the proper ffurl_read() function
1905  * on this URLContext, not using the fd directly (as the tls
1906  * protocol does). This shouldn't be an issue for tls though,
1907  * since the client starts the conversation there, so there
1908  * is no extra data that we might buffer up here.
1909  */
1910  ret = http_read_header(h, &new_loc);
1911  if (ret < 0)
1912  goto fail;
1913 
1914  attempts++;
1915  if (s->http_code == 407 &&
1916  (cur_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
1917  s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2) {
1918  ffurl_closep(&s->hd);
1919  goto redo;
1920  }
1921 
1922  if (s->http_code < 400)
1923  return 0;
1924  ret = ff_http_averror(s->http_code, AVERROR(EIO));
1925 
1926 fail:
1927  http_proxy_close(h);
1928  return ret;
1929 }
1930 
1931 static int http_proxy_write(URLContext *h, const uint8_t *buf, int size)
1932 {
1933  HTTPContext *s = h->priv_data;
1934  return ffurl_write(s->hd, buf, size);
1935 }
1936 
1938  .name = "httpproxy",
1939  .url_open = http_proxy_open,
1940  .url_read = http_buf_read,
1941  .url_write = http_proxy_write,
1942  .url_close = http_proxy_close,
1943  .url_get_file_handle = http_get_file_handle,
1944  .priv_data_size = sizeof(HTTPContext),
1945  .flags = URL_PROTOCOL_FLAG_NETWORK,
1946 };
1947 #endif /* CONFIG_HTTPPROXY_PROTOCOL */
static int http_get_line(HTTPContext *s, char *line, int line_size)
Definition: http.c:637
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:568
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.
Definition: utils.c:4797
static void update_metadata(URLContext *h, char *data)
Definition: http.c:1555
static void parse_content_range(URLContext *h, const char *p)
Definition: http.c:690
AVDictionary * metadata
Definition: http.c:110
#define NULL
Definition: coverity.c:32
static int http_connect(URLContext *h, const char *path, const char *local_path, const char *hoststr, const char *auth, const char *proxyauth, int *new_location)
Definition: http.c:1213
void 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.
Definition: url.c:80
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
version
Definition: libkvazaar.c:292
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. ...
Definition: avio.c:307
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
uint8_t * post_data
Definition: http.c:96
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
#define AV_OPT_FLAG_EXPORT
The option is intended for exporting values to the caller.
Definition: opt.h:284
#define AV_OPT_FLAG_DEPRECATED
set if option is deprecated, users should refer to AVOption.help text for more information ...
Definition: opt.h:293
HTTPAuthType
Authentication types, ordered from weakest to strongest.
Definition: httpauth.h:28
#define BUFFER_SIZE
Definition: http.c:49
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static int http_close(URLContext *h)
Definition: http.c:1693
else temp
Definition: vf_mcdeint.c:256
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:420
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle...
Definition: avstring.c:56
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:45
AVIOInterruptCB interrupt_callback
Definition: url.h:47
HTTPAuthState proxy_auth_state
Definition: http.c:74
Definition: http.c:59
#define AVIO_FLAG_READ
read-only
Definition: avio.h:674
char * icy_metadata_headers
Definition: http.c:108
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
const URLProtocol ff_http_protocol
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:675
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:223
uint64_t icy_metaint
Definition: http.c:107
#define AVERROR_HTTP_NOT_FOUND
Definition: error.h:79
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
int flags
Definition: url.h:43
static int http_listen(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: http.c:524
char * content_type
Definition: http.c:84
const char * key
uint64_t filesize
Definition: http.c:71
static void error(const char *err)
static int http_getc(HTTPContext *s)
Definition: http.c:620
HTTP Authentication state structure.
Definition: httpauth.h:55
int auth_type
The currently chosen auth type.
Definition: httpauth.h:59
#define WHITESPACES
Definition: http.c:54
int is_connected_server
Definition: http.c:129
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that&#39;s been allocated with av_malloc() or another memory allocation function...
Definition: dict.h:73
#define HTTP_SINGLE
Definition: http.c:51
#define MAX_URL_SIZE
Definition: internal.h:30
static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
Definition: http.c:821
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int end_chunked_post
Definition: http.c:91
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.
Definition: avstring.c:45
static int http_get_file_handle(URLContext *h)
Definition: http.c:1776
static int http_buf_read(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1379
uint8_t
#define av_malloc(s)
int post_datalen
Definition: http.c:97
AVOptions.
int ff_http_averror(int status_code, int default_averror)
Definition: http.c:391
miscellaneous OS support macros and functions.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
static int http_read_header(URLContext *h, int *new_location)
Definition: http.c:1150
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
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
Definition: undefined.txt:32
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
int is_akamai
Definition: http.c:98
static int http_open_cnx(URLContext *h, AVDictionary **options)
Definition: http.c:262
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition: parseutils.c:489
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition: bprint.c:158
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
Init a print buffer using a pre-existing buffer.
Definition: bprint.c:85
#define NEEDS_ESCAPE(ch)
uint32_t tag
Definition: movenc.c:1534
#define DEFAULT_USER_AGENT
Definition: http.c:135
#define AVERROR_EOF
End of file.
Definition: error.h:55
void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
Initialize the authentication state based on another HTTP URLContext.
Definition: http.c:181
uint64_t icy_data_read
Definition: http.c:105
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
HTTP 1.0 Basic auth from RFC 1945 (also in RFC 2617)
Definition: httpauth.h:30
ptrdiff_t size
Definition: opengl_enc.c:100
static const uint8_t header[24]
Definition: sdr2.c:67
static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
Definition: http.c:191
int ff_http_do_new_request2(URLContext *h, const char *uri, AVDictionary **opts)
Send a new HTTP request, reusing the old connection.
Definition: http.c:337
int line_count
Definition: http.c:66
#define av_log(a,...)
unsigned char * buf_end
Definition: http.c:65
static void body(uint32_t ABCD[4], const uint8_t *src, int nblocks)
Definition: md5.c:101
#define U(x)
Definition: vp56_arith.h:37
#define src
Definition: vp8dsp.c:254
int ff_http_get_shutdown_status(URLContext *h)
Get the HTTP shutdown response status, be used after http_shutdown.
Definition: http.c:317
int is_multi_client
Definition: http.c:127
int chunked_post
Definition: http.c:89
static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
Definition: http.c:1713
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 you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the and we are assuming vf_foobar is as well We are also assuming vf_foobar is not an edge detector so you can update the boilerplate with your credits Doxy Next chunk is the Doxygen about the file See https
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...
Definition: avio.c:294
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int reconnect_delay_max
Definition: http.c:123
#define E
Definition: http.c:134
const char * protocol_whitelist
Definition: url.h:49
static int http_write(URLContext *h, const uint8_t *buf, int size)
Definition: http.c:1638
static const AVOption options[]
Definition: http.c:137
unsigned int pos
Definition: spdifenc.c:410
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
static int http_handshake(URLContext *c)
Definition: http.c:488
Definition: graph2dot.c:48
uint64_t off
Definition: http.c:71
simple assert() macros that are a bit more flexible than ISO C assert().
#define OFFSET(x)
Definition: http.c:132
#define fail()
Definition: checkasm.h:122
uint64_t chunksize
Definition: http.c:69
AVDictionary * chained_options
Definition: http.c:116
#define AVERROR_HTTP_SERVER_ERROR
Definition: error.h:81
char * referer
Definition: http.c:80
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.
Definition: http.c:1189
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
static int store_icy(URLContext *h, int size)
Definition: http.c:1583
AVDictionary * opts
Definition: movenc.c:50
char * headers
Definition: http.c:76
char * user_agent
Definition: http.c:79
#define AVERROR_HTTP_UNAUTHORIZED
Definition: error.h:77
char * icy_metadata_packet
Definition: http.c:109
int ffurl_get_short_seek(URLContext *h)
Return the current short seek threshold value for this URL.
Definition: avio.c:649
#define FFMIN(a, b)
Definition: common.h:96
static int http_get_short_seek(URLContext *h)
Definition: http.c:1782
const URLProtocol ff_httpproxy_protocol
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
int chunkend
Definition: http.c:70
int send_expect_100
Definition: http.c:118
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb)
Waits for up to &#39;timeout&#39; microseconds.
Definition: network.c:98
int willclose
Definition: http.c:87
int is_mediagateway
Definition: http.c:99
int ffurl_handshake(URLContext *c)
Perform one step of the protocol handshake to accept a new client.
Definition: avio.c:235
int reconnect
Definition: http.c:120
int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
Definition: network.c:551
#define s(width, name)
Definition: cbs_vp9.c:257
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:185
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:625
int ffurl_accept(URLContext *s, URLContext **c)
Accept an URLContext c on an URLContext s.
Definition: avio.c:227
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
AVDictionary * cookie_dict
Definition: http.c:102
int stale
Auth ok, but needs to be resent with a new nonce.
Definition: httpauth.h:71
offset must point to a pointer immediately followed by an int for the length
Definition: opt.h:229
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:443
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition: url.c:36
int reconnect_streamed
Definition: http.c:122
static int http_read(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1621
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
const char * protocol_blacklist
Definition: url.h:50
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
char * http_proxy
Definition: http.c:75
int av_opt_set_dict(void *obj, AVDictionary **options)
Set all the options from a given dictionary on an object.
Definition: opt.c:1652
HandshakeState handshake_step
Definition: http.c:128
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:693
int seekable
Control seekability, 0 = disable, 1 = enable, -1 = probe.
Definition: http.c:88
#define MAX_EXPIRY
Definition: http.c:53
Definition: url.h:38
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:676
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
unsigned char buffer[BUFFER_SIZE]
Definition: http.c:65
char * http_version
Definition: http.c:78
Describe the class of an AVClass context structure.
Definition: log.h:67
#define SPACE_CHARS
Definition: internal.h:352
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
Definition: vf_neighbor.c:198
void * priv_data
Definition: url.h:41
#define AVERROR_HTTP_OTHER_4XX
Definition: error.h:80
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
#define snprintf
Definition: snprintf.h:34
static av_const int av_isxdigit(int c)
Locale-independent conversion of ASCII isxdigit.
Definition: avstring.h:251
int icy
Definition: http.c:103
misc parsing utilities
char * ff_http_auth_create_response(HTTPAuthState *state, const char *auth, const char *path, const char *method)
Definition: httpauth.c:245
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0f/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(UINT64_C(1)<< 63)))#define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};static void cpy1(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, len);}static void cpy2(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 2 *len);}static void cpy4(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 4 *len);}static void cpy8(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;}void swri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len){int ch;int off=0;const int os=(out->planar?1:out->ch_count)*out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){int planes=in->planar?in->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){int planes=out->planar?out->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){int planes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
const char * name
Definition: url.h:55
URLContext * hd
Definition: http.c:64
static int has_header(const char *str, const char *header)
Definition: http.c:1142
char * mime_type
Definition: http.c:77
#define SIZE_SPECIFIER
Definition: internal.h:262
#define flags(name, subs,...)
Definition: cbs_av1.c:564
#define AVERROR_HTTP_FORBIDDEN
Definition: error.h:78
int ffurl_close(URLContext *h)
Definition: avio.c:466
static int process_line(URLContext *h, char *line, int line_count, int *new_location)
Definition: http.c:906
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:333
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()...
Definition: avstring.c:184
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
Main libavformat public API header.
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
Definition: swscale.txt:33
char * cookies
holds newline ( ) delimited Set-Cookie header field values (without the "Set-Cookie: " field name) ...
Definition: http.c:100
#define MAX_REDIRECTS
Definition: http.c:50
static int parse_content_encoding(URLContext *h, const char *p)
Definition: http.c:705
const struct URLProtocol * prot
Definition: url.h:40
int reconnect_at_eof
Definition: http.c:121
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...
Definition: dict.c:147
HandshakeState
Definition: http.c:55
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...
Definition: http.c:1060
int http_code
Definition: http.c:67
char * filename
specified URL
Definition: url.h:42
int listen
Definition: http.c:124
static int http_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: http.c:555
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:531
char * key
Definition: dict.h:86
void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, const char *value)
Definition: httpauth.c:90
int multiple_requests
Definition: http.c:95
HTTPAuthState auth_state
Definition: http.c:73
#define av_free(p)
static int cookie_string(AVDictionary *dict, char **cookies)
Definition: http.c:883
char * value
Definition: dict.h:87
const URLProtocol ff_https_protocol
int len
static int parse_location(HTTPContext *s, const char *p)
Definition: http.c:676
char * resource
Definition: http.c:125
char * location
Definition: http.c:72
static int http_shutdown(URLContext *h, int flags)
Definition: http.c:1664
static int http_write_reply(URLContext *h, int status_code)
Definition: http.c:408
#define AV_OPT_FLAG_READONLY
The option may not be set through the AVOptions API, only read.
Definition: opt.h:289
int end_header
Definition: http.c:93
unsigned char * buf_ptr
Definition: http.c:65
#define D
Definition: http.c:133
#define AVERROR_HTTP_BAD_REQUEST
Definition: error.h:76
char * method
Definition: http.c:119
static int parse_icy(HTTPContext *s, const char *tag, const char *p)
Definition: http.c:739
uint64_t end_off
Definition: http.c:71
static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
Definition: http.c:761
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1487
#define av_freep(p)
static int http_read_stream_all(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1543
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key, ignoring the suffix of the found key string.
Definition: dict.h:70
unbuffered private I/O API
static void handle_http_errors(URLContext *h, int error)
Definition: http.c:482
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 parse_set_cookie(const char *set_cookie, AVDictionary **dict)
Definition: http.c:786
static int64_t http_seek(URLContext *h, int64_t off, int whence)
Definition: http.c:1771
static double val(void *priv, double ch)
Definition: aeval.c:76
int reply_code
Definition: http.c:126
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:462
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
Definition: avio.c:406
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263
static int http_accept(URLContext *s, URLContext **c)
Definition: http.c:596
GLuint buffer
Definition: opengl_enc.c:101
#define HTTP_CLASS(flavor)
Definition: http.c:1788
No authentication specified.
Definition: httpauth.h:29
static int check_http_code(URLContext *h, int http_code, const char *end)
Definition: http.c:661
const char * name
Definition: opengl_enc.c:102
static uint8_t tmp[11]
Definition: aes_ctr.c:26