mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-27 09:52:17 +00:00
tls: Use custom IO to read from the URLContext
This avoids hijacking the fd, by reading using the normal URLContext functions instead. This allowing reading data that has been buffered in the underlying URLContext. This avoids using the libraries own send functions that can cause SIGPIPE. The fd is still used for polling the lowlevel socket, for waiting for retries. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
3efe0393e4
commit
d15eec4d6b
@ -36,6 +36,33 @@
|
||||
if (c->cred) \
|
||||
gnutls_certificate_free_credentials(c->cred); \
|
||||
} while (0)
|
||||
|
||||
static ssize_t gnutls_url_pull(gnutls_transport_ptr_t transport,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
URLContext *h = (URLContext*) transport;
|
||||
int ret = ffurl_read(h, buf, len);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
if (ret == AVERROR(EAGAIN))
|
||||
errno = EAGAIN;
|
||||
else
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
static ssize_t gnutls_url_push(gnutls_transport_ptr_t transport,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
URLContext *h = (URLContext*) transport;
|
||||
int ret = ffurl_write(h, buf, len);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
if (ret == AVERROR(EAGAIN))
|
||||
errno = EAGAIN;
|
||||
else
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
#elif CONFIG_OPENSSL
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/ssl.h>
|
||||
@ -49,6 +76,70 @@
|
||||
if (c->ctx) \
|
||||
SSL_CTX_free(c->ctx); \
|
||||
} while (0)
|
||||
|
||||
static int url_bio_create(BIO *b)
|
||||
{
|
||||
b->init = 1;
|
||||
b->ptr = NULL;
|
||||
b->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int url_bio_destroy(BIO *b)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int url_bio_bread(BIO *b, char *buf, int len)
|
||||
{
|
||||
URLContext *h = b->ptr;
|
||||
int ret = ffurl_read(h, buf, len);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret == AVERROR(EAGAIN))
|
||||
BIO_set_retry_read(b);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int url_bio_bwrite(BIO *b, const char *buf, int len)
|
||||
{
|
||||
URLContext *h = b->ptr;
|
||||
int ret = ffurl_write(h, buf, len);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret == AVERROR(EAGAIN))
|
||||
BIO_set_retry_write(b);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long url_bio_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
if (cmd == BIO_CTRL_FLUSH) {
|
||||
BIO_clear_retry_flags(b);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int url_bio_bputs(BIO *b, const char *str)
|
||||
{
|
||||
return url_bio_bwrite(b, str, strlen(str));
|
||||
}
|
||||
|
||||
static BIO_METHOD url_bio_method = {
|
||||
.type = BIO_TYPE_SOURCE_SINK,
|
||||
.name = "urlprotocol bio",
|
||||
.bwrite = url_bio_bwrite,
|
||||
.bread = url_bio_bread,
|
||||
.bputs = url_bio_bputs,
|
||||
.bgets = NULL,
|
||||
.ctrl = url_bio_ctrl,
|
||||
.create = url_bio_create,
|
||||
.destroy = url_bio_destroy,
|
||||
};
|
||||
|
||||
#endif
|
||||
#include "network.h"
|
||||
#include "os_support.h"
|
||||
@ -148,6 +239,9 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op
|
||||
struct addrinfo hints = { 0 }, *ai = NULL;
|
||||
const char *proxy_path;
|
||||
int use_proxy;
|
||||
#if CONFIG_OPENSSL
|
||||
BIO *bio;
|
||||
#endif
|
||||
|
||||
ff_tls_init();
|
||||
|
||||
@ -220,8 +314,10 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op
|
||||
}
|
||||
}
|
||||
gnutls_credentials_set(c->session, GNUTLS_CRD_CERTIFICATE, c->cred);
|
||||
gnutls_transport_set_ptr(c->session, (gnutls_transport_ptr_t)
|
||||
(intptr_t) c->fd);
|
||||
c->tcp->flags |= AVIO_FLAG_NONBLOCK;
|
||||
gnutls_transport_set_pull_function(c->session, gnutls_url_pull);
|
||||
gnutls_transport_set_push_function(c->session, gnutls_url_push);
|
||||
gnutls_transport_set_ptr(c->session, c->tcp);
|
||||
gnutls_priority_set_direct(c->session, "NORMAL", NULL);
|
||||
while (1) {
|
||||
ret = gnutls_handshake(c->session);
|
||||
@ -293,7 +389,10 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op
|
||||
ret = AVERROR(EIO);
|
||||
goto fail;
|
||||
}
|
||||
SSL_set_fd(c->ssl, c->fd);
|
||||
bio = BIO_new(&url_bio_method);
|
||||
c->tcp->flags |= AVIO_FLAG_NONBLOCK;
|
||||
bio->ptr = c->tcp;
|
||||
SSL_set_bio(c->ssl, bio, bio);
|
||||
if (!c->listen && !numerichost)
|
||||
SSL_set_tlsext_host_name(c->ssl, host);
|
||||
while (1) {
|
||||
|
Loading…
Reference in New Issue
Block a user