1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifdef WIN32 18/* POSIX defines 1024 for the FD_SETSIZE */ 19#define FD_SETSIZE 1024 20#endif 21 22#include "apr.h" 23#include "apr_poll.h" 24#include "apr_time.h" 25#include "apr_portable.h" 26#include "apr_arch_file_io.h" 27#include "apr_arch_networkio.h" 28#include "apr_arch_poll_private.h" 29#include "apr_arch_inherit.h" 30 31static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD; 32 33static apr_status_t pollset_cleanup(void *p) 34{ 35 apr_pollset_t *pollset = (apr_pollset_t *) p; 36 if (pollset->provider->cleanup) { 37 (*pollset->provider->cleanup)(pollset); 38 } 39 if (pollset->flags & APR_POLLSET_WAKEABLE) { 40 apr_poll_close_wakeup_pipe(pollset->wakeup_pipe); 41 } 42 43 return APR_SUCCESS; 44} 45 46#if defined(HAVE_KQUEUE) 47extern const apr_pollset_provider_t *apr_pollset_provider_kqueue; 48#endif 49#if defined(HAVE_PORT_CREATE) 50extern const apr_pollset_provider_t *apr_pollset_provider_port; 51#endif 52#if defined(HAVE_EPOLL) 53extern const apr_pollset_provider_t *apr_pollset_provider_epoll; 54#endif 55#if defined(HAVE_AIO_MSGQ) 56extern const apr_pollset_provider_t *apr_pollset_provider_aio_msgq; 57#endif 58#if defined(HAVE_POLL) 59extern const apr_pollset_provider_t *apr_pollset_provider_poll; 60#endif 61extern const apr_pollset_provider_t *apr_pollset_provider_select; 62 63static const apr_pollset_provider_t *pollset_provider(apr_pollset_method_e method) 64{ 65 const apr_pollset_provider_t *provider = NULL; 66 switch (method) { 67 case APR_POLLSET_KQUEUE: 68#if defined(HAVE_KQUEUE) 69 provider = apr_pollset_provider_kqueue; 70#endif 71 break; 72 case APR_POLLSET_PORT: 73#if defined(HAVE_PORT_CREATE) 74 provider = apr_pollset_provider_port; 75#endif 76 break; 77 case APR_POLLSET_EPOLL: 78#if defined(HAVE_EPOLL) 79 provider = apr_pollset_provider_epoll; 80#endif 81 break; 82 case APR_POLLSET_AIO_MSGQ: 83#if defined(HAVE_AIO_MSGQ) 84 provider = apr_pollset_provider_aio_msgq; 85#endif 86 break; 87 case APR_POLLSET_POLL: 88#if defined(HAVE_POLL) 89 provider = apr_pollset_provider_poll; 90#endif 91 break; 92 case APR_POLLSET_SELECT: 93 provider = apr_pollset_provider_select; 94 break; 95 case APR_POLLSET_DEFAULT: 96 break; 97 } 98 return provider; 99} 100 101APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **ret_pollset, 102 apr_uint32_t size, 103 apr_pool_t *p, 104 apr_uint32_t flags, 105 apr_pollset_method_e method) 106{ 107 apr_status_t rv; 108 apr_pollset_t *pollset; 109 const apr_pollset_provider_t *provider = NULL; 110 111 *ret_pollset = NULL; 112 113 #ifdef WIN32 114 /* Favor WSAPoll if supported. 115 * This will work only if ws2_32.dll has WSAPoll funtion. 116 * In other cases it will fall back to select() method unless 117 * the APR_POLLSET_NODEFAULT is added to the flags. 118 */ 119 if (method == APR_POLLSET_DEFAULT) { 120 method = APR_POLLSET_POLL; 121 } 122 #endif 123 124 if (method == APR_POLLSET_DEFAULT) 125 method = pollset_default_method; 126 while (provider == NULL) { 127 provider = pollset_provider(method); 128 if (!provider) { 129 if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) 130 return APR_ENOTIMPL; 131 if (method == pollset_default_method) 132 return APR_ENOTIMPL; 133 method = pollset_default_method; 134 } 135 } 136 if (flags & APR_POLLSET_WAKEABLE) { 137 /* Add room for wakeup descriptor */ 138 size++; 139 } 140 141 pollset = apr_palloc(p, sizeof(*pollset)); 142 pollset->nelts = 0; 143 pollset->nalloc = size; 144 pollset->pool = p; 145 pollset->flags = flags; 146 pollset->provider = provider; 147 148 rv = (*provider->create)(pollset, size, p, flags); 149 if (rv == APR_ENOTIMPL) { 150 if (method == pollset_default_method) { 151 return rv; 152 } 153 provider = pollset_provider(pollset_default_method); 154 if (!provider) { 155 return APR_ENOTIMPL; 156 } 157 rv = (*provider->create)(pollset, size, p, flags); 158 if (rv != APR_SUCCESS) { 159 return rv; 160 } 161 pollset->provider = provider; 162 } 163 else if (rv != APR_SUCCESS) { 164 return rv; 165 } 166 if (flags & APR_POLLSET_WAKEABLE) { 167 /* Create wakeup pipe */ 168 if ((rv = apr_poll_create_wakeup_pipe(pollset->pool, &pollset->wakeup_pfd, 169 pollset->wakeup_pipe)) 170 != APR_SUCCESS) { 171 return rv; 172 } 173 174 if ((rv = apr_pollset_add(pollset, &pollset->wakeup_pfd)) != APR_SUCCESS) { 175 return rv; 176 } 177 } 178 if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup) 179 apr_pool_cleanup_register(p, pollset, pollset_cleanup, 180 apr_pool_cleanup_null); 181 182 *ret_pollset = pollset; 183 return APR_SUCCESS; 184} 185 186APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset) 187{ 188 return pollset->provider->name; 189} 190 191APR_DECLARE(const char *) apr_poll_method_defname() 192{ 193 const apr_pollset_provider_t *provider = NULL; 194 195 provider = pollset_provider(pollset_default_method); 196 if (provider) 197 return provider->name; 198 else 199 return "unknown"; 200} 201 202APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, 203 apr_uint32_t size, 204 apr_pool_t *p, 205 apr_uint32_t flags) 206{ 207 apr_pollset_method_e method = APR_POLLSET_DEFAULT; 208 return apr_pollset_create_ex(pollset, size, p, flags, method); 209} 210 211APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset) 212{ 213 if (pollset->flags & APR_POLLSET_WAKEABLE || 214 pollset->provider->cleanup) 215 return apr_pool_cleanup_run(pollset->pool, pollset, 216 pollset_cleanup); 217 else 218 return APR_SUCCESS; 219} 220 221APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset) 222{ 223 if (pollset->flags & APR_POLLSET_WAKEABLE) 224 return apr_file_putc(1, pollset->wakeup_pipe[1]); 225 else 226 return APR_EINIT; 227} 228 229APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, 230 const apr_pollfd_t *descriptor) 231{ 232 return (*pollset->provider->add)(pollset, descriptor); 233} 234 235APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, 236 const apr_pollfd_t *descriptor) 237{ 238 return (*pollset->provider->remove)(pollset, descriptor); 239} 240 241APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, 242 apr_interval_time_t timeout, 243 apr_int32_t *num, 244 const apr_pollfd_t **descriptors) 245{ 246 return (*pollset->provider->poll)(pollset, timeout, num, descriptors); 247} 248