src/http/modules/ngx_http_grpc_module.c - nginx source code

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Maxim Dounin
  3. * Copyright (C) Nginx, Inc.
  4. */


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


  8. typedef struct {
  9.     ngx_array_t               *flushes;
  10.     ngx_array_t               *lengths;
  11.     ngx_array_t               *values;
  12.     ngx_hash_t                 hash;
  13. } ngx_http_grpc_headers_t;


  14. typedef struct {
  15.     ngx_http_upstream_conf_t   upstream;

  16.     ngx_http_grpc_headers_t    headers;
  17.     ngx_array_t               *headers_source;

  18.     ngx_str_t                  host;
  19.     ngx_uint_t                 host_set;

  20.     ngx_array_t               *grpc_lengths;
  21.     ngx_array_t               *grpc_values;

  22. #if (NGX_HTTP_SSL)
  23.     ngx_uint_t                 ssl;
  24.     ngx_uint_t                 ssl_protocols;
  25.     ngx_str_t                  ssl_ciphers;
  26.     ngx_uint_t                 ssl_verify_depth;
  27.     ngx_str_t                  ssl_trusted_certificate;
  28.     ngx_str_t                  ssl_crl;
  29.     ngx_array_t               *ssl_conf_commands;
  30. #endif
  31. } ngx_http_grpc_loc_conf_t;


  32. typedef enum {
  33.     ngx_http_grpc_st_start = 0,
  34.     ngx_http_grpc_st_length_2,
  35.     ngx_http_grpc_st_length_3,
  36.     ngx_http_grpc_st_type,
  37.     ngx_http_grpc_st_flags,
  38.     ngx_http_grpc_st_stream_id,
  39.     ngx_http_grpc_st_stream_id_2,
  40.     ngx_http_grpc_st_stream_id_3,
  41.     ngx_http_grpc_st_stream_id_4,
  42.     ngx_http_grpc_st_payload,
  43.     ngx_http_grpc_st_padding
  44. } ngx_http_grpc_state_e;


  45. typedef struct {
  46.     size_t                     init_window;
  47.     size_t                     send_window;
  48.     size_t                     recv_window;
  49.     ngx_uint_t                 last_stream_id;
  50. } ngx_http_grpc_conn_t;


  51. typedef struct {
  52.     ngx_http_grpc_state_e      state;
  53.     ngx_uint_t                 frame_state;
  54.     ngx_uint_t                 fragment_state;

  55.     ngx_chain_t               *in;
  56.     ngx_chain_t               *out;
  57.     ngx_chain_t               *free;
  58.     ngx_chain_t               *busy;

  59.     ngx_http_grpc_conn_t      *connection;

  60.     ngx_uint_t                 id;

  61.     ngx_uint_t                 pings;
  62.     ngx_uint_t                 settings;

  63.     off_t                      length;

  64.     ssize_t                    send_window;
  65.     size_t                     recv_window;

  66.     size_t                     rest;
  67.     ngx_uint_t                 stream_id;
  68.     u_char                     type;
  69.     u_char                     flags;
  70.     u_char                     padding;

  71.     ngx_uint_t                 error;
  72.     ngx_uint_t                 window_update;

  73.     ngx_uint_t                 setting_id;
  74.     ngx_uint_t                 setting_value;

  75.     u_char                     ping_data[8];

  76.     ngx_uint_t                 index;
  77.     ngx_str_t                  name;
  78.     ngx_str_t                  value;

  79.     u_char                    *field_end;
  80.     size_t                     field_length;
  81.     size_t                     field_rest;
  82.     u_char                     field_state;

  83.     unsigned                   literal:1;
  84.     unsigned                   field_huffman:1;

  85.     unsigned                   header_sent:1;
  86.     unsigned                   output_closed:1;
  87.     unsigned                   output_blocked:1;
  88.     unsigned                   parsing_headers:1;
  89.     unsigned                   end_stream:1;
  90.     unsigned                   done:1;
  91.     unsigned                   status:1;
  92.     unsigned                   rst:1;
  93.     unsigned                   goaway:1;

  94.     ngx_http_request_t        *request;

  95.     ngx_str_t                  host;
  96. } ngx_http_grpc_ctx_t;


  97. typedef struct {
  98.     u_char                     length_0;
  99.     u_char                     length_1;
  100.     u_char                     length_2;
  101.     u_char                     type;
  102.     u_char                     flags;
  103.     u_char                     stream_id_0;
  104.     u_char                     stream_id_1;
  105.     u_char                     stream_id_2;
  106.     u_char                     stream_id_3;
  107. } ngx_http_grpc_frame_t;


  108. static ngx_int_t ngx_http_grpc_eval(ngx_http_request_t *r,
  109.     ngx_http_grpc_ctx_t *ctx, ngx_http_grpc_loc_conf_t *glcf);
  110. static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r);
  111. static ngx_int_t ngx_http_grpc_reinit_request(ngx_http_request_t *r);
  112. static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in);
  113. static ngx_int_t ngx_http_grpc_process_header(ngx_http_request_t *r);
  114. static ngx_int_t ngx_http_grpc_filter_init(void *data);
  115. static ngx_int_t ngx_http_grpc_filter(void *data, ssize_t bytes);

  116. static ngx_int_t ngx_http_grpc_parse_frame(ngx_http_request_t *r,
  117.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
  118. static ngx_int_t ngx_http_grpc_parse_header(ngx_http_request_t *r,
  119.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
  120. static ngx_int_t ngx_http_grpc_parse_fragment(ngx_http_request_t *r,
  121.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
  122. static ngx_int_t ngx_http_grpc_validate_header_name(ngx_http_request_t *r,
  123.     ngx_str_t *s);
  124. static ngx_int_t ngx_http_grpc_validate_header_value(ngx_http_request_t *r,
  125.     ngx_str_t *s);
  126. static ngx_int_t ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r,
  127.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
  128. static ngx_int_t ngx_http_grpc_parse_goaway(ngx_http_request_t *r,
  129.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
  130. static ngx_int_t ngx_http_grpc_parse_window_update(ngx_http_request_t *r,
  131.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
  132. static ngx_int_t ngx_http_grpc_parse_settings(ngx_http_request_t *r,
  133.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
  134. static ngx_int_t ngx_http_grpc_parse_ping(ngx_http_request_t *r,
  135.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);

  136. static ngx_int_t ngx_http_grpc_send_settings_ack(ngx_http_request_t *r,
  137.     ngx_http_grpc_ctx_t *ctx);
  138. static ngx_int_t ngx_http_grpc_send_ping_ack(ngx_http_request_t *r,
  139.     ngx_http_grpc_ctx_t *ctx);
  140. static ngx_int_t ngx_http_grpc_send_window_update(ngx_http_request_t *r,
  141.     ngx_http_grpc_ctx_t *ctx);

  142. static ngx_chain_t *ngx_http_grpc_get_buf(ngx_http_request_t *r,
  143.     ngx_http_grpc_ctx_t *ctx);
  144. static ngx_http_grpc_ctx_t *ngx_http_grpc_get_ctx(ngx_http_request_t *r);
  145. static ngx_int_t ngx_http_grpc_get_connection_data(ngx_http_request_t *r,
  146.     ngx_http_grpc_ctx_t *ctx, ngx_peer_connection_t *pc);
  147. static void ngx_http_grpc_cleanup(void *data);

  148. static void ngx_http_grpc_abort_request(ngx_http_request_t *r);
  149. static void ngx_http_grpc_finalize_request(ngx_http_request_t *r,
  150.     ngx_int_t rc);

  151. static ngx_int_t ngx_http_grpc_internal_trailers_variable(
  152.     ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);

  153. static ngx_int_t ngx_http_grpc_add_variables(ngx_conf_t *cf);
  154. static void *ngx_http_grpc_create_loc_conf(ngx_conf_t *cf);
  155. static char *ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf,
  156.     void *parent, void *child);
  157. static ngx_int_t ngx_http_grpc_init_headers(ngx_conf_t *cf,
  158.     ngx_http_grpc_loc_conf_t *conf, ngx_http_grpc_headers_t *headers,
  159.     ngx_keyval_t *default_headers);

  160. static char *ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd,
  161.     void *conf);

  162. #if (NGX_HTTP_SSL)
  163. static char *ngx_http_grpc_ssl_password_file(ngx_conf_t *cf,
  164.     ngx_command_t *cmd, void *conf);
  165. static char *ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post,
  166.     void *data);
  167. static ngx_int_t ngx_http_grpc_merge_ssl(ngx_conf_t *cf,
  168.     ngx_http_grpc_loc_conf_t *conf, ngx_http_grpc_loc_conf_t *prev);
  169. static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf,
  170.     ngx_http_grpc_loc_conf_t *glcf);
  171. #endif


  172. static ngx_conf_bitmask_t  ngx_http_grpc_next_upstream_masks[] = {
  173.     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
  174.     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
  175.     { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
  176.     { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
  177.     { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
  178.     { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
  179.     { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
  180.     { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
  181.     { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
  182.     { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
  183.     { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
  184.     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
  185.     { ngx_null_string, 0 }
  186. };


  187. #if (NGX_HTTP_SSL)

  188. static ngx_conf_bitmask_t  ngx_http_grpc_ssl_protocols[] = {
  189.     { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
  190.     { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
  191.     { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
  192.     { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
  193.     { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
  194.     { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
  195.     { ngx_null_string, 0 }
  196. };

  197. static ngx_conf_post_t  ngx_http_grpc_ssl_conf_command_post =
  198.     { ngx_http_grpc_ssl_conf_command_check };

  199. #endif


  200. static ngx_command_t  ngx_http_grpc_commands[] = {

  201.     { ngx_string("grpc_pass"),
  202.       NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
  203.       ngx_http_grpc_pass,
  204.       NGX_HTTP_LOC_CONF_OFFSET,
  205.       0,
  206.       NULL },

  207.     { ngx_string("grpc_bind"),
  208.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
  209.       ngx_http_upstream_bind_set_slot,
  210.       NGX_HTTP_LOC_CONF_OFFSET,
  211.       offsetof(ngx_http_grpc_loc_conf_t, upstream.local),
  212.       NULL },

  213.     { ngx_string("grpc_socket_keepalive"),
  214.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  215.       ngx_conf_set_flag_slot,
  216.       NGX_HTTP_LOC_CONF_OFFSET,
  217.       offsetof(ngx_http_grpc_loc_conf_t, upstream.socket_keepalive),
  218.       NULL },

  219.     { ngx_string("grpc_connect_timeout"),
  220.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  221.       ngx_conf_set_msec_slot,
  222.       NGX_HTTP_LOC_CONF_OFFSET,
  223.       offsetof(ngx_http_grpc_loc_conf_t, upstream.connect_timeout),
  224.       NULL },

  225.     { ngx_string("grpc_send_timeout"),
  226.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  227.       ngx_conf_set_msec_slot,
  228.       NGX_HTTP_LOC_CONF_OFFSET,
  229.       offsetof(ngx_http_grpc_loc_conf_t, upstream.send_timeout),
  230.       NULL },

  231.     { ngx_string("grpc_intercept_errors"),
  232.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  233.       ngx_conf_set_flag_slot,
  234.       NGX_HTTP_LOC_CONF_OFFSET,
  235.       offsetof(ngx_http_grpc_loc_conf_t, upstream.intercept_errors),
  236.       NULL },

  237.     { ngx_string("grpc_buffer_size"),
  238.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  239.       ngx_conf_set_size_slot,
  240.       NGX_HTTP_LOC_CONF_OFFSET,
  241.       offsetof(ngx_http_grpc_loc_conf_t, upstream.buffer_size),
  242.       NULL },

  243.     { ngx_string("grpc_read_timeout"),
  244.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  245.       ngx_conf_set_msec_slot,
  246.       NGX_HTTP_LOC_CONF_OFFSET,
  247.       offsetof(ngx_http_grpc_loc_conf_t, upstream.read_timeout),
  248.       NULL },

  249.     { ngx_string("grpc_next_upstream"),
  250.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  251.       ngx_conf_set_bitmask_slot,
  252.       NGX_HTTP_LOC_CONF_OFFSET,
  253.       offsetof(ngx_http_grpc_loc_conf_t, upstream.next_upstream),
  254.       &ngx_http_grpc_next_upstream_masks },

  255.     { ngx_string("grpc_next_upstream_tries"),
  256.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  257.       ngx_conf_set_num_slot,
  258.       NGX_HTTP_LOC_CONF_OFFSET,
  259.       offsetof(ngx_http_grpc_loc_conf_t, upstream.next_upstream_tries),
  260.       NULL },

  261.     { ngx_string("grpc_next_upstream_timeout"),
  262.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  263.       ngx_conf_set_msec_slot,
  264.       NGX_HTTP_LOC_CONF_OFFSET,
  265.       offsetof(ngx_http_grpc_loc_conf_t, upstream.next_upstream_timeout),
  266.       NULL },

  267.     { ngx_string("grpc_set_header"),
  268.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
  269.       ngx_conf_set_keyval_slot,
  270.       NGX_HTTP_LOC_CONF_OFFSET,
  271.       offsetof(ngx_http_grpc_loc_conf_t, headers_source),
  272.       NULL },

  273.     { ngx_string("grpc_pass_header"),
  274.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  275.       ngx_conf_set_str_array_slot,
  276.       NGX_HTTP_LOC_CONF_OFFSET,
  277.       offsetof(ngx_http_grpc_loc_conf_t, upstream.pass_headers),
  278.       NULL },

  279.     { ngx_string("grpc_hide_header"),
  280.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  281.       ngx_conf_set_str_array_slot,
  282.       NGX_HTTP_LOC_CONF_OFFSET,
  283.       offsetof(ngx_http_grpc_loc_conf_t, upstream.hide_headers),
  284.       NULL },

  285.     { ngx_string("grpc_ignore_headers"),
  286.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  287.       ngx_conf_set_bitmask_slot,
  288.       NGX_HTTP_LOC_CONF_OFFSET,
  289.       offsetof(ngx_http_grpc_loc_conf_t, upstream.ignore_headers),
  290.       &ngx_http_upstream_ignore_headers_masks },

  291. #if (NGX_HTTP_SSL)

  292.     { ngx_string("grpc_ssl_session_reuse"),
  293.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  294.       ngx_conf_set_flag_slot,
  295.       NGX_HTTP_LOC_CONF_OFFSET,
  296.       offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_session_reuse),
  297.       NULL },

  298.     { ngx_string("grpc_ssl_protocols"),
  299.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  300.       ngx_conf_set_bitmask_slot,
  301.       NGX_HTTP_LOC_CONF_OFFSET,
  302.       offsetof(ngx_http_grpc_loc_conf_t, ssl_protocols),
  303.       &ngx_http_grpc_ssl_protocols },

  304.     { ngx_string("grpc_ssl_ciphers"),
  305.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  306.       ngx_conf_set_str_slot,
  307.       NGX_HTTP_LOC_CONF_OFFSET,
  308.       offsetof(ngx_http_grpc_loc_conf_t, ssl_ciphers),
  309.       NULL },

  310.     { ngx_string("grpc_ssl_name"),
  311.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  312.       ngx_http_set_complex_value_slot,
  313.       NGX_HTTP_LOC_CONF_OFFSET,
  314.       offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_name),
  315.       NULL },

  316.     { ngx_string("grpc_ssl_server_name"),
  317.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  318.       ngx_conf_set_flag_slot,
  319.       NGX_HTTP_LOC_CONF_OFFSET,
  320.       offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_server_name),
  321.       NULL },

  322.     { ngx_string("grpc_ssl_verify"),
  323.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
  324.       ngx_conf_set_flag_slot,
  325.       NGX_HTTP_LOC_CONF_OFFSET,
  326.       offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_verify),
  327.       NULL },

  328.     { ngx_string("grpc_ssl_verify_depth"),
  329.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  330.       ngx_conf_set_num_slot,
  331.       NGX_HTTP_LOC_CONF_OFFSET,
  332.       offsetof(ngx_http_grpc_loc_conf_t, ssl_verify_depth),
  333.       NULL },

  334.     { ngx_string("grpc_ssl_trusted_certificate"),
  335.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  336.       ngx_conf_set_str_slot,
  337.       NGX_HTTP_LOC_CONF_OFFSET,
  338.       offsetof(ngx_http_grpc_loc_conf_t, ssl_trusted_certificate),
  339.       NULL },

  340.     { ngx_string("grpc_ssl_crl"),
  341.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  342.       ngx_conf_set_str_slot,
  343.       NGX_HTTP_LOC_CONF_OFFSET,
  344.       offsetof(ngx_http_grpc_loc_conf_t, ssl_crl),
  345.       NULL },

  346.     { ngx_string("grpc_ssl_certificate"),
  347.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  348.       ngx_http_set_complex_value_zero_slot,
  349.       NGX_HTTP_LOC_CONF_OFFSET,
  350.       offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate),
  351.       NULL },

  352.     { ngx_string("grpc_ssl_certificate_key"),
  353.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  354.       ngx_http_set_complex_value_zero_slot,
  355.       NGX_HTTP_LOC_CONF_OFFSET,
  356.       offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate_key),
  357.       NULL },

  358.     { ngx_string("grpc_ssl_password_file"),
  359.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  360.       ngx_http_grpc_ssl_password_file,
  361.       NGX_HTTP_LOC_CONF_OFFSET,
  362.       0,
  363.       NULL },

  364.     { ngx_string("grpc_ssl_conf_command"),
  365.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
  366.       ngx_conf_set_keyval_slot,
  367.       NGX_HTTP_LOC_CONF_OFFSET,
  368.       offsetof(ngx_http_grpc_loc_conf_t, ssl_conf_commands),
  369.       &ngx_http_grpc_ssl_conf_command_post },

  370. #endif

  371.       ngx_null_command
  372. };


  373. static ngx_http_module_t  ngx_http_grpc_module_ctx = {
  374.     ngx_http_grpc_add_variables,           /* preconfiguration */
  375.     NULL,                                  /* postconfiguration */

  376.     NULL,                                  /* create main configuration */
  377.     NULL,                                  /* init main configuration */

  378.     NULL,                                  /* create server configuration */
  379.     NULL,                                  /* merge server configuration */

  380.     ngx_http_grpc_create_loc_conf,         /* create location configuration */
  381.     ngx_http_grpc_merge_loc_conf           /* merge location configuration */
  382. };


  383. ngx_module_t  ngx_http_grpc_module = {
  384.     NGX_MODULE_V1,
  385.     &ngx_http_grpc_module_ctx,             /* module context */
  386.     ngx_http_grpc_commands,                /* module directives */
  387.     NGX_HTTP_MODULE,                       /* module type */
  388.     NULL,                                  /* init master */
  389.     NULL,                                  /* init module */
  390.     NULL,                                  /* init process */
  391.     NULL,                                  /* init thread */
  392.     NULL,                                  /* exit thread */
  393.     NULL,                                  /* exit process */
  394.     NULL,                                  /* exit master */
  395.     NGX_MODULE_V1_PADDING
  396. };


  397. static u_char  ngx_http_grpc_connection_start[] =
  398.     "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"         /* connection preface */

  399.     "\x00\x00\x12\x04\x00\x00\x00\x00\x00"     /* settings frame */
  400.     "\x00\x01\x00\x00\x00\x00"                 /* header table size */
  401.     "\x00\x02\x00\x00\x00\x00"                 /* disable push */
  402.     "\x00\x04\x7f\xff\xff\xff"                 /* initial window */

  403.     "\x00\x00\x04\x08\x00\x00\x00\x00\x00"     /* window update frame */
  404.     "\x7f\xff\x00\x00";


  405. static ngx_keyval_t  ngx_http_grpc_headers[] = {
  406.     { ngx_string("Content-Length"), ngx_string("$content_length") },
  407.     { ngx_string("TE"), ngx_string("$grpc_internal_trailers") },
  408.     { ngx_string("Host"), ngx_string("") },
  409.     { ngx_string("Connection"), ngx_string("") },
  410.     { ngx_string("Transfer-Encoding"), ngx_string("") },
  411.     { ngx_string("Keep-Alive"), ngx_string("") },
  412.     { ngx_string("Expect"), ngx_string("") },
  413.     { ngx_string("Upgrade"), ngx_string("") },
  414.     { ngx_null_string, ngx_null_string }
  415. };


  416. static ngx_str_t  ngx_http_grpc_hide_headers[] = {
  417.     ngx_string("Date"),
  418.     ngx_string("Server"),
  419.     ngx_string("X-Accel-Expires"),
  420.     ngx_string("X-Accel-Redirect"),
  421.     ngx_string("X-Accel-Limit-Rate"),
  422.     ngx_string("X-Accel-Buffering"),
  423.     ngx_string("X-Accel-Charset"),
  424.     ngx_null_string
  425. };


  426. static ngx_http_variable_t  ngx_http_grpc_vars[] = {

  427.     { ngx_string("grpc_internal_trailers"), NULL,
  428.       ngx_http_grpc_internal_trailers_variable, 0,
  429.       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },

  430.       ngx_http_null_variable
  431. };


  432. static ngx_int_t
  433. ngx_http_grpc_handler(ngx_http_request_t *r)
  434. {
  435.     ngx_int_t                  rc;
  436.     ngx_http_upstream_t       *u;
  437.     ngx_http_grpc_ctx_t       *ctx;
  438.     ngx_http_grpc_loc_conf_t  *glcf;

  439.     if (ngx_http_upstream_create(r) != NGX_OK) {
  440.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  441.     }

  442.     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t));
  443.     if (ctx == NULL) {
  444.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  445.     }

  446.     ctx->request = r;

  447.     ngx_http_set_ctx(r, ctx, ngx_http_grpc_module);

  448.     glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);

  449.     u = r->upstream;

  450.     if (glcf->grpc_lengths == NULL) {
  451.         ctx->host = glcf->host;

  452. #if (NGX_HTTP_SSL)
  453.         u->ssl = glcf->ssl;

  454.         if (u->ssl) {
  455.             ngx_str_set(&u->schema, "grpcs://");

  456.         } else {
  457.             ngx_str_set(&u->schema, "grpc://");
  458.         }
  459. #else
  460.         ngx_str_set(&u->schema, "grpc://");
  461. #endif

  462.     } else {
  463.         if (ngx_http_grpc_eval(r, ctx, glcf) != NGX_OK) {
  464.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  465.         }
  466.     }

  467.     u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module;

  468.     u->conf = &glcf->upstream;

  469.     u->create_request = ngx_http_grpc_create_request;
  470.     u->reinit_request = ngx_http_grpc_reinit_request;
  471.     u->process_header = ngx_http_grpc_process_header;
  472.     u->abort_request = ngx_http_grpc_abort_request;
  473.     u->finalize_request = ngx_http_grpc_finalize_request;

  474.     u->input_filter_init = ngx_http_grpc_filter_init;
  475.     u->input_filter = ngx_http_grpc_filter;
  476.     u->input_filter_ctx = ctx;

  477.     r->request_body_no_buffering = 1;

  478.     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

  479.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  480.         return rc;
  481.     }

  482.     return NGX_DONE;
  483. }


  484. static ngx_int_t
  485. ngx_http_grpc_eval(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  486.     ngx_http_grpc_loc_conf_t *glcf)
  487. {
  488.     size_t                add;
  489.     ngx_url_t             url;
  490.     ngx_http_upstream_t  *u;

  491.     ngx_memzero(&url, sizeof(ngx_url_t));

  492.     if (ngx_http_script_run(r, &url.url, glcf->grpc_lengths->elts, 0,
  493.                             glcf->grpc_values->elts)
  494.         == NULL)
  495.     {
  496.         return NGX_ERROR;
  497.     }

  498.     if (url.url.len > 7
  499.         && ngx_strncasecmp(url.url.data, (u_char *) "grpc://", 7) == 0)
  500.     {
  501.         add = 7;

  502.     } else if (url.url.len > 8
  503.                && ngx_strncasecmp(url.url.data, (u_char *) "grpcs://", 8) == 0)
  504.     {

  505. #if (NGX_HTTP_SSL)
  506.         add = 8;
  507.         r->upstream->ssl = 1;
  508. #else
  509.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  510.                       "grpcs protocol requires SSL support");
  511.         return NGX_ERROR;
  512. #endif

  513.     } else {
  514.         add = 0;
  515.     }

  516.     u = r->upstream;

  517.     if (add) {
  518.         u->schema.len = add;
  519.         u->schema.data = url.url.data;

  520.         url.url.data += add;
  521.         url.url.len -= add;

  522.     } else {
  523.         ngx_str_set(&u->schema, "grpc://");
  524.     }

  525.     url.no_resolve = 1;

  526.     if (ngx_parse_url(r->pool, &url) != NGX_OK) {
  527.         if (url.err) {
  528.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  529.                           "%s in upstream \"%V\"", url.err, &url.url);
  530.         }

  531.         return NGX_ERROR;
  532.     }

  533.     u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
  534.     if (u->resolved == NULL) {
  535.         return NGX_ERROR;
  536.     }

  537.     if (url.addrs) {
  538.         u->resolved->sockaddr = url.addrs[0].sockaddr;
  539.         u->resolved->socklen = url.addrs[0].socklen;
  540.         u->resolved->name = url.addrs[0].name;
  541.         u->resolved->naddrs = 1;
  542.     }

  543.     u->resolved->host = url.host;
  544.     u->resolved->port = url.port;
  545.     u->resolved->no_port = url.no_port;

  546.     if (url.family != AF_UNIX) {

  547.         if (url.no_port) {
  548.             ctx->host = url.host;

  549.         } else {
  550.             ctx->host.len = url.host.len + 1 + url.port_text.len;
  551.             ctx->host.data = url.host.data;
  552.         }

  553.     } else {
  554.         ngx_str_set(&ctx->host, "localhost");
  555.     }

  556.     return NGX_OK;
  557. }


  558. static ngx_int_t
  559. ngx_http_grpc_create_request(ngx_http_request_t *r)
  560. {
  561.     u_char                       *p, *tmp, *key_tmp, *val_tmp, *headers_frame;
  562.     size_t                        len, tmp_len, key_len, val_len, uri_len;
  563.     uintptr_t                     escape;
  564.     ngx_buf_t                    *b;
  565.     ngx_uint_t                    i, next;
  566.     ngx_chain_t                  *cl, *body;
  567.     ngx_list_part_t              *part;
  568.     ngx_table_elt_t              *header;
  569.     ngx_http_grpc_ctx_t          *ctx;
  570.     ngx_http_upstream_t          *u;
  571.     ngx_http_grpc_frame_t        *f;
  572.     ngx_http_script_code_pt       code;
  573.     ngx_http_grpc_loc_conf_t     *glcf;
  574.     ngx_http_script_engine_t      e, le;
  575.     ngx_http_script_len_code_pt   lcode;

  576.     u = r->upstream;

  577.     glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);

  578.     ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);

  579.     len = sizeof(ngx_http_grpc_connection_start) - 1
  580.           + sizeof(ngx_http_grpc_frame_t);             /* headers frame */

  581.     /* :method header */

  582.     if (r->method == NGX_HTTP_GET || r->method == NGX_HTTP_POST) {
  583.         len += 1;
  584.         tmp_len = 0;

  585.     } else {
  586.         len += 1 + NGX_HTTP_V2_INT_OCTETS + r->method_name.len;
  587.         tmp_len = r->method_name.len;
  588.     }

  589.     /* :scheme header */

  590.     len += 1;

  591.     /* :path header */

  592.     if (r->valid_unparsed_uri) {
  593.         escape = 0;
  594.         uri_len = r->unparsed_uri.len;

  595.     } else {
  596.         escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
  597.                                     NGX_ESCAPE_URI);
  598.         uri_len = r->uri.len + escape + sizeof("?") - 1 + r->args.len;
  599.     }

  600.     len += 1 + NGX_HTTP_V2_INT_OCTETS + uri_len;

  601.     if (tmp_len < uri_len) {
  602.         tmp_len = uri_len;
  603.     }

  604.     /* :authority header */

  605.     if (!glcf->host_set) {
  606.         len += 1 + NGX_HTTP_V2_INT_OCTETS + ctx->host.len;

  607.         if (tmp_len < ctx->host.len) {
  608.             tmp_len = ctx->host.len;
  609.         }
  610.     }

  611.     /* other headers */

  612.     ngx_http_script_flush_no_cacheable_variables(r, glcf->headers.flushes);
  613.     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));

  614.     le.ip = glcf->headers.lengths->elts;
  615.     le.request = r;
  616.     le.flushed = 1;

  617.     while (*(uintptr_t *) le.ip) {

  618.         lcode = *(ngx_http_script_len_code_pt *) le.ip;
  619.         key_len = lcode(&le);

  620.         for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  621.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  622.         }
  623.         le.ip += sizeof(uintptr_t);

  624.         if (val_len == 0) {
  625.             continue;
  626.         }

  627.         len += 1 + NGX_HTTP_V2_INT_OCTETS + key_len
  628.                  + NGX_HTTP_V2_INT_OCTETS + val_len;

  629.         if (tmp_len < key_len) {
  630.             tmp_len = key_len;
  631.         }

  632.         if (tmp_len < val_len) {
  633.             tmp_len = val_len;
  634.         }
  635.     }

  636.     if (glcf->upstream.pass_request_headers) {
  637.         part = &r->headers_in.headers.part;
  638.         header = part->elts;

  639.         for (i = 0; /* void */; i++) {

  640.             if (i >= part->nelts) {
  641.                 if (part->next == NULL) {
  642.                     break;
  643.                 }

  644.                 part = part->next;
  645.                 header = part->elts;
  646.                 i = 0;
  647.             }

  648.             if (ngx_hash_find(&glcf->headers.hash, header[i].hash,
  649.                               header[i].lowcase_key, header[i].key.len))
  650.             {
  651.                 continue;
  652.             }

  653.             len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
  654.                      + NGX_HTTP_V2_INT_OCTETS + header[i].value.len;

  655.             if (tmp_len < header[i].key.len) {
  656.                 tmp_len = header[i].key.len;
  657.             }

  658.             if (tmp_len < header[i].value.len) {
  659.                 tmp_len = header[i].value.len;
  660.             }
  661.         }
  662.     }

  663.     /* continuation frames */

  664.     len += sizeof(ngx_http_grpc_frame_t)
  665.            * (len / NGX_HTTP_V2_DEFAULT_FRAME_SIZE);


  666.     b = ngx_create_temp_buf(r->pool, len);
  667.     if (b == NULL) {
  668.         return NGX_ERROR;
  669.     }

  670.     cl = ngx_alloc_chain_link(r->pool);
  671.     if (cl == NULL) {
  672.         return NGX_ERROR;
  673.     }

  674.     cl->buf = b;
  675.     cl->next = NULL;

  676.     tmp = ngx_palloc(r->pool, tmp_len * 3);
  677.     if (tmp == NULL) {
  678.         return NGX_ERROR;
  679.     }

  680.     key_tmp = tmp + tmp_len;
  681.     val_tmp = tmp + 2 * tmp_len;

  682.     /* connection preface */

  683.     b->last = ngx_copy(b->last, ngx_http_grpc_connection_start,
  684.                        sizeof(ngx_http_grpc_connection_start) - 1);

  685.     /* headers frame */

  686.     headers_frame = b->last;

  687.     f = (ngx_http_grpc_frame_t *) b->last;
  688.     b->last += sizeof(ngx_http_grpc_frame_t);

  689.     f->length_0 = 0;
  690.     f->length_1 = 0;
  691.     f->length_2 = 0;
  692.     f->type = NGX_HTTP_V2_HEADERS_FRAME;
  693.     f->flags = 0;
  694.     f->stream_id_0 = 0;
  695.     f->stream_id_1 = 0;
  696.     f->stream_id_2 = 0;
  697.     f->stream_id_3 = 1;

  698.     if (r->method == NGX_HTTP_GET) {
  699.         *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_GET_INDEX);

  700.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  701.                        "grpc header: \":method: GET\"");

  702.     } else if (r->method == NGX_HTTP_POST) {
  703.         *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_POST_INDEX);

  704.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  705.                        "grpc header: \":method: POST\"");

  706.     } else {
  707.         *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_METHOD_INDEX);
  708.         b->last = ngx_http_v2_write_value(b->last, r->method_name.data,
  709.                                           r->method_name.len, tmp);

  710.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  711.                        "grpc header: \":method: %V\"", &r->method_name);
  712.     }

  713. #if (NGX_HTTP_SSL)
  714.     if (u->ssl) {
  715.         *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);

  716.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  717.                        "grpc header: \":scheme: https\"");
  718.     } else
  719. #endif
  720.     {
  721.         *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX);

  722.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  723.                        "grpc header: \":scheme: http\"");
  724.     }

  725.     if (r->valid_unparsed_uri) {

  726.         if (r->unparsed_uri.len == 1 && r->unparsed_uri.data[0] == '/') {
  727.             *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_PATH_ROOT_INDEX);

  728.         } else {
  729.             *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
  730.             b->last = ngx_http_v2_write_value(b->last, r->unparsed_uri.data,
  731.                                               r->unparsed_uri.len, tmp);
  732.         }

  733.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  734.                        "grpc header: \":path: %V\"", &r->unparsed_uri);

  735.     } else if (escape || r->args.len > 0) {
  736.         p = val_tmp;

  737.         if (escape) {
  738.             p = (u_char *) ngx_escape_uri(p, r->uri.data, r->uri.len,
  739.                                           NGX_ESCAPE_URI);

  740.         } else {
  741.             p = ngx_copy(p, r->uri.data, r->uri.len);
  742.         }

  743.         if (r->args.len > 0) {
  744.             *p++ = '?';
  745.             p = ngx_copy(p, r->args.data, r->args.len);
  746.         }

  747.         *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
  748.         b->last = ngx_http_v2_write_value(b->last, val_tmp, p - val_tmp, tmp);

  749.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  750.                        "grpc header: \":path: %*s\"", p - val_tmp, val_tmp);

  751.     } else {
  752.         *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
  753.         b->last = ngx_http_v2_write_value(b->last, r->uri.data,
  754.                                           r->uri.len, tmp);

  755.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  756.                        "grpc header: \":path: %V\"", &r->uri);
  757.     }

  758.     if (!glcf->host_set) {
  759.         *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
  760.         b->last = ngx_http_v2_write_value(b->last, ctx->host.data,
  761.                                           ctx->host.len, tmp);

  762.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  763.                        "grpc header: \":authority: %V\"", &ctx->host);
  764.     }

  765.     ngx_memzero(&e, sizeof(ngx_http_script_engine_t));

  766.     e.ip = glcf->headers.values->elts;
  767.     e.request = r;
  768.     e.flushed = 1;

  769.     le.ip = glcf->headers.lengths->elts;

  770.     while (*(uintptr_t *) le.ip) {

  771.         lcode = *(ngx_http_script_len_code_pt *) le.ip;
  772.         key_len = lcode(&le);

  773.         for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  774.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  775.         }
  776.         le.ip += sizeof(uintptr_t);

  777.         if (val_len == 0) {
  778.             e.skip = 1;

  779.             while (*(uintptr_t *) e.ip) {
  780.                 code = *(ngx_http_script_code_pt *) e.ip;
  781.                 code((ngx_http_script_engine_t *) &e);
  782.             }
  783.             e.ip += sizeof(uintptr_t);

  784.             e.skip = 0;

  785.             continue;
  786.         }

  787.         *b->last++ = 0;

  788.         e.pos = key_tmp;

  789.         code = *(ngx_http_script_code_pt *) e.ip;
  790.         code((ngx_http_script_engine_t *) &e);

  791.         b->last = ngx_http_v2_write_name(b->last, key_tmp, key_len, tmp);

  792.         e.pos = val_tmp;

  793.         while (*(uintptr_t *) e.ip) {
  794.             code = *(ngx_http_script_code_pt *) e.ip;
  795.             code((ngx_http_script_engine_t *) &e);
  796.         }
  797.         e.ip += sizeof(uintptr_t);

  798.         b->last = ngx_http_v2_write_value(b->last, val_tmp, val_len, tmp);

  799. #if (NGX_DEBUG)
  800.         if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
  801.             ngx_strlow(key_tmp, key_tmp, key_len);

  802.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  803.                            "grpc header: \"%*s: %*s\"",
  804.                            key_len, key_tmp, val_len, val_tmp);
  805.         }
  806. #endif
  807.     }

  808.     if (glcf->upstream.pass_request_headers) {
  809.         part = &r->headers_in.headers.part;
  810.         header = part->elts;

  811.         for (i = 0; /* void */; i++) {

  812.             if (i >= part->nelts) {
  813.                 if (part->next == NULL) {
  814.                     break;
  815.                 }

  816.                 part = part->next;
  817.                 header = part->elts;
  818.                 i = 0;
  819.             }

  820.             if (ngx_hash_find(&glcf->headers.hash, header[i].hash,
  821.                               header[i].lowcase_key, header[i].key.len))
  822.             {
  823.                 continue;
  824.             }

  825.             *b->last++ = 0;

  826.             b->last = ngx_http_v2_write_name(b->last, header[i].key.data,
  827.                                              header[i].key.len, tmp);

  828.             b->last = ngx_http_v2_write_value(b->last, header[i].value.data,
  829.                                               header[i].value.len, tmp);

  830. #if (NGX_DEBUG)
  831.             if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
  832.                 ngx_strlow(tmp, header[i].key.data, header[i].key.len);

  833.                 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  834.                                "grpc header: \"%*s: %V\"",
  835.                                header[i].key.len, tmp, &header[i].value);
  836.             }
  837. #endif
  838.         }
  839.     }

  840.     /* update headers frame length */

  841.     len = b->last - headers_frame - sizeof(ngx_http_grpc_frame_t);

  842.     if (len > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
  843.         len = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
  844.         next = 1;

  845.     } else {
  846.         next = 0;
  847.     }

  848.     f = (ngx_http_grpc_frame_t *) headers_frame;

  849.     f->length_0 = (u_char) ((len >> 16) & 0xff);
  850.     f->length_1 = (u_char) ((len >> 8) & 0xff);
  851.     f->length_2 = (u_char) (len & 0xff);

  852.     /* create additional continuation frames */

  853.     p = headers_frame;

  854.     while (next) {
  855.         p += sizeof(ngx_http_grpc_frame_t) + NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
  856.         len = b->last - p;

  857.         ngx_memmove(p + sizeof(ngx_http_grpc_frame_t), p, len);
  858.         b->last += sizeof(ngx_http_grpc_frame_t);

  859.         if (len > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
  860.             len = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
  861.             next = 1;

  862.         } else {
  863.             next = 0;
  864.         }

  865.         f = (ngx_http_grpc_frame_t *) p;

  866.         f->length_0 = (u_char) ((len >> 16) & 0xff);
  867.         f->length_1 = (u_char) ((len >> 8) & 0xff);
  868.         f->length_2 = (u_char) (len & 0xff);
  869.         f->type = NGX_HTTP_V2_CONTINUATION_FRAME;
  870.         f->flags = 0;
  871.         f->stream_id_0 = 0;
  872.         f->stream_id_1 = 0;
  873.         f->stream_id_2 = 0;
  874.         f->stream_id_3 = 1;
  875.     }

  876.     f->flags |= NGX_HTTP_V2_END_HEADERS_FLAG;

  877.     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  878.                    "grpc header: %*xs%s, len: %uz",
  879.                    (size_t) ngx_min(b->last - b->pos, 256), b->pos,
  880.                    b->last - b->pos > 256 ? "..." : "",
  881.                    b->last - b->pos);

  882.     if (r->request_body_no_buffering) {

  883.         u->request_bufs = cl;

  884.     } else {

  885.         body = u->request_bufs;
  886.         u->request_bufs = cl;

  887.         if (body == NULL) {
  888.             f = (ngx_http_grpc_frame_t *) headers_frame;
  889.             f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;
  890.         }

  891.         while (body) {
  892.             b = ngx_alloc_buf(r->pool);
  893.             if (b == NULL) {
  894.                 return NGX_ERROR;
  895.             }

  896.             ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));

  897.             cl->next = ngx_alloc_chain_link(r->pool);
  898.             if (cl->next == NULL) {
  899.                 return NGX_ERROR;
  900.             }

  901.             cl = cl->next;
  902.             cl->buf = b;

  903.             body = body->next;
  904.         }

  905.         b->last_buf = 1;
  906.     }

  907.     u->output.output_filter = ngx_http_grpc_body_output_filter;
  908.     u->output.filter_ctx = r;

  909.     b->flush = 1;
  910.     cl->next = NULL;

  911.     return NGX_OK;
  912. }


  913. static ngx_int_t
  914. ngx_http_grpc_reinit_request(ngx_http_request_t *r)
  915. {
  916.     ngx_http_grpc_ctx_t  *ctx;

  917.     ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);

  918.     if (ctx == NULL) {
  919.         return NGX_OK;
  920.     }

  921.     ctx->state = 0;
  922.     ctx->header_sent = 0;
  923.     ctx->output_closed = 0;
  924.     ctx->output_blocked = 0;
  925.     ctx->parsing_headers = 0;
  926.     ctx->end_stream = 0;
  927.     ctx->done = 0;
  928.     ctx->status = 0;
  929.     ctx->rst = 0;
  930.     ctx->goaway = 0;
  931.     ctx->connection = NULL;

  932.     return NGX_OK;
  933. }


  934. static ngx_int_t
  935. ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in)
  936. {
  937.     ngx_http_request_t  *r = data;

  938.     off_t                   file_pos;
  939.     u_char                 *p, *pos, *start;
  940.     size_t                  len, limit;
  941.     ngx_buf_t              *b;
  942.     ngx_int_t               rc;
  943.     ngx_uint_t              next, last;
  944.     ngx_chain_t            *cl, *out, *ln, **ll;
  945.     ngx_http_upstream_t    *u;
  946.     ngx_http_grpc_ctx_t    *ctx;
  947.     ngx_http_grpc_frame_t  *f;

  948.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  949.                    "grpc output filter");

  950.     ctx = ngx_http_grpc_get_ctx(r);

  951.     if (ctx == NULL) {
  952.         return NGX_ERROR;
  953.     }

  954.     if (in) {
  955.         if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
  956.             return NGX_ERROR;
  957.         }
  958.     }

  959.     out = NULL;
  960.     ll = &out;

  961.     if (!ctx->header_sent) {
  962.         /* first buffer contains headers */

  963.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  964.                        "grpc output header");

  965.         ctx->header_sent = 1;

  966.         if (ctx->id != 1) {
  967.             /*
  968.              * keepalive connection: skip connection preface,
  969.              * update stream identifiers
  970.              */

  971.             b = ctx->in->buf;
  972.             b->pos += sizeof(ngx_http_grpc_connection_start) - 1;

  973.             p = b->pos;

  974.             while (p < b->last) {
  975.                 f = (ngx_http_grpc_frame_t *) p;
  976.                 p += sizeof(ngx_http_grpc_frame_t);

  977.                 f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
  978.                 f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
  979.                 f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
  980.                 f->stream_id_3 = (u_char) (ctx->id & 0xff);

  981.                 p += (f->length_0 << 16) + (f->length_1 << 8) + f->length_2;
  982.             }
  983.         }

  984.         if (ctx->in->buf->last_buf) {
  985.             ctx->output_closed = 1;
  986.         }

  987.         *ll = ctx->in;
  988.         ll = &ctx->in->next;

  989.         ctx->in = ctx->in->next;
  990.     }

  991.     if (ctx->out) {
  992.         /* queued control frames */

  993.         *ll = ctx->out;

  994.         for (cl = ctx->out, ll = &cl->next; cl; cl = cl->next) {
  995.             ll = &cl->next;
  996.         }

  997.         ctx->out = NULL;
  998.     }

  999.     f = NULL;
  1000.     last = 0;

  1001.     limit = ngx_max(0, ctx->send_window);

  1002.     if (limit > ctx->connection->send_window) {
  1003.         limit = ctx->connection->send_window;
  1004.     }

  1005.     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1006.                    "grpc output limit: %uz w:%z:%uz",
  1007.                    limit, ctx->send_window, ctx->connection->send_window);

  1008. #if (NGX_SUPPRESS_WARN)
  1009.     file_pos = 0;
  1010.     pos = NULL;
  1011.     cl = NULL;
  1012. #endif

  1013.     in = ctx->in;

  1014.     while (in && limit > 0) {

  1015.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
  1016.                        "grpc output in  l:%d f:%d %p, pos %p, size: %z "
  1017.                        "file: %O, size: %O",
  1018.                        in->buf->last_buf,
  1019.                        in->buf->in_file,
  1020.                        in->buf->start, in->buf->pos,
  1021.                        in->buf->last - in->buf->pos,
  1022.                        in->buf->file_pos,
  1023.                        in->buf->file_last - in->buf->file_pos);

  1024.         if (ngx_buf_special(in->buf)) {
  1025.             goto next;
  1026.         }

  1027.         if (in->buf->in_file) {
  1028.             file_pos = in->buf->file_pos;

  1029.         } else {
  1030.             pos = in->buf->pos;
  1031.         }

  1032.         next = 0;

  1033.         do {

  1034.             cl = ngx_http_grpc_get_buf(r, ctx);
  1035.             if (cl == NULL) {
  1036.                 return NGX_ERROR;
  1037.             }

  1038.             b = cl->buf;

  1039.             f = (ngx_http_grpc_frame_t *) b->last;
  1040.             b->last += sizeof(ngx_http_grpc_frame_t);

  1041.             *ll = cl;
  1042.             ll = &cl->next;

  1043.             cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
  1044.             if (cl == NULL) {
  1045.                 return NGX_ERROR;
  1046.             }

  1047.             b = cl->buf;
  1048.             start = b->start;

  1049.             ngx_memcpy(b, in->buf, sizeof(ngx_buf_t));

  1050.             /*
  1051.              * restore b->start to preserve memory allocated in the buffer,
  1052.              * to reuse it later for headers and control frames
  1053.              */

  1054.             b->start = start;

  1055.             if (in->buf->in_file) {
  1056.                 b->file_pos = file_pos;
  1057.                 file_pos += ngx_min(NGX_HTTP_V2_DEFAULT_FRAME_SIZE, limit);

  1058.                 if (file_pos >= in->buf->file_last) {
  1059.                     file_pos = in->buf->file_last;
  1060.                     next = 1;
  1061.                 }

  1062.                 b->file_last = file_pos;
  1063.                 len = (ngx_uint_t) (file_pos - b->file_pos);

  1064.             } else {
  1065.                 b->pos = pos;
  1066.                 pos += ngx_min(NGX_HTTP_V2_DEFAULT_FRAME_SIZE, limit);

  1067.                 if (pos >= in->buf->last) {
  1068.                     pos = in->buf->last;
  1069.                     next = 1;
  1070.                 }

  1071.                 b->last = pos;
  1072.                 len = (ngx_uint_t) (pos - b->pos);
  1073.             }

  1074.             b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
  1075.             b->shadow = in->buf;
  1076.             b->last_shadow = next;

  1077.             b->last_buf = 0;
  1078.             b->last_in_chain = 0;

  1079.             *ll = cl;
  1080.             ll = &cl->next;

  1081.             f->length_0 = (u_char) ((len >> 16) & 0xff);
  1082.             f->length_1 = (u_char) ((len >> 8) & 0xff);
  1083.             f->length_2 = (u_char) (len & 0xff);
  1084.             f->type = NGX_HTTP_V2_DATA_FRAME;
  1085.             f->flags = 0;
  1086.             f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
  1087.             f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
  1088.             f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
  1089.             f->stream_id_3 = (u_char) (ctx->id & 0xff);

  1090.             limit -= len;
  1091.             ctx->send_window -= len;
  1092.             ctx->connection->send_window -= len;

  1093.         } while (!next && limit > 0);

  1094.         if (!next) {
  1095.             /*
  1096.              * if the buffer wasn't fully sent due to flow control limits,
  1097.              * preserve position for future use
  1098.              */

  1099.             if (in->buf->in_file) {
  1100.                 in->buf->file_pos = file_pos;

  1101.             } else {
  1102.                 in->buf->pos = pos;
  1103.             }

  1104.             break;
  1105.         }

  1106.     next:

  1107.         if (in->buf->last_buf) {
  1108.             last = 1;
  1109.         }

  1110.         ln = in;
  1111.         in = in->next;

  1112.         ngx_free_chain(r->pool, ln);
  1113.     }

  1114.     ctx->in = in;

  1115.     if (last) {

  1116.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1117.                        "grpc output last");

  1118.         ctx->output_closed = 1;

  1119.         if (f) {
  1120.             f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;

  1121.         } else {
  1122.             cl = ngx_http_grpc_get_buf(r, ctx);
  1123.             if (cl == NULL) {
  1124.                 return NGX_ERROR;
  1125.             }

  1126.             b = cl->buf;

  1127.             f = (ngx_http_grpc_frame_t *) b->last;
  1128.             b->last += sizeof(ngx_http_grpc_frame_t);

  1129.             f->length_0 = 0;
  1130.             f->length_1 = 0;
  1131.             f->length_2 = 0;
  1132.             f->type = NGX_HTTP_V2_DATA_FRAME;
  1133.             f->flags = NGX_HTTP_V2_END_STREAM_FLAG;
  1134.             f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
  1135.             f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
  1136.             f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
  1137.             f->stream_id_3 = (u_char) (ctx->id & 0xff);

  1138.             *ll = cl;
  1139.             ll = &cl->next;
  1140.         }

  1141.         cl->buf->last_buf = 1;
  1142.     }

  1143.     *ll = NULL;

  1144. #if (NGX_DEBUG)

  1145.     for (cl = out; cl; cl = cl->next) {
  1146.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
  1147.                        "grpc output out l:%d f:%d %p, pos %p, size: %z "
  1148.                        "file: %O, size: %O",
  1149.                        cl->buf->last_buf,
  1150.                        cl->buf->in_file,
  1151.                        cl->buf->start, cl->buf->pos,
  1152.                        cl->buf->last - cl->buf->pos,
  1153.                        cl->buf->file_pos,
  1154.                        cl->buf->file_last - cl->buf->file_pos);
  1155.     }

  1156.     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1157.                    "grpc output limit: %uz w:%z:%uz",
  1158.                    limit, ctx->send_window, ctx->connection->send_window);

  1159. #endif

  1160.     rc = ngx_chain_writer(&r->upstream->writer, out);

  1161.     ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
  1162.                             (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter);

  1163.     for (cl = ctx->free; cl; cl = cl->next) {

  1164.         /* mark original buffers as sent */

  1165.         if (cl->buf->shadow) {
  1166.             if (cl->buf->last_shadow) {
  1167.                 b = cl->buf->shadow;
  1168.                 b->pos = b->last;
  1169.             }

  1170.             cl->buf->shadow = NULL;
  1171.         }
  1172.     }

  1173.     if (rc == NGX_OK && ctx->in) {
  1174.         rc = NGX_AGAIN;
  1175.     }

  1176.     if (rc == NGX_AGAIN) {
  1177.         ctx->output_blocked = 1;

  1178.     } else {
  1179.         ctx->output_blocked = 0;
  1180.     }

  1181.     if (ctx->done) {

  1182.         /*
  1183.          * We have already got the response and were sending some additional
  1184.          * control frames.  Even if there is still something unsent, stop
  1185.          * here anyway.
  1186.          */

  1187.         u = r->upstream;
  1188.         u->length = 0;

  1189.         if (ctx->in == NULL
  1190.             && ctx->out == NULL
  1191.             && ctx->output_closed
  1192.             && !ctx->output_blocked
  1193.             && !ctx->goaway
  1194.             && ctx->state == ngx_http_grpc_st_start)
  1195.         {
  1196.             u->keepalive = 1;
  1197.         }

  1198.         ngx_post_event(u->peer.connection->read, &ngx_posted_events);
  1199.     }

  1200.     return rc;
  1201. }


  1202. static ngx_int_t
  1203. ngx_http_grpc_process_header(ngx_http_request_t *r)
  1204. {
  1205.     ngx_str_t                      *status_line;
  1206.     ngx_int_t                       rc, status;
  1207.     ngx_buf_t                      *b;
  1208.     ngx_table_elt_t                *h;
  1209.     ngx_http_upstream_t            *u;
  1210.     ngx_http_grpc_ctx_t            *ctx;
  1211.     ngx_http_upstream_header_t     *hh;
  1212.     ngx_http_upstream_main_conf_t  *umcf;

  1213.     u = r->upstream;
  1214.     b = &u->buffer;

  1215.     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1216.                    "grpc response: %*xs%s, len: %uz",
  1217.                    (size_t) ngx_min(b->last - b->pos, 256),
  1218.                    b->pos, b->last - b->pos > 256 ? "..." : "",
  1219.                    b->last - b->pos);

  1220.     ctx = ngx_http_grpc_get_ctx(r);

  1221.     if (ctx == NULL) {
  1222.         return NGX_ERROR;
  1223.     }

  1224.     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);

  1225.     for ( ;; ) {

  1226.         if (ctx->state < ngx_http_grpc_st_payload) {

  1227.             rc = ngx_http_grpc_parse_frame(r, ctx, b);

  1228.             if (rc == NGX_AGAIN) {

  1229.                 /*
  1230.                  * there can be a lot of window update frames,
  1231.                  * so we reset buffer if it is empty and we haven't
  1232.                  * started parsing headers yet
  1233.                  */

  1234.                 if (!ctx->parsing_headers) {
  1235.                     b->pos = b->start;
  1236.                     b->last = b->pos;
  1237.                 }

  1238.                 return NGX_AGAIN;
  1239.             }

  1240.             if (rc == NGX_ERROR) {
  1241.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1242.             }

  1243.             /*
  1244.              * RFC 7540 says that implementations MUST discard frames
  1245.              * that have unknown or unsupported types.  However, extension
  1246.              * frames that appear in the middle of a header block are
  1247.              * not permitted.  Also, for obvious reasons CONTINUATION frames
  1248.              * cannot appear before headers, and DATA frames are not expected
  1249.              * to appear before all headers are parsed.
  1250.              */

  1251.             if (ctx->type == NGX_HTTP_V2_DATA_FRAME
  1252.                 || (ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME
  1253.                     && !ctx->parsing_headers)
  1254.                 || (ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME
  1255.                     && ctx->parsing_headers))
  1256.             {
  1257.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1258.                               "upstream sent unexpected http2 frame: %d",
  1259.                               ctx->type);
  1260.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1261.             }

  1262.             if (ctx->stream_id && ctx->stream_id != ctx->id) {
  1263.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1264.                               "upstream sent frame for unknown stream %ui",
  1265.                               ctx->stream_id);
  1266.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1267.             }
  1268.         }

  1269.         /* frame payload */

  1270.         if (ctx->type == NGX_HTTP_V2_RST_STREAM_FRAME) {

  1271.             rc = ngx_http_grpc_parse_rst_stream(r, ctx, b);

  1272.             if (rc == NGX_AGAIN) {
  1273.                 return NGX_AGAIN;
  1274.             }

  1275.             if (rc == NGX_ERROR) {
  1276.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1277.             }

  1278.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1279.                           "upstream rejected request with error %ui",
  1280.                           ctx->error);

  1281.             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1282.         }

  1283.         if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {

  1284.             rc = ngx_http_grpc_parse_goaway(r, ctx, b);

  1285.             if (rc == NGX_AGAIN) {
  1286.                 return NGX_AGAIN;
  1287.             }

  1288.             if (rc == NGX_ERROR) {
  1289.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1290.             }

  1291.             /*
  1292.              * If stream_id is lower than one we use, our
  1293.              * request won't be processed and needs to be retried.
  1294.              * If stream_id is greater or equal to the one we use,
  1295.              * we can continue normally (except we can't use this
  1296.              * connection for additional requests).  If there is
  1297.              * a real error, the connection will be closed.
  1298.              */

  1299.             if (ctx->stream_id < ctx->id) {

  1300.                 /* TODO: we can retry non-idempotent requests */

  1301.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1302.                               "upstream sent goaway with error %ui",
  1303.                               ctx->error);

  1304.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1305.             }

  1306.             ctx->goaway = 1;

  1307.             continue;
  1308.         }

  1309.         if (ctx->type == NGX_HTTP_V2_WINDOW_UPDATE_FRAME) {

  1310.             rc = ngx_http_grpc_parse_window_update(r, ctx, b);

  1311.             if (rc == NGX_AGAIN) {
  1312.                 return NGX_AGAIN;
  1313.             }

  1314.             if (rc == NGX_ERROR) {
  1315.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1316.             }

  1317.             if (ctx->in) {
  1318.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1319.             }

  1320.             continue;
  1321.         }

  1322.         if (ctx->type == NGX_HTTP_V2_SETTINGS_FRAME) {

  1323.             rc = ngx_http_grpc_parse_settings(r, ctx, b);

  1324.             if (rc == NGX_AGAIN) {
  1325.                 return NGX_AGAIN;
  1326.             }

  1327.             if (rc == NGX_ERROR) {
  1328.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1329.             }

  1330.             if (ctx->in) {
  1331.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1332.             }

  1333.             continue;
  1334.         }

  1335.         if (ctx->type == NGX_HTTP_V2_PING_FRAME) {

  1336.             rc = ngx_http_grpc_parse_ping(r, ctx, b);

  1337.             if (rc == NGX_AGAIN) {
  1338.                 return NGX_AGAIN;
  1339.             }

  1340.             if (rc == NGX_ERROR) {
  1341.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1342.             }

  1343.             ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1344.             continue;
  1345.         }

  1346.         if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
  1347.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1348.                           "upstream sent unexpected push promise frame");
  1349.             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1350.         }

  1351.         if (ctx->type != NGX_HTTP_V2_HEADERS_FRAME
  1352.             && ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME)
  1353.         {
  1354.             /* priority, unknown frames */

  1355.             if (b->last - b->pos < (ssize_t) ctx->rest) {
  1356.                 ctx->rest -= b->last - b->pos;
  1357.                 b->pos = b->last;
  1358.                 return NGX_AGAIN;
  1359.             }

  1360.             b->pos += ctx->rest;
  1361.             ctx->rest = 0;
  1362.             ctx->state = ngx_http_grpc_st_start;

  1363.             continue;
  1364.         }

  1365.         /* headers */

  1366.         for ( ;; ) {

  1367.             rc = ngx_http_grpc_parse_header(r, ctx, b);

  1368.             if (rc == NGX_AGAIN) {
  1369.                 break;
  1370.             }

  1371.             if (rc == NGX_OK) {

  1372.                 /* a header line has been parsed successfully */

  1373.                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1374.                                "grpc header: \"%V: %V\"",
  1375.                                &ctx->name, &ctx->value);

  1376.                 if (ctx->name.len && ctx->name.data[0] == ':') {

  1377.                     if (ctx->name.len != sizeof(":status") - 1
  1378.                         || ngx_strncmp(ctx->name.data, ":status",
  1379.                                        sizeof(":status") - 1)
  1380.                            != 0)
  1381.                     {
  1382.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1383.                                       "upstream sent invalid header \"%V: %V\"",
  1384.                                       &ctx->name, &ctx->value);
  1385.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1386.                     }

  1387.                     if (ctx->status) {
  1388.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1389.                                       "upstream sent duplicate :status header");
  1390.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1391.                     }

  1392.                     status_line = &ctx->value;

  1393.                     if (status_line->len != 3) {
  1394.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1395.                                       "upstream sent invalid :status \"%V\"",
  1396.                                       status_line);
  1397.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1398.                     }

  1399.                     status = ngx_atoi(status_line->data, 3);

  1400.                     if (status == NGX_ERROR) {
  1401.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1402.                                       "upstream sent invalid :status \"%V\"",
  1403.                                       status_line);
  1404.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1405.                     }

  1406.                     if (status < NGX_HTTP_OK) {
  1407.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1408.                                       "upstream sent unexpected :status \"%V\"",
  1409.                                       status_line);
  1410.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1411.                     }

  1412.                     u->headers_in.status_n = status;

  1413.                     if (u->state && u->state->status == 0) {
  1414.                         u->state->status = status;
  1415.                     }

  1416.                     ctx->status = 1;

  1417.                     continue;

  1418.                 } else if (!ctx->status) {
  1419.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1420.                                   "upstream sent no :status header");
  1421.                     return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1422.                 }

  1423.                 h = ngx_list_push(&u->headers_in.headers);
  1424.                 if (h == NULL) {
  1425.                     return NGX_ERROR;
  1426.                 }

  1427.                 h->key = ctx->name;
  1428.                 h->value = ctx->value;
  1429.                 h->lowcase_key = h->key.data;
  1430.                 h->hash = ngx_hash_key(h->key.data, h->key.len);

  1431.                 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
  1432.                                    h->lowcase_key, h->key.len);

  1433.                 if (hh) {
  1434.                     rc = hh->handler(r, h, hh->offset);

  1435.                     if (rc != NGX_OK) {
  1436.                         return rc;
  1437.                     }
  1438.                 }

  1439.                 continue;
  1440.             }

  1441.             if (rc == NGX_HTTP_PARSE_HEADER_DONE) {

  1442.                 /* a whole header has been parsed successfully */

  1443.                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1444.                                "grpc header done");

  1445.                 if (ctx->end_stream) {
  1446.                     u->headers_in.content_length_n = 0;

  1447.                     if (ctx->in == NULL
  1448.                         && ctx->out == NULL
  1449.                         && ctx->output_closed
  1450.                         && !ctx->output_blocked
  1451.                         && !ctx->goaway
  1452.                         && b->last == b->pos)
  1453.                     {
  1454.                         u->keepalive = 1;
  1455.                     }
  1456.                 }

  1457.                 return NGX_OK;
  1458.             }

  1459.             /* there was error while a header line parsing */

  1460.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1461.                           "upstream sent invalid header");

  1462.             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1463.         }

  1464.         /* rc == NGX_AGAIN */

  1465.         if (ctx->rest == 0) {
  1466.             ctx->state = ngx_http_grpc_st_start;
  1467.             continue;
  1468.         }

  1469.         return NGX_AGAIN;
  1470.     }
  1471. }


  1472. static ngx_int_t
  1473. ngx_http_grpc_filter_init(void *data)
  1474. {
  1475.     ngx_http_grpc_ctx_t  *ctx = data;

  1476.     ngx_http_request_t   *r;
  1477.     ngx_http_upstream_t  *u;

  1478.     r = ctx->request;
  1479.     u = r->upstream;

  1480.     if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
  1481.         || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
  1482.         || r->method == NGX_HTTP_HEAD)
  1483.     {
  1484.         ctx->length = 0;

  1485.     } else {
  1486.         ctx->length = u->headers_in.content_length_n;
  1487.     }

  1488.     if (ctx->end_stream) {

  1489.         if (ctx->length > 0) {
  1490.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1491.                           "upstream prematurely closed stream");
  1492.             return NGX_ERROR;
  1493.         }

  1494.         u->length = 0;
  1495.         ctx->done = 1;

  1496.     } else {
  1497.         u->length = 1;
  1498.     }

  1499.     return NGX_OK;
  1500. }


  1501. static ngx_int_t
  1502. ngx_http_grpc_filter(void *data, ssize_t bytes)
  1503. {
  1504.     ngx_http_grpc_ctx_t  *ctx = data;

  1505.     ngx_int_t             rc;
  1506.     ngx_buf_t            *b, *buf;
  1507.     ngx_chain_t          *cl, **ll;
  1508.     ngx_table_elt_t      *h;
  1509.     ngx_http_request_t   *r;
  1510.     ngx_http_upstream_t  *u;

  1511.     r = ctx->request;
  1512.     u = r->upstream;
  1513.     b = &u->buffer;

  1514.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1515.                    "grpc filter bytes:%z", bytes);

  1516.     b->pos = b->last;
  1517.     b->last += bytes;

  1518.     for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
  1519.         ll = &cl->next;
  1520.     }

  1521.     for ( ;; ) {

  1522.         if (ctx->state < ngx_http_grpc_st_payload) {

  1523.             rc = ngx_http_grpc_parse_frame(r, ctx, b);

  1524.             if (rc == NGX_AGAIN) {

  1525.                 if (ctx->done) {

  1526.                     if (ctx->length > 0) {
  1527.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1528.                                       "upstream prematurely closed stream");
  1529.                         return NGX_ERROR;
  1530.                     }

  1531.                     /*
  1532.                      * We have finished parsing the response and the
  1533.                      * remaining control frames.  If there are unsent
  1534.                      * control frames, post a write event to send them.
  1535.                      */

  1536.                     if (ctx->out) {
  1537.                         ngx_post_event(u->peer.connection->write,
  1538.                                        &ngx_posted_events);
  1539.                         return NGX_AGAIN;
  1540.                     }

  1541.                     u->length = 0;

  1542.                     if (ctx->in == NULL
  1543.                         && ctx->output_closed
  1544.                         && !ctx->output_blocked
  1545.                         && !ctx->goaway
  1546.                         && ctx->state == ngx_http_grpc_st_start)
  1547.                     {
  1548.                         u->keepalive = 1;
  1549.                     }

  1550.                     break;
  1551.                 }

  1552.                 return NGX_AGAIN;
  1553.             }

  1554.             if (rc == NGX_ERROR) {
  1555.                 return NGX_ERROR;
  1556.             }

  1557.             if ((ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME
  1558.                  && !ctx->parsing_headers)
  1559.                 || (ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME
  1560.                     && ctx->parsing_headers))
  1561.             {
  1562.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1563.                               "upstream sent unexpected http2 frame: %d",
  1564.                               ctx->type);
  1565.                 return NGX_ERROR;
  1566.             }

  1567.             if (ctx->type == NGX_HTTP_V2_DATA_FRAME) {

  1568.                 if (ctx->stream_id != ctx->id) {
  1569.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1570.                                   "upstream sent data frame "
  1571.                                   "for unknown stream %ui",
  1572.                                   ctx->stream_id);
  1573.                     return NGX_ERROR;
  1574.                 }

  1575.                 if (ctx->rest > ctx->recv_window) {
  1576.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1577.                                   "upstream violated stream flow control, "
  1578.                                   "received %uz data frame with window %uz",
  1579.                                   ctx->rest, ctx->recv_window);
  1580.                     return NGX_ERROR;
  1581.                 }

  1582.                 if (ctx->rest > ctx->connection->recv_window) {
  1583.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1584.                                   "upstream violated connection flow control, "
  1585.                                   "received %uz data frame with window %uz",
  1586.                                   ctx->rest, ctx->connection->recv_window);
  1587.                     return NGX_ERROR;
  1588.                 }

  1589.                 ctx->recv_window -= ctx->rest;
  1590.                 ctx->connection->recv_window -= ctx->rest;

  1591.                 if (ctx->connection->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4
  1592.                     || ctx->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4)
  1593.                 {
  1594.                     if (ngx_http_grpc_send_window_update(r, ctx) != NGX_OK) {
  1595.                         return NGX_ERROR;
  1596.                     }

  1597.                     ngx_post_event(u->peer.connection->write,
  1598.                                    &ngx_posted_events);
  1599.                 }
  1600.             }

  1601.             if (ctx->stream_id && ctx->stream_id != ctx->id) {
  1602.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1603.                               "upstream sent frame for unknown stream %ui",
  1604.                               ctx->stream_id);
  1605.                 return NGX_ERROR;
  1606.             }

  1607.             if (ctx->stream_id && ctx->done
  1608.                 && ctx->type != NGX_HTTP_V2_RST_STREAM_FRAME
  1609.                 && ctx->type != NGX_HTTP_V2_WINDOW_UPDATE_FRAME)
  1610.             {
  1611.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1612.                               "upstream sent frame for closed stream %ui",
  1613.                               ctx->stream_id);
  1614.                 return NGX_ERROR;
  1615.             }

  1616.             ctx->padding = 0;
  1617.         }

  1618.         if (ctx->state == ngx_http_grpc_st_padding) {

  1619.             if (b->last - b->pos < (ssize_t) ctx->rest) {
  1620.                 ctx->rest -= b->last - b->pos;
  1621.                 b->pos = b->last;
  1622.                 return NGX_AGAIN;
  1623.             }

  1624.             b->pos += ctx->rest;
  1625.             ctx->rest = 0;
  1626.             ctx->state = ngx_http_grpc_st_start;

  1627.             if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
  1628.                 ctx->done = 1;
  1629.             }

  1630.             continue;
  1631.         }

  1632.         /* frame payload */

  1633.         if (ctx->type == NGX_HTTP_V2_RST_STREAM_FRAME) {

  1634.             rc = ngx_http_grpc_parse_rst_stream(r, ctx, b);

  1635.             if (rc == NGX_AGAIN) {
  1636.                 return NGX_AGAIN;
  1637.             }

  1638.             if (rc == NGX_ERROR) {
  1639.                 return NGX_ERROR;
  1640.             }

  1641.             if (ctx->error || !ctx->done) {
  1642.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1643.                               "upstream rejected request with error %ui",
  1644.                               ctx->error);
  1645.                 return NGX_ERROR;
  1646.             }

  1647.             if (ctx->rst) {
  1648.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1649.                               "upstream sent frame for closed stream %ui",
  1650.                               ctx->stream_id);
  1651.                 return NGX_ERROR;
  1652.             }

  1653.             ctx->rst = 1;

  1654.             continue;
  1655.         }

  1656.         if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {

  1657.             rc = ngx_http_grpc_parse_goaway(r, ctx, b);

  1658.             if (rc == NGX_AGAIN) {
  1659.                 return NGX_AGAIN;
  1660.             }

  1661.             if (rc == NGX_ERROR) {
  1662.                 return NGX_ERROR;
  1663.             }

  1664.             /*
  1665.              * If stream_id is lower than one we use, our
  1666.              * request won't be processed and needs to be retried.
  1667.              * If stream_id is greater or equal to the one we use,
  1668.              * we can continue normally (except we can't use this
  1669.              * connection for additional requests).  If there is
  1670.              * a real error, the connection will be closed.
  1671.              */

  1672.             if (ctx->stream_id < ctx->id) {

  1673.                 /* TODO: we can retry non-idempotent requests */

  1674.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1675.                               "upstream sent goaway with error %ui",
  1676.                               ctx->error);

  1677.                 return NGX_ERROR;
  1678.             }

  1679.             ctx->goaway = 1;

  1680.             continue;
  1681.         }

  1682.         if (ctx->type == NGX_HTTP_V2_WINDOW_UPDATE_FRAME) {

  1683.             rc = ngx_http_grpc_parse_window_update(r, ctx, b);

  1684.             if (rc == NGX_AGAIN) {
  1685.                 return NGX_AGAIN;
  1686.             }

  1687.             if (rc == NGX_ERROR) {
  1688.                 return NGX_ERROR;
  1689.             }

  1690.             if (ctx->in) {
  1691.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1692.             }

  1693.             continue;
  1694.         }

  1695.         if (ctx->type == NGX_HTTP_V2_SETTINGS_FRAME) {

  1696.             rc = ngx_http_grpc_parse_settings(r, ctx, b);

  1697.             if (rc == NGX_AGAIN) {
  1698.                 return NGX_AGAIN;
  1699.             }

  1700.             if (rc == NGX_ERROR) {
  1701.                 return NGX_ERROR;
  1702.             }

  1703.             if (ctx->in) {
  1704.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1705.             }

  1706.             continue;
  1707.         }

  1708.         if (ctx->type == NGX_HTTP_V2_PING_FRAME) {

  1709.             rc = ngx_http_grpc_parse_ping(r, ctx, b);

  1710.             if (rc == NGX_AGAIN) {
  1711.                 return NGX_AGAIN;
  1712.             }

  1713.             if (rc == NGX_ERROR) {
  1714.                 return NGX_ERROR;
  1715.             }

  1716.             ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1717.             continue;
  1718.         }

  1719.         if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
  1720.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1721.                           "upstream sent unexpected push promise frame");
  1722.             return NGX_ERROR;
  1723.         }

  1724.         if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME
  1725.             || ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME)
  1726.         {
  1727.             for ( ;; ) {

  1728.                 rc = ngx_http_grpc_parse_header(r, ctx, b);

  1729.                 if (rc == NGX_AGAIN) {
  1730.                     break;
  1731.                 }

  1732.                 if (rc == NGX_OK) {

  1733.                     /* a header line has been parsed successfully */

  1734.                     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1735.                                    "grpc trailer: \"%V: %V\"",
  1736.                                    &ctx->name, &ctx->value);

  1737.                     if (ctx->name.len && ctx->name.data[0] == ':') {
  1738.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1739.                                       "upstream sent invalid "
  1740.                                       "trailer \"%V: %V\"",
  1741.                                       &ctx->name, &ctx->value);
  1742.                         return NGX_ERROR;
  1743.                     }

  1744.                     h = ngx_list_push(&u->headers_in.trailers);
  1745.                     if (h == NULL) {
  1746.                         return NGX_ERROR;
  1747.                     }

  1748.                     h->key = ctx->name;
  1749.                     h->value = ctx->value;
  1750.                     h->lowcase_key = h->key.data;
  1751.                     h->hash = ngx_hash_key(h->key.data, h->key.len);

  1752.                     continue;
  1753.                 }

  1754.                 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {

  1755.                     /* a whole header has been parsed successfully */

  1756.                     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1757.                                    "grpc trailer done");

  1758.                     if (ctx->end_stream) {
  1759.                         ctx->done = 1;
  1760.                         break;
  1761.                     }

  1762.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1763.                                   "upstream sent trailer without "
  1764.                                   "end stream flag");
  1765.                     return NGX_ERROR;
  1766.                 }

  1767.                 /* there was error while a header line parsing */

  1768.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1769.                               "upstream sent invalid trailer");

  1770.                 return NGX_ERROR;
  1771.             }

  1772.             if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
  1773.                 continue;
  1774.             }

  1775.             /* rc == NGX_AGAIN */

  1776.             if (ctx->rest == 0) {
  1777.                 ctx->state = ngx_http_grpc_st_start;
  1778.                 continue;
  1779.             }

  1780.             return NGX_AGAIN;
  1781.         }

  1782.         if (ctx->type != NGX_HTTP_V2_DATA_FRAME) {

  1783.             /* priority, unknown frames */

  1784.             if (b->last - b->pos < (ssize_t) ctx->rest) {
  1785.                 ctx->rest -= b->last - b->pos;
  1786.                 b->pos = b->last;
  1787.                 return NGX_AGAIN;
  1788.             }

  1789.             b->pos += ctx->rest;
  1790.             ctx->rest = 0;
  1791.             ctx->state = ngx_http_grpc_st_start;

  1792.             continue;
  1793.         }

  1794.         /*
  1795.          * data frame:
  1796.          *
  1797.          * +---------------+
  1798.          * |Pad Length? (8)|
  1799.          * +---------------+-----------------------------------------------+
  1800.          * |                            Data (*)                         ...
  1801.          * +---------------------------------------------------------------+
  1802.          * |                           Padding (*)                       ...
  1803.          * +---------------------------------------------------------------+
  1804.          */

  1805.         if (ctx->flags & NGX_HTTP_V2_PADDED_FLAG) {

  1806.             if (ctx->rest == 0) {
  1807.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1808.                               "upstream sent too short http2 frame");
  1809.                 return NGX_ERROR;
  1810.             }

  1811.             if (b->pos == b->last) {
  1812.                 return NGX_AGAIN;
  1813.             }

  1814.             ctx->flags &= ~NGX_HTTP_V2_PADDED_FLAG;
  1815.             ctx->padding = *b->pos++;
  1816.             ctx->rest -= 1;

  1817.             if (ctx->padding > ctx->rest) {
  1818.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1819.                               "upstream sent http2 frame with too long "
  1820.                               "padding: %d in frame %uz",
  1821.                               ctx->padding, ctx->rest);
  1822.                 return NGX_ERROR;
  1823.             }

  1824.             continue;
  1825.         }

  1826.         if (ctx->rest == ctx->padding) {
  1827.             goto done;
  1828.         }

  1829.         if (b->pos == b->last) {
  1830.             return NGX_AGAIN;
  1831.         }

  1832.         cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
  1833.         if (cl == NULL) {
  1834.             return NGX_ERROR;
  1835.         }

  1836.         *ll = cl;
  1837.         ll = &cl->next;

  1838.         buf = cl->buf;

  1839.         buf->flush = 1;
  1840.         buf->memory = 1;

  1841.         buf->pos = b->pos;
  1842.         buf->tag = u->output.tag;

  1843.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1844.                        "grpc output buf %p", buf->pos);

  1845.         if (b->last - b->pos < (ssize_t) ctx->rest - ctx->padding) {

  1846.             ctx->rest -= b->last - b->pos;
  1847.             b->pos = b->last;
  1848.             buf->last = b->pos;

  1849.             if (ctx->length != -1) {

  1850.                 if (buf->last - buf->pos > ctx->length) {
  1851.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1852.                                   "upstream sent response body larger "
  1853.                                   "than indicated content length");
  1854.                     return NGX_ERROR;
  1855.                 }

  1856.                 ctx->length -= buf->last - buf->pos;
  1857.             }

  1858.             return NGX_AGAIN;
  1859.         }

  1860.         b->pos += ctx->rest - ctx->padding;
  1861.         buf->last = b->pos;
  1862.         ctx->rest = ctx->padding;

  1863.         if (ctx->length != -1) {

  1864.             if (buf->last - buf->pos > ctx->length) {
  1865.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1866.                               "upstream sent response body larger "
  1867.                               "than indicated content length");
  1868.                 return NGX_ERROR;
  1869.             }

  1870.             ctx->length -= buf->last - buf->pos;
  1871.         }

  1872.     done:

  1873.         if (ctx->padding) {
  1874.             ctx->state = ngx_http_grpc_st_padding;
  1875.             continue;
  1876.         }

  1877.         ctx->state = ngx_http_grpc_st_start;

  1878.         if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
  1879.             ctx->done = 1;
  1880.         }
  1881.     }

  1882.     return NGX_OK;
  1883. }


  1884. static ngx_int_t
  1885. ngx_http_grpc_parse_frame(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  1886.     ngx_buf_t *b)
  1887. {
  1888.     u_char                 ch, *p;
  1889.     ngx_http_grpc_state_e  state;

  1890.     state = ctx->state;

  1891.     for (p = b->pos; p < b->last; p++) {
  1892.         ch = *p;

  1893. #if 0
  1894.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1895.                        "grpc frame byte: %02Xd, s:%d", ch, state);
  1896. #endif

  1897.         switch (state) {

  1898.         case ngx_http_grpc_st_start:
  1899.             ctx->rest = ch << 16;
  1900.             state = ngx_http_grpc_st_length_2;
  1901.             break;

  1902.         case ngx_http_grpc_st_length_2:
  1903.             ctx->rest |= ch << 8;
  1904.             state = ngx_http_grpc_st_length_3;
  1905.             break;

  1906.         case ngx_http_grpc_st_length_3:
  1907.             ctx->rest |= ch;

  1908.             if (ctx->rest > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
  1909.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1910.                               "upstream sent too large http2 frame: %uz",
  1911.                               ctx->rest);
  1912.                 return NGX_ERROR;
  1913.             }

  1914.             state = ngx_http_grpc_st_type;
  1915.             break;

  1916.         case ngx_http_grpc_st_type:
  1917.             ctx->type = ch;
  1918.             state = ngx_http_grpc_st_flags;
  1919.             break;

  1920.         case ngx_http_grpc_st_flags:
  1921.             ctx->flags = ch;
  1922.             state = ngx_http_grpc_st_stream_id;
  1923.             break;

  1924.         case ngx_http_grpc_st_stream_id:
  1925.             ctx->stream_id = (ch & 0x7f) << 24;
  1926.             state = ngx_http_grpc_st_stream_id_2;
  1927.             break;

  1928.         case ngx_http_grpc_st_stream_id_2:
  1929.             ctx->stream_id |= ch << 16;
  1930.             state = ngx_http_grpc_st_stream_id_3;
  1931.             break;

  1932.         case ngx_http_grpc_st_stream_id_3:
  1933.             ctx->stream_id |= ch << 8;
  1934.             state = ngx_http_grpc_st_stream_id_4;
  1935.             break;

  1936.         case ngx_http_grpc_st_stream_id_4:
  1937.             ctx->stream_id |= ch;

  1938.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1939.                            "grpc frame: %d, len: %uz, f:%d, i:%ui",
  1940.                            ctx->type, ctx->rest, ctx->flags, ctx->stream_id);

  1941.             b->pos = p + 1;

  1942.             ctx->state = ngx_http_grpc_st_payload;
  1943.             ctx->frame_state = 0;

  1944.             return NGX_OK;

  1945.         /* suppress warning */
  1946.         case ngx_http_grpc_st_payload:
  1947.         case ngx_http_grpc_st_padding:
  1948.             break;
  1949.         }
  1950.     }

  1951.     b->pos = p;
  1952.     ctx->state = state;

  1953.     return NGX_AGAIN;
  1954. }


  1955. static ngx_int_t
  1956. ngx_http_grpc_parse_header(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  1957.     ngx_buf_t *b)
  1958. {
  1959.     u_char     ch, *p, *last;
  1960.     size_t     min;
  1961.     ngx_int_t  rc;
  1962.     enum {
  1963.         sw_start = 0,
  1964.         sw_padding_length,
  1965.         sw_dependency,
  1966.         sw_dependency_2,
  1967.         sw_dependency_3,
  1968.         sw_dependency_4,
  1969.         sw_weight,
  1970.         sw_fragment,
  1971.         sw_padding
  1972.     } state;

  1973.     state = ctx->frame_state;

  1974.     if (state == sw_start) {

  1975.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1976.                        "grpc parse header: start");

  1977.         if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME) {
  1978.             ctx->parsing_headers = 1;
  1979.             ctx->fragment_state = 0;

  1980.             min = (ctx->flags & NGX_HTTP_V2_PADDED_FLAG ? 1 : 0)
  1981.                   + (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG ? 5 : 0);

  1982.             if (ctx->rest < min) {
  1983.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1984.                               "upstream sent headers frame "
  1985.                               "with invalid length: %uz",
  1986.                               ctx->rest);
  1987.                 return NGX_ERROR;
  1988.             }

  1989.             if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
  1990.                 ctx->end_stream = 1;
  1991.             }

  1992.             if (ctx->flags & NGX_HTTP_V2_PADDED_FLAG) {
  1993.                 state = sw_padding_length;

  1994.             } else if (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG) {
  1995.                 state = sw_dependency;

  1996.             } else {
  1997.                 state = sw_fragment;
  1998.             }

  1999.         } else if (ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME) {
  2000.             state = sw_fragment;
  2001.         }

  2002.         ctx->padding = 0;
  2003.         ctx->frame_state = state;
  2004.     }

  2005.     if (state < sw_fragment) {

  2006.         if (b->last - b->pos < (ssize_t) ctx->rest) {
  2007.             last = b->last;

  2008.         } else {
  2009.             last = b->pos + ctx->rest;
  2010.         }

  2011.         for (p = b->pos; p < last; p++) {
  2012.             ch = *p;

  2013. #if 0
  2014.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2015.                            "grpc header byte: %02Xd s:%d", ch, state);
  2016. #endif

  2017.             /*
  2018.              * headers frame:
  2019.              *
  2020.              * +---------------+
  2021.              * |Pad Length? (8)|
  2022.              * +-+-------------+----------------------------------------------+
  2023.              * |E|                 Stream Dependency? (31)                    |
  2024.              * +-+-------------+----------------------------------------------+
  2025.              * |  Weight? (8)  |
  2026.              * +-+-------------+----------------------------------------------+
  2027.              * |                   Header Block Fragment (*)                ...
  2028.              * +--------------------------------------------------------------+
  2029.              * |                           Padding (*)                      ...
  2030.              * +--------------------------------------------------------------+
  2031.              */

  2032.             switch (state) {

  2033.             case sw_padding_length:

  2034.                 ctx->padding = ch;

  2035.                 if (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG) {
  2036.                     state = sw_dependency;
  2037.                     break;
  2038.                 }

  2039.                 goto fragment;

  2040.             case sw_dependency:
  2041.                 state = sw_dependency_2;
  2042.                 break;

  2043.             case sw_dependency_2:
  2044.                 state = sw_dependency_3;
  2045.                 break;

  2046.             case sw_dependency_3:
  2047.                 state = sw_dependency_4;
  2048.                 break;

  2049.             case sw_dependency_4:
  2050.                 state = sw_weight;
  2051.                 break;

  2052.             case sw_weight:
  2053.                 goto fragment;

  2054.             /* suppress warning */
  2055.             case sw_start:
  2056.             case sw_fragment:
  2057.             case sw_padding:
  2058.                 break;
  2059.             }
  2060.         }

  2061.         ctx->rest -= p - b->pos;
  2062.         b->pos = p;

  2063.         ctx->frame_state = state;
  2064.         return NGX_AGAIN;

  2065.     fragment:

  2066.         p++;
  2067.         ctx->rest -= p - b->pos;
  2068.         b->pos = p;

  2069.         if (ctx->padding > ctx->rest) {
  2070.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2071.                           "upstream sent http2 frame with too long "
  2072.                           "padding: %d in frame %uz",
  2073.                           ctx->padding, ctx->rest);
  2074.             return NGX_ERROR;
  2075.         }

  2076.         state = sw_fragment;
  2077.         ctx->frame_state = state;
  2078.     }

  2079.     if (state == sw_fragment) {

  2080.         rc = ngx_http_grpc_parse_fragment(r, ctx, b);

  2081.         if (rc == NGX_AGAIN) {
  2082.             return NGX_AGAIN;
  2083.         }

  2084.         if (rc == NGX_ERROR) {
  2085.             return NGX_ERROR;
  2086.         }

  2087.         if (rc == NGX_OK) {
  2088.             return NGX_OK;
  2089.         }

  2090.         /* rc == NGX_DONE */

  2091.         state = sw_padding;
  2092.         ctx->frame_state = state;
  2093.     }

  2094.     if (state == sw_padding) {

  2095.         if (b->last - b->pos < (ssize_t) ctx->rest) {

  2096.             ctx->rest -= b->last - b->pos;
  2097.             b->pos = b->last;

  2098.             return NGX_AGAIN;
  2099.         }

  2100.         b->pos += ctx->rest;
  2101.         ctx->rest = 0;

  2102.         ctx->state = ngx_http_grpc_st_start;

  2103.         if (ctx->flags & NGX_HTTP_V2_END_HEADERS_FLAG) {

  2104.             if (ctx->fragment_state) {
  2105.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2106.                               "upstream sent truncated http2 header");
  2107.                 return NGX_ERROR;
  2108.             }

  2109.             ctx->parsing_headers = 0;

  2110.             return NGX_HTTP_PARSE_HEADER_DONE;
  2111.         }

  2112.         return NGX_AGAIN;
  2113.     }

  2114.     /* unreachable */

  2115.     return NGX_ERROR;
  2116. }


  2117. static ngx_int_t
  2118. ngx_http_grpc_parse_fragment(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2119.     ngx_buf_t *b)
  2120. {
  2121.     u_char      ch, *p, *last;
  2122.     size_t      size;
  2123.     ngx_uint_t  index, size_update;
  2124.     enum {
  2125.         sw_start = 0,
  2126.         sw_index,
  2127.         sw_name_length,
  2128.         sw_name_length_2,
  2129.         sw_name_length_3,
  2130.         sw_name_length_4,
  2131.         sw_name,
  2132.         sw_name_bytes,
  2133.         sw_value_length,
  2134.         sw_value_length_2,
  2135.         sw_value_length_3,
  2136.         sw_value_length_4,
  2137.         sw_value,
  2138.         sw_value_bytes
  2139.     } state;

  2140.     /* header block fragment */

  2141. #if 0
  2142.     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2143.                    "grpc header fragment %p:%p rest:%uz",
  2144.                    b->pos, b->last, ctx->rest);
  2145. #endif

  2146.     if (b->last - b->pos < (ssize_t) ctx->rest - ctx->padding) {
  2147.         last = b->last;

  2148.     } else {
  2149.         last = b->pos + ctx->rest - ctx->padding;
  2150.     }

  2151.     state = ctx->fragment_state;

  2152.     for (p = b->pos; p < last; p++) {
  2153.         ch = *p;

  2154. #if 0
  2155.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2156.                        "grpc header byte: %02Xd s:%d", ch, state);
  2157. #endif

  2158.         switch (state) {

  2159.         case sw_start:
  2160.             ctx->index = 0;

  2161.             if ((ch & 0x80) == 0x80) {
  2162.                 /*
  2163.                  * indexed header:
  2164.                  *
  2165.                  *   0   1   2   3   4   5   6   7
  2166.                  * +---+---+---+---+---+---+---+---+
  2167.                  * | 1 |        Index (7+)         |
  2168.                  * +---+---------------------------+
  2169.                  */

  2170.                 index = ch & ~0x80;

  2171.                 if (index == 0 || index > 61) {
  2172.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2173.                                   "upstream sent invalid http2 "
  2174.                                   "table index: %ui", index);
  2175.                     return NGX_ERROR;
  2176.                 }

  2177.                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2178.                                "grpc indexed header: %ui", index);

  2179.                 ctx->index = index;
  2180.                 ctx->literal = 0;

  2181.                 goto done;

  2182.             } else if ((ch & 0xc0) == 0x40) {
  2183.                 /*
  2184.                  * literal header with incremental indexing:
  2185.                  *
  2186.                  *   0   1   2   3   4   5   6   7
  2187.                  * +---+---+---+---+---+---+---+---+
  2188.                  * | 0 | 1 |      Index (6+)       |
  2189.                  * +---+---+-----------------------+
  2190.                  * | H |     Value Length (7+)     |
  2191.                  * +---+---------------------------+
  2192.                  * | Value String (Length octets)  |
  2193.                  * +-------------------------------+
  2194.                  *
  2195.                  *   0   1   2   3   4   5   6   7
  2196.                  * +---+---+---+---+---+---+---+---+
  2197.                  * | 0 | 1 |           0           |
  2198.                  * +---+---+-----------------------+
  2199.                  * | H |     Name Length (7+)      |
  2200.                  * +---+---------------------------+
  2201.                  * |  Name String (Length octets)  |
  2202.                  * +---+---------------------------+
  2203.                  * | H |     Value Length (7+)     |
  2204.                  * +---+---------------------------+
  2205.                  * | Value String (Length octets)  |
  2206.                  * +-------------------------------+
  2207.                  */

  2208.                 index = ch & ~0xc0;

  2209.                 if (index > 61) {
  2210.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2211.                                   "upstream sent invalid http2 "
  2212.                                   "table index: %ui", index);
  2213.                     return NGX_ERROR;
  2214.                 }

  2215.                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2216.                                "grpc literal header: %ui", index);

  2217.                 if (index == 0) {
  2218.                     state = sw_name_length;
  2219.                     break;
  2220.                 }

  2221.                 ctx->index = index;
  2222.                 ctx->literal = 1;

  2223.                 state = sw_value_length;
  2224.                 break;

  2225.             } else if ((ch & 0xe0) == 0x20) {
  2226.                 /*
  2227.                  * dynamic table size update:
  2228.                  *
  2229.                  *   0   1   2   3   4   5   6   7
  2230.                  * +---+---+---+---+---+---+---+---+
  2231.                  * | 0 | 0 | 1 |   Max size (5+)   |
  2232.                  * +---+---------------------------+
  2233.                  */

  2234.                 size_update = ch & ~0xe0;

  2235.                 if (size_update > 0) {
  2236.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2237.                                   "upstream sent invalid http2 "
  2238.                                   "dynamic table size update: %ui",
  2239.                                   size_update);
  2240.                     return NGX_ERROR;
  2241.                 }

  2242.                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2243.                                "grpc table size update: %ui", size_update);

  2244.                 break;

  2245.             } else if ((ch & 0xf0) == 0x10) {
  2246.                 /*
  2247.                  *  literal header field never indexed:
  2248.                  *
  2249.                  *   0   1   2   3   4   5   6   7
  2250.                  * +---+---+---+---+---+---+---+---+
  2251.                  * | 0 | 0 | 0 | 1 |  Index (4+)   |
  2252.                  * +---+---+-----------------------+
  2253.                  * | H |     Value Length (7+)     |
  2254.                  * +---+---------------------------+
  2255.                  * | Value String (Length octets)  |
  2256.                  * +-------------------------------+
  2257.                  *
  2258.                  *   0   1   2   3   4   5   6   7
  2259.                  * +---+---+---+---+---+---+---+---+
  2260.                  * | 0 | 0 | 0 | 1 |       0       |
  2261.                  * +---+---+-----------------------+
  2262.                  * | H |     Name Length (7+)      |
  2263.                  * +---+---------------------------+
  2264.                  * |  Name String (Length octets)  |
  2265.                  * +---+---------------------------+
  2266.                  * | H |     Value Length (7+)     |
  2267.                  * +---+---------------------------+
  2268.                  * | Value String (Length octets)  |
  2269.                  * +-------------------------------+
  2270.                  */

  2271.                 index = ch & ~0xf0;

  2272.                 if (index == 0x0f) {
  2273.                     ctx->index = index;
  2274.                     ctx->literal = 1;
  2275.                     state = sw_index;
  2276.                     break;
  2277.                 }

  2278.                 if (index == 0) {
  2279.                     state = sw_name_length;
  2280.                     break;
  2281.                 }

  2282.                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2283.                                "grpc literal header never indexed: %ui",
  2284.                                index);

  2285.                 ctx->index = index;
  2286.                 ctx->literal = 1;

  2287.                 state = sw_value_length;
  2288.                 break;

  2289.             } else if ((ch & 0xf0) == 0x00) {
  2290.                 /*
  2291.                  * literal header field without indexing:
  2292.                  *
  2293.                  *   0   1   2   3   4   5   6   7
  2294.                  * +---+---+---+---+---+---+---+---+
  2295.                  * | 0 | 0 | 0 | 0 |  Index (4+)   |
  2296.                  * +---+---+-----------------------+
  2297.                  * | H |     Value Length (7+)     |
  2298.                  * +---+---------------------------+
  2299.                  * | Value String (Length octets)  |
  2300.                  * +-------------------------------+
  2301.                  *
  2302.                  *   0   1   2   3   4   5   6   7
  2303.                  * +---+---+---+---+---+---+---+---+
  2304.                  * | 0 | 0 | 0 | 0 |       0       |
  2305.                  * +---+---+-----------------------+
  2306.                  * | H |     Name Length (7+)      |
  2307.                  * +---+---------------------------+
  2308.                  * |  Name String (Length octets)  |
  2309.                  * +---+---------------------------+
  2310.                  * | H |     Value Length (7+)     |
  2311.                  * +---+---------------------------+
  2312.                  * | Value String (Length octets)  |
  2313.                  * +-------------------------------+
  2314.                  */

  2315.                 index = ch & ~0xf0;

  2316.                 if (index == 0x0f) {
  2317.                     ctx->index = index;
  2318.                     ctx->literal = 1;
  2319.                     state = sw_index;
  2320.                     break;
  2321.                 }

  2322.                 if (index == 0) {
  2323.                     state = sw_name_length;
  2324.                     break;
  2325.                 }

  2326.                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2327.                                "grpc literal header without indexing: %ui",
  2328.                                index);

  2329.                 ctx->index = index;
  2330.                 ctx->literal = 1;

  2331.                 state = sw_value_length;
  2332.                 break;
  2333.             }

  2334.             /* not reached */

  2335.             return NGX_ERROR;

  2336.         case sw_index:
  2337.             ctx->index = ctx->index + (ch & ~0x80);

  2338.             if (ch & 0x80) {
  2339.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2340.                               "upstream sent http2 table index "
  2341.                               "with continuation flag");
  2342.                 return NGX_ERROR;
  2343.             }

  2344.             if (ctx->index > 61) {
  2345.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2346.                               "upstream sent invalid http2 "
  2347.                               "table index: %ui", ctx->index);
  2348.                 return NGX_ERROR;
  2349.             }

  2350.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2351.                            "grpc header index: %ui", ctx->index);

  2352.             state = sw_value_length;
  2353.             break;

  2354.         case sw_name_length:
  2355.             ctx->field_huffman = ch & 0x80 ? 1 : 0;
  2356.             ctx->field_length = ch & ~0x80;

  2357.             if (ctx->field_length == 0x7f) {
  2358.                 state = sw_name_length_2;
  2359.                 break;
  2360.             }

  2361.             if (ctx->field_length == 0) {
  2362.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2363.                               "upstream sent zero http2 "
  2364.                               "header name length");
  2365.                 return NGX_ERROR;
  2366.             }

  2367.             state = sw_name;
  2368.             break;

  2369.         case sw_name_length_2:
  2370.             ctx->field_length += ch & ~0x80;

  2371.             if (ch & 0x80) {
  2372.                 state = sw_name_length_3;
  2373.                 break;
  2374.             }

  2375.             state = sw_name;
  2376.             break;

  2377.         case sw_name_length_3:
  2378.             ctx->field_length += (ch & ~0x80) << 7;

  2379.             if (ch & 0x80) {
  2380.                 state = sw_name_length_4;
  2381.                 break;
  2382.             }

  2383.             state = sw_name;
  2384.             break;

  2385.         case sw_name_length_4:
  2386.             ctx->field_length += (ch & ~0x80) << 14;

  2387.             if (ch & 0x80) {
  2388.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2389.                               "upstream sent too large http2 "
  2390.                               "header name length");
  2391.                 return NGX_ERROR;
  2392.             }

  2393.             state = sw_name;
  2394.             break;

  2395.         case sw_name:
  2396.             ctx->name.len = ctx->field_huffman ?
  2397.                             ctx->field_length * 8 / 5 : ctx->field_length;

  2398.             ctx->name.data = ngx_pnalloc(r->pool, ctx->name.len + 1);
  2399.             if (ctx->name.data == NULL) {
  2400.                 return NGX_ERROR;
  2401.             }

  2402.             ctx->field_end = ctx->name.data;
  2403.             ctx->field_rest = ctx->field_length;
  2404.             ctx->field_state = 0;

  2405.             state = sw_name_bytes;

  2406.             /* fall through */

  2407.         case sw_name_bytes:

  2408.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2409.                            "grpc name: len:%uz h:%d last:%uz, rest:%uz",
  2410.                            ctx->field_length,
  2411.                            ctx->field_huffman,
  2412.                            last - p,
  2413.                            ctx->rest - (p - b->pos));

  2414.             size = ngx_min(last - p, (ssize_t) ctx->field_rest);
  2415.             ctx->field_rest -= size;

  2416.             if (ctx->field_huffman) {
  2417.                 if (ngx_http_huff_decode(&ctx->field_state, p, size,
  2418.                                          &ctx->field_end,
  2419.                                          ctx->field_rest == 0,
  2420.                                          r->connection->log)
  2421.                     != NGX_OK)
  2422.                 {
  2423.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2424.                                   "upstream sent invalid encoded header");
  2425.                     return NGX_ERROR;
  2426.                 }

  2427.                 ctx->name.len = ctx->field_end - ctx->name.data;
  2428.                 ctx->name.data[ctx->name.len] = '\0';

  2429.             } else {
  2430.                 ctx->field_end = ngx_cpymem(ctx->field_end, p, size);
  2431.                 ctx->name.data[ctx->name.len] = '\0';
  2432.             }

  2433.             p += size - 1;

  2434.             if (ctx->field_rest == 0) {
  2435.                 state = sw_value_length;
  2436.             }

  2437.             break;

  2438.         case sw_value_length:
  2439.             ctx->field_huffman = ch & 0x80 ? 1 : 0;
  2440.             ctx->field_length = ch & ~0x80;

  2441.             if (ctx->field_length == 0x7f) {
  2442.                 state = sw_value_length_2;
  2443.                 break;
  2444.             }

  2445.             if (ctx->field_length == 0) {
  2446.                 ngx_str_set(&ctx->value, "");
  2447.                 goto done;
  2448.             }

  2449.             state = sw_value;
  2450.             break;

  2451.         case sw_value_length_2:
  2452.             ctx->field_length += ch & ~0x80;

  2453.             if (ch & 0x80) {
  2454.                 state = sw_value_length_3;
  2455.                 break;
  2456.             }

  2457.             state = sw_value;
  2458.             break;

  2459.         case sw_value_length_3:
  2460.             ctx->field_length += (ch & ~0x80) << 7;

  2461.             if (ch & 0x80) {
  2462.                 state = sw_value_length_4;
  2463.                 break;
  2464.             }

  2465.             state = sw_value;
  2466.             break;

  2467.         case sw_value_length_4:
  2468.             ctx->field_length += (ch & ~0x80) << 14;

  2469.             if (ch & 0x80) {
  2470.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2471.                               "upstream sent too large http2 "
  2472.                               "header value length");
  2473.                 return NGX_ERROR;
  2474.             }

  2475.             state = sw_value;
  2476.             break;

  2477.         case sw_value:
  2478.             ctx->value.len = ctx->field_huffman ?
  2479.                              ctx->field_length * 8 / 5 : ctx->field_length;

  2480.             ctx->value.data = ngx_pnalloc(r->pool, ctx->value.len + 1);
  2481.             if (ctx->value.data == NULL) {
  2482.                 return NGX_ERROR;
  2483.             }

  2484.             ctx->field_end = ctx->value.data;
  2485.             ctx->field_rest = ctx->field_length;
  2486.             ctx->field_state = 0;

  2487.             state = sw_value_bytes;

  2488.             /* fall through */

  2489.         case sw_value_bytes:

  2490.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2491.                            "grpc value: len:%uz h:%d last:%uz, rest:%uz",
  2492.                            ctx->field_length,
  2493.                            ctx->field_huffman,
  2494.                            last - p,
  2495.                            ctx->rest - (p - b->pos));

  2496.             size = ngx_min(last - p, (ssize_t) ctx->field_rest);
  2497.             ctx->field_rest -= size;

  2498.             if (ctx->field_huffman) {
  2499.                 if (ngx_http_huff_decode(&ctx->field_state, p, size,
  2500.                                          &ctx->field_end,
  2501.                                          ctx->field_rest == 0,
  2502.                                          r->connection->log)
  2503.                     != NGX_OK)
  2504.                 {
  2505.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2506.                                   "upstream sent invalid encoded header");
  2507.                     return NGX_ERROR;
  2508.                 }

  2509.                 ctx->value.len = ctx->field_end - ctx->value.data;
  2510.                 ctx->value.data[ctx->value.len] = '\0';

  2511.             } else {
  2512.                 ctx->field_end = ngx_cpymem(ctx->field_end, p, size);
  2513.                 ctx->value.data[ctx->value.len] = '\0';
  2514.             }

  2515.             p += size - 1;

  2516.             if (ctx->field_rest == 0) {
  2517.                 goto done;
  2518.             }

  2519.             break;
  2520.         }

  2521.         continue;

  2522.     done:

  2523.         p++;
  2524.         ctx->rest -= p - b->pos;
  2525.         ctx->fragment_state = sw_start;
  2526.         b->pos = p;

  2527.         if (ctx->index) {
  2528.             ctx->name = *ngx_http_v2_get_static_name(ctx->index);
  2529.         }

  2530.         if (ctx->index && !ctx->literal) {
  2531.             ctx->value = *ngx_http_v2_get_static_value(ctx->index);
  2532.         }

  2533.         if (!ctx->index) {
  2534.             if (ngx_http_grpc_validate_header_name(r, &ctx->name) != NGX_OK) {
  2535.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2536.                               "upstream sent invalid header: \"%V: %V\"",
  2537.                               &ctx->name, &ctx->value);
  2538.                 return NGX_ERROR;
  2539.             }
  2540.         }

  2541.         if (!ctx->index || ctx->literal) {
  2542.             if (ngx_http_grpc_validate_header_value(r, &ctx->value) != NGX_OK) {
  2543.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2544.                               "upstream sent invalid header: \"%V: %V\"",
  2545.                               &ctx->name, &ctx->value);
  2546.                 return NGX_ERROR;
  2547.             }
  2548.         }

  2549.         return NGX_OK;
  2550.     }

  2551.     ctx->rest -= p - b->pos;
  2552.     ctx->fragment_state = state;
  2553.     b->pos = p;

  2554.     if (ctx->rest > ctx->padding) {
  2555.         return NGX_AGAIN;
  2556.     }

  2557.     return NGX_DONE;
  2558. }


  2559. static ngx_int_t
  2560. ngx_http_grpc_validate_header_name(ngx_http_request_t *r, ngx_str_t *s)
  2561. {
  2562.     u_char      ch;
  2563.     ngx_uint_t  i;

  2564.     for (i = 0; i < s->len; i++) {
  2565.         ch = s->data[i];

  2566.         if (ch == ':' && i > 0) {
  2567.             return NGX_ERROR;
  2568.         }

  2569.         if (ch >= 'A' && ch <= 'Z') {
  2570.             return NGX_ERROR;
  2571.         }

  2572.         if (ch <= 0x20 || ch == 0x7f) {
  2573.             return NGX_ERROR;
  2574.         }
  2575.     }

  2576.     return NGX_OK;
  2577. }


  2578. static ngx_int_t
  2579. ngx_http_grpc_validate_header_value(ngx_http_request_t *r, ngx_str_t *s)
  2580. {
  2581.     u_char      ch;
  2582.     ngx_uint_t  i;

  2583.     for (i = 0; i < s->len; i++) {
  2584.         ch = s->data[i];

  2585.         if (ch == '\0' || ch == CR || ch == LF) {
  2586.             return NGX_ERROR;
  2587.         }
  2588.     }

  2589.     return NGX_OK;
  2590. }


  2591. static ngx_int_t
  2592. ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2593.     ngx_buf_t *b)
  2594. {
  2595.     u_char  ch, *p, *last;
  2596.     enum {
  2597.         sw_start = 0,
  2598.         sw_error_2,
  2599.         sw_error_3,
  2600.         sw_error_4
  2601.     } state;

  2602.     if (b->last - b->pos < (ssize_t) ctx->rest) {
  2603.         last = b->last;

  2604.     } else {
  2605.         last = b->pos + ctx->rest;
  2606.     }

  2607.     state = ctx->frame_state;

  2608.     if (state == sw_start) {
  2609.         if (ctx->rest != 4) {
  2610.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2611.                           "upstream sent rst stream frame "
  2612.                           "with invalid length: %uz",
  2613.                           ctx->rest);
  2614.             return NGX_ERROR;
  2615.         }
  2616.     }

  2617.     for (p = b->pos; p < last; p++) {
  2618.         ch = *p;

  2619. #if 0
  2620.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2621.                        "grpc rst byte: %02Xd s:%d", ch, state);
  2622. #endif

  2623.         switch (state) {

  2624.         case sw_start:
  2625.             ctx->error = (ngx_uint_t) ch << 24;
  2626.             state = sw_error_2;
  2627.             break;

  2628.         case sw_error_2:
  2629.             ctx->error |= ch << 16;
  2630.             state = sw_error_3;
  2631.             break;

  2632.         case sw_error_3:
  2633.             ctx->error |= ch << 8;
  2634.             state = sw_error_4;
  2635.             break;

  2636.         case sw_error_4:
  2637.             ctx->error |= ch;
  2638.             state = sw_start;

  2639.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2640.                            "grpc error: %ui", ctx->error);

  2641.             break;
  2642.         }
  2643.     }

  2644.     ctx->rest -= p - b->pos;
  2645.     ctx->frame_state = state;
  2646.     b->pos = p;

  2647.     if (ctx->rest > 0) {
  2648.         return NGX_AGAIN;
  2649.     }

  2650.     ctx->state = ngx_http_grpc_st_start;

  2651.     return NGX_OK;
  2652. }


  2653. static ngx_int_t
  2654. ngx_http_grpc_parse_goaway(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2655.     ngx_buf_t *b)
  2656. {
  2657.     u_char  ch, *p, *last;
  2658.     enum {
  2659.         sw_start = 0,
  2660.         sw_last_stream_id_2,
  2661.         sw_last_stream_id_3,
  2662.         sw_last_stream_id_4,
  2663.         sw_error,
  2664.         sw_error_2,
  2665.         sw_error_3,
  2666.         sw_error_4,
  2667.         sw_debug
  2668.     } state;

  2669.     if (b->last - b->pos < (ssize_t) ctx->rest) {
  2670.         last = b->last;

  2671.     } else {
  2672.         last = b->pos + ctx->rest;
  2673.     }

  2674.     state = ctx->frame_state;

  2675.     if (state == sw_start) {

  2676.         if (ctx->stream_id) {
  2677.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2678.                           "upstream sent goaway frame "
  2679.                           "with non-zero stream id: %ui",
  2680.                           ctx->stream_id);
  2681.             return NGX_ERROR;
  2682.         }

  2683.         if (ctx->rest < 8) {
  2684.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2685.                           "upstream sent goaway frame "
  2686.                           "with invalid length: %uz",
  2687.                           ctx->rest);
  2688.             return NGX_ERROR;
  2689.         }
  2690.     }

  2691.     for (p = b->pos; p < last; p++) {
  2692.         ch = *p;

  2693. #if 0
  2694.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2695.                        "grpc goaway byte: %02Xd s:%d", ch, state);
  2696. #endif

  2697.         switch (state) {

  2698.         case sw_start:
  2699.             ctx->stream_id = (ch & 0x7f) << 24;
  2700.             state = sw_last_stream_id_2;
  2701.             break;

  2702.         case sw_last_stream_id_2:
  2703.             ctx->stream_id |= ch << 16;
  2704.             state = sw_last_stream_id_3;
  2705.             break;

  2706.         case sw_last_stream_id_3:
  2707.             ctx->stream_id |= ch << 8;
  2708.             state = sw_last_stream_id_4;
  2709.             break;

  2710.         case sw_last_stream_id_4:
  2711.             ctx->stream_id |= ch;
  2712.             state = sw_error;
  2713.             break;

  2714.         case sw_error:
  2715.             ctx->error = (ngx_uint_t) ch << 24;
  2716.             state = sw_error_2;
  2717.             break;

  2718.         case sw_error_2:
  2719.             ctx->error |= ch << 16;
  2720.             state = sw_error_3;
  2721.             break;

  2722.         case sw_error_3:
  2723.             ctx->error |= ch << 8;
  2724.             state = sw_error_4;
  2725.             break;

  2726.         case sw_error_4:
  2727.             ctx->error |= ch;
  2728.             state = sw_debug;
  2729.             break;

  2730.         case sw_debug:
  2731.             break;
  2732.         }
  2733.     }

  2734.     ctx->rest -= p - b->pos;
  2735.     ctx->frame_state = state;
  2736.     b->pos = p;

  2737.     if (ctx->rest > 0) {
  2738.         return NGX_AGAIN;
  2739.     }

  2740.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2741.                    "grpc goaway: %ui, stream %ui",
  2742.                    ctx->error, ctx->stream_id);

  2743.     ctx->state = ngx_http_grpc_st_start;

  2744.     return NGX_OK;
  2745. }


  2746. static ngx_int_t
  2747. ngx_http_grpc_parse_window_update(ngx_http_request_t *r,
  2748.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b)
  2749. {
  2750.     u_char  ch, *p, *last;
  2751.     enum {
  2752.         sw_start = 0,
  2753.         sw_size_2,
  2754.         sw_size_3,
  2755.         sw_size_4
  2756.     } state;

  2757.     if (b->last - b->pos < (ssize_t) ctx->rest) {
  2758.         last = b->last;

  2759.     } else {
  2760.         last = b->pos + ctx->rest;
  2761.     }

  2762.     state = ctx->frame_state;

  2763.     if (state == sw_start) {
  2764.         if (ctx->rest != 4) {
  2765.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2766.                           "upstream sent window update frame "
  2767.                           "with invalid length: %uz",
  2768.                           ctx->rest);
  2769.             return NGX_ERROR;
  2770.         }
  2771.     }

  2772.     for (p = b->pos; p < last; p++) {
  2773.         ch = *p;

  2774. #if 0
  2775.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2776.                        "grpc window update byte: %02Xd s:%d", ch, state);
  2777. #endif

  2778.         switch (state) {

  2779.         case sw_start:
  2780.             ctx->window_update = (ch & 0x7f) << 24;
  2781.             state = sw_size_2;
  2782.             break;

  2783.         case sw_size_2:
  2784.             ctx->window_update |= ch << 16;
  2785.             state = sw_size_3;
  2786.             break;

  2787.         case sw_size_3:
  2788.             ctx->window_update |= ch << 8;
  2789.             state = sw_size_4;
  2790.             break;

  2791.         case sw_size_4:
  2792.             ctx->window_update |= ch;
  2793.             state = sw_start;
  2794.             break;
  2795.         }
  2796.     }

  2797.     ctx->rest -= p - b->pos;
  2798.     ctx->frame_state = state;
  2799.     b->pos = p;

  2800.     if (ctx->rest > 0) {
  2801.         return NGX_AGAIN;
  2802.     }

  2803.     ctx->state = ngx_http_grpc_st_start;

  2804.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2805.                    "grpc window update: %ui", ctx->window_update);

  2806.     if (ctx->stream_id) {

  2807.         if (ctx->window_update > (size_t) NGX_HTTP_V2_MAX_WINDOW
  2808.                                  - ctx->send_window)
  2809.         {
  2810.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2811.                           "upstream sent too large window update");
  2812.             return NGX_ERROR;
  2813.         }

  2814.         ctx->send_window += ctx->window_update;

  2815.     } else {

  2816.         if (ctx->window_update > NGX_HTTP_V2_MAX_WINDOW
  2817.                                  - ctx->connection->send_window)
  2818.         {
  2819.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2820.                           "upstream sent too large window update");
  2821.             return NGX_ERROR;
  2822.         }

  2823.         ctx->connection->send_window += ctx->window_update;
  2824.     }

  2825.     return NGX_OK;
  2826. }


  2827. static ngx_int_t
  2828. ngx_http_grpc_parse_settings(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2829.     ngx_buf_t *b)
  2830. {
  2831.     u_char   ch, *p, *last;
  2832.     ssize_t  window_update;
  2833.     enum {
  2834.         sw_start = 0,
  2835.         sw_id,
  2836.         sw_id_2,
  2837.         sw_value,
  2838.         sw_value_2,
  2839.         sw_value_3,
  2840.         sw_value_4
  2841.     } state;

  2842.     if (b->last - b->pos < (ssize_t) ctx->rest) {
  2843.         last = b->last;

  2844.     } else {
  2845.         last = b->pos + ctx->rest;
  2846.     }

  2847.     state = ctx->frame_state;

  2848.     if (state == sw_start) {

  2849.         if (ctx->stream_id) {
  2850.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2851.                           "upstream sent settings frame "
  2852.                           "with non-zero stream id: %ui",
  2853.                           ctx->stream_id);
  2854.             return NGX_ERROR;
  2855.         }

  2856.         if (ctx->flags & NGX_HTTP_V2_ACK_FLAG) {
  2857.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2858.                            "grpc settings ack");

  2859.             if (ctx->rest != 0) {
  2860.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2861.                               "upstream sent settings frame "
  2862.                               "with ack flag and non-zero length: %uz",
  2863.                               ctx->rest);
  2864.                 return NGX_ERROR;
  2865.             }

  2866.             ctx->state = ngx_http_grpc_st_start;

  2867.             return NGX_OK;
  2868.         }

  2869.         if (ctx->rest % 6 != 0) {
  2870.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2871.                           "upstream sent settings frame "
  2872.                           "with invalid length: %uz",
  2873.                           ctx->rest);
  2874.             return NGX_ERROR;
  2875.         }

  2876.         if (ctx->free == NULL && ctx->settings++ > 1000) {
  2877.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2878.                           "upstream sent too many settings frames");
  2879.             return NGX_ERROR;
  2880.         }
  2881.     }

  2882.     for (p = b->pos; p < last; p++) {
  2883.         ch = *p;

  2884. #if 0
  2885.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2886.                        "grpc settings byte: %02Xd s:%d", ch, state);
  2887. #endif

  2888.         switch (state) {

  2889.         case sw_start:
  2890.         case sw_id:
  2891.             ctx->setting_id = ch << 8;
  2892.             state = sw_id_2;
  2893.             break;

  2894.         case sw_id_2:
  2895.             ctx->setting_id |= ch;
  2896.             state = sw_value;
  2897.             break;

  2898.         case sw_value:
  2899.             ctx->setting_value = (ngx_uint_t) ch << 24;
  2900.             state = sw_value_2;
  2901.             break;

  2902.         case sw_value_2:
  2903.             ctx->setting_value |= ch << 16;
  2904.             state = sw_value_3;
  2905.             break;

  2906.         case sw_value_3:
  2907.             ctx->setting_value |= ch << 8;
  2908.             state = sw_value_4;
  2909.             break;

  2910.         case sw_value_4:
  2911.             ctx->setting_value |= ch;
  2912.             state = sw_id;

  2913.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2914.                            "grpc setting: %ui %ui",
  2915.                            ctx->setting_id, ctx->setting_value);

  2916.             /*
  2917.              * The following settings are defined by the protocol:
  2918.              *
  2919.              * SETTINGS_HEADER_TABLE_SIZE, SETTINGS_ENABLE_PUSH,
  2920.              * SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE,
  2921.              * SETTINGS_MAX_FRAME_SIZE, SETTINGS_MAX_HEADER_LIST_SIZE
  2922.              *
  2923.              * Only SETTINGS_INITIAL_WINDOW_SIZE seems to be needed in
  2924.              * a simple client.
  2925.              */

  2926.             if (ctx->setting_id == 0x04) {
  2927.                 /* SETTINGS_INITIAL_WINDOW_SIZE */

  2928.                 if (ctx->setting_value > NGX_HTTP_V2_MAX_WINDOW) {
  2929.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2930.                                   "upstream sent settings frame "
  2931.                                   "with too large initial window size: %ui",
  2932.                                   ctx->setting_value);
  2933.                     return NGX_ERROR;
  2934.                 }

  2935.                 window_update = ctx->setting_value
  2936.                                 - ctx->connection->init_window;
  2937.                 ctx->connection->init_window = ctx->setting_value;

  2938.                 if (ctx->send_window > 0
  2939.                     && window_update > (ssize_t) NGX_HTTP_V2_MAX_WINDOW
  2940.                                        - ctx->send_window)
  2941.                 {
  2942.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2943.                                   "upstream sent settings frame "
  2944.                                   "with too large initial window size: %ui",
  2945.                                   ctx->setting_value);
  2946.                     return NGX_ERROR;
  2947.                 }

  2948.                 ctx->send_window += window_update;
  2949.             }

  2950.             break;
  2951.         }
  2952.     }

  2953.     ctx->rest -= p - b->pos;
  2954.     ctx->frame_state = state;
  2955.     b->pos = p;

  2956.     if (ctx->rest > 0) {
  2957.         return NGX_AGAIN;
  2958.     }

  2959.     ctx->state = ngx_http_grpc_st_start;

  2960.     return ngx_http_grpc_send_settings_ack(r, ctx);
  2961. }


  2962. static ngx_int_t
  2963. ngx_http_grpc_parse_ping(ngx_http_request_t *r,
  2964.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b)
  2965. {
  2966.     u_char  ch, *p, *last;
  2967.     enum {
  2968.         sw_start = 0,
  2969.         sw_data_2,
  2970.         sw_data_3,
  2971.         sw_data_4,
  2972.         sw_data_5,
  2973.         sw_data_6,
  2974.         sw_data_7,
  2975.         sw_data_8
  2976.     } state;

  2977.     if (b->last - b->pos < (ssize_t) ctx->rest) {
  2978.         last = b->last;

  2979.     } else {
  2980.         last = b->pos + ctx->rest;
  2981.     }

  2982.     state = ctx->frame_state;

  2983.     if (state == sw_start) {

  2984.         if (ctx->stream_id) {
  2985.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2986.                           "upstream sent ping frame "
  2987.                           "with non-zero stream id: %ui",
  2988.                           ctx->stream_id);
  2989.             return NGX_ERROR;
  2990.         }

  2991.         if (ctx->rest != 8) {
  2992.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2993.                           "upstream sent ping frame "
  2994.                           "with invalid length: %uz",
  2995.                           ctx->rest);
  2996.             return NGX_ERROR;
  2997.         }

  2998.         if (ctx->flags & NGX_HTTP_V2_ACK_FLAG) {
  2999.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3000.                           "upstream sent ping frame with ack flag");
  3001.             return NGX_ERROR;
  3002.         }

  3003.         if (ctx->free == NULL && ctx->pings++ > 1000) {
  3004.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3005.                           "upstream sent too many ping frames");
  3006.             return NGX_ERROR;
  3007.         }
  3008.     }

  3009.     for (p = b->pos; p < last; p++) {
  3010.         ch = *p;

  3011. #if 0
  3012.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3013.                        "grpc ping byte: %02Xd s:%d", ch, state);
  3014. #endif

  3015.         if (state < sw_data_8) {
  3016.             ctx->ping_data[state] = ch;
  3017.             state++;

  3018.         } else {
  3019.             ctx->ping_data[7] = ch;
  3020.             state = sw_start;

  3021.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3022.                            "grpc ping");
  3023.         }
  3024.     }

  3025.     ctx->rest -= p - b->pos;
  3026.     ctx->frame_state = state;
  3027.     b->pos = p;

  3028.     if (ctx->rest > 0) {
  3029.         return NGX_AGAIN;
  3030.     }

  3031.     ctx->state = ngx_http_grpc_st_start;

  3032.     return ngx_http_grpc_send_ping_ack(r, ctx);
  3033. }


  3034. static ngx_int_t
  3035. ngx_http_grpc_send_settings_ack(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
  3036. {
  3037.     ngx_chain_t            *cl, **ll;
  3038.     ngx_http_grpc_frame_t  *f;

  3039.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3040.                    "grpc send settings ack");

  3041.     for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
  3042.         ll = &cl->next;
  3043.     }

  3044.     cl = ngx_http_grpc_get_buf(r, ctx);
  3045.     if (cl == NULL) {
  3046.         return NGX_ERROR;
  3047.     }

  3048.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3049.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3050.     f->length_0 = 0;
  3051.     f->length_1 = 0;
  3052.     f->length_2 = 0;
  3053.     f->type = NGX_HTTP_V2_SETTINGS_FRAME;
  3054.     f->flags = NGX_HTTP_V2_ACK_FLAG;
  3055.     f->stream_id_0 = 0;
  3056.     f->stream_id_1 = 0;
  3057.     f->stream_id_2 = 0;
  3058.     f->stream_id_3 = 0;

  3059.     *ll = cl;

  3060.     return NGX_OK;
  3061. }


  3062. static ngx_int_t
  3063. ngx_http_grpc_send_ping_ack(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
  3064. {
  3065.     ngx_chain_t            *cl, **ll;
  3066.     ngx_http_grpc_frame_t  *f;

  3067.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3068.                    "grpc send ping ack");

  3069.     for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
  3070.         ll = &cl->next;
  3071.     }

  3072.     cl = ngx_http_grpc_get_buf(r, ctx);
  3073.     if (cl == NULL) {
  3074.         return NGX_ERROR;
  3075.     }

  3076.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3077.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3078.     f->length_0 = 0;
  3079.     f->length_1 = 0;
  3080.     f->length_2 = 8;
  3081.     f->type = NGX_HTTP_V2_PING_FRAME;
  3082.     f->flags = NGX_HTTP_V2_ACK_FLAG;
  3083.     f->stream_id_0 = 0;
  3084.     f->stream_id_1 = 0;
  3085.     f->stream_id_2 = 0;
  3086.     f->stream_id_3 = 0;

  3087.     cl->buf->last = ngx_copy(cl->buf->last, ctx->ping_data, 8);

  3088.     *ll = cl;

  3089.     return NGX_OK;
  3090. }


  3091. static ngx_int_t
  3092. ngx_http_grpc_send_window_update(ngx_http_request_t *r,
  3093.     ngx_http_grpc_ctx_t *ctx)
  3094. {
  3095.     size_t                  n;
  3096.     ngx_chain_t            *cl, **ll;
  3097.     ngx_http_grpc_frame_t  *f;

  3098.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3099.                    "grpc send window update: %uz %uz",
  3100.                    ctx->connection->recv_window, ctx->recv_window);

  3101.     for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
  3102.         ll = &cl->next;
  3103.     }

  3104.     cl = ngx_http_grpc_get_buf(r, ctx);
  3105.     if (cl == NULL) {
  3106.         return NGX_ERROR;
  3107.     }

  3108.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3109.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3110.     f->length_0 = 0;
  3111.     f->length_1 = 0;
  3112.     f->length_2 = 4;
  3113.     f->type = NGX_HTTP_V2_WINDOW_UPDATE_FRAME;
  3114.     f->flags = 0;
  3115.     f->stream_id_0 = 0;
  3116.     f->stream_id_1 = 0;
  3117.     f->stream_id_2 = 0;
  3118.     f->stream_id_3 = 0;

  3119.     n = NGX_HTTP_V2_MAX_WINDOW - ctx->connection->recv_window;
  3120.     ctx->connection->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3121.     *cl->buf->last++ = (u_char) ((n >> 24) & 0xff);
  3122.     *cl->buf->last++ = (u_char) ((n >> 16) & 0xff);
  3123.     *cl->buf->last++ = (u_char) ((n >> 8) & 0xff);
  3124.     *cl->buf->last++ = (u_char) (n & 0xff);

  3125.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3126.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3127.     f->length_0 = 0;
  3128.     f->length_1 = 0;
  3129.     f->length_2 = 4;
  3130.     f->type = NGX_HTTP_V2_WINDOW_UPDATE_FRAME;
  3131.     f->flags = 0;
  3132.     f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
  3133.     f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
  3134.     f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
  3135.     f->stream_id_3 = (u_char) (ctx->id & 0xff);

  3136.     n = NGX_HTTP_V2_MAX_WINDOW - ctx->recv_window;
  3137.     ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3138.     *cl->buf->last++ = (u_char) ((n >> 24) & 0xff);
  3139.     *cl->buf->last++ = (u_char) ((n >> 16) & 0xff);
  3140.     *cl->buf->last++ = (u_char) ((n >> 8) & 0xff);
  3141.     *cl->buf->last++ = (u_char) (n & 0xff);

  3142.     *ll = cl;

  3143.     return NGX_OK;
  3144. }


  3145. static ngx_chain_t *
  3146. ngx_http_grpc_get_buf(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
  3147. {
  3148.     u_char       *start;
  3149.     ngx_buf_t    *b;
  3150.     ngx_chain_t  *cl;

  3151.     cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
  3152.     if (cl == NULL) {
  3153.         return NULL;
  3154.     }

  3155.     b = cl->buf;
  3156.     start = b->start;

  3157.     if (start == NULL) {

  3158.         /*
  3159.          * each buffer is large enough to hold two window update
  3160.          * frames in a row
  3161.          */

  3162.         start = ngx_palloc(r->pool, 2 * sizeof(ngx_http_grpc_frame_t) + 8);
  3163.         if (start == NULL) {
  3164.             return NULL;
  3165.         }

  3166.     }

  3167.     ngx_memzero(b, sizeof(ngx_buf_t));

  3168.     b->start = start;
  3169.     b->pos = start;
  3170.     b->last = start;
  3171.     b->end = start + 2 * sizeof(ngx_http_grpc_frame_t) + 8;

  3172.     b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
  3173.     b->temporary = 1;
  3174.     b->flush = 1;

  3175.     return cl;
  3176. }


  3177. static ngx_http_grpc_ctx_t *
  3178. ngx_http_grpc_get_ctx(ngx_http_request_t *r)
  3179. {
  3180.     ngx_http_grpc_ctx_t  *ctx;
  3181.     ngx_http_upstream_t  *u;

  3182.     ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);

  3183.     if (ctx->connection == NULL) {
  3184.         u = r->upstream;

  3185.         if (ngx_http_grpc_get_connection_data(r, ctx, &u->peer) != NGX_OK) {
  3186.             return NULL;
  3187.         }
  3188.     }

  3189.     return ctx;
  3190. }


  3191. static ngx_int_t
  3192. ngx_http_grpc_get_connection_data(ngx_http_request_t *r,
  3193.     ngx_http_grpc_ctx_t *ctx, ngx_peer_connection_t *pc)
  3194. {
  3195.     ngx_connection_t    *c;
  3196.     ngx_pool_cleanup_t  *cln;

  3197.     c = pc->connection;

  3198.     if (pc->cached) {

  3199.         /*
  3200.          * for cached connections, connection data can be found
  3201.          * in the cleanup handler
  3202.          */

  3203.         for (cln = c->pool->cleanup; cln; cln = cln->next) {
  3204.             if (cln->handler == ngx_http_grpc_cleanup) {
  3205.                 ctx->connection = cln->data;
  3206.                 break;
  3207.             }
  3208.         }

  3209.         if (ctx->connection == NULL) {
  3210.             ngx_log_error(NGX_LOG_ERR, c->log, 0,
  3211.                           "no connection data found for "
  3212.                           "keepalive http2 connection");
  3213.             return NGX_ERROR;
  3214.         }

  3215.         ctx->send_window = ctx->connection->init_window;
  3216.         ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3217.         ctx->connection->last_stream_id += 2;
  3218.         ctx->id = ctx->connection->last_stream_id;

  3219.         return NGX_OK;
  3220.     }

  3221.     cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_http_grpc_conn_t));
  3222.     if (cln == NULL) {
  3223.         return NGX_ERROR;
  3224.     }

  3225.     cln->handler = ngx_http_grpc_cleanup;
  3226.     ctx->connection = cln->data;

  3227.     ctx->connection->init_window = NGX_HTTP_V2_DEFAULT_WINDOW;
  3228.     ctx->connection->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
  3229.     ctx->connection->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3230.     ctx->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
  3231.     ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3232.     ctx->id = 1;
  3233.     ctx->connection->last_stream_id = 1;

  3234.     return NGX_OK;
  3235. }


  3236. static void
  3237. ngx_http_grpc_cleanup(void *data)
  3238. {
  3239. #if 0
  3240.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  3241.                    "grpc cleanup");
  3242. #endif
  3243.     return;
  3244. }


  3245. static void
  3246. ngx_http_grpc_abort_request(ngx_http_request_t *r)
  3247. {
  3248.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3249.                    "abort grpc request");
  3250.     return;
  3251. }


  3252. static void
  3253. ngx_http_grpc_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
  3254. {
  3255.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3256.                    "finalize grpc request");
  3257.     return;
  3258. }


  3259. static ngx_int_t
  3260. ngx_http_grpc_internal_trailers_variable(ngx_http_request_t *r,
  3261.     ngx_http_variable_value_t *v, uintptr_t data)
  3262. {
  3263.     ngx_table_elt_t  *te;

  3264.     te = r->headers_in.te;

  3265.     if (te == NULL) {
  3266.         v->not_found = 1;
  3267.         return NGX_OK;
  3268.     }

  3269.     if (ngx_strlcasestrn(te->value.data, te->value.data + te->value.len,
  3270.                          (u_char *) "trailers", 8 - 1)
  3271.         == NULL)
  3272.     {
  3273.         v->not_found = 1;
  3274.         return NGX_OK;
  3275.     }

  3276.     v->valid = 1;
  3277.     v->no_cacheable = 0;
  3278.     v->not_found = 0;

  3279.     v->data = (u_char *) "trailers";
  3280.     v->len = sizeof("trailers") - 1;

  3281.     return NGX_OK;
  3282. }


  3283. static ngx_int_t
  3284. ngx_http_grpc_add_variables(ngx_conf_t *cf)
  3285. {
  3286.     ngx_http_variable_t  *var, *v;

  3287.     for (v = ngx_http_grpc_vars; v->name.len; v++) {
  3288.         var = ngx_http_add_variable(cf, &v->name, v->flags);
  3289.         if (var == NULL) {
  3290.             return NGX_ERROR;
  3291.         }

  3292.         var->get_handler = v->get_handler;
  3293.         var->data = v->data;
  3294.     }

  3295.     return NGX_OK;
  3296. }


  3297. static void *
  3298. ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
  3299. {
  3300.     ngx_http_grpc_loc_conf_t  *conf;

  3301.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_grpc_loc_conf_t));
  3302.     if (conf == NULL) {
  3303.         return NULL;
  3304.     }

  3305.     /*
  3306.      * set by ngx_pcalloc():
  3307.      *
  3308.      *     conf->upstream.ignore_headers = 0;
  3309.      *     conf->upstream.next_upstream = 0;
  3310.      *     conf->upstream.hide_headers_hash = { NULL, 0 };
  3311.      *
  3312.      *     conf->headers.lengths = NULL;
  3313.      *     conf->headers.values = NULL;
  3314.      *     conf->headers.hash = { NULL, 0 };
  3315.      *     conf->host = { 0, NULL };
  3316.      *     conf->host_set = 0;
  3317.      *     conf->ssl = 0;
  3318.      *     conf->ssl_protocols = 0;
  3319.      *     conf->ssl_ciphers = { 0, NULL };
  3320.      *     conf->ssl_trusted_certificate = { 0, NULL };
  3321.      *     conf->ssl_crl = { 0, NULL };
  3322.      */

  3323.     conf->upstream.local = NGX_CONF_UNSET_PTR;
  3324.     conf->upstream.socket_keepalive = NGX_CONF_UNSET;
  3325.     conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
  3326.     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
  3327.     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
  3328.     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
  3329.     conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;

  3330.     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;

  3331.     conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
  3332.     conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;

  3333.     conf->upstream.intercept_errors = NGX_CONF_UNSET;

  3334. #if (NGX_HTTP_SSL)
  3335.     conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
  3336.     conf->upstream.ssl_name = NGX_CONF_UNSET_PTR;
  3337.     conf->upstream.ssl_server_name = NGX_CONF_UNSET;
  3338.     conf->upstream.ssl_verify = NGX_CONF_UNSET;
  3339.     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
  3340.     conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR;
  3341.     conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR;
  3342.     conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR;
  3343.     conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
  3344. #endif

  3345.     /* the hardcoded values */
  3346.     conf->upstream.cyclic_temp_file = 0;
  3347.     conf->upstream.buffering = 0;
  3348.     conf->upstream.ignore_client_abort = 0;
  3349.     conf->upstream.send_lowat = 0;
  3350.     conf->upstream.bufs.num = 0;
  3351.     conf->upstream.busy_buffers_size = 0;
  3352.     conf->upstream.max_temp_file_size = 0;
  3353.     conf->upstream.temp_file_write_size = 0;
  3354.     conf->upstream.pass_request_headers = 1;
  3355.     conf->upstream.pass_request_body = 1;
  3356.     conf->upstream.force_ranges = 0;
  3357.     conf->upstream.pass_trailers = 1;
  3358.     conf->upstream.preserve_output = 1;

  3359.     conf->headers_source = NGX_CONF_UNSET_PTR;

  3360.     ngx_str_set(&conf->upstream.module, "grpc");

  3361.     return conf;
  3362. }


  3363. static char *
  3364. ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  3365. {
  3366.     ngx_http_grpc_loc_conf_t *prev = parent;
  3367.     ngx_http_grpc_loc_conf_t *conf = child;

  3368.     ngx_int_t                  rc;
  3369.     ngx_hash_init_t            hash;
  3370.     ngx_http_core_loc_conf_t  *clcf;

  3371.     ngx_conf_merge_ptr_value(conf->upstream.local,
  3372.                               prev->upstream.local, NULL);

  3373.     ngx_conf_merge_value(conf->upstream.socket_keepalive,
  3374.                               prev->upstream.socket_keepalive, 0);

  3375.     ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
  3376.                               prev->upstream.next_upstream_tries, 0);

  3377.     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
  3378.                               prev->upstream.connect_timeout, 60000);

  3379.     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
  3380.                               prev->upstream.send_timeout, 60000);

  3381.     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
  3382.                               prev->upstream.read_timeout, 60000);

  3383.     ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
  3384.                               prev->upstream.next_upstream_timeout, 0);

  3385.     ngx_conf_merge_size_value(conf->upstream.buffer_size,
  3386.                               prev->upstream.buffer_size,
  3387.                               (size_t) ngx_pagesize);

  3388.     ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
  3389.                               prev->upstream.ignore_headers,
  3390.                               NGX_CONF_BITMASK_SET);

  3391.     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
  3392.                               prev->upstream.next_upstream,
  3393.                               (NGX_CONF_BITMASK_SET
  3394.                                |NGX_HTTP_UPSTREAM_FT_ERROR
  3395.                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

  3396.     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
  3397.         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
  3398.                                        |NGX_HTTP_UPSTREAM_FT_OFF;
  3399.     }

  3400.     ngx_conf_merge_value(conf->upstream.intercept_errors,
  3401.                               prev->upstream.intercept_errors, 0);

  3402. #if (NGX_HTTP_SSL)

  3403.     if (ngx_http_grpc_merge_ssl(cf, conf, prev) != NGX_OK) {
  3404.         return NGX_CONF_ERROR;
  3405.     }

  3406.     ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
  3407.                               prev->upstream.ssl_session_reuse, 1);

  3408.     ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
  3409.                               (NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));

  3410.     ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
  3411.                              "DEFAULT");

  3412.     ngx_conf_merge_ptr_value(conf->upstream.ssl_name,
  3413.                               prev->upstream.ssl_name, NULL);
  3414.     ngx_conf_merge_value(conf->upstream.ssl_server_name,
  3415.                               prev->upstream.ssl_server_name, 0);
  3416.     ngx_conf_merge_value(conf->upstream.ssl_verify,
  3417.                               prev->upstream.ssl_verify, 0);
  3418.     ngx_conf_merge_uint_value(conf->ssl_verify_depth,
  3419.                               prev->ssl_verify_depth, 1);
  3420.     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
  3421.                               prev->ssl_trusted_certificate, "");
  3422.     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");

  3423.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate,
  3424.                               prev->upstream.ssl_certificate, NULL);
  3425.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key,
  3426.                               prev->upstream.ssl_certificate_key, NULL);
  3427.     ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords,
  3428.                               prev->upstream.ssl_passwords, NULL);

  3429.     ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
  3430.                               prev->ssl_conf_commands, NULL);

  3431.     if (conf->ssl && ngx_http_grpc_set_ssl(cf, conf) != NGX_OK) {
  3432.         return NGX_CONF_ERROR;
  3433.     }

  3434. #endif

  3435.     hash.max_size = 512;
  3436.     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
  3437.     hash.name = "grpc_headers_hash";

  3438.     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
  3439.             &prev->upstream, ngx_http_grpc_hide_headers, &hash)
  3440.         != NGX_OK)
  3441.     {
  3442.         return NGX_CONF_ERROR;
  3443.     }

  3444.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

  3445.     if (clcf->noname
  3446.         && conf->upstream.upstream == NULL && conf->grpc_lengths == NULL)
  3447.     {
  3448.         conf->upstream.upstream = prev->upstream.upstream;
  3449.         conf->host = prev->host;

  3450.         conf->grpc_lengths = prev->grpc_lengths;
  3451.         conf->grpc_values = prev->grpc_values;

  3452. #if (NGX_HTTP_SSL)
  3453.         conf->ssl = prev->ssl;
  3454. #endif
  3455.     }

  3456.     if (clcf->lmt_excpt && clcf->handler == NULL
  3457.         && (conf->upstream.upstream || conf->grpc_lengths))
  3458.     {
  3459.         clcf->handler = ngx_http_grpc_handler;
  3460.     }

  3461.     ngx_conf_merge_ptr_value(conf->headers_source, prev->headers_source, NULL);

  3462.     if (conf->headers_source == prev->headers_source) {
  3463.         conf->headers = prev->headers;
  3464.         conf->host_set = prev->host_set;
  3465.     }

  3466.     rc = ngx_http_grpc_init_headers(cf, conf, &conf->headers,
  3467.                                     ngx_http_grpc_headers);
  3468.     if (rc != NGX_OK) {
  3469.         return NGX_CONF_ERROR;
  3470.     }

  3471.     /*
  3472.      * special handling to preserve conf->headers in the "http" section
  3473.      * to inherit it to all servers
  3474.      */

  3475.     if (prev->headers.hash.buckets == NULL
  3476.         && conf->headers_source == prev->headers_source)
  3477.     {
  3478.         prev->headers = conf->headers;
  3479.         prev->host_set = conf->host_set;
  3480.     }

  3481.     return NGX_CONF_OK;
  3482. }


  3483. static ngx_int_t
  3484. ngx_http_grpc_init_headers(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf,
  3485.     ngx_http_grpc_headers_t *headers, ngx_keyval_t *default_headers)
  3486. {
  3487.     u_char                       *p;
  3488.     size_t                        size;
  3489.     uintptr_t                    *code;
  3490.     ngx_uint_t                    i;
  3491.     ngx_array_t                   headers_names, headers_merged;
  3492.     ngx_keyval_t                 *src, *s, *h;
  3493.     ngx_hash_key_t               *hk;
  3494.     ngx_hash_init_t               hash;
  3495.     ngx_http_script_compile_t     sc;
  3496.     ngx_http_script_copy_code_t  *copy;

  3497.     if (headers->hash.buckets) {
  3498.         return NGX_OK;
  3499.     }

  3500.     if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
  3501.         != NGX_OK)
  3502.     {
  3503.         return NGX_ERROR;
  3504.     }

  3505.     if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
  3506.         != NGX_OK)
  3507.     {
  3508.         return NGX_ERROR;
  3509.     }

  3510.     headers->lengths = ngx_array_create(cf->pool, 64, 1);
  3511.     if (headers->lengths == NULL) {
  3512.         return NGX_ERROR;
  3513.     }

  3514.     headers->values = ngx_array_create(cf->pool, 512, 1);
  3515.     if (headers->values == NULL) {
  3516.         return NGX_ERROR;
  3517.     }

  3518.     if (conf->headers_source) {

  3519.         src = conf->headers_source->elts;
  3520.         for (i = 0; i < conf->headers_source->nelts; i++) {

  3521.             if (src[i].key.len == 4
  3522.                 && ngx_strncasecmp(src[i].key.data, (u_char *) "Host", 4) == 0)
  3523.             {
  3524.                 conf->host_set = 1;
  3525.             }

  3526.             s = ngx_array_push(&headers_merged);
  3527.             if (s == NULL) {
  3528.                 return NGX_ERROR;
  3529.             }

  3530.             *s = src[i];
  3531.         }
  3532.     }

  3533.     h = default_headers;

  3534.     while (h->key.len) {

  3535.         src = headers_merged.elts;
  3536.         for (i = 0; i < headers_merged.nelts; i++) {
  3537.             if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
  3538.                 goto next;
  3539.             }
  3540.         }

  3541.         s = ngx_array_push(&headers_merged);
  3542.         if (s == NULL) {
  3543.             return NGX_ERROR;
  3544.         }

  3545.         *s = *h;

  3546.     next:

  3547.         h++;
  3548.     }


  3549.     src = headers_merged.elts;
  3550.     for (i = 0; i < headers_merged.nelts; i++) {

  3551.         hk = ngx_array_push(&headers_names);
  3552.         if (hk == NULL) {
  3553.             return NGX_ERROR;
  3554.         }

  3555.         hk->key = src[i].key;
  3556.         hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
  3557.         hk->value = (void *) 1;

  3558.         if (src[i].value.len == 0) {
  3559.             continue;
  3560.         }

  3561.         copy = ngx_array_push_n(headers->lengths,
  3562.                                 sizeof(ngx_http_script_copy_code_t));
  3563.         if (copy == NULL) {
  3564.             return NGX_ERROR;
  3565.         }

  3566.         copy->code = (ngx_http_script_code_pt) (void *)
  3567.                                                  ngx_http_script_copy_len_code;
  3568.         copy->len = src[i].key.len;

  3569.         size = (sizeof(ngx_http_script_copy_code_t)
  3570.                 + src[i].key.len + sizeof(uintptr_t) - 1)
  3571.                & ~(sizeof(uintptr_t) - 1);

  3572.         copy = ngx_array_push_n(headers->values, size);
  3573.         if (copy == NULL) {
  3574.             return NGX_ERROR;
  3575.         }

  3576.         copy->code = ngx_http_script_copy_code;
  3577.         copy->len = src[i].key.len;

  3578.         p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
  3579.         ngx_memcpy(p, src[i].key.data, src[i].key.len);

  3580.         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  3581.         sc.cf = cf;
  3582.         sc.source = &src[i].value;
  3583.         sc.flushes = &headers->flushes;
  3584.         sc.lengths = &headers->lengths;
  3585.         sc.values = &headers->values;

  3586.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  3587.             return NGX_ERROR;
  3588.         }

  3589.         code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
  3590.         if (code == NULL) {
  3591.             return NGX_ERROR;
  3592.         }

  3593.         *code = (uintptr_t) NULL;

  3594.         code = ngx_array_push_n(headers->values, sizeof(uintptr_t));
  3595.         if (code == NULL) {
  3596.             return NGX_ERROR;
  3597.         }

  3598.         *code = (uintptr_t) NULL;
  3599.     }

  3600.     code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
  3601.     if (code == NULL) {
  3602.         return NGX_ERROR;
  3603.     }

  3604.     *code = (uintptr_t) NULL;


  3605.     hash.hash = &headers->hash;
  3606.     hash.key = ngx_hash_key_lc;
  3607.     hash.max_size = 512;
  3608.     hash.bucket_size = 64;
  3609.     hash.name = "grpc_headers_hash";
  3610.     hash.pool = cf->pool;
  3611.     hash.temp_pool = NULL;

  3612.     return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
  3613. }


  3614. static char *
  3615. ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3616. {
  3617.     ngx_http_grpc_loc_conf_t *glcf = conf;

  3618.     size_t                      add;
  3619.     ngx_str_t                  *value, *url;
  3620.     ngx_url_t                   u;
  3621.     ngx_uint_t                  n;
  3622.     ngx_http_core_loc_conf_t   *clcf;
  3623.     ngx_http_script_compile_t   sc;

  3624.     if (glcf->upstream.upstream || glcf->grpc_lengths) {
  3625.         return "is duplicate";
  3626.     }

  3627.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

  3628.     clcf->handler = ngx_http_grpc_handler;

  3629.     if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
  3630.         clcf->auto_redirect = 1;
  3631.     }

  3632.     value = cf->args->elts;

  3633.     url = &value[1];

  3634.     n = ngx_http_script_variables_count(url);

  3635.     if (n) {

  3636.         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  3637.         sc.cf = cf;
  3638.         sc.source = url;
  3639.         sc.lengths = &glcf->grpc_lengths;
  3640.         sc.values = &glcf->grpc_values;
  3641.         sc.variables = n;
  3642.         sc.complete_lengths = 1;
  3643.         sc.complete_values = 1;

  3644.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  3645.             return NGX_CONF_ERROR;
  3646.         }

  3647. #if (NGX_HTTP_SSL)
  3648.         glcf->ssl = 1;
  3649. #endif

  3650.         return NGX_CONF_OK;
  3651.     }

  3652.     if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) {
  3653.         add = 7;

  3654.     } else if (ngx_strncasecmp(url->data, (u_char *) "grpcs://", 8) == 0) {

  3655. #if (NGX_HTTP_SSL)
  3656.         glcf->ssl = 1;

  3657.         add = 8;
  3658. #else
  3659.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3660.                            "grpcs protocol requires SSL support");
  3661.         return NGX_CONF_ERROR;
  3662. #endif

  3663.     } else {
  3664.         add = 0;
  3665.     }

  3666.     ngx_memzero(&u, sizeof(ngx_url_t));

  3667.     u.url.len = url->len - add;
  3668.     u.url.data = url->data + add;
  3669.     u.no_resolve = 1;

  3670.     glcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
  3671.     if (glcf->upstream.upstream == NULL) {
  3672.         return NGX_CONF_ERROR;
  3673.     }

  3674.     if (u.family != AF_UNIX) {

  3675.         if (u.no_port) {
  3676.             glcf->host = u.host;

  3677.         } else {
  3678.             glcf->host.len = u.host.len + 1 + u.port_text.len;
  3679.             glcf->host.data = u.host.data;
  3680.         }

  3681.     } else {
  3682.         ngx_str_set(&glcf->host, "localhost");
  3683.     }

  3684.     return NGX_CONF_OK;
  3685. }


  3686. #if (NGX_HTTP_SSL)

  3687. static char *
  3688. ngx_http_grpc_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3689. {
  3690.     ngx_http_grpc_loc_conf_t *glcf = conf;

  3691.     ngx_str_t  *value;

  3692.     if (glcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
  3693.         return "is duplicate";
  3694.     }

  3695.     value = cf->args->elts;

  3696.     glcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);

  3697.     if (glcf->upstream.ssl_passwords == NULL) {
  3698.         return NGX_CONF_ERROR;
  3699.     }

  3700.     return NGX_CONF_OK;
  3701. }


  3702. static char *
  3703. ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
  3704. {
  3705. #ifndef SSL_CONF_FLAG_FILE
  3706.     return "is not supported on this platform";
  3707. #else
  3708.     return NGX_CONF_OK;
  3709. #endif
  3710. }


  3711. static ngx_int_t
  3712. ngx_http_grpc_merge_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf,
  3713.     ngx_http_grpc_loc_conf_t *prev)
  3714. {
  3715.     ngx_uint_t  preserve;

  3716.     if (conf->ssl_protocols == 0
  3717.         && conf->ssl_ciphers.data == NULL
  3718.         && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
  3719.         && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
  3720.         && conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
  3721.         && conf->upstream.ssl_verify == NGX_CONF_UNSET
  3722.         && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
  3723.         && conf->ssl_trusted_certificate.data == NULL
  3724.         && conf->ssl_crl.data == NULL
  3725.         && conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
  3726.         && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
  3727.     {
  3728.         if (prev->upstream.ssl) {
  3729.             conf->upstream.ssl = prev->upstream.ssl;
  3730.             return NGX_OK;
  3731.         }

  3732.         preserve = 1;

  3733.     } else {
  3734.         preserve = 0;
  3735.     }

  3736.     conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
  3737.     if (conf->upstream.ssl == NULL) {
  3738.         return NGX_ERROR;
  3739.     }

  3740.     conf->upstream.ssl->log = cf->log;

  3741.     /*
  3742.      * special handling to preserve conf->upstream.ssl
  3743.      * in the "http" section to inherit it to all servers
  3744.      */

  3745.     if (preserve) {
  3746.         prev->upstream.ssl = conf->upstream.ssl;
  3747.     }

  3748.     return NGX_OK;
  3749. }


  3750. static ngx_int_t
  3751. ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
  3752. {
  3753.     ngx_pool_cleanup_t  *cln;

  3754.     if (glcf->upstream.ssl->ctx) {
  3755.         return NGX_OK;
  3756.     }

  3757.     if (ngx_ssl_create(glcf->upstream.ssl, glcf->ssl_protocols, NULL)
  3758.         != NGX_OK)
  3759.     {
  3760.         return NGX_ERROR;
  3761.     }

  3762.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  3763.     if (cln == NULL) {
  3764.         ngx_ssl_cleanup_ctx(glcf->upstream.ssl);
  3765.         return NGX_ERROR;
  3766.     }

  3767.     cln->handler = ngx_ssl_cleanup_ctx;
  3768.     cln->data = glcf->upstream.ssl;

  3769.     if (ngx_ssl_ciphers(cf, glcf->upstream.ssl, &glcf->ssl_ciphers, 0)
  3770.         != NGX_OK)
  3771.     {
  3772.         return NGX_ERROR;
  3773.     }

  3774.     if (glcf->upstream.ssl_certificate
  3775.         && glcf->upstream.ssl_certificate->value.len)
  3776.     {
  3777.         if (glcf->upstream.ssl_certificate_key == NULL) {
  3778.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  3779.                           "no \"grpc_ssl_certificate_key\" is defined "
  3780.                           "for certificate \"%V\"",
  3781.                           &glcf->upstream.ssl_certificate->value);
  3782.             return NGX_ERROR;
  3783.         }

  3784.         if (glcf->upstream.ssl_certificate->lengths
  3785.             || glcf->upstream.ssl_certificate_key->lengths)
  3786.         {
  3787.             glcf->upstream.ssl_passwords =
  3788.                   ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords);
  3789.             if (glcf->upstream.ssl_passwords == NULL) {
  3790.                 return NGX_ERROR;
  3791.             }

  3792.         } else {
  3793.             if (ngx_ssl_certificate(cf, glcf->upstream.ssl,
  3794.                                     &glcf->upstream.ssl_certificate->value,
  3795.                                     &glcf->upstream.ssl_certificate_key->value,
  3796.                                     glcf->upstream.ssl_passwords)
  3797.                 != NGX_OK)
  3798.             {
  3799.                 return NGX_ERROR;
  3800.             }
  3801.         }
  3802.     }

  3803.     if (glcf->upstream.ssl_verify) {
  3804.         if (glcf->ssl_trusted_certificate.len == 0) {
  3805.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  3806.                       "no grpc_ssl_trusted_certificate for grpc_ssl_verify");
  3807.             return NGX_ERROR;
  3808.         }

  3809.         if (ngx_ssl_trusted_certificate(cf, glcf->upstream.ssl,
  3810.                                         &glcf->ssl_trusted_certificate,
  3811.                                         glcf->ssl_verify_depth)
  3812.             != NGX_OK)
  3813.         {
  3814.             return NGX_ERROR;
  3815.         }

  3816.         if (ngx_ssl_crl(cf, glcf->upstream.ssl, &glcf->ssl_crl) != NGX_OK) {
  3817.             return NGX_ERROR;
  3818.         }
  3819.     }

  3820.     if (ngx_ssl_client_session_cache(cf, glcf->upstream.ssl,
  3821.                                      glcf->upstream.ssl_session_reuse)
  3822.         != NGX_OK)
  3823.     {
  3824.         return NGX_ERROR;
  3825.     }

  3826. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation

  3827.     if (SSL_CTX_set_alpn_protos(glcf->upstream.ssl->ctx,
  3828.                                 (u_char *) "\x02h2", 3)
  3829.         != 0)
  3830.     {
  3831.         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
  3832.                       "SSL_CTX_set_alpn_protos() failed");
  3833.         return NGX_ERROR;
  3834.     }

  3835. #endif

  3836.     if (ngx_ssl_conf_commands(cf, glcf->upstream.ssl, glcf->ssl_conf_commands)
  3837.         != NGX_OK)
  3838.     {
  3839.         return NGX_ERROR;
  3840.     }

  3841.     return NGX_OK;
  3842. }

  3843. #endif