Commit 2f5e4399 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

tls: use I/O vector for receiving

parent 3f72fbdd
......@@ -42,7 +42,7 @@ struct vlc_tls
void *sys;
int fd;
ssize_t (*recv)(struct vlc_tls *, void *, size_t);
ssize_t (*readv)(struct vlc_tls *, struct iovec *, unsigned);
ssize_t (*writev)(struct vlc_tls *, const struct iovec *, unsigned);
int (*shutdown)(struct vlc_tls *, bool duplex);
void (*close)(vlc_tls_t *);
......
......@@ -39,19 +39,30 @@ static const char *stream_content;
static size_t stream_length;
static bool stream_bad;
static ssize_t recv_callback(struct vlc_tls *tls, void *buf, size_t len)
static ssize_t recv_callback(struct vlc_tls *tls, struct iovec *iov,
unsigned count)
{
size_t copy = len;
size_t rcvd = 0;
while (count > 0)
{
size_t copy = iov->iov_len;
if (copy > stream_length)
copy = stream_length;
if (copy > 0)
{
memcpy(buf, stream_content, copy);
memcpy(iov->iov_base, stream_content, copy);
stream_content += copy;
stream_length -= copy;
rcvd += copy;
}
iov++;
count--;
}
(void) tls;
return copy;
return rcvd;
}
static void close_callback(struct vlc_tls *tls)
......@@ -61,7 +72,7 @@ static void close_callback(struct vlc_tls *tls)
static struct vlc_tls chunked_tls =
{
.recv = recv_callback,
.readv = recv_callback,
.close = close_callback,
};
......
......@@ -525,15 +525,18 @@ static const struct vlc_h2_parser_cbs vlc_h2_parser_callbacks =
static ssize_t vlc_https_recv(vlc_tls_t *tls, void *buf, size_t len)
{
struct pollfd ufd;
struct iovec iov;
size_t count = 0;
ufd.fd = tls->fd;
ufd.events = POLLIN;
iov.iov_base = buf;
iov.iov_len = len;
while (count < len)
while (iov.iov_len > 0)
{
int canc = vlc_savecancel();
ssize_t val = tls->recv(tls, (char *)buf + count, len - count);
ssize_t val = tls->readv(tls, &iov, 1);
vlc_restorecancel(canc);
......@@ -542,6 +545,8 @@ static ssize_t vlc_https_recv(vlc_tls_t *tls, void *buf, size_t len)
if (val >= 0)
{
iov.iov_base = (char *)iov.iov_base + val;
iov.iov_len -= val;
count += val;
continue;
}
......
......@@ -157,6 +157,29 @@ static ssize_t vlc_gnutls_writev (gnutls_transport_ptr_t ptr,
return sendmsg (fd, &msg, MSG_NOSIGNAL);
}
static ssize_t gnutls_Recv(vlc_tls_t *tls, struct iovec *iov, unsigned count)
{
gnutls_session_t session = tls->sys;
size_t rcvd = 0;
while (count > 0)
{
ssize_t val = gnutls_record_recv(session, iov->iov_base, iov->iov_len);
if (val < 0)
return rcvd ? (ssize_t)rcvd : gnutls_Error(tls, val);
rcvd += val;
if ((size_t)val < iov->iov_len)
break;
iov++;
count--;
}
return rcvd;
}
static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov,
unsigned count)
{
......@@ -182,14 +205,6 @@ static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov,
return (val < 0) ? gnutls_Error (tls, val) : val;
}
static ssize_t gnutls_Recv (vlc_tls_t *tls, void *buf, size_t length)
{
gnutls_session_t session = tls->sys;
ssize_t val = gnutls_record_recv (session, buf, length);
return (val < 0) ? gnutls_Error (tls, val) : val;
}
static int gnutls_Shutdown(vlc_tls_t *tls, bool duplex)
{
gnutls_session_t session = tls->sys;
......@@ -278,8 +293,8 @@ static int gnutls_SessionOpen(vlc_tls_creds_t *creds, vlc_tls_t *tls, int type,
gnutls_transport_set_int (session, fd);
gnutls_transport_set_vec_push_function (session, vlc_gnutls_writev);
tls->sys = session;
tls->readv = gnutls_Recv;
tls->writev = gnutls_Send;
tls->recv = gnutls_Recv;
tls->shutdown = gnutls_Shutdown;
tls->close = gnutls_Close;
return VLC_SUCCESS;
......
......@@ -60,7 +60,7 @@ vlc_module_begin ()
/*
* The server module currently uses an OSX only API, to be compatible with 10.6.
* If the module is needed on iOS, then the "modern" keychain lookup API need to be
If the module is needed on iOS, then the "modern" keychain lookup API need to be
* implemented.
*/
#if !TARGET_OS_IPHONE
......@@ -486,13 +486,17 @@ static ssize_t st_Send (vlc_tls_t *session, const struct iovec *iov,
/**
* Receives data through a TLS session.
*/
static ssize_t st_Recv (vlc_tls_t *session, void *buf, size_t length)
static ssize_t st_Recv (vlc_tls_t *session, struct iovec *iov, unsigned count)
{
vlc_tls_sys_t *sys = session->sys;
assert(sys);
if (unlikely(count == 0))
return 0;
size_t actualSize;
OSStatus ret = SSLRead(sys->p_context, buf, length, &actualSize);
OSStatus ret = SSLRead(sys->p_context, iov->iov_base, iov->iov_len,
&actualSize);
if (ret == errSSLWouldBlock && actualSize)
return actualSize;
......@@ -565,8 +569,8 @@ static int st_SessionOpenCommon (vlc_tls_creds_t *crd, vlc_tls_t *session,
sys->p_context = NULL;
session->sys = sys;
session->readv = st_Recv;
session->writev = st_Send;
session->recv = st_Recv;
session->shutdown = st_SessionShutdown;
session->close = st_SessionClose;
crd->handshake = st_Handshake;
......
......@@ -220,9 +220,12 @@ error:
ssize_t vlc_tls_Read(vlc_tls_t *session, void *buf, size_t len, bool waitall)
{
struct pollfd ufd;
struct iovec iov;
ufd.fd = session->fd;
ufd.events = POLLIN;
iov.iov_base = buf;
iov.iov_len = len;
for (size_t rcvd = 0;;)
{
......@@ -232,16 +235,16 @@ ssize_t vlc_tls_Read(vlc_tls_t *session, void *buf, size_t len, bool waitall)
return -1;
}
ssize_t val = session->recv(session, buf, len);
ssize_t val = session->readv(session, &iov, 1);
if (val > 0)
{
if (!waitall)
return val;
buf = ((char *)buf) + val;
len -= val;
iov.iov_base = (char *)iov.iov_base + val;
iov.iov_len -= val;
rcvd += val;
}
if (len == 0 || val == 0)
if (iov.iov_len == 0 || val == 0)
return rcvd;
if (val == -1 && errno != EINTR && errno != EAGAIN)
return rcvd ? (ssize_t)rcvd : -1;
......@@ -315,9 +318,15 @@ error:
return NULL;
}
static ssize_t vlc_tls_DummyReceive(vlc_tls_t *tls, void *buf, size_t len)
static ssize_t vlc_tls_DummyReceive(vlc_tls_t *tls, struct iovec *iov,
unsigned count)
{
return recv(tls->fd, buf, len, 0);
struct msghdr msg =
{
.msg_iov = iov,
.msg_iovlen = count,
};
return recvmsg(tls->fd, &msg, 0);
}
static ssize_t vlc_tls_DummySend(vlc_tls_t *tls, const struct iovec *iov,
......@@ -349,7 +358,7 @@ vlc_tls_t *vlc_tls_DummyCreate(vlc_object_t *obj, int fd)
session->obj = obj;
session->fd = fd;
session->recv = vlc_tls_DummyReceive;
session->readv = vlc_tls_DummyReceive;
session->writev = vlc_tls_DummySend;
session->shutdown = vlc_tls_DummyShutdown;
session->close = vlc_tls_DummyClose;
......
......@@ -199,7 +199,9 @@ int main(void)
char buf[12];
struct iovec iov;
val = tls->recv(tls, buf, sizeof (buf));
iov.iov_base = buf;
iov.iov_len = sizeof (buf);
val = tls->readv(tls, &iov, 1);
assert(val == -1 && errno == EAGAIN);
val = vlc_tls_Write(tls, "Hello ", 6);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment