diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2015-05-22 02:28:22 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-05-22 02:28:27 +0200 |
commit | 162644c8331df0ba4e45bf77262f09d2ed98a2e6 (patch) | |
tree | 382db9f9a2d1e5c23ada70bdcebe24407ff029f5 | |
parent | 6b56fcbd10a56d2a7a116c0de4ee032b895456c2 (diff) | |
parent | d15eec4d6bdfa3bd4c4b5b7dd2dbd699ba253d02 (diff) | |
download | ffmpeg-162644c8331df0ba4e45bf77262f09d2ed98a2e6.tar.gz |
Merge commit 'd15eec4d6bdfa3bd4c4b5b7dd2dbd699ba253d02'
* commit 'd15eec4d6bdfa3bd4c4b5b7dd2dbd699ba253d02':
tls: Use custom IO to read from the URLContext
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/tls.c | 105 |
1 files changed, 102 insertions, 3 deletions
diff --git a/libavformat/tls.c b/libavformat/tls.c index 2a415c9287..77b932c397 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -39,6 +39,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> @@ -52,6 +79,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 #if HAVE_POLL_H #include <poll.h> @@ -174,6 +265,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 if ((ret = ff_tls_init()) < 0) return ret; @@ -252,8 +346,10 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op } else if (c->cert_file || c->key_file) av_log(h, AV_LOG_ERROR, "cert and key required\n"); 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); @@ -328,7 +424,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) { |