[vlc-commits] tls: use I/O vector for receiving

Rémi Denis-Courmont git at videolan.org
Wed Jan 13 21:49:49 CET 2016


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Jan 10 23:04:53 2016 +0200| [2f5e439929bfb3675d1e3e1cc3e6ac03c8731f85] | committer: Rémi Denis-Courmont

tls: use I/O vector for receiving

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2f5e439929bfb3675d1e3e1cc3e6ac03c8731f85
---

 include/vlc_tls.h                  |    2 +-
 modules/access/http/chunked_test.c |   31 +++++++++++++++++++++----------
 modules/access/http/h2conn.c       |    9 +++++++--
 modules/misc/gnutls.c              |   33 ++++++++++++++++++++++++---------
 modules/misc/securetransport.c     |   12 ++++++++----
 src/network/tls.c                  |   23 ++++++++++++++++-------
 test/modules/misc/tls.c            |    4 +++-
 7 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/include/vlc_tls.h b/include/vlc_tls.h
index 224763c..1b65894 100644
--- a/include/vlc_tls.h
+++ b/include/vlc_tls.h
@@ -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 *);
diff --git a/modules/access/http/chunked_test.c b/modules/access/http/chunked_test.c
index 3efac11..90c4edd 100644
--- a/modules/access/http/chunked_test.c
+++ b/modules/access/http/chunked_test.c
@@ -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;
-    if (copy > stream_length)
-        copy = stream_length;
-    if (copy > 0)
+    size_t rcvd = 0;
+
+    while (count > 0)
     {
-        memcpy(buf, stream_content, copy);
-        stream_content += copy;
-        stream_length -= copy;
+        size_t copy = iov->iov_len;
+        if (copy > stream_length)
+            copy = stream_length;
+
+        if (copy > 0)
+        {
+            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,
 };
 
diff --git a/modules/access/http/h2conn.c b/modules/access/http/h2conn.c
index f6d2a01..60ec980 100644
--- a/modules/access/http/h2conn.c
+++ b/modules/access/http/h2conn.c
@@ -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;
         }
diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
index 0d0f737..8512516 100644
--- a/modules/misc/gnutls.c
+++ b/modules/misc/gnutls.c
@@ -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;
diff --git a/modules/misc/securetransport.c b/modules/misc/securetransport.c
index 2c3e9b3..afb1d62 100644
--- a/modules/misc/securetransport.c
+++ b/modules/misc/securetransport.c
@@ -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;
diff --git a/src/network/tls.c b/src/network/tls.c
index 49adc9e..0b88966 100644
--- a/src/network/tls.c
+++ b/src/network/tls.c
@@ -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;
diff --git a/test/modules/misc/tls.c b/test/modules/misc/tls.c
index 5eb6660..bb54e25 100644
--- a/test/modules/misc/tls.c
+++ b/test/modules/misc/tls.c
@@ -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);



More information about the vlc-commits mailing list