1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#ifdef WIN32 18251875Speter/* POSIX defines 1024 for the FD_SETSIZE */ 19251875Speter#define FD_SETSIZE 1024 20251875Speter#endif 21251875Speter 22251875Speter#include "apr.h" 23251875Speter#include "apr_poll.h" 24251875Speter#include "apr_time.h" 25251875Speter#include "apr_portable.h" 26251875Speter#include "apr_arch_file_io.h" 27251875Speter#include "apr_arch_networkio.h" 28251875Speter#include "apr_arch_poll_private.h" 29251875Speter 30251875Speter#ifdef POLL_USES_SELECT 31251875Speter 32251875SpeterAPR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, int num, 33251875Speter apr_int32_t *nsds, 34251875Speter apr_interval_time_t timeout) 35251875Speter{ 36251875Speter fd_set readset, writeset, exceptset; 37251875Speter int rv, i; 38251875Speter int maxfd = -1; 39251875Speter struct timeval tv, *tvptr; 40251875Speter#ifdef NETWARE 41251875Speter apr_datatype_e set_type = APR_NO_DESC; 42251875Speter#endif 43251875Speter 44251875Speter#ifdef WIN32 45251875Speter /* On Win32, select() must be presented with at least one socket to 46251875Speter * poll on, or select() will return WSAEINVAL. So, we'll just 47251875Speter * short-circuit and bail now. 48251875Speter */ 49251875Speter if (num == 0) { 50251875Speter (*nsds) = 0; 51251875Speter if (timeout > 0) { 52251875Speter apr_sleep(timeout); 53251875Speter return APR_TIMEUP; 54251875Speter } 55251875Speter return APR_SUCCESS; 56251875Speter } 57251875Speter#endif 58251875Speter 59251875Speter if (timeout < 0) { 60251875Speter tvptr = NULL; 61251875Speter } 62251875Speter else { 63251875Speter tv.tv_sec = (long) apr_time_sec(timeout); 64251875Speter tv.tv_usec = (long) apr_time_usec(timeout); 65251875Speter tvptr = &tv; 66251875Speter } 67251875Speter 68251875Speter FD_ZERO(&readset); 69251875Speter FD_ZERO(&writeset); 70251875Speter FD_ZERO(&exceptset); 71251875Speter 72251875Speter for (i = 0; i < num; i++) { 73251875Speter apr_os_sock_t fd; 74251875Speter 75251875Speter aprset[i].rtnevents = 0; 76251875Speter 77251875Speter if (aprset[i].desc_type == APR_POLL_SOCKET) { 78251875Speter#ifdef NETWARE 79251875Speter if (HAS_PIPES(set_type)) { 80251875Speter return APR_EBADF; 81251875Speter } 82251875Speter else { 83251875Speter set_type = APR_POLL_SOCKET; 84251875Speter } 85251875Speter#endif 86251875Speter fd = aprset[i].desc.s->socketdes; 87251875Speter } 88251875Speter else if (aprset[i].desc_type == APR_POLL_FILE) { 89251875Speter#if !APR_FILES_AS_SOCKETS 90251875Speter return APR_EBADF; 91251875Speter#else 92251875Speter#ifdef NETWARE 93251875Speter if (aprset[i].desc.f->is_pipe && !HAS_SOCKETS(set_type)) { 94251875Speter set_type = APR_POLL_FILE; 95251875Speter } 96251875Speter else 97251875Speter return APR_EBADF; 98251875Speter#endif /* NETWARE */ 99251875Speter 100251875Speter fd = aprset[i].desc.f->filedes; 101251875Speter 102251875Speter#endif /* APR_FILES_AS_SOCKETS */ 103251875Speter } 104251875Speter else { 105251875Speter break; 106251875Speter } 107251875Speter#if !defined(WIN32) && !defined(NETWARE) /* socket sets handled with array of handles */ 108251875Speter if (fd >= FD_SETSIZE) { 109251875Speter /* XXX invent new error code so application has a clue */ 110251875Speter return APR_EBADF; 111251875Speter } 112251875Speter#endif 113251875Speter if (aprset[i].reqevents & APR_POLLIN) { 114251875Speter FD_SET(fd, &readset); 115251875Speter } 116251875Speter if (aprset[i].reqevents & APR_POLLOUT) { 117251875Speter FD_SET(fd, &writeset); 118251875Speter } 119251875Speter if (aprset[i].reqevents & 120251875Speter (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { 121251875Speter FD_SET(fd, &exceptset); 122251875Speter } 123251875Speter if ((int) fd > maxfd) { 124251875Speter maxfd = (int) fd; 125251875Speter } 126251875Speter } 127251875Speter 128251875Speter#ifdef NETWARE 129251875Speter if (HAS_PIPES(set_type)) { 130251875Speter rv = pipe_select(maxfd + 1, &readset, &writeset, &exceptset, tvptr); 131251875Speter } 132251875Speter else { 133251875Speter#endif 134251875Speter 135251875Speter rv = select(maxfd + 1, &readset, &writeset, &exceptset, tvptr); 136251875Speter 137251875Speter#ifdef NETWARE 138251875Speter } 139251875Speter#endif 140251875Speter 141251875Speter (*nsds) = rv; 142251875Speter if ((*nsds) == 0) { 143251875Speter return APR_TIMEUP; 144251875Speter } 145251875Speter if ((*nsds) < 0) { 146251875Speter return apr_get_netos_error(); 147251875Speter } 148251875Speter 149251875Speter (*nsds) = 0; 150251875Speter for (i = 0; i < num; i++) { 151251875Speter apr_os_sock_t fd; 152251875Speter 153251875Speter if (aprset[i].desc_type == APR_POLL_SOCKET) { 154251875Speter fd = aprset[i].desc.s->socketdes; 155251875Speter } 156251875Speter else if (aprset[i].desc_type == APR_POLL_FILE) { 157251875Speter#if !APR_FILES_AS_SOCKETS 158251875Speter return APR_EBADF; 159251875Speter#else 160251875Speter fd = aprset[i].desc.f->filedes; 161251875Speter#endif 162251875Speter } 163251875Speter else { 164251875Speter break; 165251875Speter } 166251875Speter if (FD_ISSET(fd, &readset)) { 167251875Speter aprset[i].rtnevents |= APR_POLLIN; 168251875Speter } 169251875Speter if (FD_ISSET(fd, &writeset)) { 170251875Speter aprset[i].rtnevents |= APR_POLLOUT; 171251875Speter } 172251875Speter if (FD_ISSET(fd, &exceptset)) { 173251875Speter aprset[i].rtnevents |= APR_POLLERR; 174251875Speter } 175251875Speter if (aprset[i].rtnevents) { 176251875Speter (*nsds)++; 177251875Speter } 178251875Speter } 179251875Speter 180251875Speter return APR_SUCCESS; 181251875Speter} 182251875Speter 183251875Speter#endif /* POLL_USES_SELECT */ 184251875Speter 185251875Speterstruct apr_pollset_private_t 186251875Speter{ 187251875Speter fd_set readset, writeset, exceptset; 188251875Speter int maxfd; 189251875Speter apr_pollfd_t *query_set; 190251875Speter apr_pollfd_t *result_set; 191251875Speter apr_uint32_t flags; 192251875Speter#ifdef NETWARE 193251875Speter int set_type; 194251875Speter#endif 195251875Speter}; 196251875Speter 197251875Speterstatic apr_status_t impl_pollset_create(apr_pollset_t *pollset, 198251875Speter apr_uint32_t size, 199251875Speter apr_pool_t *p, 200251875Speter apr_uint32_t flags) 201251875Speter{ 202251875Speter if (flags & APR_POLLSET_THREADSAFE) { 203251875Speter pollset->p = NULL; 204251875Speter return APR_ENOTIMPL; 205251875Speter } 206251875Speter#ifdef FD_SETSIZE 207251875Speter if (size > FD_SETSIZE) { 208251875Speter pollset->p = NULL; 209251875Speter return APR_EINVAL; 210251875Speter } 211251875Speter#endif 212251875Speter pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); 213251875Speter FD_ZERO(&(pollset->p->readset)); 214251875Speter FD_ZERO(&(pollset->p->writeset)); 215251875Speter FD_ZERO(&(pollset->p->exceptset)); 216251875Speter pollset->p->maxfd = 0; 217251875Speter#ifdef NETWARE 218251875Speter pollset->p->set_type = APR_NO_DESC; 219251875Speter#endif 220251875Speter pollset->p->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); 221251875Speter pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); 222251875Speter 223251875Speter return APR_SUCCESS; 224251875Speter} 225251875Speter 226251875Speterstatic apr_status_t impl_pollset_add(apr_pollset_t *pollset, 227251875Speter const apr_pollfd_t *descriptor) 228251875Speter{ 229251875Speter apr_os_sock_t fd; 230251875Speter 231251875Speter if (pollset->nelts == pollset->nalloc) { 232251875Speter return APR_ENOMEM; 233251875Speter } 234251875Speter 235251875Speter pollset->p->query_set[pollset->nelts] = *descriptor; 236251875Speter 237251875Speter if (descriptor->desc_type == APR_POLL_SOCKET) { 238251875Speter#ifdef NETWARE 239251875Speter /* NetWare can't handle mixed descriptor types in select() */ 240251875Speter if (HAS_PIPES(pollset->p->set_type)) { 241251875Speter return APR_EBADF; 242251875Speter } 243251875Speter else { 244251875Speter pollset->p->set_type = APR_POLL_SOCKET; 245251875Speter } 246251875Speter#endif 247251875Speter fd = descriptor->desc.s->socketdes; 248251875Speter } 249251875Speter else { 250251875Speter#if !APR_FILES_AS_SOCKETS 251251875Speter if ((pollset->flags & APR_POLLSET_WAKEABLE) && 252251875Speter descriptor->desc.f == pollset->wakeup_pipe[0]) 253251875Speter fd = (apr_os_sock_t)descriptor->desc.f->filedes; 254251875Speter else 255251875Speter return APR_EBADF; 256251875Speter#else 257251875Speter#ifdef NETWARE 258251875Speter /* NetWare can't handle mixed descriptor types in select() */ 259251875Speter if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->p->set_type)) { 260251875Speter pollset->p->set_type = APR_POLL_FILE; 261251875Speter fd = descriptor->desc.f->filedes; 262251875Speter } 263251875Speter else { 264251875Speter return APR_EBADF; 265251875Speter } 266251875Speter#else 267251875Speter fd = descriptor->desc.f->filedes; 268251875Speter#endif 269251875Speter#endif 270251875Speter } 271251875Speter#if !defined(WIN32) && !defined(NETWARE) /* socket sets handled with array of handles */ 272251875Speter if (fd >= FD_SETSIZE) { 273251875Speter /* XXX invent new error code so application has a clue */ 274251875Speter return APR_EBADF; 275251875Speter } 276251875Speter#endif 277251875Speter if (descriptor->reqevents & APR_POLLIN) { 278251875Speter FD_SET(fd, &(pollset->p->readset)); 279251875Speter } 280251875Speter if (descriptor->reqevents & APR_POLLOUT) { 281251875Speter FD_SET(fd, &(pollset->p->writeset)); 282251875Speter } 283251875Speter if (descriptor->reqevents & 284251875Speter (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { 285251875Speter FD_SET(fd, &(pollset->p->exceptset)); 286251875Speter } 287251875Speter if ((int) fd > pollset->p->maxfd) { 288251875Speter pollset->p->maxfd = (int) fd; 289251875Speter } 290251875Speter pollset->nelts++; 291251875Speter return APR_SUCCESS; 292251875Speter} 293251875Speter 294251875Speterstatic apr_status_t impl_pollset_remove(apr_pollset_t * pollset, 295251875Speter const apr_pollfd_t * descriptor) 296251875Speter{ 297251875Speter apr_uint32_t i; 298251875Speter apr_os_sock_t fd; 299251875Speter 300251875Speter if (descriptor->desc_type == APR_POLL_SOCKET) { 301251875Speter fd = descriptor->desc.s->socketdes; 302251875Speter } 303251875Speter else { 304251875Speter#if !APR_FILES_AS_SOCKETS 305251875Speter return APR_EBADF; 306251875Speter#else 307251875Speter fd = descriptor->desc.f->filedes; 308251875Speter#endif 309251875Speter } 310251875Speter 311251875Speter for (i = 0; i < pollset->nelts; i++) { 312251875Speter if (descriptor->desc.s == pollset->p->query_set[i].desc.s) { 313251875Speter /* Found an instance of the fd: remove this and any other copies */ 314251875Speter apr_uint32_t dst = i; 315251875Speter apr_uint32_t old_nelts = pollset->nelts; 316251875Speter pollset->nelts--; 317251875Speter for (i++; i < old_nelts; i++) { 318251875Speter if (descriptor->desc.s == pollset->p->query_set[i].desc.s) { 319251875Speter pollset->nelts--; 320251875Speter } 321251875Speter else { 322251875Speter pollset->p->query_set[dst] = pollset->p->query_set[i]; 323251875Speter dst++; 324251875Speter } 325251875Speter } 326251875Speter FD_CLR(fd, &(pollset->p->readset)); 327251875Speter FD_CLR(fd, &(pollset->p->writeset)); 328251875Speter FD_CLR(fd, &(pollset->p->exceptset)); 329251875Speter if (((int) fd == pollset->p->maxfd) && (pollset->p->maxfd > 0)) { 330251875Speter pollset->p->maxfd--; 331251875Speter } 332251875Speter return APR_SUCCESS; 333251875Speter } 334251875Speter } 335251875Speter 336251875Speter return APR_NOTFOUND; 337251875Speter} 338251875Speter 339251875Speterstatic apr_status_t impl_pollset_poll(apr_pollset_t *pollset, 340251875Speter apr_interval_time_t timeout, 341251875Speter apr_int32_t *num, 342251875Speter const apr_pollfd_t **descriptors) 343251875Speter{ 344251875Speter int rs; 345251875Speter apr_uint32_t i, j; 346251875Speter struct timeval tv, *tvptr; 347251875Speter fd_set readset, writeset, exceptset; 348251875Speter apr_status_t rv = APR_SUCCESS; 349251875Speter 350251875Speter#ifdef WIN32 351251875Speter /* On Win32, select() must be presented with at least one socket to 352251875Speter * poll on, or select() will return WSAEINVAL. So, we'll just 353251875Speter * short-circuit and bail now. 354251875Speter */ 355251875Speter if (pollset->nelts == 0) { 356251875Speter (*num) = 0; 357251875Speter if (timeout > 0) { 358251875Speter apr_sleep(timeout); 359251875Speter return APR_TIMEUP; 360251875Speter } 361251875Speter return APR_SUCCESS; 362251875Speter } 363251875Speter#endif 364251875Speter 365251875Speter if (timeout < 0) { 366251875Speter tvptr = NULL; 367251875Speter } 368251875Speter else { 369251875Speter tv.tv_sec = (long) apr_time_sec(timeout); 370251875Speter tv.tv_usec = (long) apr_time_usec(timeout); 371251875Speter tvptr = &tv; 372251875Speter } 373251875Speter 374251875Speter memcpy(&readset, &(pollset->p->readset), sizeof(fd_set)); 375251875Speter memcpy(&writeset, &(pollset->p->writeset), sizeof(fd_set)); 376251875Speter memcpy(&exceptset, &(pollset->p->exceptset), sizeof(fd_set)); 377251875Speter 378251875Speter#ifdef NETWARE 379251875Speter if (HAS_PIPES(pollset->p->set_type)) { 380251875Speter rs = pipe_select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset, 381251875Speter tvptr); 382251875Speter } 383251875Speter else 384251875Speter#endif 385251875Speter rs = select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset, 386251875Speter tvptr); 387251875Speter 388251875Speter (*num) = rs; 389251875Speter if (rs < 0) { 390251875Speter return apr_get_netos_error(); 391251875Speter } 392251875Speter if (rs == 0) { 393251875Speter return APR_TIMEUP; 394251875Speter } 395251875Speter j = 0; 396251875Speter for (i = 0; i < pollset->nelts; i++) { 397251875Speter apr_os_sock_t fd; 398251875Speter if (pollset->p->query_set[i].desc_type == APR_POLL_SOCKET) { 399251875Speter fd = pollset->p->query_set[i].desc.s->socketdes; 400251875Speter } 401251875Speter else { 402251875Speter if ((pollset->flags & APR_POLLSET_WAKEABLE) && 403251875Speter pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) { 404251875Speter apr_pollset_drain_wakeup_pipe(pollset); 405251875Speter rv = APR_EINTR; 406251875Speter continue; 407251875Speter } 408251875Speter else { 409251875Speter#if !APR_FILES_AS_SOCKETS 410251875Speter return APR_EBADF; 411251875Speter#else 412251875Speter fd = pollset->p->query_set[i].desc.f->filedes; 413251875Speter#endif 414251875Speter } 415251875Speter } 416251875Speter if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) || 417251875Speter FD_ISSET(fd, &exceptset)) { 418251875Speter pollset->p->result_set[j] = pollset->p->query_set[i]; 419251875Speter pollset->p->result_set[j].rtnevents = 0; 420251875Speter if (FD_ISSET(fd, &readset)) { 421251875Speter pollset->p->result_set[j].rtnevents |= APR_POLLIN; 422251875Speter } 423251875Speter if (FD_ISSET(fd, &writeset)) { 424251875Speter pollset->p->result_set[j].rtnevents |= APR_POLLOUT; 425251875Speter } 426251875Speter if (FD_ISSET(fd, &exceptset)) { 427251875Speter pollset->p->result_set[j].rtnevents |= APR_POLLERR; 428251875Speter } 429251875Speter j++; 430251875Speter } 431251875Speter } 432251875Speter if (((*num) = j) != 0) 433251875Speter rv = APR_SUCCESS; 434251875Speter 435251875Speter if (descriptors) 436251875Speter *descriptors = pollset->p->result_set; 437251875Speter return rv; 438251875Speter} 439251875Speter 440251875Speterstatic apr_pollset_provider_t impl = { 441251875Speter impl_pollset_create, 442251875Speter impl_pollset_add, 443251875Speter impl_pollset_remove, 444251875Speter impl_pollset_poll, 445251875Speter NULL, 446251875Speter "select" 447251875Speter}; 448251875Speter 449251875Speterapr_pollset_provider_t *apr_pollset_provider_select = &impl; 450