[vlc-commits] tls: use I/O vector for sending
Rémi Denis-Courmont
git at videolan.org
Wed Jan 13 21:49:48 CET 2016
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Jan 10 16:33:26 2016 +0200| [96868b695142fcb4be17880c89474f6138a3ba7f] | committer: Rémi Denis-Courmont
tls: use I/O vector for sending
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=96868b695142fcb4be17880c89474f6138a3ba7f
---
include/vlc_tls.h | 2 +-
modules/access/http/h2output.c | 7 ++++++-
modules/access/http/h2output_test.c | 11 +++++++----
modules/misc/gnutls.c | 36 ++++++++++++++++++++++++++++++-----
modules/misc/securetransport.c | 11 ++++++++---
src/network/tls.c | 23 +++++++++++++++-------
test/modules/misc/tls.c | 6 +++++-
7 files changed, 74 insertions(+), 22 deletions(-)
diff --git a/include/vlc_tls.h b/include/vlc_tls.h
index ca1a88e..224763c 100644
--- a/include/vlc_tls.h
+++ b/include/vlc_tls.h
@@ -43,7 +43,7 @@ struct vlc_tls
int fd;
ssize_t (*recv)(struct vlc_tls *, void *, size_t);
- ssize_t (*send)(struct vlc_tls *, const void *, size_t);
+ ssize_t (*writev)(struct vlc_tls *, const struct iovec *, unsigned);
int (*shutdown)(struct vlc_tls *, bool duplex);
void (*close)(vlc_tls_t *);
};
diff --git a/modules/access/http/h2output.c b/modules/access/http/h2output.c
index 6cd7085..dd57804 100644
--- a/modules/access/http/h2output.c
+++ b/modules/access/http/h2output.c
@@ -190,20 +190,25 @@ static void vlc_h2_output_flush_unlocked(struct vlc_h2_output *out)
static ssize_t vlc_https_send(vlc_tls_t *tls, const void *buf, size_t len)
{
struct pollfd ufd;
+ struct iovec iov;
size_t count = 0;
ufd.fd = tls->fd;
ufd.events = POLLOUT;
+ iov.iov_base = (void *)buf;
+ iov.iov_len = len;
while (count < len)
{
int canc = vlc_savecancel();
- ssize_t val = tls->send(tls, (char *)buf + count, len - count);
+ ssize_t val = tls->writev(tls, &iov, 1);
vlc_restorecancel(canc);
if (val > 0)
{
+ iov.iov_base = (char *)iov.iov_base + val;
+ iov.iov_len -= val;
count += val;
continue;
}
diff --git a/modules/access/http/h2output_test.c b/modules/access/http/h2output_test.c
index 0569c32..34d29b4 100644
--- a/modules/access/http/h2output_test.c
+++ b/modules/access/http/h2output_test.c
@@ -40,11 +40,14 @@ static bool send_failure = false;
static bool expect_hello = true;
static vlc_sem_t rx;
-static ssize_t send_callback(vlc_tls_t *tls, const void *buf, size_t len)
+static ssize_t send_callback(vlc_tls_t *tls, const struct iovec *iov,
+ unsigned count)
{
- const uint8_t *p = buf;
+ assert(count == 1);
+ assert(tls->writev == send_callback);
- assert(tls->send == send_callback);
+ const uint8_t *p = iov->iov_base;
+ size_t len = iov->iov_len;
if (expect_hello)
{
@@ -71,7 +74,7 @@ static ssize_t send_callback(vlc_tls_t *tls, const void *buf, size_t len)
static vlc_tls_t fake_tls =
{
- .send = send_callback,
+ .writev = send_callback,
};
static struct vlc_h2_frame *frame(unsigned char c)
diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
index 271b66f..8b3e224 100644
--- a/modules/misc/gnutls.c
+++ b/modules/misc/gnutls.c
@@ -159,11 +159,28 @@ static ssize_t vlc_gnutls_writev (gnutls_transport_ptr_t ptr,
}
#endif
-static ssize_t gnutls_Send (vlc_tls_t *tls, const void *buf, size_t length)
+static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov,
+ unsigned count)
{
gnutls_session_t session = tls->sys;
- ssize_t val = gnutls_record_send (session, buf, length);
+ ssize_t val;
+ if (!gnutls_record_check_corked(session))
+ {
+ gnutls_record_cork(session);
+
+ while (count > 0)
+ {
+ val = gnutls_record_send(session, iov->iov_base, iov->iov_len);
+ if (val < (ssize_t)iov->iov_len)
+ break;
+
+ iov++;
+ count--;
+ }
+ }
+
+ val = gnutls_record_uncork(session, 0);
return (val < 0) ? gnutls_Error (tls, val) : val;
}
@@ -178,9 +195,18 @@ static ssize_t gnutls_Recv (vlc_tls_t *tls, void *buf, size_t length)
static int gnutls_Shutdown(vlc_tls_t *tls, bool duplex)
{
gnutls_session_t session = tls->sys;
- int val = gnutls_bye(session, duplex ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
+ ssize_t val;
+
+ /* Flush any pending data */
+ val = gnutls_record_uncork(session, 0);
+ if (val < 0)
+ return gnutls_Error(tls, val);
- return (val < 0) ? gnutls_Error(tls, val) : 0;
+ val = gnutls_bye(session, duplex ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
+ if (val < 0)
+ return gnutls_Error(tls, val);
+
+ return 0;
}
static void gnutls_Close (vlc_tls_t *tls)
@@ -256,7 +282,7 @@ static int gnutls_SessionOpen(vlc_tls_creds_t *creds, vlc_tls_t *tls, int type,
gnutls_transport_set_vec_push_function (session, vlc_gnutls_writev);
#endif
tls->sys = session;
- tls->send = gnutls_Send;
+ tls->writev = gnutls_Send;
tls->recv = gnutls_Recv;
tls->shutdown = gnutls_Shutdown;
tls->close = gnutls_Close;
diff --git a/modules/misc/securetransport.c b/modules/misc/securetransport.c
index 3aac855..2c3e9b3 100644
--- a/modules/misc/securetransport.c
+++ b/modules/misc/securetransport.c
@@ -427,12 +427,16 @@ static int st_Handshake (vlc_tls_creds_t *crd, vlc_tls_t *session,
/**
* Sends data through a TLS session.
*/
-static ssize_t st_Send (vlc_tls_t *session, const void *buf, size_t length)
+static ssize_t st_Send (vlc_tls_t *session, const struct iovec *iov,
+ unsigned count)
{
vlc_tls_sys_t *sys = session->sys;
assert(sys);
OSStatus ret = noErr;
+ if (unlikely(count == 0))
+ return 0;
+
/*
* SSLWrite does not return the number of bytes actually written to
* the socket, but the number of bytes written to the internal cache.
@@ -466,7 +470,8 @@ static ssize_t st_Send (vlc_tls_t *session, const void *buf, size_t length)
}
} else {
- ret = SSLWrite(sys->p_context, buf, length, &actualSize);
+ ret = SSLWrite(sys->p_context, iov->iov_base, iov->iov_len,
+ &actualSize);
if (ret == errSSLWouldBlock) {
sys->i_send_buffered_bytes = length;
@@ -560,7 +565,7 @@ static int st_SessionOpenCommon (vlc_tls_creds_t *crd, vlc_tls_t *session,
sys->p_context = NULL;
session->sys = sys;
- session->send = st_Send;
+ session->writev = st_Send;
session->recv = st_Recv;
session->shutdown = st_SessionShutdown;
session->close = st_SessionClose;
diff --git a/src/network/tls.c b/src/network/tls.c
index 8ef2451..49adc9e 100644
--- a/src/network/tls.c
+++ b/src/network/tls.c
@@ -253,9 +253,12 @@ ssize_t vlc_tls_Read(vlc_tls_t *session, void *buf, size_t len, bool waitall)
ssize_t vlc_tls_Write(vlc_tls_t *session, const void *buf, size_t len)
{
struct pollfd ufd;
+ struct iovec iov;
ufd.fd = session->fd;
ufd.events = POLLOUT;
+ iov.iov_base = (void *)buf;
+ iov.iov_len = len;
for (size_t sent = 0;;)
{
@@ -265,14 +268,14 @@ ssize_t vlc_tls_Write(vlc_tls_t *session, const void *buf, size_t len)
return -1;
}
- ssize_t val = session->send(session, buf, len);
+ ssize_t val = session->writev(session, &iov, 1);
if (val > 0)
{
- buf = ((const char *)buf) + val;
- len -= val;
+ iov.iov_base = ((char *)iov.iov_base) + val;
+ iov.iov_len -= val;
sent += val;
}
- if (len == 0 || val == 0)
+ if (iov.iov_len == 0 || val == 0)
return sent;
if (val == -1 && errno != EINTR && errno != EAGAIN)
return sent ? (ssize_t)sent : -1;
@@ -317,9 +320,15 @@ static ssize_t vlc_tls_DummyReceive(vlc_tls_t *tls, void *buf, size_t len)
return recv(tls->fd, buf, len, 0);
}
-static ssize_t vlc_tls_DummySend(vlc_tls_t *tls, const void *buf, size_t len)
+static ssize_t vlc_tls_DummySend(vlc_tls_t *tls, const struct iovec *iov,
+ unsigned count)
{
- return send(tls->fd, buf, len, MSG_NOSIGNAL);
+ const struct msghdr msg =
+ {
+ .msg_iov = (struct iovec *)iov,
+ .msg_iovlen = count,
+ };
+ return sendmsg(tls->fd, &msg, MSG_NOSIGNAL);
}
static int vlc_tls_DummyShutdown(vlc_tls_t *tls, bool duplex)
@@ -341,7 +350,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->send = vlc_tls_DummySend;
+ session->writev = vlc_tls_DummySend;
session->shutdown = vlc_tls_DummyShutdown;
session->close = vlc_tls_DummyClose;
return session;
diff --git a/test/modules/misc/tls.c b/test/modules/misc/tls.c
index 5dba11f..5eb6660 100644
--- a/test/modules/misc/tls.c
+++ b/test/modules/misc/tls.c
@@ -197,6 +197,7 @@ int main(void)
/* Do some I/O */
char buf[12];
+ struct iovec iov;
val = tls->recv(tls, buf, sizeof (buf));
assert(val == -1 && errno == EAGAIN);
@@ -228,13 +229,16 @@ int main(void)
size_t bytes = 0;
unsigned seed = 0;
+ iov.iov_base = data;
+ iov.iov_len = sizeof (data);
+
do
{
for (size_t i = 0; i < sizeof (data); i++)
data[i] = rand_r(&seed);
bytes += sizeof (data);
}
- while ((val = tls->send(tls, data, sizeof (data))) == sizeof (data));
+ while ((val = tls->writev(tls, &iov, 1)) == sizeof (data));
bytes -= sizeof (data);
if (val > 0)
More information about the vlc-commits
mailing list