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 *****************************************************************************/
32 # include <winsock2.h>
34 ssize_t
recvmsg(int fd
, struct msghdr
*msg
, int flags
)
36 if (msg
->msg_controllen
!= 0)
42 if (msg
->msg_iovlen
> IOV_MAX
)
48 WSABUF
*buf
= malloc(msg
->msg_iovlen
* sizeof (*buf
));
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
;
63 ret
= WSARecvFrom(fd
, buf
, msg
->msg_iovlen
, &rcvd
, &dwFlags
,
64 msg
->msg_name
, &fromlen
, NULL
, NULL
);
66 ret
= WSARecv(fd
, buf
, msg
->msg_iovlen
, &rcvd
, &dwFlags
,
72 msg
->msg_namelen
= fromlen
;
73 msg
->msg_flags
= dwFlags
;
77 switch (WSAGetLastError())
86 #elif defined __native_client__
91 #ifdef HAVE_SYS_SOCKET_H
92 #include <sys/socket.h>
98 ssize_t
recvmsg(int fd
, struct msghdr
*msg
, int flags
)
100 if (msg
->msg_controllen
!= 0)
106 if ((msg
->msg_iovlen
<= 0) || (msg
->msg_iovlen
> IOV_MAX
))
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
) {
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);
133 res
= recvfrom(fd
, data
, full_size
, flags
, msg
->msg_name
, &msg
->msg_namelen
);
135 res
= recv(fd
, data
, full_size
, flags
);
139 if ((size_t)res
<= 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
;
155 memcpy(msg
->msg_iov
[i
].iov_base
, src
, to_copy
);
166 #error recvmsg not implemented on your platform!