1/* ====================================================================
2 *    Licensed to the Apache Software Foundation (ASF) under one
3 *    or more contributor license agreements.  See the NOTICE file
4 *    distributed with this work for additional information
5 *    regarding copyright ownership.  The ASF licenses this file
6 *    to you under the Apache License, Version 2.0 (the
7 *    "License"); you may not use this file except in compliance
8 *    with the License.  You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 *    Unless required by applicable law or agreed to in writing,
13 *    software distributed under the License is distributed on an
14 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 *    KIND, either express or implied.  See the License for the
16 *    specific language governing permissions and limitations
17 *    under the License.
18 * ====================================================================
19 */
20
21#include <apr_pools.h>
22#include <apr_poll.h>
23#include <apr_version.h>
24
25#include "serf.h"
26#include "serf_bucket_util.h"
27
28#include "serf_private.h"
29
30static apr_status_t read_from_client(serf_incoming_t *client)
31{
32    return APR_ENOTIMPL;
33}
34
35static apr_status_t write_to_client(serf_incoming_t *client)
36{
37    return APR_ENOTIMPL;
38}
39
40apr_status_t serf__process_client(serf_incoming_t *client, apr_int16_t events)
41{
42    apr_status_t rv;
43    if ((events & APR_POLLIN) != 0) {
44        rv = read_from_client(client);
45        if (rv) {
46            return rv;
47        }
48    }
49
50    if ((events & APR_POLLHUP) != 0) {
51        return APR_ECONNRESET;
52    }
53
54    if ((events & APR_POLLERR) != 0) {
55        return APR_EGENERAL;
56    }
57
58    if ((events & APR_POLLOUT) != 0) {
59        rv = write_to_client(client);
60        if (rv) {
61            return rv;
62        }
63    }
64
65    return APR_SUCCESS;
66}
67
68apr_status_t serf__process_listener(serf_listener_t *l)
69{
70    apr_status_t rv;
71    apr_socket_t *in;
72    apr_pool_t *p;
73    /* THIS IS NOT OPTIMAL */
74    apr_pool_create(&p, l->pool);
75
76    rv = apr_socket_accept(&in, l->skt, p);
77
78    if (rv) {
79        apr_pool_destroy(p);
80        return rv;
81    }
82
83    rv = l->accept_func(l->ctx, l, l->accept_baton, in, p);
84
85    if (rv) {
86        apr_pool_destroy(p);
87        return rv;
88    }
89
90    return rv;
91}
92
93
94apr_status_t serf_incoming_create(
95    serf_incoming_t **client,
96    serf_context_t *ctx,
97    apr_socket_t *insock,
98    void *request_baton,
99    serf_incoming_request_cb_t request,
100    apr_pool_t *pool)
101{
102    apr_status_t rv;
103    serf_incoming_t *ic = apr_palloc(pool, sizeof(*ic));
104
105    ic->ctx = ctx;
106    ic->baton.type = SERF_IO_CLIENT;
107    ic->baton.u.client = ic;
108    ic->request_baton =  request_baton;
109    ic->request = request;
110    ic->skt = insock;
111    ic->desc.desc_type = APR_POLL_SOCKET;
112    ic->desc.desc.s = ic->skt;
113    ic->desc.reqevents = APR_POLLIN;
114
115    rv = ctx->pollset_add(ctx->pollset_baton,
116                         &ic->desc, &ic->baton);
117    *client = ic;
118
119    return rv;
120}
121
122
123apr_status_t serf_listener_create(
124    serf_listener_t **listener,
125    serf_context_t *ctx,
126    const char *host,
127    apr_uint16_t port,
128    void *accept_baton,
129    serf_accept_client_t accept,
130    apr_pool_t *pool)
131{
132    apr_sockaddr_t *sa;
133    apr_status_t rv;
134    serf_listener_t *l = apr_palloc(pool, sizeof(*l));
135
136    l->ctx = ctx;
137    l->baton.type = SERF_IO_LISTENER;
138    l->baton.u.listener = l;
139    l->accept_func = accept;
140    l->accept_baton = accept_baton;
141
142    apr_pool_create(&l->pool, pool);
143
144    rv = apr_sockaddr_info_get(&sa, host, APR_UNSPEC, port, 0, l->pool);
145    if (rv)
146        return rv;
147
148    rv = apr_socket_create(&l->skt, sa->family,
149                           SOCK_STREAM,
150#if APR_MAJOR_VERSION > 0
151                           APR_PROTO_TCP,
152#endif
153                           l->pool);
154    if (rv)
155        return rv;
156
157    rv = apr_socket_opt_set(l->skt, APR_SO_REUSEADDR, 1);
158    if (rv)
159        return rv;
160
161    rv = apr_socket_bind(l->skt, sa);
162    if (rv)
163        return rv;
164
165    rv = apr_socket_listen(l->skt, 5);
166    if (rv)
167        return rv;
168
169    l->desc.desc_type = APR_POLL_SOCKET;
170    l->desc.desc.s = l->skt;
171    l->desc.reqevents = APR_POLLIN;
172
173    rv = ctx->pollset_add(ctx->pollset_baton,
174                            &l->desc, &l->baton);
175    if (rv)
176        return rv;
177
178    *listener = l;
179
180    return APR_SUCCESS;
181}
182