[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