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