mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
http: Add a new protocol for opening connections via http proxies
This opens a plain TCP connection through the proxy via the CONNECT HTTP method. Normally, this is allowed for connections on port 443, but can in general be used to allow connections to any port (depending on proxy configuration), and could thus be used to tunnel any TCP connection via a HTTP proxy. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
bf7723a640
commit
9f1dae944e
@ -242,6 +242,7 @@ void av_register_all(void)
|
||||
REGISTER_PROTOCOL (FILE, file);
|
||||
REGISTER_PROTOCOL (GOPHER, gopher);
|
||||
REGISTER_PROTOCOL (HTTP, http);
|
||||
REGISTER_PROTOCOL (HTTPPROXY, httpproxy);
|
||||
REGISTER_PROTOCOL (HTTPS, https);
|
||||
REGISTER_PROTOCOL (MMSH, mmsh);
|
||||
REGISTER_PROTOCOL (MMST, mmst);
|
||||
|
@ -578,3 +578,118 @@ URLProtocol ff_https_protocol = {
|
||||
.priv_data_class = &https_context_class,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_HTTPPROXY_PROTOCOL
|
||||
static int http_proxy_close(URLContext *h)
|
||||
{
|
||||
HTTPContext *s = h->priv_data;
|
||||
if (s->hd)
|
||||
ffurl_close(s->hd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int http_proxy_open(URLContext *h, const char *uri, int flags)
|
||||
{
|
||||
HTTPContext *s = h->priv_data;
|
||||
char hostname[1024], hoststr[1024];
|
||||
char auth[1024], pathbuf[1024], *path;
|
||||
char line[1024], lower_url[100];
|
||||
int port, ret = 0;
|
||||
HTTPAuthType cur_auth_type;
|
||||
char *authstr;
|
||||
|
||||
h->is_streamed = 1;
|
||||
|
||||
av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
|
||||
pathbuf, sizeof(pathbuf), uri);
|
||||
ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
|
||||
path = pathbuf;
|
||||
if (*path == '/')
|
||||
path++;
|
||||
|
||||
ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port,
|
||||
NULL);
|
||||
redo:
|
||||
ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
|
||||
&h->interrupt_callback, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth,
|
||||
path, "CONNECT");
|
||||
snprintf(s->buffer, sizeof(s->buffer),
|
||||
"CONNECT %s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"%s%s"
|
||||
"\r\n",
|
||||
path,
|
||||
hoststr,
|
||||
authstr ? "Proxy-" : "", authstr ? authstr : "");
|
||||
av_freep(&authstr);
|
||||
|
||||
if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
|
||||
goto fail;
|
||||
|
||||
s->buf_ptr = s->buffer;
|
||||
s->buf_end = s->buffer;
|
||||
s->line_count = 0;
|
||||
s->filesize = -1;
|
||||
cur_auth_type = s->proxy_auth_state.auth_type;
|
||||
|
||||
for (;;) {
|
||||
int new_loc;
|
||||
// Note: This uses buffering, potentially reading more than the
|
||||
// HTTP header. If tunneling a protocol where the server starts
|
||||
// the conversation, we might buffer part of that here, too.
|
||||
// Reading that requires using the proper ffurl_read() function
|
||||
// on this URLContext, not using the fd directly (as the tls
|
||||
// protocol does). This shouldn't be an issue for tls though,
|
||||
// since the client starts the conversation there, so there
|
||||
// is no extra data that we might buffer up here.
|
||||
if (http_get_line(s, line, sizeof(line)) < 0) {
|
||||
ret = AVERROR(EIO);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
av_dlog(h, "header='%s'\n", line);
|
||||
|
||||
ret = process_line(h, line, s->line_count, &new_loc);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
if (ret == 0)
|
||||
break;
|
||||
s->line_count++;
|
||||
}
|
||||
if (s->http_code == 407 && cur_auth_type == HTTP_AUTH_NONE &&
|
||||
s->proxy_auth_state.auth_type != HTTP_AUTH_NONE) {
|
||||
ffurl_close(s->hd);
|
||||
s->hd = NULL;
|
||||
goto redo;
|
||||
}
|
||||
|
||||
if (s->http_code < 400)
|
||||
return 0;
|
||||
ret = AVERROR(EIO);
|
||||
|
||||
fail:
|
||||
http_proxy_close(h);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int http_proxy_write(URLContext *h, const uint8_t *buf, int size)
|
||||
{
|
||||
HTTPContext *s = h->priv_data;
|
||||
return ffurl_write(s->hd, buf, size);
|
||||
}
|
||||
|
||||
URLProtocol ff_httpproxy_protocol = {
|
||||
.name = "httpproxy",
|
||||
.url_open = http_proxy_open,
|
||||
.url_read = http_buf_read,
|
||||
.url_write = http_proxy_write,
|
||||
.url_close = http_proxy_close,
|
||||
.url_get_file_handle = http_get_file_handle,
|
||||
.priv_data_size = sizeof(HTTPContext),
|
||||
};
|
||||
#endif
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "libavutil/avutil.h"
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 53
|
||||
#define LIBAVFORMAT_VERSION_MINOR 14
|
||||
#define LIBAVFORMAT_VERSION_MINOR 15
|
||||
#define LIBAVFORMAT_VERSION_MICRO 0
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user