src/http/v2/ngx_http_v2_module.c - nginx source code

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Nginx, Inc.
  3. * Copyright (C) Valentin V. Bartenev
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>
  8. #include <ngx_http_v2_module.h>


  9. static ngx_int_t ngx_http_v2_add_variables(ngx_conf_t *cf);

  10. static ngx_int_t ngx_http_v2_variable(ngx_http_request_t *r,
  11.     ngx_http_variable_value_t *v, uintptr_t data);

  12. static ngx_int_t ngx_http_v2_module_init(ngx_cycle_t *cycle);

  13. static void *ngx_http_v2_create_main_conf(ngx_conf_t *cf);
  14. static char *ngx_http_v2_init_main_conf(ngx_conf_t *cf, void *conf);
  15. static void *ngx_http_v2_create_srv_conf(ngx_conf_t *cf);
  16. static char *ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent,
  17.     void *child);
  18. static void *ngx_http_v2_create_loc_conf(ngx_conf_t *cf);
  19. static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent,
  20.     void *child);

  21. static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post,
  22.     void *data);
  23. static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data);
  24. static char *ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data);
  25. static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post,
  26.     void *data);
  27. static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data);
  28. static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd,
  29.     void *conf);


  30. static ngx_conf_deprecated_t  ngx_http_v2_recv_timeout_deprecated = {
  31.     ngx_conf_deprecated, "http2_recv_timeout", "client_header_timeout"
  32. };

  33. static ngx_conf_deprecated_t  ngx_http_v2_idle_timeout_deprecated = {
  34.     ngx_conf_deprecated, "http2_idle_timeout", "keepalive_timeout"
  35. };

  36. static ngx_conf_deprecated_t  ngx_http_v2_max_requests_deprecated = {
  37.     ngx_conf_deprecated, "http2_max_requests", "keepalive_requests"
  38. };

  39. static ngx_conf_deprecated_t  ngx_http_v2_max_field_size_deprecated = {
  40.     ngx_conf_deprecated, "http2_max_field_size", "large_client_header_buffers"
  41. };

  42. static ngx_conf_deprecated_t  ngx_http_v2_max_header_size_deprecated = {
  43.     ngx_conf_deprecated, "http2_max_header_size", "large_client_header_buffers"
  44. };


  45. static ngx_conf_post_t  ngx_http_v2_recv_buffer_size_post =
  46.     { ngx_http_v2_recv_buffer_size };
  47. static ngx_conf_post_t  ngx_http_v2_pool_size_post =
  48.     { ngx_http_v2_pool_size };
  49. static ngx_conf_post_t  ngx_http_v2_preread_size_post =
  50.     { ngx_http_v2_preread_size };
  51. static ngx_conf_post_t  ngx_http_v2_streams_index_mask_post =
  52.     { ngx_http_v2_streams_index_mask };
  53. static ngx_conf_post_t  ngx_http_v2_chunk_size_post =
  54.     { ngx_http_v2_chunk_size };


  55. static ngx_command_t  ngx_http_v2_commands[] = {

  56.     { ngx_string("http2"),
  57.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
  58.       ngx_conf_set_flag_slot,
  59.       NGX_HTTP_SRV_CONF_OFFSET,
  60.       offsetof(ngx_http_v2_srv_conf_t, enable),
  61.       NULL },

  62.     { ngx_string("http2_recv_buffer_size"),
  63.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
  64.       ngx_conf_set_size_slot,
  65.       NGX_HTTP_MAIN_CONF_OFFSET,
  66.       offsetof(ngx_http_v2_main_conf_t, recv_buffer_size),
  67.       &ngx_http_v2_recv_buffer_size_post },

  68.     { ngx_string("http2_pool_size"),
  69.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  70.       ngx_conf_set_size_slot,
  71.       NGX_HTTP_SRV_CONF_OFFSET,
  72.       offsetof(ngx_http_v2_srv_conf_t, pool_size),
  73.       &ngx_http_v2_pool_size_post },

  74.     { ngx_string("http2_max_concurrent_streams"),
  75.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  76.       ngx_conf_set_num_slot,
  77.       NGX_HTTP_SRV_CONF_OFFSET,
  78.       offsetof(ngx_http_v2_srv_conf_t, concurrent_streams),
  79.       NULL },

  80.     { ngx_string("http2_max_concurrent_pushes"),
  81.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  82.       ngx_http_v2_obsolete,
  83.       0,
  84.       0,
  85.       NULL },

  86.     { ngx_string("http2_max_requests"),
  87.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  88.       ngx_http_v2_obsolete,
  89.       0,
  90.       0,
  91.       &ngx_http_v2_max_requests_deprecated },

  92.     { ngx_string("http2_max_field_size"),
  93.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  94.       ngx_http_v2_obsolete,
  95.       0,
  96.       0,
  97.       &ngx_http_v2_max_field_size_deprecated },

  98.     { ngx_string("http2_max_header_size"),
  99.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  100.       ngx_http_v2_obsolete,
  101.       0,
  102.       0,
  103.       &ngx_http_v2_max_header_size_deprecated },

  104.     { ngx_string("http2_body_preread_size"),
  105.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  106.       ngx_conf_set_size_slot,
  107.       NGX_HTTP_SRV_CONF_OFFSET,
  108.       offsetof(ngx_http_v2_srv_conf_t, preread_size),
  109.       &ngx_http_v2_preread_size_post },

  110.     { ngx_string("http2_streams_index_size"),
  111.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  112.       ngx_conf_set_num_slot,
  113.       NGX_HTTP_SRV_CONF_OFFSET,
  114.       offsetof(ngx_http_v2_srv_conf_t, streams_index_mask),
  115.       &ngx_http_v2_streams_index_mask_post },

  116.     { ngx_string("http2_recv_timeout"),
  117.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  118.       ngx_http_v2_obsolete,
  119.       0,
  120.       0,
  121.       &ngx_http_v2_recv_timeout_deprecated },

  122.     { ngx_string("http2_idle_timeout"),
  123.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
  124.       ngx_http_v2_obsolete,
  125.       0,
  126.       0,
  127.       &ngx_http_v2_idle_timeout_deprecated },

  128.     { ngx_string("http2_chunk_size"),
  129.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  130.       ngx_conf_set_size_slot,
  131.       NGX_HTTP_LOC_CONF_OFFSET,
  132.       offsetof(ngx_http_v2_loc_conf_t, chunk_size),
  133.       &ngx_http_v2_chunk_size_post },

  134.     { ngx_string("http2_push_preload"),
  135.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  136.       ngx_http_v2_obsolete,
  137.       0,
  138.       0,
  139.       NULL },

  140.     { ngx_string("http2_push"),
  141.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  142.       ngx_http_v2_obsolete,
  143.       0,
  144.       0,
  145.       NULL },

  146.       ngx_null_command
  147. };


  148. static ngx_http_module_t  ngx_http_v2_module_ctx = {
  149.     ngx_http_v2_add_variables,             /* preconfiguration */
  150.     NULL,                                  /* postconfiguration */

  151.     ngx_http_v2_create_main_conf,          /* create main configuration */
  152.     ngx_http_v2_init_main_conf,            /* init main configuration */

  153.     ngx_http_v2_create_srv_conf,           /* create server configuration */
  154.     ngx_http_v2_merge_srv_conf,            /* merge server configuration */

  155.     ngx_http_v2_create_loc_conf,           /* create location configuration */
  156.     ngx_http_v2_merge_loc_conf             /* merge location configuration */
  157. };


  158. ngx_module_t  ngx_http_v2_module = {
  159.     NGX_MODULE_V1,
  160.     &ngx_http_v2_module_ctx,               /* module context */
  161.     ngx_http_v2_commands,                  /* module directives */
  162.     NGX_HTTP_MODULE,                       /* module type */
  163.     NULL,                                  /* init master */
  164.     ngx_http_v2_module_init,               /* init module */
  165.     NULL,                                  /* init process */
  166.     NULL,                                  /* init thread */
  167.     NULL,                                  /* exit thread */
  168.     NULL,                                  /* exit process */
  169.     NULL,                                  /* exit master */
  170.     NGX_MODULE_V1_PADDING
  171. };


  172. static ngx_http_variable_t  ngx_http_v2_vars[] = {

  173.     { ngx_string("http2"), NULL,
  174.       ngx_http_v2_variable, 0, 0, 0 },

  175.       ngx_http_null_variable
  176. };


  177. static ngx_int_t
  178. ngx_http_v2_add_variables(ngx_conf_t *cf)
  179. {
  180.     ngx_http_variable_t  *var, *v;

  181.     for (v = ngx_http_v2_vars; v->name.len; v++) {
  182.         var = ngx_http_add_variable(cf, &v->name, v->flags);
  183.         if (var == NULL) {
  184.             return NGX_ERROR;
  185.         }

  186.         var->get_handler = v->get_handler;
  187.         var->data = v->data;
  188.     }

  189.     return NGX_OK;
  190. }


  191. static ngx_int_t
  192. ngx_http_v2_variable(ngx_http_request_t *r,
  193.     ngx_http_variable_value_t *v, uintptr_t data)
  194. {

  195.     if (r->stream) {
  196. #if (NGX_HTTP_SSL)

  197.         if (r->connection->ssl) {
  198.             v->len = sizeof("h2") - 1;
  199.             v->valid = 1;
  200.             v->no_cacheable = 0;
  201.             v->not_found = 0;
  202.             v->data = (u_char *) "h2";

  203.             return NGX_OK;
  204.         }

  205. #endif
  206.         v->len = sizeof("h2c") - 1;
  207.         v->valid = 1;
  208.         v->no_cacheable = 0;
  209.         v->not_found = 0;
  210.         v->data = (u_char *) "h2c";

  211.         return NGX_OK;
  212.     }

  213.     *v = ngx_http_variable_null_value;

  214.     return NGX_OK;
  215. }


  216. static ngx_int_t
  217. ngx_http_v2_module_init(ngx_cycle_t *cycle)
  218. {
  219.     return NGX_OK;
  220. }


  221. static void *
  222. ngx_http_v2_create_main_conf(ngx_conf_t *cf)
  223. {
  224.     ngx_http_v2_main_conf_t  *h2mcf;

  225.     h2mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_main_conf_t));
  226.     if (h2mcf == NULL) {
  227.         return NULL;
  228.     }

  229.     h2mcf->recv_buffer_size = NGX_CONF_UNSET_SIZE;

  230.     return h2mcf;
  231. }


  232. static char *
  233. ngx_http_v2_init_main_conf(ngx_conf_t *cf, void *conf)
  234. {
  235.     ngx_http_v2_main_conf_t *h2mcf = conf;

  236.     ngx_conf_init_size_value(h2mcf->recv_buffer_size, 256 * 1024);

  237.     return NGX_CONF_OK;
  238. }


  239. static void *
  240. ngx_http_v2_create_srv_conf(ngx_conf_t *cf)
  241. {
  242.     ngx_http_v2_srv_conf_t  *h2scf;

  243.     h2scf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_srv_conf_t));
  244.     if (h2scf == NULL) {
  245.         return NULL;
  246.     }

  247.     h2scf->enable = NGX_CONF_UNSET;

  248.     h2scf->pool_size = NGX_CONF_UNSET_SIZE;

  249.     h2scf->concurrent_streams = NGX_CONF_UNSET_UINT;

  250.     h2scf->preread_size = NGX_CONF_UNSET_SIZE;

  251.     h2scf->streams_index_mask = NGX_CONF_UNSET_UINT;

  252.     return h2scf;
  253. }


  254. static char *
  255. ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
  256. {
  257.     ngx_http_v2_srv_conf_t *prev = parent;
  258.     ngx_http_v2_srv_conf_t *conf = child;

  259.     ngx_conf_merge_value(conf->enable, prev->enable, 0);

  260.     ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096);

  261.     ngx_conf_merge_uint_value(conf->concurrent_streams,
  262.                               prev->concurrent_streams, 128);

  263.     ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536);

  264.     ngx_conf_merge_uint_value(conf->streams_index_mask,
  265.                               prev->streams_index_mask, 32 - 1);

  266.     return NGX_CONF_OK;
  267. }


  268. static void *
  269. ngx_http_v2_create_loc_conf(ngx_conf_t *cf)
  270. {
  271.     ngx_http_v2_loc_conf_t  *h2lcf;

  272.     h2lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_loc_conf_t));
  273.     if (h2lcf == NULL) {
  274.         return NULL;
  275.     }

  276.     h2lcf->chunk_size = NGX_CONF_UNSET_SIZE;

  277.     return h2lcf;
  278. }


  279. static char *
  280. ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  281. {
  282.     ngx_http_v2_loc_conf_t *prev = parent;
  283.     ngx_http_v2_loc_conf_t *conf = child;

  284.     ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024);

  285.     return NGX_CONF_OK;
  286. }


  287. static char *
  288. ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data)
  289. {
  290.     size_t *sp = data;

  291.     if (*sp <= NGX_HTTP_V2_STATE_BUFFER_SIZE) {
  292.         return "value is too small";
  293.     }

  294.     return NGX_CONF_OK;
  295. }


  296. static char *
  297. ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data)
  298. {
  299.     size_t *sp = data;

  300.     if (*sp < NGX_MIN_POOL_SIZE) {
  301.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  302.                            "the pool size must be no less than %uz",
  303.                            NGX_MIN_POOL_SIZE);

  304.         return NGX_CONF_ERROR;
  305.     }

  306.     if (*sp % NGX_POOL_ALIGNMENT) {
  307.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  308.                            "the pool size must be a multiple of %uz",
  309.                            NGX_POOL_ALIGNMENT);

  310.         return NGX_CONF_ERROR;
  311.     }

  312.     return NGX_CONF_OK;
  313. }


  314. static char *
  315. ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data)
  316. {
  317.     size_t *sp = data;

  318.     if (*sp > NGX_HTTP_V2_MAX_WINDOW) {
  319.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  320.                            "the maximum body preread buffer size is %uz",
  321.                            NGX_HTTP_V2_MAX_WINDOW);

  322.         return NGX_CONF_ERROR;
  323.     }

  324.     return NGX_CONF_OK;
  325. }


  326. static char *
  327. ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data)
  328. {
  329.     ngx_uint_t *np = data;

  330.     ngx_uint_t  mask;

  331.     mask = *np - 1;

  332.     if (*np == 0 || (*np & mask)) {
  333.         return "must be a power of two";
  334.     }

  335.     *np = mask;

  336.     return NGX_CONF_OK;
  337. }


  338. static char *
  339. ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data)
  340. {
  341.     size_t *sp = data;

  342.     if (*sp == 0) {
  343.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  344.                            "the http2 chunk size cannot be zero");

  345.         return NGX_CONF_ERROR;
  346.     }

  347.     if (*sp > NGX_HTTP_V2_MAX_FRAME_SIZE) {
  348.         *sp = NGX_HTTP_V2_MAX_FRAME_SIZE;
  349.     }

  350.     return NGX_CONF_OK;
  351. }


  352. static char *
  353. ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  354. {
  355.     ngx_conf_deprecated_t  *d = cmd->post;

  356.     if (d) {
  357.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  358.                            "the \"%s\" directive is obsolete, "
  359.                            "use the \"%s\" directive instead",
  360.                            d->old_name, d->new_name);

  361.     } else {
  362.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  363.                            "the \"%V\" directive is obsolete, ignored",
  364.                            &cmd->name);
  365.     }

  366.     return NGX_CONF_OK;
  367. }