From dd96c11d5e0166ce6c597d178ee4827193cff16d Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 24 Jan 2013 16:05:52 +0100 Subject: stream: implement some HTTP specific options for stream_lavf The "http:" protocol has been switched to use ffmpeg's HTTP implementation some time ago. One problem with this was that many HTTP specific options stopped working, because they were obviously implemented for the internal HTTP implementation only. Add the missing things. Note that many options will work for ffmpeg only, as Libav's HTTP implementation is missing these. They will silently be ignored on Libav. Some options we can't fix: --ipv4-only-proxy, --prefer-ipv4, --prefer-ipv6 As far as I can see, not even libavformat internals distinguish between ipv4 and ipv6. --user, --passwd ffmpeg probably supports specifying these in the URL directly. --- stream/asf_streaming.c | 2 -- stream/cookies.c | 21 +++++++++++++++++++++ stream/cookies.h | 1 + stream/http.c | 2 -- stream/network.h | 12 ++++++++++++ stream/stream_lavf.c | 28 +++++++++++++++++++++++++++- stream/stream_udp.c | 2 -- 7 files changed, 61 insertions(+), 7 deletions(-) (limited to 'stream') diff --git a/stream/asf_streaming.c b/stream/asf_streaming.c index 3982c19340..862d7c3177 100644 --- a/stream/asf_streaming.c +++ b/stream/asf_streaming.c @@ -45,8 +45,6 @@ #include "demux/asfguid.h" -extern int network_bandwidth; - static int asf_http_streaming_start(stream_t *stream, int *demuxer_type); static int asf_read_wrapper(int fd, void *buffer, int len, streaming_ctrl_t *stream_ctrl) { diff --git a/stream/cookies.c b/stream/cookies.c index d8f8b051f9..5d772b8a6a 100644 --- a/stream/cookies.c +++ b/stream/cookies.c @@ -261,3 +261,24 @@ cookies_set(HTTP_header_t * http_hdr, const char *domain, const char *url) http_set_field(http_hdr, buf); free(buf); } + +// Return a cookies string as expected by lavf (libavformat/http.c). The format +// is like a Set-Cookie header (http://curl.haxx.se/rfc/cookie_spec.html), +// separated by newlines. +char *cookies_lavf(void) +{ + if (!cookie_list) + cookie_list = load_cookies(); + + struct cookie_list_type *list = cookie_list; + char *res = talloc_strdup(NULL, ""); + + while (list) { + res = talloc_asprintf_append_buffer(res, + "%s=%s; path=%s; domain=%s; %s\n", list->name, list->value, + list->path, list->domain, list->secure ? "secure" : ""); + list = list->next; + } + + return res; +} diff --git a/stream/cookies.h b/stream/cookies.h index 88ff96d66a..a24560631b 100644 --- a/stream/cookies.h +++ b/stream/cookies.h @@ -28,5 +28,6 @@ void cookies_set(HTTP_header_t * http_hdr, const char *hostname, const char *url); +char *cookies_lavf(void); #endif /* MPLAYER_COOKIES_H */ diff --git a/stream/http.c b/stream/http.c index 11fe7ed6de..bb96739c45 100644 --- a/stream/http.c +++ b/stream/http.c @@ -45,8 +45,6 @@ #include -extern int network_bandwidth; - typedef struct { unsigned metaint; unsigned metapos; diff --git a/stream/network.h b/stream/network.h index 6e21453b16..a2d1d3d173 100644 --- a/stream/network.h +++ b/stream/network.h @@ -63,6 +63,18 @@ extern const mime_struct_t mime_type_table[]; extern char **network_http_header_fields; +extern char *network_username; +extern char *network_password; +extern int network_bandwidth; +extern char *network_useragent; +extern char *network_referrer; +extern int network_cookies_enabled; +extern char *cookies_file; + +extern int network_prefer_ipv4; +extern int network_ipv4_only_proxy; +extern int reuse_socket; + streaming_ctrl_t *streaming_ctrl_new(void); int streaming_bufferize( streaming_ctrl_t *streaming_ctrl, char *buffer, int size); diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index 0b540e26bc..d652bf27a8 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -27,6 +27,9 @@ #include "core/m_struct.h" #include "demux/demux.h" +#include "network.h" +#include "cookies.h" + static int fill_buffer(stream_t *s, char *buffer, int max_len) { AVIOContext *avio = s->priv; @@ -97,6 +100,7 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format) int flags = 0; AVIOContext *avio = NULL; int res = STREAM_ERROR; + AVDictionary *dict = NULL; void *temp = talloc_new(NULL); if (mode == STREAM_READ) @@ -137,7 +141,28 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format) filename = talloc_asprintf(temp, "mmsh://%.*s", BSTR_P(b_filename)); } - int err = avio_open(&avio, filename, flags); +#ifdef CONFIG_NETWORKING + // HTTP specific options (other protocols ignore them) + if (network_useragent) + av_dict_set(&dict, "user-agent", network_useragent, 0); + if (network_cookies_enabled) + av_dict_set(&dict, "cookies", talloc_steal(temp, cookies_lavf()), 0); + char *cust_headers = talloc_strdup(temp, ""); + if (network_referrer) { + cust_headers = talloc_asprintf_append(cust_headers, "Referer: %s\r\n", + network_referrer); + } + if (network_http_header_fields) { + for (int n = 0; network_http_header_fields[n]; n++) { + cust_headers = talloc_asprintf_append(cust_headers, "%s\r\n", + network_http_header_fields[n]); + } + } + if (strlen(cust_headers)) + av_dict_set(&dict, "headers", cust_headers, 0); +#endif + + int err = avio_open2(&avio, filename, flags, NULL, &dict); if (err < 0) { if (err == AVERROR_PROTOCOL_NOT_FOUND) mp_msg(MSGT_OPEN, MSGL_ERR, "[ffmpeg] Protocol not found. Make sure" @@ -178,6 +203,7 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format) res = STREAM_OK; out: + av_dict_free(&dict); talloc_free(temp); return res; } diff --git a/stream/stream_udp.c b/stream/stream_udp.c index fc7da19aa0..d447a9238c 100644 --- a/stream/stream_udp.c +++ b/stream/stream_udp.c @@ -60,8 +60,6 @@ udp_streaming_start (stream_t *stream) static int udp_stream_open (stream_t *stream, int mode, void *opts, int *file_format) { - extern int network_bandwidth; - mp_msg (MSGT_OPEN, MSGL_INFO, "STREAM_UDP, URL: %s\n", stream->url); stream->streaming_ctrl = streaming_ctrl_new (); if (!stream->streaming_ctrl) -- cgit v1.2.3