demux: es: refactor seek
[vlc.git] / compat / recvmsg.c
blob1c348fcee2a5b36e472b24269b876c66a8ce8871
1 /*****************************************************************************
2 * recvmsg.c: POSIX recvmsg() replacement
3 *****************************************************************************
4 * Copyright © 2017 VLC authors and VideoLAN
5 * Copyright © 2016 Rémi Denis-Courmont
7 * Authors: Rémi Denis-Courmont
8 * Dennis Hamester <dhamester@jusst.de>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
29 #ifdef _WIN32
30 # include <errno.h>
31 # include <stdlib.h>
32 # include <winsock2.h>
34 ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
36 if (msg->msg_controllen != 0)
38 errno = ENOSYS;
39 return -1;
42 if (msg->msg_iovlen > IOV_MAX)
44 errno = EINVAL;
45 return -1;
48 WSABUF *buf = malloc(msg->msg_iovlen * sizeof (*buf));
49 if (buf == NULL)
50 return -1;
52 for (unsigned i = 0; i < msg->msg_iovlen; i++)
54 buf[i].len = msg->msg_iov[i].iov_len;
55 buf[i].buf = msg->msg_iov[i].iov_base;
58 DWORD dwFlags = flags;
59 INT fromlen = msg->msg_namelen;
60 DWORD rcvd;
61 int ret;
62 if (fromlen)
63 ret = WSARecvFrom(fd, buf, msg->msg_iovlen, &rcvd, &dwFlags,
64 msg->msg_name, &fromlen, NULL, NULL);
65 else
66 ret = WSARecv(fd, buf, msg->msg_iovlen, &rcvd, &dwFlags,
67 NULL, NULL);
68 free(buf);
70 if (ret == 0)
72 msg->msg_namelen = fromlen;
73 msg->msg_flags = dwFlags;
74 return rcvd;
77 switch (WSAGetLastError())
79 case WSAEWOULDBLOCK:
80 errno = EAGAIN;
81 break;
83 return -1;
86 #elif defined __native_client__
87 #include <errno.h>
88 #include <limits.h>
89 #include <stdlib.h>
90 #include <string.h>
91 #ifdef HAVE_SYS_SOCKET_H
92 #include <sys/socket.h>
93 #endif
94 #ifdef HAVE_SYS_UIO_H
95 #include <sys/uio.h>
96 #endif
98 ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
100 if (msg->msg_controllen != 0)
102 errno = ENOSYS;
103 return -1;
106 if ((msg->msg_iovlen <= 0) || (msg->msg_iovlen > IOV_MAX))
108 errno = EMSGSIZE;
109 return -1;
112 size_t full_size = 0;
113 for (int i = 0; i < msg->msg_iovlen; ++i)
114 full_size += msg->msg_iov[i].iov_len;
116 if (full_size > SSIZE_MAX) {
117 errno = EINVAL;
118 return -1;
122 * We always allocate here, because whether recv/recvfrom allow NULL message
123 * or not is unspecified.
125 char *data = malloc(full_size ? full_size : 1);
126 if (!data) {
127 errno = ENOMEM;
128 return -1;
131 ssize_t res;
132 if (msg->msg_name)
133 res = recvfrom(fd, data, full_size, flags, msg->msg_name, &msg->msg_namelen);
134 else
135 res = recv(fd, data, full_size, flags);
137 if (res > 0) {
138 size_t left;
139 if ((size_t)res <= full_size) {
140 left = res;
141 msg->msg_flags = 0;
143 else {
144 left = full_size;
145 msg->msg_flags = MSG_TRUNC;
148 const char *src = data;
149 for (int i = 0; (i < msg->msg_iovlen) && (left > 0); ++i)
151 size_t to_copy = msg->msg_iov[i].iov_len;
152 if (to_copy > left)
153 to_copy = left;
155 memcpy(msg->msg_iov[i].iov_base, src, to_copy);
156 src += to_copy;
157 left -= to_copy;
161 free(data);
162 return res;
165 #else
166 #error recvmsg not implemented on your platform!
167 #endif