TLSContext *c = h->priv_data;
switch (ret) {
case errSSLWouldBlock:
- break;
+ return AVERROR(EAGAIN);
case errSSLXCertChainInvalid:
av_log(h, AV_LOG_ERROR, "Invalid certificate chain\n");
return AVERROR(EIO);
static int import_pem(URLContext *h, char *path, CFArrayRef *array)
{
+#if !HAVE_SECITEMIMPORT
+ return AVERROR_PATCHWELCOME;
+#else
AVIOContext *s = NULL;
CFDataRef data = NULL;
int64_t ret = 0;
if (s)
avio_close(s);
return ret;
+#endif
}
static int load_ca(URLContext *h)
{
URLContext *h = (URLContext*)connection;
TLSContext *c = h->priv_data;
- int read = ffurl_read_complete(c->tls_shared.tcp, data, *dataLength);
+ size_t requested = *dataLength;
+ int read = ffurl_read(c->tls_shared.tcp, data, requested);
if (read <= 0) {
*dataLength = 0;
switch(AVUNERROR(read)) {
}
} else {
*dataLength = read;
- return noErr;
+ if (read < requested)
+ return errSSLWouldBlock;
+ else
+ return noErr;
}
}
if (peerTrust)
CFRelease(peerTrust);
}
- if (status == noErr)
+ if (status == noErr) {
break;
-
- av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session: %i\n", (int)status);
- ret = AVERROR(EIO);
- goto fail;
+ } else if (status != errSSLWouldBlock) {
+ av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session: %i\n", (int)status);
+ ret = AVERROR(EIO);
+ goto fail;
+ }
}
return 0;
case errSSLClosedGraceful:
case errSSLClosedNoNotify:
return 0;
+ case errSSLWouldBlock:
+ if (processed > 0)
+ return processed;
default:
return (int)status;
}
static int tls_read(URLContext *h, uint8_t *buf, int size)
{
TLSContext *c = h->priv_data;
- size_t processed = 0;
- int ret = SSLRead(c->ssl_context, buf, size, &processed);
+ size_t available = 0, processed = 0;
+ int ret;
+ SSLGetBufferedReadSize(c->ssl_context, &available);
+ if (available)
+ size = FFMIN(available, size);
+ ret = SSLRead(c->ssl_context, buf, size, &processed);
ret = map_ssl_error(ret, processed);
if (ret > 0)
return ret;