xref: /freebsd/lib/libsys/recvmmsg.c (revision 1f155d48f878495d31592c59cab82f975c210ad8)
129d079c9SBrooks Davis /*
229d079c9SBrooks Davis  * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
329d079c9SBrooks Davis  * All rights reserved.
429d079c9SBrooks Davis  *
529d079c9SBrooks Davis  * Redistribution and use in source and binary forms, with or without
629d079c9SBrooks Davis  * modification, are permitted provided that the following conditions
729d079c9SBrooks Davis  * are met:
829d079c9SBrooks Davis  * 1. Redistributions of source code must retain the above copyright
929d079c9SBrooks Davis  *    notice(s), this list of conditions and the following disclaimer as
1029d079c9SBrooks Davis  *    the first lines of this file unmodified other than the possible
1129d079c9SBrooks Davis  *    addition of one or more copyright notices.
1229d079c9SBrooks Davis  * 2. Redistributions in binary form must reproduce the above copyright
1329d079c9SBrooks Davis  *    notice(s), this list of conditions and the following disclaimer in
1429d079c9SBrooks Davis  *    the documentation and/or other materials provided with the
1529d079c9SBrooks Davis  *    distribution.
1629d079c9SBrooks Davis  *
1729d079c9SBrooks Davis  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
1829d079c9SBrooks Davis  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1929d079c9SBrooks Davis  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2029d079c9SBrooks Davis  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
2129d079c9SBrooks Davis  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2229d079c9SBrooks Davis  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2329d079c9SBrooks Davis  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2429d079c9SBrooks Davis  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2529d079c9SBrooks Davis  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
2629d079c9SBrooks Davis  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
2729d079c9SBrooks Davis  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2829d079c9SBrooks Davis  */
2929d079c9SBrooks Davis 
3029d079c9SBrooks Davis #include <sys/types.h>
3129d079c9SBrooks Davis #include <sys/socket.h>
3229d079c9SBrooks Davis #include <errno.h>
3329d079c9SBrooks Davis #include <poll.h>
3429d079c9SBrooks Davis #include <stddef.h>
35*1f155d48SKyle Evans #include <ssp/ssp.h>
3629d079c9SBrooks Davis #include "libc_private.h"
3729d079c9SBrooks Davis 
3829d079c9SBrooks Davis ssize_t
__ssp_real(recvmmsg)39*1f155d48SKyle Evans __ssp_real(recvmmsg)(int s, struct mmsghdr *__restrict msgvec, size_t vlen,
40*1f155d48SKyle Evans     int flags, const struct timespec *__restrict timeout)
4129d079c9SBrooks Davis {
4229d079c9SBrooks Davis 	struct pollfd pfd[1];
4329d079c9SBrooks Davis 	size_t i, rcvd;
4429d079c9SBrooks Davis 	ssize_t ret;
4529d079c9SBrooks Davis 	int res;
4629d079c9SBrooks Davis 	short ev;
4729d079c9SBrooks Davis 
4829d079c9SBrooks Davis 	if (timeout != NULL) {
4929d079c9SBrooks Davis 		pfd[0].fd = s;
5029d079c9SBrooks Davis 		pfd[0].revents = 0;
5129d079c9SBrooks Davis 		pfd[0].events = ev = POLLIN | POLLRDNORM | POLLRDBAND |
5229d079c9SBrooks Davis 		    POLLPRI;
5329d079c9SBrooks Davis 		res = ppoll(&pfd[0], 1, timeout, NULL);
5429d079c9SBrooks Davis 		if (res == -1 || res == 0)
5529d079c9SBrooks Davis 			return (res);
5629d079c9SBrooks Davis 		if (pfd[0].revents & POLLNVAL) {
5729d079c9SBrooks Davis 			errno = EBADF;
5829d079c9SBrooks Davis 			return (-1);
5929d079c9SBrooks Davis 		}
6029d079c9SBrooks Davis 		if ((pfd[0].revents & ev) == 0) {
6129d079c9SBrooks Davis 			errno = ETIMEDOUT;
6229d079c9SBrooks Davis 			return (-1);
6329d079c9SBrooks Davis 		}
6429d079c9SBrooks Davis 	}
6529d079c9SBrooks Davis 
6629d079c9SBrooks Davis 	ret = __sys_recvmsg(s, &msgvec[0].msg_hdr, flags);
6729d079c9SBrooks Davis 	if (ret == -1)
6829d079c9SBrooks Davis 		return (ret);
6929d079c9SBrooks Davis 
7029d079c9SBrooks Davis 	msgvec[0].msg_len = ret;
7129d079c9SBrooks Davis 
7229d079c9SBrooks Davis 	/*
7329d079c9SBrooks Davis 	 * Do non-blocking receive for second and later messages if
7429d079c9SBrooks Davis 	 * WAITFORONE is set.
7529d079c9SBrooks Davis 	 */
7629d079c9SBrooks Davis 	if (flags & MSG_WAITFORONE)
7729d079c9SBrooks Davis 		flags |= MSG_DONTWAIT;
7829d079c9SBrooks Davis 
7929d079c9SBrooks Davis 	rcvd = 1;
8029d079c9SBrooks Davis 	for (i = rcvd; i < vlen; i++, rcvd++) {
8129d079c9SBrooks Davis 		ret = __sys_recvmsg(s, &msgvec[i].msg_hdr, flags);
8229d079c9SBrooks Davis 		if (ret == -1) {
8329d079c9SBrooks Davis 			/* We have received messages. Let caller know
8429d079c9SBrooks Davis 			 * about the data received, socket error is
8529d079c9SBrooks Davis 			 * returned on next invocation.
8629d079c9SBrooks Davis 			 */
8729d079c9SBrooks Davis 			return (rcvd);
8829d079c9SBrooks Davis 		}
8929d079c9SBrooks Davis 
9029d079c9SBrooks Davis 		/* Save received bytes. */
9129d079c9SBrooks Davis 		msgvec[i].msg_len = ret;
9229d079c9SBrooks Davis 	}
9329d079c9SBrooks Davis 
9429d079c9SBrooks Davis 	return (rcvd);
9529d079c9SBrooks Davis }
96