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 30static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD; 31#if defined(HAVE_KQUEUE) 32extern apr_pollcb_provider_t *apr_pollcb_provider_kqueue; 33#endif 34#if defined(HAVE_PORT_CREATE) 35extern apr_pollcb_provider_t *apr_pollcb_provider_port; 36#endif 37#if defined(HAVE_EPOLL) 38extern apr_pollcb_provider_t *apr_pollcb_provider_epoll; 39#endif 40#if defined(HAVE_POLL) 41extern apr_pollcb_provider_t *apr_pollcb_provider_poll; 42#endif 43 44static apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method) 45{ 46 apr_pollcb_provider_t *provider = NULL; 47 switch (method) { 48 case APR_POLLSET_KQUEUE: 49#if defined(HAVE_KQUEUE) 50 provider = apr_pollcb_provider_kqueue; 51#endif 52 break; 53 case APR_POLLSET_PORT: 54#if defined(HAVE_PORT_CREATE) 55 provider = apr_pollcb_provider_port; 56#endif 57 break; 58 case APR_POLLSET_EPOLL: 59#if defined(HAVE_EPOLL) 60 provider = apr_pollcb_provider_epoll; 61#endif 62 break; 63 case APR_POLLSET_POLL: 64#if defined(HAVE_POLL) 65 provider = apr_pollcb_provider_poll; 66#endif 67 break; 68 case APR_POLLSET_SELECT: 69 case APR_POLLSET_DEFAULT: 70 break; 71 } 72 return provider; 73} 74 75APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb, 76 apr_uint32_t size, 77 apr_pool_t *p, 78 apr_uint32_t flags, 79 apr_pollset_method_e method) 80{ 81 apr_status_t rv; 82 apr_pollcb_t *pollcb; 83 apr_pollcb_provider_t *provider = NULL; 84 85 *ret_pollcb = NULL; 86 87 #ifdef WIN32 88 /* This will work only if ws2_32.dll has WSAPoll funtion. 89 * We could check the presence of the function here, 90 * but someone might implement other pollcb method in 91 * the future. 92 */ 93 if (method == APR_POLLSET_DEFAULT) { 94 method = APR_POLLSET_POLL; 95 } 96 #endif 97 98 if (method == APR_POLLSET_DEFAULT) 99 method = pollset_default_method; 100 while (provider == NULL) { 101 provider = pollcb_provider(method); 102 if (!provider) { 103 if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) 104 return APR_ENOTIMPL; 105 if (method == pollset_default_method) 106 return APR_ENOTIMPL; 107 method = pollset_default_method; 108 } 109 } 110 111 pollcb = apr_palloc(p, sizeof(*pollcb)); 112 pollcb->nelts = 0; 113 pollcb->nalloc = size; 114 pollcb->pool = p; 115 pollcb->provider = provider; 116 117 rv = (*provider->create)(pollcb, size, p, flags); 118 if (rv == APR_ENOTIMPL) { 119 if (method == pollset_default_method) { 120 return rv; 121 } 122 123 if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) { 124 return rv; 125 } 126 127 /* Try with default provider */ 128 provider = pollcb_provider(pollset_default_method); 129 if (!provider) { 130 return APR_ENOTIMPL; 131 } 132 rv = (*provider->create)(pollcb, size, p, flags); 133 if (rv != APR_SUCCESS) { 134 return rv; 135 } 136 pollcb->provider = provider; 137 } 138 139 *ret_pollcb = pollcb; 140 return APR_SUCCESS; 141} 142 143APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, 144 apr_uint32_t size, 145 apr_pool_t *p, 146 apr_uint32_t flags) 147{ 148 apr_pollset_method_e method = APR_POLLSET_DEFAULT; 149 return apr_pollcb_create_ex(pollcb, size, p, flags, method); 150} 151 152APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, 153 apr_pollfd_t *descriptor) 154{ 155 return (*pollcb->provider->add)(pollcb, descriptor); 156} 157 158APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, 159 apr_pollfd_t *descriptor) 160{ 161 return (*pollcb->provider->remove)(pollcb, descriptor); 162} 163 164 165APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, 166 apr_interval_time_t timeout, 167 apr_pollcb_cb_t func, 168 void *baton) 169{ 170 return (*pollcb->provider->poll)(pollcb, timeout, func, baton); 171} 172