]> granicus.if.org Git - apache/blob - server/mpm/simple/simple_io.c
fix function names in trace messages
[apache] / server / mpm / simple / simple_io.c
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 "httpd.h"
18 #include "http_log.h"
19 #include "ap_listen.h"
20 #include "simple_types.h"
21 #include "simple_io.h"
22 #include "simple_event.h"
23
24 #include "http_connection.h"
25 #include "util_filter.h"
26 #include "http_main.h"
27 #include "scoreboard.h"
28 #include "http_vhost.h"
29
30 static void simple_io_timeout_cb(simple_core_t * sc, void *baton)
31 {
32     simple_conn_t *scon = (simple_conn_t *) baton;
33     /* pqXXXXX: handle timeouts. */
34     conn_rec *c = scon->c;
35     conn_state_t *cs = c->cs;
36
37     cs = NULL;
38
39     ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
40                  "io timeout hit (?)");
41 }
42
43 static apr_status_t simple_io_process(simple_conn_t * scon)
44 {
45     apr_status_t rv;
46     simple_core_t *sc;
47     conn_rec *c;
48     conn_state_t *cs;
49
50     if (scon->c->clogging_input_filters && !scon->c->aborted) {
51         /* Since we have an input filter which 'cloggs' the input stream,
52          * like mod_ssl, lets just do the normal read from input filters,
53          * like the Worker MPM does.
54          */
55         ap_run_process_connection(scon->c);
56         if (scon->c->cs->state != CONN_STATE_SUSPENDED) {
57             scon->c->cs->state = CONN_STATE_LINGER;
58         }
59     }
60
61     sc = scon->sc;
62     c = scon->c;
63     cs = c->cs;
64
65     while (!c->aborted) {
66
67         cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR | APR_POLLIN;
68         rv = apr_pollcb_remove(sc->pollcb, &cs->pfd);
69         if (rv) {
70             ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
71                          "process_socket: apr_pollcb_remove failure");
72             /*AP_DEBUG_ASSERT(rv == APR_SUCCESS);*/
73         }
74         
75         if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
76             if (!c->aborted) {
77                 ap_run_process_connection(c);
78                 /* state will be updated upon return
79                  * fall thru to either wait for readability/timeout or
80                  * do lingering close
81                  */
82             }
83             else {
84                 cs->state = CONN_STATE_LINGER;
85             }
86         }
87
88         if (cs->state == CONN_STATE_WRITE_COMPLETION) {
89             ap_filter_t *output_filter = c->output_filters;
90             while (output_filter->next != NULL) {
91                 output_filter = output_filter->next;
92             }
93
94             rv = output_filter->frec->filter_func.out_func(output_filter,
95                                                            NULL);
96
97             if (rv != APR_SUCCESS) {
98                 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
99                              "network write failure in core output filter");
100                 cs->state = CONN_STATE_LINGER;
101             }
102             else if (c->data_in_output_filters) {
103                 /* Still in WRITE_COMPLETION_STATE:
104                  * Set a write timeout for this connection, and let the
105                  * event thread poll for writeability.
106                  */
107
108                 simple_register_timer(scon->sc,
109                                       simple_io_timeout_cb,
110                                       scon,
111                                       scon->c->base_server !=
112                                       NULL ? scon->c->base_server->
113                                       timeout : ap_server_conf->timeout,
114                                       scon->pool);
115
116                 cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
117
118                 rv = apr_pollcb_add(sc->pollcb, &cs->pfd);
119
120                 if (rv != APR_SUCCESS) {
121                     ap_log_error(APLOG_MARK, APLOG_WARNING, rv,
122                                  ap_server_conf,
123                                  "apr_pollcb_add: failed in write completion");
124                     AP_DEBUG_ASSERT(rv == APR_SUCCESS);
125                 }
126                 return APR_SUCCESS;
127             }
128             else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted) {
129                 c->cs->state = CONN_STATE_LINGER;
130             }
131             else if (c->data_in_input_filters) {
132                 cs->state = CONN_STATE_READ_REQUEST_LINE;
133             }
134             else {
135                 cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
136             }
137         }
138
139         if (cs->state == CONN_STATE_LINGER) {
140             ap_lingering_close(c);
141             apr_pool_destroy(scon->pool);
142             return APR_SUCCESS;
143         }
144
145         if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
146             simple_register_timer(scon->sc,
147                                   simple_io_timeout_cb,
148                                   scon,
149                                   scon->c->base_server !=
150                                   NULL ? scon->c->base_server->
151                                   timeout : ap_server_conf->timeout,
152                                   scon->pool);
153
154             cs->pfd.reqevents = APR_POLLIN;
155
156             rv = apr_pollcb_add(sc->pollcb, &cs->pfd);
157
158             if (rv) {
159                 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
160                              "process_socket: apr_pollcb_add failure in read request line");
161                 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
162             }
163
164             return APR_SUCCESS;
165         }
166     }
167
168     ap_lingering_close(c);
169     apr_pool_destroy(scon->pool);
170     return APR_SUCCESS;
171 }
172
173 static void *simple_io_invoke(apr_thread_t * thread, void *baton)
174 {
175     simple_sb_t *sb = (simple_sb_t *) baton;
176     simple_conn_t *scon = (simple_conn_t *) sb->baton;
177     apr_status_t rv;
178
179     scon->c->current_thread = thread;
180
181     rv = simple_io_process(scon);
182
183     if (rv) {
184         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf,
185                      "simple_io_invoke: simple_io_process failed (?)");
186     }
187
188     return NULL;
189 }
190
191 static void *simple_io_setup_conn(apr_thread_t * thread, void *baton)
192 {
193     apr_status_t rv;
194     ap_sb_handle_t *sbh;
195     conn_state_t *cs;
196     long conn_id = 0;
197     simple_sb_t *sb;
198     simple_conn_t *scon = (simple_conn_t *) baton;
199
200     /* pqXXXXX: remove this. */
201     ap_create_sb_handle(&sbh, scon->pool, 0, 0);
202
203     scon->ba = apr_bucket_alloc_create(scon->pool);
204
205     scon->c = ap_run_create_connection(scon->pool, ap_server_conf, scon->sock,
206                                        conn_id, sbh, scon->ba);
207
208     scon->c->cs = apr_pcalloc(scon->pool, sizeof(conn_state_t));
209     cs = scon->c->cs;
210     sb = apr_pcalloc(scon->pool, sizeof(simple_sb_t));
211
212     scon->c->current_thread = thread;
213
214     cs->pfd.p = scon->pool;
215     cs->pfd.desc_type = APR_POLL_SOCKET;
216     cs->pfd.desc.s = scon->sock;
217     cs->pfd.reqevents = APR_POLLIN;
218
219     sb->type = SIMPLE_PT_CORE_IO;
220     sb->baton = scon;
221     cs->pfd.client_data = sb;
222
223     ap_update_vhost_given_ip(scon->c);
224
225     rv = ap_run_pre_connection(scon->c, scon->sock);
226     if (rv != OK && rv != DONE) {
227         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
228                      "simple_io_setup_conn: connection aborted");
229         scon->c->aborted = 1;
230     }
231
232     scon->c->cs->state = CONN_STATE_READ_REQUEST_LINE;
233
234     rv = simple_io_process(scon);
235
236     if (rv) {
237         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf,
238                      "simple_io_setup_conn: simple_io_process failed (?)");
239     }
240
241     return NULL;
242 }
243
244 apr_status_t simple_io_accept(simple_core_t * sc, simple_sb_t * sb)
245 {
246     apr_status_t rv;
247     apr_pool_t *ptrans;
248     apr_socket_t *socket;
249     ap_listen_rec *lr = (ap_listen_rec *) sb->baton;
250
251     /* pqXXXXXX: Consider doing pool recycling like the event/worker MPMs do. */
252     apr_pool_create(&ptrans, NULL);
253
254     apr_pool_tag(ptrans, "transaction");
255
256     rv = apr_socket_accept(&socket, lr->sd, ptrans);
257     if (rv) {
258         /* pqXXXXXX: unixd.c has _tons_ of custom handling on return values
259          * from accept, but it seems really crazy, it either worked, or didn't, 
260          * but taking this approach of swallowing the error it is possible we have a 
261          * fatal error on our listening socket, but we don't notice.  
262          * 
263          * Need to discuss this on dev@
264          */
265         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
266                      "simple_io_accept: apr_socket_accept failed");
267         return APR_SUCCESS;
268     }
269     else {
270         simple_conn_t *scon = apr_pcalloc(ptrans, sizeof(simple_conn_t));
271         scon->pool = ptrans;
272         scon->sock = socket;
273         scon->sc = sc;
274
275         return apr_thread_pool_push(sc->workers,
276                                     simple_io_setup_conn,
277                                     scon,
278                                     APR_THREAD_TASK_PRIORITY_NORMAL, NULL);
279     }
280
281     return APR_SUCCESS;
282 }
283
284 apr_status_t simple_io_event_process(simple_core_t * sc, simple_sb_t * sb)
285 {
286     /* pqXXXXX: In theory, if we have non-blocking operations on the connection
287      *  we can do them here, before pushing to another thread, thats just
288      * not implemented right now.
289      */
290     return apr_thread_pool_push(sc->workers,
291                                 simple_io_invoke,
292                                 sb, APR_THREAD_TASK_PRIORITY_NORMAL, NULL);
293 }