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