157416Smarkm/* Licensed to the Apache Software Foundation (ASF) under one or more
257416Smarkm * contributor license agreements.  See the NOTICE file distributed with
357416Smarkm * this work for additional information regarding copyright ownership.
457416Smarkm * The ASF licenses this file to You under the Apache License, Version 2.0
557416Smarkm * (the "License"); you may not use this file except in compliance with
657416Smarkm * the License.  You may obtain a copy of the License at
757416Smarkm *
857416Smarkm *     http://www.apache.org/licenses/LICENSE-2.0
957416Smarkm *
1057416Smarkm * Unless required by applicable law or agreed to in writing, software
1157416Smarkm * distributed under the License is distributed on an "AS IS" BASIS,
1257416Smarkm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1357416Smarkm * See the License for the specific language governing permissions and
1457416Smarkm * limitations under the License.
1557416Smarkm */
1657416Smarkm
1757416Smarkm#ifdef WIN32
1857416Smarkm/* POSIX defines 1024 for the FD_SETSIZE */
1957416Smarkm#define FD_SETSIZE 1024
2057416Smarkm#endif
2157416Smarkm
2257416Smarkm#include "apr.h"
2357416Smarkm#include "apr_poll.h"
2457416Smarkm#include "apr_time.h"
2557416Smarkm#include "apr_portable.h"
2657416Smarkm#include "apr_arch_file_io.h"
2757416Smarkm#include "apr_arch_networkio.h"
2857416Smarkm#include "apr_arch_poll_private.h"
2957416Smarkm
3057416Smarkmstatic apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD;
3157416Smarkm#if defined(HAVE_KQUEUE)
3257416Smarkmextern apr_pollcb_provider_t *apr_pollcb_provider_kqueue;
3357416Smarkm#endif
3457416Smarkm#if defined(HAVE_PORT_CREATE)
3557416Smarkmextern apr_pollcb_provider_t *apr_pollcb_provider_port;
3657416Smarkm#endif
3757416Smarkm#if defined(HAVE_EPOLL)
3857416Smarkmextern apr_pollcb_provider_t *apr_pollcb_provider_epoll;
3957416Smarkm#endif
40233294Sstas#if defined(HAVE_POLL)
4157416Smarkmextern apr_pollcb_provider_t *apr_pollcb_provider_poll;
4257416Smarkm#endif
4357416Smarkm
4457416Smarkmstatic apr_pollcb_provider_t *pollcb_provider(apr_pollset_method_e method)
4557416Smarkm{
4657416Smarkm    apr_pollcb_provider_t *provider = NULL;
4757416Smarkm    switch (method) {
4857416Smarkm        case APR_POLLSET_KQUEUE:
4957416Smarkm#if defined(HAVE_KQUEUE)
5057416Smarkm            provider = apr_pollcb_provider_kqueue;
5157416Smarkm#endif
5257416Smarkm        break;
5357416Smarkm        case APR_POLLSET_PORT:
5457416Smarkm#if defined(HAVE_PORT_CREATE)
5557416Smarkm            provider = apr_pollcb_provider_port;
5657416Smarkm#endif
5757416Smarkm        break;
5857416Smarkm        case APR_POLLSET_EPOLL:
5957416Smarkm#if defined(HAVE_EPOLL)
6057416Smarkm            provider = apr_pollcb_provider_epoll;
6157416Smarkm#endif
6257416Smarkm        break;
6357416Smarkm        case APR_POLLSET_POLL:
6457416Smarkm#if defined(HAVE_POLL)
6557416Smarkm            provider = apr_pollcb_provider_poll;
6657416Smarkm#endif
6757416Smarkm        break;
6857416Smarkm        case APR_POLLSET_SELECT:
6957416Smarkm        case APR_POLLSET_AIO_MSGQ:
7057416Smarkm        case APR_POLLSET_DEFAULT:
7157416Smarkm        break;
7257416Smarkm    }
7357416Smarkm    return provider;
7457416Smarkm}
7557416Smarkm
7657416SmarkmAPR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb,
7757416Smarkm                                               apr_uint32_t size,
7857416Smarkm                                               apr_pool_t *p,
7957416Smarkm                                               apr_uint32_t flags,
8057416Smarkm                                               apr_pollset_method_e method)
8157416Smarkm{
8257416Smarkm    apr_status_t rv;
8357416Smarkm    apr_pollcb_t *pollcb;
8457416Smarkm    apr_pollcb_provider_t *provider = NULL;
8557416Smarkm
8657416Smarkm    *ret_pollcb = NULL;
8757416Smarkm
8857416Smarkm #ifdef WIN32
8957416Smarkm    /* This will work only if ws2_32.dll has WSAPoll funtion.
9057416Smarkm     * We could check the presence of the function here,
9157416Smarkm     * but someone might implement other pollcb method in
9257416Smarkm     * the future.
9357416Smarkm     */
9457416Smarkm    if (method == APR_POLLSET_DEFAULT) {
9557416Smarkm        method = APR_POLLSET_POLL;
9657416Smarkm    }
9757416Smarkm #endif
9857416Smarkm
9957416Smarkm    if (method == APR_POLLSET_DEFAULT)
10057416Smarkm        method = pollset_default_method;
10157416Smarkm    while (provider == NULL) {
10257416Smarkm        provider = pollcb_provider(method);
10357416Smarkm        if (!provider) {
10457416Smarkm            if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT)
10557416Smarkm                return APR_ENOTIMPL;
10657416Smarkm            if (method == pollset_default_method)
10757416Smarkm                return APR_ENOTIMPL;
10857416Smarkm            method = pollset_default_method;
10957416Smarkm        }
11057416Smarkm    }
11157416Smarkm
11257416Smarkm    pollcb = apr_palloc(p, sizeof(*pollcb));
11357416Smarkm    pollcb->nelts = 0;
11457416Smarkm    pollcb->nalloc = size;
11557416Smarkm    pollcb->pool = p;
11657416Smarkm    pollcb->provider = provider;
11757416Smarkm
11857416Smarkm    rv = (*provider->create)(pollcb, size, p, flags);
11957416Smarkm    if (rv == APR_ENOTIMPL) {
12057416Smarkm        if (method == pollset_default_method) {
12157416Smarkm            return rv;
12257416Smarkm        }
12357416Smarkm
12457416Smarkm        if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT) {
12557416Smarkm            return rv;
12657416Smarkm        }
12757416Smarkm
12857416Smarkm        /* Try with default provider */
12957416Smarkm        provider = pollcb_provider(pollset_default_method);
13057416Smarkm        if (!provider) {
13157416Smarkm            return APR_ENOTIMPL;
13257416Smarkm        }
13357416Smarkm        rv = (*provider->create)(pollcb, size, p, flags);
13457416Smarkm        if (rv != APR_SUCCESS) {
13557416Smarkm            return rv;
13657416Smarkm        }
13757416Smarkm        pollcb->provider = provider;
13857416Smarkm    }
13957416Smarkm
14057416Smarkm    *ret_pollcb = pollcb;
14157416Smarkm    return APR_SUCCESS;
14257416Smarkm}
14357416Smarkm
14457416SmarkmAPR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
14557416Smarkm                                            apr_uint32_t size,
14657416Smarkm                                            apr_pool_t *p,
14757416Smarkm                                            apr_uint32_t flags)
14857416Smarkm{
14957416Smarkm    apr_pollset_method_e method = APR_POLLSET_DEFAULT;
15057416Smarkm    return apr_pollcb_create_ex(pollcb, size, p, flags, method);
15157416Smarkm}
15257416Smarkm
15357416SmarkmAPR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
15457416Smarkm                                         apr_pollfd_t *descriptor)
15557416Smarkm{
15657416Smarkm    return (*pollcb->provider->add)(pollcb, descriptor);
15757416Smarkm}
15857416Smarkm
15957416SmarkmAPR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
16057416Smarkm                                            apr_pollfd_t *descriptor)
16157416Smarkm{
16257416Smarkm    return (*pollcb->provider->remove)(pollcb, descriptor);
16357416Smarkm}
16457416Smarkm
16557416Smarkm
16657416SmarkmAPR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
16757416Smarkm                                          apr_interval_time_t timeout,
16857416Smarkm                                          apr_pollcb_cb_t func,
16957416Smarkm                                          void *baton)
17057416Smarkm{
17157416Smarkm    return (*pollcb->provider->poll)(pollcb, timeout, func, baton);
17257416Smarkm}
17357416Smarkm