Apache HTTPD
h2_config.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
19#include <apr_hash.h>
20#include <apr_lib.h>
21
22#include <httpd.h>
23#include <http_core.h>
24#include <http_config.h>
25#include <http_log.h>
26#include <http_vhost.h>
27
28#include <ap_mpm.h>
29
30#include <apr_strings.h>
31
32#include "h2.h"
33#include "h2_conn_ctx.h"
34#include "h2_c1.h"
35#include "h2_config.h"
36#include "h2_protocol.h"
37#include "h2_private.h"
38
39#define DEF_VAL (-1)
40
41#define H2_CONFIG_GET(a, b, n) \
42 (((a)->n == DEF_VAL)? (b) : (a))->n
43
44#define H2_CONFIG_SET(a, n, v) \
45 ((a)->n = v)
46
47#define CONFIG_CMD_SET(cmd,dir,var,val) \
48 h2_config_seti(((cmd)->path? (dir) : NULL), h2_config_sget((cmd)->server), var, val)
49
50#define CONFIG_CMD_SET64(cmd,dir,var,val) \
51 h2_config_seti64(((cmd)->path? (dir) : NULL), h2_config_sget((cmd)->server), var, val)
52
53/* Apache httpd module configuration for h2. */
54typedef struct h2_config {
55 const char *name;
56 int h2_max_streams; /* max concurrent # streams (http2) */
57 int h2_window_size; /* stream window size (http2) */
58 int min_workers; /* min # of worker threads/child */
59 int max_workers; /* max # of worker threads/child */
60 apr_interval_time_t idle_limit; /* max duration for idle workers */
61 int stream_max_mem_size; /* max # bytes held in memory/stream */
62 int h2_direct; /* if mod_h2 is active directly */
63 int modern_tls_only; /* Accept only modern TLS in HTTP/2 connections */
64 int h2_upgrade; /* Allow HTTP/1 upgrade to h2/h2c */
65 apr_int64_t tls_warmup_size; /* Amount of TLS data to send before going full write size */
66 int tls_cooldown_secs; /* Seconds of idle time before going back to small TLS records */
67 int h2_push; /* if HTTP/2 server push is enabled */
68 struct apr_hash_t *priorities; /* map of content-type to h2_priority records */
69
70 int push_diary_size; /* # of entries in push diary */
71 int copy_files; /* if files shall be copied vs setaside on output */
72 apr_array_header_t *push_list; /* list of h2_push_res configurations */
73 apr_table_t *early_headers; /* HTTP headers for a 103 response */
74 int early_hints; /* support status code 103 */
79 int max_data_frame_len; /* max # bytes in a single h2 DATA frame */
80 int proxy_requests; /* act as forward proxy */
81 int h2_websockets; /* if mod_h2 negotiating WebSockets */
83
84typedef struct h2_dir_config {
85 const char *name;
86 int h2_upgrade; /* Allow HTTP/1 upgrade to h2/h2c */
87 int h2_push; /* if HTTP/2 server push is enabled */
88 apr_array_header_t *push_list; /* list of h2_push_res configurations */
89 apr_table_t *early_headers; /* HTTP headers for a 103 response */
90 int early_hints; /* support status code 103 */
93
94
96 "default",
97 100, /* max_streams */
98 H2_INITIAL_WINDOW_SIZE, /* window_size */
99 -1, /* min workers */
100 -1, /* max workers */
101 apr_time_from_sec(10 * 60), /* workers idle limit */
102 32 * 1024, /* stream max mem size */
103 -1, /* h2 direct mode */
104 1, /* modern TLS only */
105 -1, /* HTTP/1 Upgrade support */
106 1024*1024, /* TLS warmup size */
107 1, /* TLS cooldown secs */
108 1, /* HTTP/2 server push enabled */
109 NULL, /* map of content-type to priorities */
110 256, /* push diary size */
111 0, /* copy files across threads */
112 NULL, /* push list */
113 NULL, /* early headers */
114 0, /* early hints, http status 103 */
115 0, /* padding bits */
116 1, /* padding always */
117 1, /* stream output buffered */
118 -1, /* beam timeout */
119 0, /* max DATA frame len, 0 == no extra limit */
120 0, /* forward proxy */
121 0, /* WebSockets negotiation, enabled */
122};
123
125 "default",
126 -1, /* HTTP/1 Upgrade support */
127 -1, /* HTTP/2 server push enabled */
128 NULL, /* push list */
129 NULL, /* early headers */
130 -1, /* early hints, http status 103 */
131 -1, /* beam timeout */
132};
133
135{
136 (void)pool;
137}
138
140{
141 h2_config *conf = (h2_config *)apr_pcalloc(pool, sizeof(h2_config));
142 char *name = apr_pstrcat(pool, "srv[", s->defn_name, "]", NULL);
143
144 conf->name = name;
145 conf->h2_max_streams = DEF_VAL;
146 conf->h2_window_size = DEF_VAL;
147 conf->min_workers = DEF_VAL;
148 conf->max_workers = DEF_VAL;
149 conf->idle_limit = DEF_VAL;
151 conf->h2_direct = DEF_VAL;
152 conf->modern_tls_only = DEF_VAL;
153 conf->h2_upgrade = DEF_VAL;
154 conf->tls_warmup_size = DEF_VAL;
156 conf->h2_push = DEF_VAL;
157 conf->priorities = NULL;
158 conf->push_diary_size = DEF_VAL;
159 conf->copy_files = DEF_VAL;
160 conf->push_list = NULL;
161 conf->early_headers = NULL;
162 conf->early_hints = DEF_VAL;
163 conf->padding_bits = DEF_VAL;
164 conf->padding_always = DEF_VAL;
165 conf->output_buffered = DEF_VAL;
166 conf->stream_timeout = DEF_VAL;
168 conf->proxy_requests = DEF_VAL;
169 conf->h2_websockets = DEF_VAL;
170 return conf;
171}
172
173static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
174{
176 h2_config *add = (h2_config *)addv;
178 char *name = apr_pstrcat(pool, "merged[", add->name, ", ", base->name, "]", NULL);
179 n->name = name;
180
181 n->h2_max_streams = H2_CONFIG_GET(add, base, h2_max_streams);
182 n->h2_window_size = H2_CONFIG_GET(add, base, h2_window_size);
183 n->min_workers = H2_CONFIG_GET(add, base, min_workers);
184 n->max_workers = H2_CONFIG_GET(add, base, max_workers);
185 n->idle_limit = H2_CONFIG_GET(add, base, idle_limit);
186 n->stream_max_mem_size = H2_CONFIG_GET(add, base, stream_max_mem_size);
187 n->h2_direct = H2_CONFIG_GET(add, base, h2_direct);
188 n->modern_tls_only = H2_CONFIG_GET(add, base, modern_tls_only);
189 n->h2_upgrade = H2_CONFIG_GET(add, base, h2_upgrade);
190 n->tls_warmup_size = H2_CONFIG_GET(add, base, tls_warmup_size);
191 n->tls_cooldown_secs = H2_CONFIG_GET(add, base, tls_cooldown_secs);
192 n->h2_push = H2_CONFIG_GET(add, base, h2_push);
193 if (add->priorities && base->priorities) {
194 n->priorities = apr_hash_overlay(pool, add->priorities, base->priorities);
195 }
196 else {
197 n->priorities = add->priorities? add->priorities : base->priorities;
198 }
199 n->push_diary_size = H2_CONFIG_GET(add, base, push_diary_size);
200 n->copy_files = H2_CONFIG_GET(add, base, copy_files);
201 n->output_buffered = H2_CONFIG_GET(add, base, output_buffered);
202 if (add->push_list && base->push_list) {
203 n->push_list = apr_array_append(pool, base->push_list, add->push_list);
204 }
205 else {
206 n->push_list = add->push_list? add->push_list : base->push_list;
207 }
208 if (add->early_headers && base->early_headers) {
209 n->early_headers = apr_table_overlay(pool, add->early_headers, base->early_headers);
210 }
211 else {
212 n->early_headers = add->early_headers? add->early_headers : base->early_headers;
213 }
214 n->early_hints = H2_CONFIG_GET(add, base, early_hints);
215 n->padding_bits = H2_CONFIG_GET(add, base, padding_bits);
216 n->padding_always = H2_CONFIG_GET(add, base, padding_always);
217 n->stream_timeout = H2_CONFIG_GET(add, base, stream_timeout);
218 n->max_data_frame_len = H2_CONFIG_GET(add, base, max_data_frame_len);
219 n->proxy_requests = H2_CONFIG_GET(add, base, proxy_requests);
220 n->h2_websockets = H2_CONFIG_GET(add, base, h2_websockets);
221 return n;
222}
223
225{
226 return h2_config_merge(pool, basev, addv);
227}
228
230{
232 const char *s = x? x : "unknown";
233 char *name = apr_pstrcat(pool, "dir[", s, "]", NULL);
234
235 conf->name = name;
236 conf->h2_upgrade = DEF_VAL;
237 conf->h2_push = DEF_VAL;
238 conf->early_hints = DEF_VAL;
239 conf->stream_timeout = DEF_VAL;
240 return conf;
241}
242
244{
248
249 n->name = apr_pstrcat(pool, "merged[", add->name, ", ", base->name, "]", NULL);
250 n->h2_upgrade = H2_CONFIG_GET(add, base, h2_upgrade);
251 n->h2_push = H2_CONFIG_GET(add, base, h2_push);
252 if (add->push_list && base->push_list) {
253 n->push_list = apr_array_append(pool, base->push_list, add->push_list);
254 }
255 else {
256 n->push_list = add->push_list? add->push_list : base->push_list;
257 }
258 if (add->early_headers && base->early_headers) {
259 n->early_headers = apr_table_overlay(pool, add->early_headers, base->early_headers);
260 }
261 else {
262 n->early_headers = add->early_headers? add->early_headers : base->early_headers;
263 }
264 n->early_hints = H2_CONFIG_GET(add, base, early_hints);
265 n->stream_timeout = H2_CONFIG_GET(add, base, stream_timeout);
266 return n;
267}
268
270{
271 switch(var) {
273 return H2_CONFIG_GET(conf, &defconf, h2_max_streams);
274 case H2_CONF_WIN_SIZE:
275 return H2_CONFIG_GET(conf, &defconf, h2_window_size);
277 return H2_CONFIG_GET(conf, &defconf, min_workers);
279 return H2_CONFIG_GET(conf, &defconf, max_workers);
281 return H2_CONFIG_GET(conf, &defconf, idle_limit);
283 return H2_CONFIG_GET(conf, &defconf, stream_max_mem_size);
285 return H2_CONFIG_GET(conf, &defconf, modern_tls_only);
286 case H2_CONF_UPGRADE:
287 return H2_CONFIG_GET(conf, &defconf, h2_upgrade);
288 case H2_CONF_DIRECT:
289 return H2_CONFIG_GET(conf, &defconf, h2_direct);
291 return H2_CONFIG_GET(conf, &defconf, tls_warmup_size);
293 return H2_CONFIG_GET(conf, &defconf, tls_cooldown_secs);
294 case H2_CONF_PUSH:
295 return H2_CONFIG_GET(conf, &defconf, h2_push);
297 return H2_CONFIG_GET(conf, &defconf, push_diary_size);
299 return H2_CONFIG_GET(conf, &defconf, copy_files);
301 return H2_CONFIG_GET(conf, &defconf, early_hints);
303 return H2_CONFIG_GET(conf, &defconf, padding_bits);
305 return H2_CONFIG_GET(conf, &defconf, padding_always);
307 return H2_CONFIG_GET(conf, &defconf, output_buffered);
309 return H2_CONFIG_GET(conf, &defconf, stream_timeout);
311 return H2_CONFIG_GET(conf, &defconf, max_data_frame_len);
313 return H2_CONFIG_GET(conf, &defconf, proxy_requests);
315 return H2_CONFIG_GET(conf, &defconf, h2_websockets);
316 default:
317 return DEF_VAL;
318 }
319}
320
322{
323 switch(var) {
325 H2_CONFIG_SET(conf, h2_max_streams, val);
326 break;
327 case H2_CONF_WIN_SIZE:
328 H2_CONFIG_SET(conf, h2_window_size, val);
329 break;
331 H2_CONFIG_SET(conf, min_workers, val);
332 break;
335 break;
337 H2_CONFIG_SET(conf, stream_max_mem_size, val);
338 break;
340 H2_CONFIG_SET(conf, modern_tls_only, val);
341 break;
342 case H2_CONF_UPGRADE:
343 H2_CONFIG_SET(conf, h2_upgrade, val);
344 break;
345 case H2_CONF_DIRECT:
346 H2_CONFIG_SET(conf, h2_direct, val);
347 break;
349 H2_CONFIG_SET(conf, tls_warmup_size, val);
350 break;
352 H2_CONFIG_SET(conf, tls_cooldown_secs, val);
353 break;
354 case H2_CONF_PUSH:
355 H2_CONFIG_SET(conf, h2_push, val);
356 break;
358 H2_CONFIG_SET(conf, push_diary_size, val);
359 break;
361 H2_CONFIG_SET(conf, copy_files, val);
362 break;
364 H2_CONFIG_SET(conf, early_hints, val);
365 break;
367 H2_CONFIG_SET(conf, padding_bits, val);
368 break;
370 H2_CONFIG_SET(conf, padding_always, val);
371 break;
373 H2_CONFIG_SET(conf, output_buffered, val);
374 break;
376 H2_CONFIG_SET(conf, max_data_frame_len, val);
377 break;
379 H2_CONFIG_SET(conf, proxy_requests, val);
380 break;
382 H2_CONFIG_SET(conf, h2_websockets, val);
383 break;
384 default:
385 break;
386 }
387}
388
390{
391 switch(var) {
393 H2_CONFIG_SET(conf, tls_warmup_size, val);
394 break;
396 H2_CONFIG_SET(conf, stream_timeout, val);
397 break;
399 H2_CONFIG_SET(conf, idle_limit, val);
400 break;
401 default:
402 h2_srv_config_seti(conf, var, (int)val);
403 break;
404 }
405}
406
408{
409 h2_config *cfg = (h2_config *)ap_get_module_config(s->module_config,
410 &http2_module);
411 ap_assert(cfg);
412 return cfg;
413}
414
416{
418 &http2_module);
419 ap_assert(cfg);
420 return cfg;
421}
422
424{
425 switch(var) {
426 case H2_CONF_UPGRADE:
427 return H2_CONFIG_GET(conf, &defdconf, h2_upgrade);
428 case H2_CONF_PUSH:
429 return H2_CONFIG_GET(conf, &defdconf, h2_push);
431 return H2_CONFIG_GET(conf, &defdconf, early_hints);
433 return H2_CONFIG_GET(conf, &defdconf, stream_timeout);
434
435 default:
436 return DEF_VAL;
437 }
438}
439
441{
442 int set_srv = !dconf;
443 if (dconf) {
444 switch(var) {
445 case H2_CONF_UPGRADE:
446 H2_CONFIG_SET(dconf, h2_upgrade, val);
447 break;
448 case H2_CONF_PUSH:
449 H2_CONFIG_SET(dconf, h2_push, val);
450 break;
452 H2_CONFIG_SET(dconf, early_hints, val);
453 break;
454 default:
455 /* not handled in dir_conf */
456 set_srv = 1;
457 break;
458 }
459 }
460
461 if (set_srv) {
462 h2_srv_config_seti(conf, var, val);
463 }
464}
465
467{
468 int set_srv = !dconf;
469 if (dconf) {
470 switch(var) {
472 H2_CONFIG_SET(dconf, stream_timeout, val);
473 break;
474 default:
475 /* not handled in dir_conf */
476 set_srv = 1;
477 break;
478 }
479 }
480
481 if (set_srv) {
483 }
484}
485
487{
489
490 if (conn_ctx && conn_ctx->server) {
491 return h2_config_sget(conn_ctx->server);
492 }
493 return h2_config_sget(c->base_server);
494}
495
500
505
510
515
520
526
531
536
538{
539 const h2_config *sconf;
540 const h2_dir_config *conf = h2_config_rget(r);
541
542 if (conf && conf->push_list) {
543 return conf->push_list;
544 }
546 return sconf? sconf->push_list : NULL;
547}
548
550{
551 const h2_config *sconf;
552 const h2_dir_config *conf = h2_config_rget(r);
553
554 if (conf && conf->early_headers) {
555 return conf->early_headers;
556 }
558 return sconf? sconf->early_headers : NULL;
559}
560
562{
563 const h2_config *conf = h2_config_get(c);
564 if (content_type && conf->priorities) {
567 return prio? prio : apr_hash_get(conf->priorities, "*", 1);
568 }
569 return NULL;
570}
571
573 void *dirconf, const char *value)
574{
576 if (ival < 1) {
577 return "value must be > 0";
578 }
580 return NULL;
581}
582
584 void *dirconf, const char *value)
585{
586 int val = (int)apr_atoi64(value);
587 if (val < 1024) {
588 return "value must be >= 1024";
589 }
591 return NULL;
592}
593
595 void *dirconf, const char *value)
596{
597 int val = (int)apr_atoi64(value);
598 if (val < 1) {
599 return "value must be > 0";
600 }
602 return NULL;
603}
604
606 void *dirconf, const char *value)
607{
608 int val = (int)apr_atoi64(value);
609 if (val < 1) {
610 return "value must be > 0";
611 }
613 return NULL;
614}
615
617 void *dirconf, const char *value)
618{
621 if (rv != APR_SUCCESS) {
622 return "Invalid idle limit value";
623 }
624 if (timeout <= 0) {
626 }
628 return NULL;
629}
630
632 void *dirconf, const char *value)
633{
634 int val = (int)apr_atoi64(value);
635 if (val < 1024) {
636 return "value must be >= 1024";
637 }
639 return NULL;
640}
641
643 void *dirconf, const char *value)
644{
645 int val = (int)apr_atoi64(value);
646 if (val < 0) {
647 return "value must be 0 or larger";
648 }
650 return NULL;
651}
652
654 void *dirconf, const char *value)
655{
656 /* deprecated, ignore */
657 (void)dirconf;
658 (void)value;
659 ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, cmd->pool, /* NO LOGNO */
660 "H2SessionExtraFiles is obsolete and will be ignored");
661 return NULL;
662}
663
665 void *dirconf, const char *value)
666{
667 if (!strcasecmp(value, "On")) {
669 "%s: this feature has been disabled and the directive "
670 "to enable it is ignored.", parms->cmd->name);
671 }
672 return NULL;
673}
674
675static const char *h2_conf_set_direct(cmd_parms *cmd,
676 void *dirconf, const char *value)
677{
678 if (!strcasecmp(value, "On")) {
680 return NULL;
681 }
682 else if (!strcasecmp(value, "Off")) {
684 return NULL;
685 }
686 return "value must be On or Off";
687}
688
689static const char *h2_conf_set_push(cmd_parms *cmd, void *dirconf, const char *value)
690{
691 if (!strcasecmp(value, "On")) {
693 return NULL;
694 }
695 else if (!strcasecmp(value, "Off")) {
697 return NULL;
698 }
699 return "value must be On or Off";
700}
701
703 void *dirconf, const char *value)
704{
705 if (!strcasecmp(value, "On")) {
706#if H2_USE_WEBSOCKETS
708 return NULL;
709#elif !H2_USE_PIPES
710 return "HTTP/2 WebSockets are not supported on this platform";
711#else
712 return "HTTP/2 WebSockets are not supported in this server version";
713#endif
714 }
715 else if (!strcasecmp(value, "Off")) {
717 return NULL;
718 }
719 return "value must be On or Off";
720}
721
722static const char *h2_conf_add_push_priority(cmd_parms *cmd, void *_cfg,
723 const char *ctype, const char *sdependency,
724 const char *sweight)
725{
726 h2_config *cfg = (h2_config *)h2_config_sget(cmd->server);
727 const char *sdefweight = "16"; /* default AFTER weight */
729 h2_priority *priority;
730 int weight;
731
732 (void)_cfg;
733 if (!*ctype) {
734 return "1st argument must be a mime-type, like 'text/css' or '*'";
735 }
736
737 if (!sweight) {
738 /* 2 args only, but which one? */
739 if (apr_isdigit(sdependency[0])) {
741 sdependency = "AFTER"; /* default dependency */
742 }
743 }
744
745 if (!strcasecmp("AFTER", sdependency)) {
747 }
748 else if (!strcasecmp("BEFORE", sdependency)) {
750 if (sweight) {
751 return "dependency 'Before' does not allow a weight";
752 }
753 }
754 else if (!strcasecmp("INTERLEAVED", sdependency)) {
756 sdefweight = "256"; /* default INTERLEAVED weight */
757 }
758 else {
759 return "dependency must be one of 'After', 'Before' or 'Interleaved'";
760 }
761
764 return apr_psprintf(cmd->pool, "weight must be a number >= %d",
766 }
767
768 priority = apr_pcalloc(cmd->pool, sizeof(*priority));
769 priority->dependency = dependency;
770 priority->weight = weight;
771
772 if (!cfg->priorities) {
773 cfg->priorities = apr_hash_make(cmd->pool);
774 }
775 apr_hash_set(cfg->priorities, ctype, (apr_ssize_t)strlen(ctype), priority);
776 return NULL;
777}
778
780 void *dirconf, const char *value)
781{
782 if (!strcasecmp(value, "On")) {
784 return NULL;
785 }
786 else if (!strcasecmp(value, "Off")) {
788 return NULL;
789 }
790 return "value must be On or Off";
791}
792
794 void *dirconf, const char *value)
795{
796 if (!strcasecmp(value, "On")) {
798 return NULL;
799 }
800 else if (!strcasecmp(value, "Off")) {
802 return NULL;
803 }
804 return "value must be On or Off";
805}
806
808 void *dirconf, const char *value)
809{
812 return NULL;
813}
814
816 void *dirconf, const char *value)
817{
820 return NULL;
821}
822
824 void *dirconf, const char *value)
825{
826 int val = (int)apr_atoi64(value);
827 if (val < 0) {
828 return "value must be >= 0";
829 }
830 if (val > 0 && (val & (val-1))) {
831 return "value must a power of 2";
832 }
833 if (val > (1 << 15)) {
834 return "value must <= 65536";
835 }
837 return NULL;
838}
839
841 void *dirconf, const char *value)
842{
843 if (!strcasecmp(value, "On")) {
845 return NULL;
846 }
847 else if (!strcasecmp(value, "Off")) {
849 return NULL;
850 }
851 return "value must be On or Off";
852}
853
855{
856 h2_push_res *new;
857 if (!*plist) {
858 *plist = apr_array_make(pool, 10, sizeof(*push));
859 }
860 new = apr_array_push(*plist);
861 new->uri_ref = push->uri_ref;
862 new->critical = push->critical;
863}
864
865static const char *h2_conf_add_push_res(cmd_parms *cmd, void *dirconf,
866 const char *arg1, const char *arg2,
867 const char *arg3)
868{
870 const char *last = arg3;
871
872 memset(&push, 0, sizeof(push));
873 if (!strcasecmp("add", arg1)) {
874 push.uri_ref = arg2;
875 }
876 else {
877 push.uri_ref = arg1;
878 last = arg2;
879 if (arg3) {
880 return "too many parameter";
881 }
882 }
883
884 if (last) {
885 if (!strcasecmp("critical", last)) {
886 push.critical = 1;
887 }
888 else {
889 return "unknown last parameter";
890 }
891 }
892
893 if (cmd->path) {
894 add_push(&(((h2_dir_config*)dirconf)->push_list), cmd->pool, &push);
895 }
896 else {
897 add_push(&(h2_config_sget(cmd->server)->push_list), cmd->pool, &push);
898 }
899 return NULL;
900}
901
902static const char *h2_conf_add_early_hint(cmd_parms *cmd, void *dirconf,
903 const char *name, const char *value)
904{
905 apr_table_t *hds, **phds;
906
907 if(!name || !*name)
908 return "Early Hint header name must not be empty";
909 if(!value)
910 return "Early Hint header value must not be empty";
911 while (apr_isspace(*value))
912 ++value;
913 if(!*value)
914 return "Early Hint header value must not be empty/only space";
916 return "Early Hint header value contains invalid characters";
917
918 if (cmd->path) {
919 phds = &((h2_dir_config*)dirconf)->early_headers;
920 }
921 else {
922 phds = &(h2_config_sget(cmd->server))->early_headers;
923 }
924 hds = *phds;
925 if (!hds) {
926 *phds = hds = apr_table_make(cmd->pool, 10);
927 }
929
930 return NULL;
931}
932
934 void *dirconf, const char *value)
935{
936 int val;
937
938 if (!strcasecmp(value, "On")) val = 1;
939 else if (!strcasecmp(value, "Off")) val = 0;
940 else return "value must be On or Off";
941
943 if (cmd->path) {
945 "H2EarlyHints = %d on path %s", val, cmd->path);
946 }
947 return NULL;
948}
949
950static const char *h2_conf_set_padding(cmd_parms *cmd, void *dirconf, const char *value)
951{
952 int val;
953
955 if (val < 0) {
956 return "number of bits must be >= 0";
957 }
958 if (val > 8) {
959 return "number of bits must be <= 8";
960 }
962 return NULL;
963}
964
966 void *dirconf, const char *value)
967{
968 if (!strcasecmp(value, "On")) {
970 return NULL;
971 }
972 else if (!strcasecmp(value, "Off")) {
974 return NULL;
975 }
976 return "value must be On or Off";
977}
978
980 void *dirconf, const char *value)
981{
982 apr_status_t rv;
984
986 if (rv != APR_SUCCESS) {
987 return "Invalid timeout value";
988 }
990 return NULL;
991}
992
994 void *dirconf, const char *value)
995{
996 if (!strcasecmp(value, "On")) {
998 return NULL;
999 }
1000 else if (!strcasecmp(value, "Off")) {
1002 return NULL;
1003 }
1004 return "value must be On or Off";
1005}
1006
1009{
1010 int threads_per_child = 0;
1011
1014
1016 if (*pminw <= 0) {
1018 }
1019 if (*pmaxw <= 0) {
1020 *pmaxw = H2MAX(4, 3 * (*pminw) / 2);
1021 }
1023}
1024
1025#define AP_END_CMD AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL)
1026
1028 AP_INIT_TAKE1("H2MaxSessionStreams", h2_conf_set_max_streams, NULL,
1029 RSRC_CONF, "maximum number of open streams per session"),
1031 RSRC_CONF, "window size on client DATA"),
1033 RSRC_CONF, "minimum number of worker threads per child"),
1035 RSRC_CONF, "maximum number of worker threads per child"),
1036 AP_INIT_TAKE1("H2MaxWorkerIdleSeconds", h2_conf_set_max_worker_idle_limit, NULL,
1037 RSRC_CONF, "maximum number of idle seconds before a worker shuts down"),
1038 AP_INIT_TAKE1("H2StreamMaxMemSize", h2_conf_set_stream_max_mem_size, NULL,
1039 RSRC_CONF, "maximum number of bytes buffered in memory for a stream"),
1040 AP_INIT_TAKE1("H2SerializeHeaders", h2_conf_set_serialize_headers, NULL,
1041 RSRC_CONF, "disabled, this directive has no longer an effect."),
1043 RSRC_CONF, "off to not impose RFC 7540 restrictions on TLS"),
1045 RSRC_CONF|OR_AUTHCFG, "on to allow HTTP/1 Upgrades to h2/h2c"),
1047 RSRC_CONF, "on to enable direct HTTP/2 mode"),
1048 AP_INIT_TAKE1("H2SessionExtraFiles", h2_conf_set_session_extra_files, NULL,
1049 RSRC_CONF, "number of extra file a session might keep open (obsolete)"),
1051 RSRC_CONF, "number of bytes on TLS connection before doing max writes"),
1052 AP_INIT_TAKE1("H2TLSCoolDownSecs", h2_conf_set_tls_cooldown_secs, NULL,
1053 RSRC_CONF, "seconds of idle time on TLS before shrinking writes"),
1055 RSRC_CONF|OR_AUTHCFG, "off to disable HTTP/2 server push"),
1057 RSRC_CONF, "define priority of PUSHed resources per content type"),
1059 RSRC_CONF, "size of push diary"),
1061 OR_FILEINFO, "on to perform copy of file data"),
1062 AP_INIT_TAKE123("H2PushResource", h2_conf_add_push_res, NULL,
1063 OR_FILEINFO|OR_AUTHCFG, "add a resource to be pushed in this location/on this server."),
1065 RSRC_CONF, "on to enable interim status 103 responses"),
1067 RSRC_CONF, "set payload padding"),
1068 AP_INIT_TAKE1("H2OutputBuffering", h2_conf_set_output_buffer, NULL,
1069 RSRC_CONF, "set stream output buffer on/off"),
1070 AP_INIT_TAKE1("H2StreamTimeout", h2_conf_set_stream_timeout, NULL,
1071 RSRC_CONF, "set stream timeout"),
1073 RSRC_CONF, "maximum number of bytes in a single HTTP/2 DATA frame"),
1075 OR_FILEINFO|OR_AUTHCFG, "add a a 'Link:' header for a 103 Early Hints response."),
1076 AP_INIT_TAKE1("H2ProxyRequests", h2_conf_set_proxy_requests, NULL,
1077 OR_FILEINFO, "Enables forward proxy requests via HTTP/2"),
1078 AP_INIT_TAKE1("H2WebSockets", h2_conf_set_websockets, NULL,
1079 RSRC_CONF, "off to disable WebSockets over HTTP/2"),
1081};
1082
1083
Apache Multi-Processing Module library.
int n
Definition ap_regex.h:278
const char apr_size_t len
Definition ap_regex.h:187
APR Hash Tables.
APR general purpose library routines.
APR Strings library.
apr_array_append(apr_pool_t *p, const apr_array_header_t *first, const apr_array_header_t *second)
Definition apr_tables.c:213
static int max_workers
Definition event.c:170
#define AP_INIT_TAKE123(directive, func, mconfig, where, help)
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
ap_conf_vector_t * base
request_rec * r
#define AP_INIT_TAKE23(directive, func, mconfig, where, help)
#define AP_INIT_TAKE2(directive, func, mconfig, where, help)
#define APLOGNO(n)
Definition http_log.h:117
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
#define APLOG_WARNING
Definition http_log.h:68
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
#define RSRC_CONF
#define OR_FILEINFO
#define OR_AUTHCFG
const char * ap_scan_http_field_content(const char *ptr)
Definition util.c:1654
#define ap_assert(exp)
Definition httpd.h:2271
apr_status_t ap_timeout_parameter_parse(const char *timeout_parameter, apr_interval_time_t *timeout, const char *default_time_unit)
Definition util.c:2622
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define apr_isspace(c)
Definition apr_lib.h:225
#define apr_isdigit(c)
Definition apr_lib.h:209
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
int strcasecmp(const char *a, const char *b)
apr_vformatter_buff_t * c
Definition apr_lib.h:175
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** last
const char * s
Definition apr_strings.h:95
apr_cmdtype_e cmd
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
#define AP_MPMQ_MAX_THREADS
Definition ap_mpm.h:160
#define H2MAX(x, y)
Definition h2.h:100
h2_dependency
Definition h2.h:103
@ H2_DEPENDANT_AFTER
Definition h2.h:104
@ H2_DEPENDANT_INTERLEAVED
Definition h2.h:105
@ H2_DEPENDANT_BEFORE
Definition h2.h:106
#define H2_INITIAL_WINDOW_SIZE
Definition h2.h:94
static void h2_srv_config_seti(h2_config *conf, h2_config_var_t var, int val)
Definition h2_config.c:321
static h2_dir_config defdconf
Definition h2_config.c:124
static const char * h2_conf_add_push_priority(cmd_parms *cmd, void *_cfg, const char *ctype, const char *sdependency, const char *sweight)
Definition h2_config.c:722
#define H2_CONFIG_SET(a, n, v)
Definition h2_config.c:44
apr_array_header_t * h2_config_push_list(request_rec *r)
Definition h2_config.c:537
apr_int64_t h2_config_sgeti64(server_rec *s, h2_config_var_t var)
Definition h2_config.c:511
static h2_config * h2_config_sget(server_rec *s)
Definition h2_config.c:407
static const char * h2_conf_set_proxy_requests(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:993
static void add_push(apr_array_header_t **plist, apr_pool_t *pool, h2_push_res *push)
Definition h2_config.c:854
static void h2_config_seti64(h2_dir_config *dconf, h2_config *conf, h2_config_var_t var, apr_int64_t val)
Definition h2_config.c:466
apr_int64_t h2_config_cgeti64(conn_rec *c, h2_config_var_t var)
Definition h2_config.c:501
static const char * h2_conf_set_tls_cooldown_secs(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:815
void * h2_config_create_dir(apr_pool_t *pool, char *x)
Definition h2_config.c:229
void * h2_config_create_svr(apr_pool_t *pool, server_rec *s)
Definition h2_config.c:139
static const char * h2_conf_set_tls_warmup_size(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:807
static const char * h2_conf_add_early_hint(cmd_parms *cmd, void *dirconf, const char *name, const char *value)
Definition h2_config.c:902
static const char * h2_conf_set_websockets(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:702
const command_rec h2_cmds[]
Definition h2_config.c:1027
static const char * h2_conf_add_push_res(cmd_parms *cmd, void *dirconf, const char *arg1, const char *arg2, const char *arg3)
Definition h2_config.c:865
const struct h2_priority * h2_cconfig_get_priority(conn_rec *c, const char *content_type)
Definition h2_config.c:561
int h2_config_rgeti(request_rec *r, h2_config_var_t var)
Definition h2_config.c:527
#define CONFIG_CMD_SET64(cmd, dir, var, val)
Definition h2_config.c:50
static const char * h2_conf_set_window_size(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:583
#define AP_END_CMD
Definition h2_config.c:1025
static const char * h2_conf_set_max_workers(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:605
static const char * h2_conf_set_session_extra_files(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:653
static const char * h2_conf_set_output_buffer(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:965
static const char * h2_conf_set_stream_timeout(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:979
static apr_int64_t h2_dir_config_geti64(const h2_dir_config *conf, h2_config_var_t var)
Definition h2_config.c:423
#define DEF_VAL
Definition h2_config.c:39
void * h2_config_merge_svr(apr_pool_t *pool, void *basev, void *addv)
Definition h2_config.c:224
static const char * h2_conf_set_min_workers(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:594
static const char * h2_conf_set_max_data_frame_len(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:642
static const char * h2_conf_set_modern_tls_only(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:779
int h2_config_geti(request_rec *r, server_rec *s, h2_config_var_t var)
Definition h2_config.c:516
#define CONFIG_CMD_SET(cmd, dir, var, val)
Definition h2_config.c:47
static const char * h2_conf_set_stream_max_mem_size(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:631
static const char * h2_conf_set_padding(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:950
static const char * h2_conf_set_push_diary_size(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:823
static void * h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
Definition h2_config.c:173
static void h2_config_seti(h2_dir_config *dconf, h2_config *conf, h2_config_var_t var, int val)
Definition h2_config.c:440
static void h2_srv_config_seti64(h2_config *conf, h2_config_var_t var, apr_int64_t val)
Definition h2_config.c:389
static const char * h2_conf_set_max_streams(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:572
static const char * h2_conf_set_early_hints(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:933
static const char * h2_conf_set_serialize_headers(cmd_parms *parms, void *dirconf, const char *value)
Definition h2_config.c:664
static const char * h2_conf_set_copy_files(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:840
void h2_get_workers_config(server_rec *s, int *pminw, int *pmaxw, apr_time_t *pidle_limit)
Definition h2_config.c:1007
static const char * h2_conf_set_direct(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:675
void * h2_config_merge_dir(apr_pool_t *pool, void *basev, void *addv)
Definition h2_config.c:243
static const char * h2_conf_set_upgrade(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:793
apr_table_t * h2_config_early_headers(request_rec *r)
Definition h2_config.c:549
apr_int64_t h2_config_geti64(request_rec *r, server_rec *s, h2_config_var_t var)
Definition h2_config.c:521
static const char * h2_conf_set_push(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:689
static const char * h2_conf_set_max_worker_idle_limit(cmd_parms *cmd, void *dirconf, const char *value)
Definition h2_config.c:616
#define H2_CONFIG_GET(a, b, n)
Definition h2_config.c:41
void h2_config_init(apr_pool_t *pool)
Definition h2_config.c:134
apr_int64_t h2_config_rgeti64(request_rec *r, h2_config_var_t var)
Definition h2_config.c:532
static const h2_dir_config * h2_config_rget(request_rec *r)
Definition h2_config.c:415
int h2_config_cgeti(conn_rec *c, h2_config_var_t var)
Definition h2_config.c:496
static apr_int64_t h2_srv_config_geti64(const h2_config *conf, h2_config_var_t var)
Definition h2_config.c:269
int h2_config_sgeti(server_rec *s, h2_config_var_t var)
Definition h2_config.c:506
static const h2_config * h2_config_get(conn_rec *c)
Definition h2_config.c:486
static h2_config defconf
Definition h2_config.c:95
h2_config_var_t
Definition h2_config.h:26
@ H2_CONF_PADDING_ALWAYS
Definition h2_config.h:43
@ H2_CONF_OUTPUT_BUFFER
Definition h2_config.h:44
@ H2_CONF_MAX_WORKER_IDLE_LIMIT
Definition h2_config.h:31
@ H2_CONF_MAX_WORKERS
Definition h2_config.h:30
@ H2_CONF_MODERN_TLS_ONLY
Definition h2_config.h:34
@ H2_CONF_PROXY_REQUESTS
Definition h2_config.h:47
@ H2_CONF_UPGRADE
Definition h2_config.h:35
@ H2_CONF_EARLY_HINTS
Definition h2_config.h:41
@ H2_CONF_PUSH
Definition h2_config.h:38
@ H2_CONF_MIN_WORKERS
Definition h2_config.h:29
@ H2_CONF_STREAM_TIMEOUT
Definition h2_config.h:45
@ H2_CONF_MAX_DATA_FRAME_LEN
Definition h2_config.h:46
@ H2_CONF_TLS_WARMUP_SIZE
Definition h2_config.h:36
@ H2_CONF_WEBSOCKETS
Definition h2_config.h:48
@ H2_CONF_WIN_SIZE
Definition h2_config.h:28
@ H2_CONF_TLS_COOLDOWN_SECS
Definition h2_config.h:37
@ H2_CONF_COPY_FILES
Definition h2_config.h:40
@ H2_CONF_STREAM_MAX_MEM
Definition h2_config.h:32
@ H2_CONF_MAX_STREAMS
Definition h2_config.h:27
@ H2_CONF_PUSH_DIARY_SIZE
Definition h2_config.h:39
@ H2_CONF_PADDING_BITS
Definition h2_config.h:42
@ H2_CONF_DIRECT
Definition h2_config.h:33
#define h2_conn_ctx_get(c)
Definition h2_conn_ctx.h:78
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
Virtual Host package.
HTTP Daemon routines.
return NULL
Definition mod_so.c:359
sconf
Definition mod_so.c:349
static int threads_per_child
Definition mod_status.c:89
char * name
Structure to store things which are per connection.
Definition httpd.h:1152
int output_buffered
Definition h2_config.c:77
apr_interval_time_t idle_limit
Definition h2_config.c:60
apr_array_header_t * push_list
Definition h2_config.c:72
int early_hints
Definition h2_config.c:74
const char * name
Definition h2_config.c:55
int h2_websockets
Definition h2_config.c:81
struct apr_hash_t * priorities
Definition h2_config.c:68
apr_int64_t tls_warmup_size
Definition h2_config.c:65
int max_data_frame_len
Definition h2_config.c:79
int h2_upgrade
Definition h2_config.c:64
int stream_max_mem_size
Definition h2_config.c:61
int min_workers
Definition h2_config.c:58
int padding_bits
Definition h2_config.c:75
int modern_tls_only
Definition h2_config.c:63
int h2_direct
Definition h2_config.c:62
int padding_always
Definition h2_config.c:76
int h2_push
Definition h2_config.c:67
int copy_files
Definition h2_config.c:71
int h2_max_streams
Definition h2_config.c:56
int proxy_requests
Definition h2_config.c:80
apr_table_t * early_headers
Definition h2_config.c:73
int push_diary_size
Definition h2_config.c:70
int h2_window_size
Definition h2_config.c:57
int tls_cooldown_secs
Definition h2_config.c:66
apr_interval_time_t stream_timeout
Definition h2_config.c:78
int max_workers
Definition h2_config.c:59
apr_table_t * early_headers
Definition h2_config.c:89
const char * name
Definition h2_config.c:85
apr_array_header_t * push_list
Definition h2_config.c:88
apr_interval_time_t stream_timeout
Definition h2_config.c:91
int weight
Definition h2.h:111
h2_dependency dependency
Definition h2.h:110
A structure that represents the current request.
Definition httpd.h:845
server_rec * server
Definition httpd.h:851
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
A structure to store information for each virtual server.
Definition httpd.h:1322
#define var
IN ULONG IN INT timeout
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray