125184Sjkh/*
225184Sjkh * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
366830Sobrien * All rights reserved.
466830Sobrien *
566830Sobrien * Redistribution and use in source and binary forms, with or without
666830Sobrien * modification, are permitted provided that the following conditions
766830Sobrien * are met:
866830Sobrien * 1. Redistributions of source code must retain the above copyright
966830Sobrien *    notice(s), this list of conditions and the following disclaimer as
1066830Sobrien *    the first lines of this file unmodified other than the possible
1166830Sobrien *    addition of one or more copyright notices.
1266830Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1366830Sobrien *    notice(s), this list of conditions and the following disclaimer in
1466830Sobrien *    the documentation and/or other materials provided with the
1566830Sobrien *    distribution.
1666830Sobrien *
1766830Sobrien * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
1866830Sobrien * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1966830Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2066830Sobrien * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
2166830Sobrien * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2266830Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2366830Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2466830Sobrien * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2566830Sobrien * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
2666830Sobrien * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
2750472Speter * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2825184Sjkh */
2966830Sobrien
3025184Sjkh#include <sys/cdefs.h>
3151231Ssheldonh__FBSDID("$FreeBSD: releng/11.0/lib/libc/gen/recvmmsg.c 295039 2016-01-29 14:12:12Z kib $");
3251231Ssheldonh
3325184Sjkh#include <sys/types.h>
3425184Sjkh#include <sys/socket.h>
3525184Sjkh#include <errno.h>
3625184Sjkh#include <poll.h>
3751231Ssheldonh#include <stddef.h>
3825184Sjkh#include "libc_private.h"
3951231Ssheldonh
4025184Sjkhssize_t
4165532Snectarrecvmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags,
4265532Snectar    const struct timespec *__restrict timeout)
4370108Sdougb{
4470108Sdougb	struct pollfd pfd[1];
4565532Snectar	size_t i, rcvd;
4670108Sdougb	ssize_t ret;
4765532Snectar	int res;
4870108Sdougb	short ev;
4965532Snectar
5065532Snectar	if (timeout != NULL) {
5165532Snectar		pfd[0].fd = s;
5265532Snectar		pfd[0].revents = 0;
5351231Ssheldonh		pfd[0].events = ev = POLLIN | POLLRDNORM | POLLRDBAND |
5451231Ssheldonh		    POLLPRI;
5551231Ssheldonh		res = ppoll(&pfd[0], 1, timeout, NULL);
5651231Ssheldonh		if (res == -1 || res == 0)
5751231Ssheldonh			return (res);
5851231Ssheldonh		if (pfd[0].revents & POLLNVAL) {
5925184Sjkh			errno = EBADF;
6066745Sdarrenr			return (-1);
6166745Sdarrenr		}
6266745Sdarrenr		if ((pfd[0].revents & ev) == 0) {
6366745Sdarrenr			errno = ETIMEDOUT;
6466745Sdarrenr			return (-1);
6566745Sdarrenr		}
6666745Sdarrenr	}
6770129Sdougb
6870129Sdougb	ret = __sys_recvmsg(s, &msgvec[0].msg_hdr, flags);
6966745Sdarrenr	if (ret == -1)
7066745Sdarrenr		return (ret);
7166745Sdarrenr
7270129Sdougb	/*
7366745Sdarrenr	 * Do non-blocking receive for second and later messages if
7466745Sdarrenr	 * WAITFORONE is set.
7566745Sdarrenr	 */
7666745Sdarrenr	if (flags & MSG_WAITFORONE)
7766745Sdarrenr		flags |= MSG_DONTWAIT;
7866745Sdarrenr
7970129Sdougb	rcvd = 1;
8070129Sdougb	for (i = rcvd; i < vlen; i++, rcvd++) {
8166745Sdarrenr		ret = __sys_recvmsg(s, &msgvec[i].msg_hdr, flags);
8266745Sdarrenr		if (ret == -1) {
8366745Sdarrenr			/* We have received messages. Let caller know
8466745Sdarrenr				 * about the data received, socket
8566745Sdarrenr				 * error is returned on next
8666745Sdarrenr				 * invocation.
8766745Sdarrenr				 */
8866745Sdarrenr			return (rcvd);
8966745Sdarrenr		}
9066745Sdarrenr
9166745Sdarrenr		/* Save received bytes. */
9266745Sdarrenr		msgvec[i].msg_len = ret;
9351231Ssheldonh	}
9451231Ssheldonh
9551231Ssheldonh	return (rcvd);
9651231Ssheldonh}
9751231Ssheldonh