recvmmsg.c revision 6c0e620fdbcd382232aa0d3be852301f2a75876d
16c0e620kib/*
26c0e620kib * Copyright (c) 2016 Boris Astardzhiev, Smartcom-Bulgaria AD
36c0e620kib * All rights reserved.
46c0e620kib *
56c0e620kib * Redistribution and use in source and binary forms, with or without
66c0e620kib * modification, are permitted provided that the following conditions
76c0e620kib * are met:
86c0e620kib * 1. Redistributions of source code must retain the above copyright
96c0e620kib *    notice(s), this list of conditions and the following disclaimer as
106c0e620kib *    the first lines of this file unmodified other than the possible
116c0e620kib *    addition of one or more copyright notices.
126c0e620kib * 2. Redistributions in binary form must reproduce the above copyright
136c0e620kib *    notice(s), this list of conditions and the following disclaimer in
146c0e620kib *    the documentation and/or other materials provided with the
156c0e620kib *    distribution.
166c0e620kib *
176c0e620kib * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
186c0e620kib * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
196c0e620kib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
206c0e620kib * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
216c0e620kib * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
226c0e620kib * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
236c0e620kib * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
246c0e620kib * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
256c0e620kib * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
266c0e620kib * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
276c0e620kib * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286c0e620kib */
296c0e620kib
306c0e620kib#include <sys/cdefs.h>
316c0e620kib__FBSDID("$FreeBSD$");
326c0e620kib
336c0e620kib#include <sys/types.h>
346c0e620kib#include <sys/socket.h>
356c0e620kib#include <errno.h>
366c0e620kib#include <poll.h>
376c0e620kib#include <stddef.h>
386c0e620kib#include "libc_private.h"
396c0e620kib
406c0e620kibssize_t
416c0e620kibrecvmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags,
426c0e620kib    const struct timespec *__restrict timeout)
436c0e620kib{
446c0e620kib	struct pollfd pfd[1];
456c0e620kib	size_t i, rcvd;
466c0e620kib	ssize_t ret;
476c0e620kib	int res;
486c0e620kib	short ev;
496c0e620kib
506c0e620kib	if (timeout != NULL) {
516c0e620kib		pfd[0].fd = s;
526c0e620kib		pfd[0].revents = 0;
536c0e620kib		pfd[0].events = ev = POLLIN | POLLRDNORM | POLLRDBAND |
546c0e620kib		    POLLPRI;
556c0e620kib		res = ppoll(&pfd[0], 1, timeout, NULL);
566c0e620kib		if (res == -1 || res == 0)
576c0e620kib			return (res);
586c0e620kib		if (pfd[0].revents & POLLNVAL) {
596c0e620kib			errno = EBADF;
606c0e620kib			return (-1);
616c0e620kib		}
626c0e620kib		if ((pfd[0].revents & ev) == 0) {
636c0e620kib			errno = ETIMEDOUT;
646c0e620kib			return (-1);
656c0e620kib		}
666c0e620kib	}
676c0e620kib
686c0e620kib	ret = __sys_recvmsg(s, &msgvec[0].msg_hdr, flags);
696c0e620kib	if (ret == -1)
706c0e620kib		return (ret);
716c0e620kib
726c0e620kib	/*
736c0e620kib	 * Do non-blocking receive for second and later messages if
746c0e620kib	 * WAITFORONE is set.
756c0e620kib	 */
766c0e620kib	if (flags & MSG_WAITFORONE)
776c0e620kib		flags |= MSG_DONTWAIT;
786c0e620kib
796c0e620kib	rcvd = 1;
806c0e620kib	for (i = rcvd; i < vlen; i++, rcvd++) {
816c0e620kib		ret = __sys_recvmsg(s, &msgvec[i].msg_hdr, flags);
826c0e620kib		if (ret == -1) {
836c0e620kib			/* We have received messages. Let caller know
846c0e620kib				 * about the data received, socket
856c0e620kib				 * error is returned on next
866c0e620kib				 * invocation.
876c0e620kib				 */
886c0e620kib			return (rcvd);
896c0e620kib		}
906c0e620kib
916c0e620kib		/* Save received bytes. */
926c0e620kib		msgvec[i].msg_len = ret;
936c0e620kib	}
946c0e620kib
956c0e620kib	return (rcvd);
966c0e620kib}
97