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 #include "apr.h"
18 #include "apr_poll.h"
19 #include "apr_arch_networkio.h"
20
21
22
23 struct apr_pollset_t {
24 apr_pool_t *pool;
25 apr_uint32_t nelts;
26 apr_uint32_t nalloc;
27 int *pollset;
28 int num_read;
29 int num_write;
30 int num_except;
31 int num_total;
32 apr_pollfd_t *query_set;
33 apr_pollfd_t *result_set;
34 };
35
36
37
apr_pollset_create(apr_pollset_t ** pollset,apr_uint32_t size,apr_pool_t * p,apr_uint32_t flags)38 APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
39 apr_uint32_t size,
40 apr_pool_t *p,
41 apr_uint32_t flags)
42 {
43 *pollset = apr_palloc(p, sizeof(**pollset));
44 (*pollset)->pool = p;
45 (*pollset)->nelts = 0;
46 (*pollset)->nalloc = size;
47 (*pollset)->pollset = apr_palloc(p, size * sizeof(int) * 3);
48 (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
49 (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
50 (*pollset)->num_read = -1;
51 return APR_SUCCESS;
52 }
53
apr_pollset_create_ex(apr_pollset_t ** pollset,apr_uint32_t size,apr_pool_t * p,apr_uint32_t flags,apr_pollset_method_e method)54 APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset,
55 apr_uint32_t size,
56 apr_pool_t *p,
57 apr_uint32_t flags,
58 apr_pollset_method_e method)
59 {
60 return apr_pollset_create(pollset, size, p, flags);
61 }
62
apr_pollset_destroy(apr_pollset_t * pollset)63 APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
64 {
65 /* A no-op function for now. If we later implement /dev/poll
66 * support, we'll need to close the /dev/poll fd here
67 */
68 return APR_SUCCESS;
69 }
70
71
72
apr_pollset_add(apr_pollset_t * pollset,const apr_pollfd_t * descriptor)73 APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
74 const apr_pollfd_t *descriptor)
75 {
76 if (pollset->nelts == pollset->nalloc) {
77 return APR_ENOMEM;
78 }
79
80 pollset->query_set[pollset->nelts] = *descriptor;
81
82 if (descriptor->desc_type != APR_POLL_SOCKET) {
83 return APR_EBADF;
84 }
85
86 pollset->nelts++;
87 pollset->num_read = -1;
88 return APR_SUCCESS;
89 }
90
91
92
apr_pollset_remove(apr_pollset_t * pollset,const apr_pollfd_t * descriptor)93 APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
94 const apr_pollfd_t *descriptor)
95 {
96 apr_uint32_t i;
97
98 for (i = 0; i < pollset->nelts; i++) {
99 if (descriptor->desc.s == pollset->query_set[i].desc.s) {
100 /* Found an instance of the fd: remove this and any other copies */
101 apr_uint32_t dst = i;
102 apr_uint32_t old_nelts = pollset->nelts;
103 pollset->nelts--;
104
105 for (i++; i < old_nelts; i++) {
106 if (descriptor->desc.s == pollset->query_set[i].desc.s) {
107 pollset->nelts--;
108 }
109 else {
110 pollset->pollset[dst] = pollset->pollset[i];
111 pollset->query_set[dst] = pollset->query_set[i];
112 dst++;
113 }
114 }
115
116 pollset->num_read = -1;
117 return APR_SUCCESS;
118 }
119 }
120
121 return APR_NOTFOUND;
122 }
123
124
125
make_pollset(apr_pollset_t * pollset)126 static void make_pollset(apr_pollset_t *pollset)
127 {
128 int i;
129 int pos = 0;
130
131 pollset->num_read = 0;
132 pollset->num_write = 0;
133 pollset->num_except = 0;
134
135 for (i = 0; i < pollset->nelts; i++) {
136 if (pollset->query_set[i].reqevents & APR_POLLIN) {
137 pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
138 pollset->num_read++;
139 }
140 }
141
142 for (i = 0; i < pollset->nelts; i++) {
143 if (pollset->query_set[i].reqevents & APR_POLLOUT) {
144 pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
145 pollset->num_write++;
146 }
147 }
148
149 for (i = 0; i < pollset->nelts; i++) {
150 if (pollset->query_set[i].reqevents & APR_POLLPRI) {
151 pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
152 pollset->num_except++;
153 }
154 }
155
156 pollset->num_total = pollset->num_read + pollset->num_write + pollset->num_except;
157 }
158
159
160
apr_pollset_poll(apr_pollset_t * pollset,apr_interval_time_t timeout,apr_int32_t * num,const apr_pollfd_t ** descriptors)161 APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
162 apr_interval_time_t timeout,
163 apr_int32_t *num,
164 const apr_pollfd_t **descriptors)
165 {
166 int rv;
167 apr_uint32_t i;
168 int *pollresult;
169 int read_pos, write_pos, except_pos;
170
171 if (pollset->num_read < 0) {
172 make_pollset(pollset);
173 }
174
175 pollresult = alloca(sizeof(int) * pollset->num_total);
176 memcpy(pollresult, pollset->pollset, sizeof(int) * pollset->num_total);
177 (*num) = 0;
178
179 if (timeout > 0) {
180 timeout /= 1000;
181 }
182
183 rv = select(pollresult, pollset->num_read, pollset->num_write, pollset->num_except, timeout);
184
185 if (rv < 0) {
186 return APR_FROM_OS_ERROR(sock_errno());
187 }
188
189 if (rv == 0) {
190 return APR_TIMEUP;
191 }
192
193 read_pos = 0;
194 write_pos = pollset->num_read;
195 except_pos = pollset->num_read + pollset->num_write;
196
197 for (i = 0; i < pollset->nelts; i++) {
198 int rtnevents = 0;
199
200 if (pollset->query_set[i].reqevents & APR_POLLIN) {
201 if (pollresult[read_pos++] != -1) {
202 rtnevents |= APR_POLLIN;
203 }
204 }
205
206 if (pollset->query_set[i].reqevents & APR_POLLOUT) {
207 if (pollresult[write_pos++] != -1) {
208 rtnevents |= APR_POLLOUT;
209 }
210 }
211
212 if (pollset->query_set[i].reqevents & APR_POLLPRI) {
213 if (pollresult[except_pos++] != -1) {
214 rtnevents |= APR_POLLPRI;
215 }
216 }
217
218 if (rtnevents) {
219 pollset->result_set[*num] = pollset->query_set[i];
220 pollset->result_set[*num].rtnevents = rtnevents;
221 (*num)++;
222 }
223 }
224
225 if (descriptors) {
226 *descriptors = pollset->result_set;
227 }
228
229 return APR_SUCCESS;
230 }
231