]> granicus.if.org Git - apache/blob - modules/http2/mod_h2.c
merged latest changes in 2.4.x
[apache] / modules / http2 / mod_h2.c
1 /* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <apr_optional.h>
17 #include <apr_optional_hooks.h>
18 #include <apr_want.h>
19
20 #include <httpd.h>
21 #include <http_log.h>
22
23 #include "mod_h2.h"
24
25 #include <nghttp2/nghttp2.h>
26 #include "h2_stream.h"
27 #include "h2_alt_svc.h"
28 #include "h2_conn.h"
29 #include "h2_task.h"
30 #include "h2_session.h"
31 #include "h2_config.h"
32 #include "h2_ctx.h"
33 #include "h2_h2.h"
34 #include "h2_switch.h"
35 #include "h2_version.h"
36
37
38 static void h2_hooks(apr_pool_t *pool);
39
40 AP_DECLARE_MODULE(h2) = {
41     STANDARD20_MODULE_STUFF,
42     NULL,
43     NULL,
44     h2_config_create_svr, /* func to create per server config */
45     h2_config_merge,      /* func to merge per server config */
46     h2_cmds,              /* command handlers */
47     h2_hooks
48 };
49
50 /* The module initialization. Called once as apache hook, before any multi
51  * processing (threaded or not) happens. It is typically at least called twice, 
52  * see
53  * http://wiki.apache.org/httpd/ModuleLife
54  * Since the first run is just a "practise" run, we want to initialize for real
55  * only on the second try. This defeats the purpose of the first dry run a bit, 
56  * since apache wants to verify that a new configuration actually will work. 
57  * So if we have trouble with the configuration, this will only be detected 
58  * when the server has already switched.
59  * On the other hand, when we initialize lib nghttp2, all possible crazy things 
60  * might happen and this might even eat threads. So, better init on the real 
61  * invocation, for now at least.
62  */
63 static int h2_post_config(apr_pool_t *p, apr_pool_t *plog,
64                           apr_pool_t *ptemp, server_rec *s)
65 {
66     void *data = NULL;
67     const char *mod_h2_init_key = "mod_h2_init_counter";
68     nghttp2_info *ngh2;
69     apr_status_t status;
70     (void)plog;(void)ptemp;
71     
72     apr_pool_userdata_get(&data, mod_h2_init_key, s->process->pool);
73     if ( data == NULL ) {
74         ap_log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
75                      "initializing post config dry run");
76         apr_pool_userdata_set((const void *)1, mod_h2_init_key,
77                               apr_pool_cleanup_null, s->process->pool);
78         return APR_SUCCESS;
79     }
80     
81     ngh2 = nghttp2_version(0);
82     ap_log_error( APLOG_MARK, APLOG_INFO, 0, s,
83                  "mod_h2 (v%s, nghttp2 %s), initializing...",
84                  MOD_H2_VERSION, ngh2? ngh2->version_str : "unknown");
85     
86     switch (h2_conn_mpm_type()) {
87         case H2_MPM_EVENT:
88         case H2_MPM_WORKER:
89             /* all fine, we know these ones */
90             break;
91         case H2_MPM_PREFORK:
92             /* ok, we now know how to handle that one */
93             break;
94         case H2_MPM_UNKNOWN:
95             /* ??? */
96             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
97                          "post_config: mpm type unknown");
98             break;
99     }
100     
101     status = h2_h2_init(p, s);
102     if (status == APR_SUCCESS) {
103         status = h2_switch_init(p, s);
104     }
105     
106     return status;
107 }
108
109 /* Runs once per created child process. Perform any process 
110  * related initionalization here.
111  */
112 static void h2_child_init(apr_pool_t *pool, server_rec *s)
113 {
114     /* Set up our connection processing */
115     apr_status_t status = h2_conn_child_init(pool, s);
116     if (status != APR_SUCCESS) {
117         ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
118                      APLOGNO(02949) "initializing connection handling");
119     }
120 }
121
122 /* Install this module into the apache2 infrastructure.
123  */
124 static void h2_hooks(apr_pool_t *pool)
125 {
126     static const char *const mod_ssl[] = { "mod_ssl.c", NULL};
127     
128     ap_log_perror(APLOG_MARK, APLOG_INFO, 0, pool, "installing hooks");
129     
130     /* Run once after configuration is set, but before mpm children initialize.
131      */
132     ap_hook_post_config(h2_post_config, mod_ssl, NULL, APR_HOOK_MIDDLE);
133     
134     /* Run once after a child process has been created.
135      */
136     ap_hook_child_init(h2_child_init, NULL, NULL, APR_HOOK_MIDDLE);
137
138     h2_h2_register_hooks();
139     h2_switch_register_hooks();
140     h2_task_register_hooks();
141
142     h2_alt_svc_register_hooks();
143     
144 }
145
146