1295039Skib/*
2295039Skib * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
3295039Skib * All rights reserved.
4295039Skib *
5295039Skib * Redistribution and use in source and binary forms, with or without
6295039Skib * modification, are permitted provided that the following conditions
7295039Skib * are met:
8295039Skib * 1. Redistributions of source code must retain the above copyright
9295039Skib *    notice(s), this list of conditions and the following disclaimer as
10295039Skib *    the first lines of this file unmodified other than the possible
11295039Skib *    addition of one or more copyright notices.
12295039Skib * 2. Redistributions in binary form must reproduce the above copyright
13295039Skib *    notice(s), this list of conditions and the following disclaimer in
14295039Skib *    the documentation and/or other materials provided with the
15295039Skib *    distribution.
16295039Skib *
17295039Skib * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
18295039Skib * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19295039Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20295039Skib * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
21295039Skib * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22295039Skib * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23295039Skib * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24295039Skib * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25295039Skib * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26295039Skib * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27295039Skib * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28295039Skib */
29295039Skib
30295039Skib#include <sys/cdefs.h>
31295039Skib__FBSDID("$FreeBSD: stable/11/lib/libc/gen/recvmmsg.c 307312 2016-10-14 09:34:48Z kib $");
32295039Skib
33295039Skib#include <sys/types.h>
34295039Skib#include <sys/socket.h>
35295039Skib#include <errno.h>
36295039Skib#include <poll.h>
37295039Skib#include <stddef.h>
38295039Skib#include "libc_private.h"
39295039Skib
40295039Skibssize_t
41295039Skibrecvmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags,
42295039Skib    const struct timespec *__restrict timeout)
43295039Skib{
44295039Skib	struct pollfd pfd[1];
45295039Skib	size_t i, rcvd;
46295039Skib	ssize_t ret;
47295039Skib	int res;
48295039Skib	short ev;
49295039Skib
50295039Skib	if (timeout != NULL) {
51295039Skib		pfd[0].fd = s;
52295039Skib		pfd[0].revents = 0;
53295039Skib		pfd[0].events = ev = POLLIN | POLLRDNORM | POLLRDBAND |
54295039Skib		    POLLPRI;
55295039Skib		res = ppoll(&pfd[0], 1, timeout, NULL);
56295039Skib		if (res == -1 || res == 0)
57295039Skib			return (res);
58295039Skib		if (pfd[0].revents & POLLNVAL) {
59295039Skib			errno = EBADF;
60295039Skib			return (-1);
61295039Skib		}
62295039Skib		if ((pfd[0].revents & ev) == 0) {
63295039Skib			errno = ETIMEDOUT;
64295039Skib			return (-1);
65295039Skib		}
66295039Skib	}
67295039Skib
68295039Skib	ret = __sys_recvmsg(s, &msgvec[0].msg_hdr, flags);
69295039Skib	if (ret == -1)
70295039Skib		return (ret);
71295039Skib
72307311Skib	msgvec[0].msg_len = ret;
73307311Skib
74295039Skib	/*
75295039Skib	 * Do non-blocking receive for second and later messages if
76295039Skib	 * WAITFORONE is set.
77295039Skib	 */
78295039Skib	if (flags & MSG_WAITFORONE)
79295039Skib		flags |= MSG_DONTWAIT;
80295039Skib
81295039Skib	rcvd = 1;
82295039Skib	for (i = rcvd; i < vlen; i++, rcvd++) {
83295039Skib		ret = __sys_recvmsg(s, &msgvec[i].msg_hdr, flags);
84295039Skib		if (ret == -1) {
85295039Skib			/* We have received messages. Let caller know
86307312Skib			 * about the data received, socket error is
87307312Skib			 * returned on next invocation.
88307312Skib			 */
89295039Skib			return (rcvd);
90295039Skib		}
91295039Skib
92295039Skib		/* Save received bytes. */
93295039Skib		msgvec[i].msg_len = ret;
94295039Skib	}
95295039Skib
96295039Skib	return (rcvd);
97295039Skib}
98