[vlc-commits] compat: Add custom implementation of recvmsg/sendmsg on NaCl

Dennis Hamester git at videolan.org
Sat Apr 1 12:03:58 CEST 2017


vlc | branch: master | Dennis Hamester <dennis.hamester at startmail.com> | Wed Mar 22 09:59:03 2017 +0100| [246f1ab22e64ffd297370ff881d9297e11ccbaef] | committer: Jean-Baptiste Kempf

compat: Add custom implementation of recvmsg/sendmsg on NaCl

On Pepper 49, recvmsg and sendmsg are implemented as stubs, which always
return ENOTSUP. Proper implementations for these functions will become
available in later Pepper versions, which should make these compat
functions obsolete.

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>

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

 compat/recvmsg.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 compat/sendmsg.c | 64 +++++++++++++++++++++++++++++++++++++++++++
 configure.ac     |  2 ++
 3 files changed, 148 insertions(+)

diff --git a/compat/recvmsg.c b/compat/recvmsg.c
index 941249f..aefeb93 100644
--- a/compat/recvmsg.c
+++ b/compat/recvmsg.c
@@ -1,8 +1,12 @@
 /*****************************************************************************
  * recvmsg.c: POSIX recvmsg() replacement
  *****************************************************************************
+ * Copyright © 2017 VLC authors and VideoLAN
  * Copyright © 2016 Rémi Denis-Courmont
  *
+ * Authors: Rémi Denis-Courmont
+ *          Dennis Hamester <dhamester at jusst.de>
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation; either version 2.1 of the License, or
@@ -78,4 +82,82 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
     }
     return -1;
 }
+
+#elif __native_client__
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
+{
+    if (msg->msg_controllen != 0)
+    {
+        errno = ENOSYS;
+        return -1;
+    }
+
+    if ((msg->msg_iovlen <= 0) || (msg->msg_iovlen > IOV_MAX))
+    {
+        errno = EMSGSIZE;
+        return -1;
+    }
+
+    size_t full_size = 0;
+    for (int i = 0; i < msg->msg_iovlen; ++i)
+        full_size += msg->msg_iov[i].iov_len;
+
+    if (full_size > SSIZE_MAX) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /**
+     * We always allocate here, because whether recv/recvfrom allow NULL message
+     * or not is unspecified.
+     */
+    char *data = malloc(full_size ? full_size : 1);
+    if (!data) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    ssize_t res;
+    if (msg->msg_name)
+        res = recvfrom(fd, data, full_size, flags, msg->msg_name, &msg->msg_namelen);
+    else
+        res = recv(fd, data, full_size, flags);
+
+    if (res > 0) {
+        size_t left;
+        if ((size_t)res <= full_size) {
+            left = res;
+            msg->msg_flags = 0;
+        }
+        else {
+            left = full_size;
+            msg->msg_flags = MSG_TRUNC;
+        }
+
+        const char *src = data;
+        for (int i = 0; (i < msg->msg_iovlen) && (left > 0); ++i)
+        {
+            size_t to_copy = msg->msg_iov[i].iov_len;
+            if (to_copy > left)
+                to_copy = left;
+
+            memcpy(msg->msg_iov[i].iov_base, src, to_copy);
+            src += to_copy;
+            left -= to_copy;
+        }
+    }
+
+    free(data);
+    return res;
+}
+
+#else
+#error recvmsg not implemented on your platform!
 #endif
diff --git a/compat/sendmsg.c b/compat/sendmsg.c
index 451ba29..8a4075c 100644
--- a/compat/sendmsg.c
+++ b/compat/sendmsg.c
@@ -1,8 +1,12 @@
 /*****************************************************************************
  * sendmsg.c: POSIX sendmsg() replacement
  *****************************************************************************
+ * Copyright © 2017 VLC authors and VideoLAN
  * Copyright © 2016 Rémi Denis-Courmont
  *
+ * Authors: Rémi Denis-Courmont
+ *          Dennis Hamester <dhamester at jusst.de>
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation; either version 2.1 of the License, or
@@ -68,4 +72,64 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
     }
     return -1;
 }
+
+#elif __native_client__
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+    if (msg->msg_controllen != 0)
+    {
+        errno = ENOSYS;
+        return -1;
+    }
+
+    if ((msg->msg_iovlen <= 0) || (msg->msg_iovlen > IOV_MAX))
+    {
+        errno = EMSGSIZE;
+        return -1;
+    }
+
+    size_t full_size = 0;
+    for (int i = 0; i < msg->msg_iovlen; ++i)
+        full_size += msg->msg_iov[i].iov_len;
+
+    if (full_size > SSIZE_MAX) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /**
+     * We always allocate here, because whether send/sento allow NULL message or
+     * not is unspecified.
+     */
+    char *data = malloc(full_size ? full_size : 1);
+    if (!data) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    size_t tmp = 0;
+    for (int i = 0; i < msg->msg_iovlen; ++i) {
+        memcpy(data + tmp, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
+        tmp += msg->msg_iov[i].iov_len;
+    }
+
+    ssize_t res;
+    if (msg->msg_name)
+        res = sendto(fd, data, full_size, flags, msg->msg_name, msg->msg_namelen);
+    else
+        res = send(fd, data, full_size, flags);
+
+    free(data);
+    return res;
+}
+
+#else
+#error sendmsg not implemented on your platform!
 #endif
diff --git a/configure.ac b/configure.ac
index 203a2bf..fde2dea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -301,6 +301,8 @@ case "${host_os}" in
     SYS=nacl
     AC_DEFINE([_XOPEN_SOURCE], [700], [POSIX and XPG 7th edition])
     AC_LIBOBJ([sigwait])
+    AC_LIBOBJ([recvmsg])
+    AC_LIBOBJ([sendmsg])
     ;;
   *)
     SYS="${host_os}"



More information about the vlc-commits mailing list