/src/httpd/server/connection.c
Line | Count | Source (jump to first uncovered line) |
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_strings.h" |
19 | | |
20 | | #include "ap_config.h" |
21 | | #include "httpd.h" |
22 | | #include "http_connection.h" |
23 | | #include "http_request.h" |
24 | | #include "http_protocol.h" |
25 | | #include "ap_mpm.h" |
26 | | #include "http_config.h" |
27 | | #include "http_core.h" |
28 | | #include "http_vhost.h" |
29 | | #include "scoreboard.h" |
30 | | #include "http_log.h" |
31 | | #include "util_filter.h" |
32 | | |
33 | | APR_HOOK_STRUCT( |
34 | | APR_HOOK_LINK(create_connection) |
35 | | APR_HOOK_LINK(process_connection) |
36 | | APR_HOOK_LINK(pre_connection) |
37 | | APR_HOOK_LINK(pre_close_connection) |
38 | | APR_HOOK_LINK(create_secondary_connection) |
39 | | ) |
40 | | AP_IMPLEMENT_HOOK_RUN_FIRST(conn_rec *,create_connection, |
41 | | (apr_pool_t *p, server_rec *server, apr_socket_t *csd, long conn_id, void *sbh, apr_bucket_alloc_t *alloc), |
42 | | (p, server, csd, conn_id, sbh, alloc), NULL) |
43 | | AP_IMPLEMENT_HOOK_RUN_FIRST(int,process_connection,(conn_rec *c),(c),DECLINED) |
44 | | AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED) |
45 | | AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_close_connection,(conn_rec *c),(c),OK,DECLINED) |
46 | | AP_IMPLEMENT_HOOK_RUN_FIRST(conn_rec *,create_secondary_connection, |
47 | | (apr_pool_t *p, conn_rec *master, apr_bucket_alloc_t *alloc), |
48 | | (p, master, alloc), NULL) |
49 | | |
50 | | AP_DECLARE(conn_rec *) ap_create_connection(apr_pool_t *p, |
51 | | server_rec *server, |
52 | | apr_socket_t *csd, |
53 | | long conn_id, void *sbh, |
54 | | apr_bucket_alloc_t *alloc, |
55 | | unsigned int outgoing) |
56 | 0 | { |
57 | 0 | conn_rec *c; |
58 | | |
59 | | /* Some day it may be flags, so deny anything but 0 or 1 for now */ |
60 | 0 | if (outgoing > 1) { |
61 | 0 | return NULL; |
62 | 0 | } |
63 | | |
64 | 0 | c = ap_run_create_connection(p, server, csd, conn_id, sbh, alloc); |
65 | |
|
66 | 0 | if (c && outgoing) { |
67 | 0 | c->outgoing = 1; |
68 | 0 | } |
69 | |
|
70 | 0 | return c; |
71 | 0 | } |
72 | | |
73 | | AP_DECLARE(conn_rec *) ap_create_secondary_connection(apr_pool_t *p, |
74 | | conn_rec *master, |
75 | | apr_bucket_alloc_t *alloc) |
76 | 0 | { |
77 | 0 | return ap_run_create_secondary_connection(p, master, alloc); |
78 | 0 | } |
79 | | |
80 | | /* |
81 | | * More machine-dependent networking gooo... on some systems, |
82 | | * you've got to be *really* sure that all the packets are acknowledged |
83 | | * before closing the connection, since the client will not be able |
84 | | * to see the last response if their TCP buffer is flushed by a RST |
85 | | * packet from us, which is what the server's TCP stack will send |
86 | | * if it receives any request data after closing the connection. |
87 | | * |
88 | | * In an ideal world, this function would be accomplished by simply |
89 | | * setting the socket option SO_LINGER and handling it within the |
90 | | * server's TCP stack while the process continues on to the next request. |
91 | | * Unfortunately, it seems that most (if not all) operating systems |
92 | | * block the server process on close() when SO_LINGER is used. |
93 | | * For those that don't, see USE_SO_LINGER below. For the rest, |
94 | | * we have created a home-brew lingering_close. |
95 | | * |
96 | | * Many operating systems tend to block, puke, or otherwise mishandle |
97 | | * calls to shutdown only half of the connection. You should define |
98 | | * NO_LINGCLOSE in ap_config.h if such is the case for your system. |
99 | | */ |
100 | | #ifndef MAX_SECS_TO_LINGER |
101 | | #define MAX_SECS_TO_LINGER 30 |
102 | | #endif |
103 | | |
104 | | AP_CORE_DECLARE(apr_status_t) ap_shutdown_conn(conn_rec *c, int flush) |
105 | 0 | { |
106 | 0 | apr_status_t rv; |
107 | 0 | apr_bucket_brigade *bb; |
108 | 0 | apr_bucket *b; |
109 | |
|
110 | 0 | bb = apr_brigade_create(c->pool, c->bucket_alloc); |
111 | |
|
112 | 0 | if (flush) { |
113 | | /* FLUSH bucket */ |
114 | 0 | b = apr_bucket_flush_create(c->bucket_alloc); |
115 | 0 | APR_BRIGADE_INSERT_TAIL(bb, b); |
116 | 0 | } |
117 | | |
118 | | /* End Of Connection bucket */ |
119 | 0 | b = ap_bucket_eoc_create(c->bucket_alloc); |
120 | 0 | APR_BRIGADE_INSERT_TAIL(bb, b); |
121 | |
|
122 | 0 | rv = ap_pass_brigade(c->output_filters, bb); |
123 | 0 | apr_brigade_destroy(bb); |
124 | 0 | return rv; |
125 | 0 | } |
126 | | |
127 | | AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) |
128 | 0 | { |
129 | 0 | (void)ap_shutdown_conn(c, 1); |
130 | 0 | } |
131 | | |
132 | | AP_DECLARE(int) ap_prep_lingering_close(conn_rec *c) |
133 | 0 | { |
134 | | /* Give protocol handlers one last chance to raise their voice */ |
135 | 0 | ap_run_pre_close_connection(c); |
136 | | |
137 | 0 | if (c->sbh) { |
138 | 0 | ap_update_child_status(c->sbh, SERVER_CLOSING, NULL); |
139 | 0 | } |
140 | 0 | return 0; |
141 | 0 | } |
142 | | |
143 | | /* we now proceed to read from the client until we get EOF, or until |
144 | | * MAX_SECS_TO_LINGER has passed. The reasons for doing this are |
145 | | * documented in a draft: |
146 | | * |
147 | | * http://tools.ietf.org/html/draft-ietf-http-connection-00.txt |
148 | | * |
149 | | * in a nutshell -- if we don't make this effort we risk causing |
150 | | * TCP RST packets to be sent which can tear down a connection before |
151 | | * all the response data has been sent to the client. |
152 | | */ |
153 | | #define SECONDS_TO_LINGER 2 |
154 | | |
155 | | AP_DECLARE(int) ap_start_lingering_close(conn_rec *c) |
156 | 0 | { |
157 | 0 | apr_socket_t *csd = ap_get_conn_socket(c); |
158 | |
|
159 | 0 | ap_assert(csd != NULL); |
160 | | |
161 | 0 | if (ap_prep_lingering_close(c)) { |
162 | 0 | return 1; |
163 | 0 | } |
164 | | |
165 | | /* Close the connection, being careful to send out whatever is still |
166 | | * in our buffers. If possible, try to avoid a hard close until the |
167 | | * client has ACKed our FIN and/or has stopped sending us data. |
168 | | */ |
169 | | |
170 | | /* Send any leftover data to the client, but never try to again */ |
171 | 0 | ap_flush_conn(c); |
172 | |
|
173 | | #ifdef NO_LINGCLOSE |
174 | | return 1; |
175 | | #else |
176 | | /* Shut down the socket for write, which will send a FIN |
177 | | * to the peer. |
178 | | */ |
179 | 0 | return (c->aborted || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE)); |
180 | 0 | #endif |
181 | 0 | } |
182 | | |
183 | | AP_DECLARE(void) ap_lingering_close(conn_rec *c) |
184 | 0 | { |
185 | 0 | char dummybuf[512]; |
186 | 0 | apr_size_t nbytes; |
187 | 0 | apr_time_t now, timeup = 0; |
188 | 0 | apr_socket_t *csd = ap_get_conn_socket(c); |
189 | |
|
190 | 0 | if (!csd) { |
191 | | /* Be safe with third-party modules that: |
192 | | * ap_set_core_module_config(c->conn_config, NULL) |
193 | | * to no-op ap_lingering_close(). |
194 | | */ |
195 | 0 | c->aborted = 1; |
196 | 0 | return; |
197 | 0 | } |
198 | | |
199 | 0 | if (ap_start_lingering_close(c)) { |
200 | 0 | apr_socket_close(csd); |
201 | 0 | return; |
202 | 0 | } |
203 | | |
204 | | /* Read available data from the client whilst it continues sending |
205 | | * it, for a maximum time of MAX_SECS_TO_LINGER. If the client |
206 | | * does not send any data within 2 seconds (a value pulled from |
207 | | * Apache 1.3 which seems to work well), give up. |
208 | | */ |
209 | 0 | apr_socket_timeout_set(csd, apr_time_from_sec(SECONDS_TO_LINGER)); |
210 | 0 | apr_socket_opt_set(csd, APR_INCOMPLETE_READ, 1); |
211 | | |
212 | | /* The common path here is that the initial apr_socket_recv() call |
213 | | * will return 0 bytes read; so that case must avoid the expensive |
214 | | * apr_time_now() call and time arithmetic. */ |
215 | |
|
216 | 0 | do { |
217 | 0 | nbytes = sizeof(dummybuf); |
218 | 0 | if (apr_socket_recv(csd, dummybuf, &nbytes) || nbytes == 0) |
219 | 0 | break; |
220 | | |
221 | 0 | now = apr_time_now(); |
222 | 0 | if (timeup == 0) { |
223 | | /* |
224 | | * First time through; |
225 | | * calculate now + 30 seconds (MAX_SECS_TO_LINGER). |
226 | | * |
227 | | * If some module requested a shortened waiting period, only wait for |
228 | | * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain |
229 | | * DoS attacks. |
230 | | */ |
231 | 0 | if (apr_table_get(c->notes, "short-lingering-close")) { |
232 | 0 | timeup = now + apr_time_from_sec(SECONDS_TO_LINGER); |
233 | 0 | } |
234 | 0 | else { |
235 | 0 | timeup = now + apr_time_from_sec(MAX_SECS_TO_LINGER); |
236 | 0 | } |
237 | 0 | continue; |
238 | 0 | } |
239 | 0 | } while (now < timeup); |
240 | | |
241 | 0 | apr_socket_close(csd); |
242 | 0 | } |
243 | | |
244 | | AP_CORE_DECLARE(void) ap_process_connection(conn_rec *c, void *csd) |
245 | 0 | { |
246 | 0 | ap_update_vhost_given_ip(c); |
247 | |
|
248 | 0 | ap_pre_connection(c, csd); |
249 | |
|
250 | 0 | if (!c->aborted) { |
251 | 0 | ap_run_process_connection(c); |
252 | 0 | } |
253 | 0 | } |