/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ #include "apr.h" #include "apr_poll.h" #include "apr_time.h" #include "networkio.h" #include "fileio.h" #if HAVE_POLL_H #include #endif #if HAVE_SYS_POLL_H #include #endif #ifdef HAVE_POLL /* We can just use poll to do our socket polling. */ static apr_int16_t get_event(apr_int16_t event) { apr_int16_t rv = 0; if (event & APR_POLLIN) rv |= POLLIN; if (event & APR_POLLPRI) rv |= POLLPRI; if (event & APR_POLLOUT) rv |= POLLOUT; if (event & APR_POLLERR) rv |= POLLERR; if (event & APR_POLLHUP) rv |= POLLHUP; if (event & APR_POLLNVAL) rv |= POLLNVAL; return rv; } static apr_int16_t get_revent(apr_int16_t event) { apr_int16_t rv = 0; if (event & POLLIN) rv |= APR_POLLIN; if (event & POLLPRI) rv |= APR_POLLPRI; if (event & POLLOUT) rv |= APR_POLLOUT; if (event & POLLERR) rv |= APR_POLLERR; if (event & POLLHUP) rv |= APR_POLLHUP; if (event & POLLNVAL) rv |= APR_POLLNVAL; return rv; } APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num, apr_int32_t *nsds, apr_interval_time_t timeout) { /* obvious optimization, it would be better if this could be allocated * on the stack. For a single file/socket, this can be otpimized * very cleanly. */ struct pollfd *pollset = apr_palloc(aprset->p, sizeof(struct pollfd) * num); int i; for (i = 0; i < num; i++) { if (aprset[i].desc_type == APR_POLL_SOCKET) { pollset[i].fd = aprset[i].desc.s->socketdes; } else if (aprset[i].desc_type == APR_POLL_FILE) { pollset[i].fd = aprset[i].desc.f->filedes; } pollset[i].events = get_event(aprset[i].reqevents); } if (timeout > 0) { timeout /= 1000; /* convert microseconds to milliseconds */ } i = poll(pollset, num, timeout); (*nsds) = i; for (i = 0; i < num; i++) { aprset[i].rtnevents = get_revent(pollset[i].revents); } if ((*nsds) < 0) { return errno; } if ((*nsds) == 0) { return APR_TIMEUP; } return APR_SUCCESS; } #else /* Use select to mimic poll */ APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, int num, apr_int32_t *nsds, apr_interval_time_t timeout) { fd_set readset, writeset, exceptset; int rv, i; int maxfd = -1; struct timeval tv, *tvptr; if (timeout < 0) { tvptr = NULL; } else { tv.tv_sec = (long)apr_time_sec(timeout); tv.tv_usec = (long)apr_time_usec(timeout); tvptr = &tv; } FD_ZERO(&readset); FD_ZERO(&writeset); FD_ZERO(&exceptset); for (i = 0; i < num; i++) { int fd; if (aprset[i].desc_type == APR_POLL_SOCKET) { fd = aprset[i].desc.s->socketdes; } else if (aprset[i].desc_type == APR_POLL_FILE) { fd = aprset[i].desc.f->filedes; } if (aprset[i].reqevents & APR_POLLIN) { FD_SET(fd, &readset); } if (aprset[i].reqevents & APR_POLLOUT) { FD_SET(fd, &writeset); } if (aprset[i].reqevents & (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { FD_SET(fd, &exceptset); } if (fd > maxfd) { maxfd = fd; } } rv = select(maxfd + 1, &readset, &writeset, &exceptset, tvptr); (*nsds) = rv; if ((*nsds) == 0) { return APR_TIMEUP; } if ((*nsds) < 0) { return errno; } for (i = 0; i < num; i++) { int fd; if (aprset[i].desc_type == APR_POLL_SOCKET) { fd = aprset[i].desc.s->socketdes; } else if (aprset[i].desc_type == APR_POLL_FILE) { fd = aprset[i].desc.f->filedes; } aprset[i].rtnevents = 0; if (FD_ISSET(fd, &readset)) { aprset[i].rtnevents |= APR_POLLIN; } if (FD_ISSET(fd, &writeset)) { aprset[i].rtnevents |= APR_POLLOUT; } if (FD_ISSET(fd, &exceptset)) { aprset[i].rtnevents |= APR_POLLERR; } } return APR_SUCCESS; } #endif