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 23struct 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 38APR_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 54APR_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 63APR_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 73APR_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 93APR_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 126static 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 161APR_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