Apache HTTPD
h2_c1.c
Go to the documentation of this file.
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 <assert.h>
18#include <apr_strings.h>
19
20#include <ap_mpm.h>
21#include <ap_mmn.h>
22
23#include <httpd.h>
24#include <http_core.h>
25#include <http_config.h>
26#include <http_log.h>
27#include <http_connection.h>
28#include <http_protocol.h>
29#include <http_request.h>
30#include <http_ssl.h>
31
32#include <mpm_common.h>
33
34#include "h2_private.h"
35#include "h2.h"
36#include "h2_bucket_beam.h"
37#include "h2_config.h"
38#include "h2_conn_ctx.h"
39#include "h2_mplx.h"
40#include "h2_session.h"
41#include "h2_stream.h"
42#include "h2_protocol.h"
43#include "h2_workers.h"
44#include "h2_c1.h"
45#include "h2_version.h"
46#include "h2_util.h"
47
48static struct h2_workers *workers;
49
50static int async_mpm;
51
54
78
85
86
88{
89 h2_session *session;
91 apr_status_t rv;
92
93 if (!workers) {
95 "workers not initialized");
96 rv = APR_EGENERAL;
97 goto cleanup;
98 }
99
100 rv = h2_session_create(&session, c, r, s, workers);
101 if (APR_SUCCESS != rv) goto cleanup;
102
104 ap_assert(ctx);
106 /* remove the input filter of mod_reqtimeout, now that the connection
107 * is established and we have switched to h2. reqtimeout has supervised
108 * possibly configured handshake timeouts and needs to get out of the way
109 * now since the rest of its state handling assumes http/1.x to take place. */
110 ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout");
111
112cleanup:
113 return rv;
114}
115
117{
119 int mpm_state = 0;
121
123 ap_assert(conn_ctx->session);
124 do {
125 if (c->cs) {
126 c->cs->sense = CONN_SENSE_DEFAULT;
127 c->cs->state = CONN_STATE_HANDLER;
128 }
129
131
134 H2_SSSN_LOG(APLOGNO(03045), conn_ctx->session,
135 "process, closing conn"));
136 c->keepalive = AP_CONN_CLOSE;
137 }
138 else {
139 c->keepalive = AP_CONN_KEEPALIVE;
140 }
141
143 break;
144 }
145 } while (!async_mpm
146 && c->keepalive == AP_CONN_KEEPALIVE
148
149 if (c->cs) {
150 switch (conn_ctx->session->state) {
155 c->cs->state = CONN_STATE_WRITE_COMPLETION;
156 if (c->cs && !conn_ctx->session->remote.emitted_count) {
157 /* let the MPM know that we are not done and want
158 * the Timeout behaviour instead of a KeepAliveTimeout
159 * See PR 63534.
160 */
161 c->cs->sense = CONN_SENSE_WANT_READ;
162 }
163 break;
166 default:
167 c->cs->state = CONN_STATE_LINGER;
168 break;
169 }
170 }
171
172 return APR_SUCCESS;
173}
174
176{
178
179 if (conn_ctx && conn_ctx->session) {
181 return (status == APR_SUCCESS)? DONE : status;
182 }
183 return DONE;
184}
185
187{
188 if (!c->master) {
189 int is_tls = ap_ssl_conn_is_ssl(c);
190 const char *needed_protocol = is_tls? "h2" : "h2c";
191 int h2_direct = h2_config_cgeti(c, H2_CONF_DIRECT);
192
193 if (h2_direct < 0) {
194 h2_direct = is_tls? 0 : 1;
195 }
196 return (h2_direct && ap_is_allowed_protocol(c, NULL, NULL, needed_protocol));
197 }
198 return 0;
199}
200
202{
203 if (!r->connection->master) {
204 int h2_upgrade = h2_config_rgeti(r, H2_CONF_UPGRADE);
205 return h2_upgrade > 0 || (h2_upgrade < 0 && !ap_ssl_conn_is_ssl(r->connection));
206 }
207 return 0;
208}
209
211{
214
215 if (c->master) goto declined;
217
218 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, process_conn");
219 if (!ctx && c->keepalives == 0) {
220 const char *proto = ap_get_protocol(c);
221
222 if (APLOGctrace1(c)) {
223 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, process_conn, "
224 "new connection using protocol '%s', direct=%d, "
225 "tls acceptable=%d", proto, h2_c1_allows_direct(c),
227 }
228
229 if (!strcmp(AP_PROTOCOL_HTTP1, proto)
232 /* Fresh connection still is on http/1.1 and H2Direct is enabled.
233 * Otherwise connection is in a fully acceptable state.
234 * -> peek at the first 24 incoming bytes
235 */
237 char *peek = NULL;
239
240 temp = apr_brigade_create(c->pool, c->bucket_alloc);
241 status = ap_get_brigade(c->input_filters, temp,
243
244 if (status != APR_SUCCESS) {
246 "h2_h2, error reading 24 bytes speculative");
248 return DECLINED;
249 }
250
252 if ((peeklen >= 24) && !memcmp(H2_MAGIC_TOKEN, peek, 24)) {
254 "h2_h2, direct mode detected");
255 ctx = h2_conn_ctx_create_for_c1(c, c->base_server,
256 ap_ssl_conn_is_ssl(c)? "h2" : "h2c");
257 }
258 else if (APLOGctrace2(c)) {
260 "h2_h2, not detected in %d bytes(base64): %s",
262 }
264 }
265 }
266
267 if (!ctx) goto declined;
268
269 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "process_conn");
270 if (!ctx->session) {
271 status = h2_c1_setup(c, NULL, ctx->server? ctx->server : c->base_server);
272 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, c, "conn_setup");
273 if (status != APR_SUCCESS) {
275 return !OK;
276 }
277 }
278 h2_c1_run(c);
279 return OK;
280
282 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, declined");
283 return DECLINED;
284}
285
287{
289
290 /* secondary connection? */
291 if (c->master) {
292 return DECLINED;
293 }
294
296 if (ctx) {
297 /* If the session has been closed correctly already, we will not
298 * find a h2_conn_ctx_there. The presence indicates that the session
299 * is still ongoing. */
300 return h2_c1_pre_close(ctx, c);
301 }
302 return DECLINED;
303}
304
305static const char* const mod_ssl[] = { "mod_ssl.c", NULL};
306static const char* const mod_reqtimeout[] = { "mod_ssl.c", "mod_reqtimeout.c", NULL};
307
309{
310 /* Our main processing needs to run quite late. Definitely after mod_ssl,
311 * as we need its connection filters, but also before reqtimeout as its
312 * method of timeouts is specific to HTTP/1.1 (as of now).
313 * The core HTTP/1 processing run as REALLY_LAST, so we will have
314 * a chance to take over before it.
315 */
318
319 /* One last chance to properly say goodbye if we have not done so
320 * already. */
322}
323
Module Magic Number.
Apache Multi-Processing Module library.
APR Strings library.
void ap_hook_pre_close_connection(ap_HOOK_pre_close_connection_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition connection.c:44
void ap_hook_process_connection(ap_HOOK_process_connection_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition connection.c:42
request_rec * r
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
apr_status_t ap_remove_input_filter_byhandle(ap_filter_t *next, const char *handle)
apr_status_t ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
#define APLOGNO(n)
Definition http_log.h:117
#define APLOGctrace2(c)
Definition http_log.h:258
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_cerror
Definition http_log.h:498
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_TRACE2
Definition http_log.h:73
#define APLOG_TRACE1
Definition http_log.h:72
#define APLOGctrace1(c)
Definition http_log.h:257
#define APLOG_DEBUG
Definition http_log.h:71
const char * ap_get_protocol(conn_rec *c)
Definition protocol.c:2397
int ap_is_allowed_protocol(conn_rec *c, request_rec *r, server_rec *s, const char *protocol)
Definition protocol.c:2564
#define AP_PROTOCOL_HTTP1
int ap_ssl_conn_is_ssl(conn_rec *c)
Definition ssl.c:90
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_STATUS_IS_EOF(s)
Definition apr_errno.h:567
apr_brigade_flush void * ctx
@ APR_BLOCK_READ
Definition apr_buckets.h:58
#define APR_HOOK_LAST
Definition apr_hooks.h:305
#define APR_RETRIEVE_OPTIONAL_FN(name)
#define APR_OPTIONAL_FN_TYPE(name)
#define ap_assert(exp)
Definition httpd.h:2271
@ AP_CONN_KEEPALIVE
Definition httpd.h:1146
@ AP_CONN_CLOSE
Definition httpd.h:1145
@ CONN_STATE_LINGER
Definition httpd.h:1264
@ CONN_STATE_WRITE_COMPLETION
Definition httpd.h:1262
@ CONN_STATE_HANDLER
Definition httpd.h:1261
@ CONN_SENSE_DEFAULT
Definition httpd.h:1272
@ CONN_SENSE_WANT_READ
Definition httpd.h:1273
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void const char apr_status_t(* cleanup)(void *))
apr_vformatter_buff_t * c
Definition apr_lib.h:175
const char * s
Definition apr_strings.h:95
int int status
apr_int64_t apr_time_t
Definition apr_time.h:45
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
#define AP_MPMQ_MPM_STATE
Definition ap_mpm.h:174
#define AP_MPMQ_IS_ASYNC
Definition ap_mpm.h:176
#define AP_MPMQ_STOPPING
Definition ap_mpm.h:142
@ H2_SESSION_ST_INIT
Definition h2.h:122
@ H2_SESSION_ST_IDLE
Definition h2.h:124
@ H2_SESSION_ST_CLEANUP
Definition h2.h:127
@ H2_SESSION_ST_DONE
Definition h2.h:123
@ H2_SESSION_ST_WAIT
Definition h2.h:126
@ H2_SESSION_ST_BUSY
Definition h2.h:125
const char * H2_MAGIC_TOKEN
Definition h2_protocol.c:56
apr_status_t h2_c1_pre_close(struct h2_conn_ctx_t *ctx, conn_rec *c)
Definition h2_c1.c:175
apr_status_t h2_c1_run(conn_rec *c)
Definition h2_c1.c:116
apr_status_t h2_c1_setup(conn_rec *c, request_rec *r, server_rec *s)
Definition h2_c1.c:87
void h2_c1_child_stopping(apr_pool_t *pool, int graceful)
Definition h2_c1.c:79
apr_OFN_ap_logio_add_bytes_in_t * h2_c_logio_add_bytes_in
Definition h2_c1.c:52
void h2_c1_register_hooks(void)
Definition h2_c1.c:308
static struct h2_workers * workers
Definition h2_c1.c:48
int h2_c1_allows_direct(conn_rec *c)
Definition h2_c1.c:186
static const char *const mod_reqtimeout[]
Definition h2_c1.c:306
static int async_mpm
Definition h2_c1.c:50
apr_status_t h2_c1_child_init(apr_pool_t *pool, server_rec *s)
Definition h2_c1.c:55
static const char *const mod_ssl[]
Definition h2_c1.c:305
apr_OFN_ap_logio_add_bytes_out_t * h2_c_logio_add_bytes_out
Definition h2_c1.c:53
int h2_c1_can_upgrade(request_rec *r)
Definition h2_c1.c:201
static int h2_c1_hook_pre_close(conn_rec *c)
Definition h2_c1.c:286
static int h2_c1_hook_process_connection(conn_rec *c)
Definition h2_c1.c:210
int h2_config_rgeti(request_rec *r, h2_config_var_t var)
Definition h2_config.c:527
void h2_get_workers_config(server_rec *s, int *pminw, int *pmaxw, apr_time_t *pidle_limit)
Definition h2_config.c:1007
void h2_config_init(apr_pool_t *pool)
Definition h2_config.c:134
int h2_config_cgeti(conn_rec *c, h2_config_var_t var)
Definition h2_config.c:496
@ H2_CONF_UPGRADE
Definition h2_config.h:35
@ H2_CONF_DIRECT
Definition h2_config.h:33
h2_conn_ctx_t * h2_conn_ctx_create_for_c1(conn_rec *c1, server_rec *s, const char *protocol)
Definition h2_conn_ctx.c:54
void h2_conn_ctx_assign_session(h2_conn_ctx_t *ctx, struct h2_session *session)
Definition h2_conn_ctx.c:71
void h2_conn_ctx_detach(conn_rec *c)
Definition h2_conn_ctx.c:37
#define h2_conn_ctx_get(c)
Definition h2_conn_ctx.h:78
apr_status_t h2_mplx_c1_child_init(apr_pool_t *pool, server_rec *s)
Definition h2_mplx.c:83
int h2_protocol_is_acceptable_c1(conn_rec *c, request_rec *r, int require_all)
apr_status_t h2_session_pre_close(h2_session *session, int async)
apr_status_t h2_session_process(h2_session *session, int async)
apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *r, server_rec *s, h2_workers *workers)
Definition h2_session.c:875
#define H2_SSSN_LOG(aplogno, s, msg)
Definition h2_session.h:201
const char * h2_util_base64url_encode(const char *data, apr_size_t dlen, apr_pool_t *pool)
Definition h2_util.c:182
void h2_workers_shutdown(h2_workers *workers, int graceful)
Definition h2_workers.c:543
h2_workers * h2_workers_create(server_rec *s, apr_pool_t *pchild, int max_slots, int min_active, apr_time_t idle_limit)
Definition h2_workers.c:422
Apache Configuration.
Apache connection library.
CORE HTTP Daemon.
Apache Logging library.
HTTP protocol handling.
Apache Request library.
SSL protocol handling.
HTTP Daemon routines.
static void ap_logio_add_bytes_in(conn_rec *c, apr_off_t bytes)
Definition mod_logio.c:77
static void ap_logio_add_bytes_out(conn_rec *c, apr_off_t bytes)
Definition mod_logio.c:67
return NULL
Definition mod_so.c:359
Multi-Processing Modules functions.
static int mpm_state
Structure to store things which are per connection.
Definition httpd.h:1152
conn_rec * master
Definition httpd.h:1248
volatile apr_time_t idle_limit
Definition h2_workers.c:81
A structure that represents the current request.
Definition httpd.h:845
conn_rec * connection
Definition httpd.h:849
A structure to store information for each virtual server.
Definition httpd.h:1322
@ AP_MODE_SPECULATIVE
Definition util_filter.h:53