src/http/modules/ngx_http_grpc_module.c - nginx-1.31.3 nginx/ @ 42f8df65b

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_certificate_cache(ngx_conf_t *cf,
  164.     ngx_command_t *cmd, void *conf);
  165. static char *ngx_http_grpc_ssl_password_file(ngx_conf_t *cf,
  166.     ngx_command_t *cmd, void *conf);
  167. static char *ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post,
  168.     void *data);
  169. static ngx_int_t ngx_http_grpc_merge_ssl(ngx_conf_t *cf,
  170.     ngx_http_grpc_loc_conf_t *conf, ngx_http_grpc_loc_conf_t *prev);
  171. static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf,
  172.     ngx_http_grpc_loc_conf_t *glcf);
  173. #endif


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


  189. #if (NGX_HTTP_SSL)

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

  199. static ngx_conf_post_t  ngx_http_grpc_ssl_conf_command_post =
  200.     { ngx_http_grpc_ssl_conf_command_check };

  201. #endif


  202. static ngx_command_t  ngx_http_grpc_commands[] = {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  293. #if (NGX_HTTP_SSL)

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

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

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

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

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

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

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

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

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

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

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

  360.     { ngx_string("grpc_ssl_certificate_cache"),
  361.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
  362.       ngx_http_grpc_ssl_certificate_cache,
  363.       NGX_HTTP_LOC_CONF_OFFSET,
  364.       0,
  365.       NULL },

  366.     { ngx_string("grpc_ssl_password_file"),
  367.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  368.       ngx_http_grpc_ssl_password_file,
  369.       NGX_HTTP_LOC_CONF_OFFSET,
  370.       0,
  371.       NULL },

  372.     { ngx_string("grpc_ssl_conf_command"),
  373.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
  374.       ngx_conf_set_keyval_slot,
  375.       NGX_HTTP_LOC_CONF_OFFSET,
  376.       offsetof(ngx_http_grpc_loc_conf_t, ssl_conf_commands),
  377.       &ngx_http_grpc_ssl_conf_command_post },

  378. #endif

  379.       ngx_null_command
  380. };


  381. static ngx_http_module_t  ngx_http_grpc_module_ctx = {
  382.     ngx_http_grpc_add_variables,           /* preconfiguration */
  383.     NULL,                                  /* postconfiguration */

  384.     NULL,                                  /* create main configuration */
  385.     NULL,                                  /* init main configuration */

  386.     NULL,                                  /* create server configuration */
  387.     NULL,                                  /* merge server configuration */

  388.     ngx_http_grpc_create_loc_conf,         /* create location configuration */
  389.     ngx_http_grpc_merge_loc_conf           /* merge location configuration */
  390. };


  391. ngx_module_t  ngx_http_grpc_module = {
  392.     NGX_MODULE_V1,
  393.     &ngx_http_grpc_module_ctx,             /* module context */
  394.     ngx_http_grpc_commands,                /* module directives */
  395.     NGX_HTTP_MODULE,                       /* module type */
  396.     NULL,                                  /* init master */
  397.     NULL,                                  /* init module */
  398.     NULL,                                  /* init process */
  399.     NULL,                                  /* init thread */
  400.     NULL,                                  /* exit thread */
  401.     NULL,                                  /* exit process */
  402.     NULL,                                  /* exit master */
  403.     NGX_MODULE_V1_PADDING
  404. };


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

  407.     "\x00\x00\x12\x04\x00\x00\x00\x00\x00"     /* settings frame */
  408.     "\x00\x01\x00\x00\x00\x00"                 /* header table size */
  409.     "\x00\x02\x00\x00\x00\x00"                 /* disable push */
  410.     "\x00\x04\x7f\xff\xff\xff"                 /* initial window */

  411.     "\x00\x00\x04\x08\x00\x00\x00\x00\x00"     /* window update frame */
  412.     "\x7f\xff\x00\x00";


  413. static ngx_keyval_t  ngx_http_grpc_headers[] = {
  414.     { ngx_string("Content-Length"), ngx_string("$content_length") },
  415.     { ngx_string("TE"), ngx_string("$grpc_internal_trailers") },
  416.     { ngx_string("Host"), ngx_string("") },
  417.     { ngx_string("Connection"), ngx_string("") },
  418.     { ngx_string("Proxy-Connection"), ngx_string("") },
  419.     { ngx_string("Transfer-Encoding"), ngx_string("") },
  420.     { ngx_string("Keep-Alive"), ngx_string("") },
  421.     { ngx_string("Expect"), ngx_string("") },
  422.     { ngx_string("Upgrade"), ngx_string("") },
  423.     { ngx_null_string, ngx_null_string }
  424. };


  425. static ngx_str_t  ngx_http_grpc_hide_headers[] = {
  426.     ngx_string("Date"),
  427.     ngx_string("Server"),
  428.     ngx_string("X-Accel-Expires"),
  429.     ngx_string("X-Accel-Redirect"),
  430.     ngx_string("X-Accel-Limit-Rate"),
  431.     ngx_string("X-Accel-Buffering"),
  432.     ngx_string("X-Accel-Charset"),
  433.     ngx_null_string
  434. };


  435. static ngx_http_variable_t  ngx_http_grpc_vars[] = {

  436.     { ngx_string("grpc_internal_trailers"), NULL,
  437.       ngx_http_grpc_internal_trailers_variable, 0,
  438.       NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },

  439.       ngx_http_null_variable
  440. };


  441. static ngx_int_t
  442. ngx_http_grpc_handler(ngx_http_request_t *r)
  443. {
  444.     ngx_int_t                  rc;
  445.     ngx_http_upstream_t       *u;
  446.     ngx_http_grpc_ctx_t       *ctx;
  447.     ngx_http_grpc_loc_conf_t  *glcf;

  448.     if (ngx_http_upstream_create(r) != NGX_OK) {
  449.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  450.     }

  451.     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t));
  452.     if (ctx == NULL) {
  453.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  454.     }

  455.     ctx->request = r;

  456.     ngx_http_set_ctx(r, ctx, ngx_http_grpc_module);

  457.     glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);

  458.     u = r->upstream;

  459.     if (glcf->grpc_lengths == NULL) {
  460.         ctx->host = glcf->host;

  461. #if (NGX_HTTP_SSL)
  462.         u->ssl = glcf->ssl;

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

  465.         } else {
  466.             ngx_str_set(&u->schema, "grpc://");
  467.         }
  468. #else
  469.         ngx_str_set(&u->schema, "grpc://");
  470. #endif

  471.     } else {
  472.         if (ngx_http_grpc_eval(r, ctx, glcf) != NGX_OK) {
  473.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  474.         }
  475.     }

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

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

  478.     u->create_request = ngx_http_grpc_create_request;
  479.     u->reinit_request = ngx_http_grpc_reinit_request;
  480.     u->process_header = ngx_http_grpc_process_header;
  481.     u->abort_request = ngx_http_grpc_abort_request;
  482.     u->finalize_request = ngx_http_grpc_finalize_request;

  483.     u->input_filter_init = ngx_http_grpc_filter_init;
  484.     u->input_filter = ngx_http_grpc_filter;
  485.     u->input_filter_ctx = ctx;

  486.     r->request_body_no_buffering = 1;

  487.     rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

  488.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  489.         return rc;
  490.     }

  491.     return NGX_DONE;
  492. }


  493. static ngx_int_t
  494. ngx_http_grpc_eval(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  495.     ngx_http_grpc_loc_conf_t *glcf)
  496. {
  497.     size_t                add;
  498.     ngx_url_t             url;
  499.     ngx_http_upstream_t  *u;

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

  501.     if (ngx_http_script_run(r, &url.url, glcf->grpc_lengths->elts, 0,
  502.                             glcf->grpc_values->elts)
  503.         == NULL)
  504.     {
  505.         return NGX_ERROR;
  506.     }

  507.     if (url.url.len > 7
  508.         && ngx_strncasecmp(url.url.data, (u_char *) "grpc://", 7) == 0)
  509.     {
  510.         add = 7;

  511.     } else if (url.url.len > 8
  512.                && ngx_strncasecmp(url.url.data, (u_char *) "grpcs://", 8) == 0)
  513.     {

  514. #if (NGX_HTTP_SSL)
  515.         add = 8;
  516.         r->upstream->ssl = 1;
  517. #else
  518.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  519.                       "grpcs protocol requires SSL support");
  520.         return NGX_ERROR;
  521. #endif

  522.     } else {
  523.         add = 0;
  524.     }

  525.     u = r->upstream;

  526.     if (add) {
  527.         u->schema.len = add;
  528.         u->schema.data = url.url.data;

  529.         url.url.data += add;
  530.         url.url.len -= add;

  531.     } else {
  532.         ngx_str_set(&u->schema, "grpc://");
  533.     }

  534.     url.no_resolve = 1;

  535.     if (ngx_parse_url(r->pool, &url) != NGX_OK) {
  536.         if (url.err) {
  537.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  538.                           "%s in upstream \"%V\"", url.err, &url.url);
  539.         }

  540.         return NGX_ERROR;
  541.     }

  542.     u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
  543.     if (u->resolved == NULL) {
  544.         return NGX_ERROR;
  545.     }

  546.     if (url.addrs) {
  547.         u->resolved->sockaddr = url.addrs[0].sockaddr;
  548.         u->resolved->socklen = url.addrs[0].socklen;
  549.         u->resolved->name = url.addrs[0].name;
  550.         u->resolved->naddrs = 1;
  551.     }

  552.     u->resolved->host = url.host;
  553.     u->resolved->port = url.port;
  554.     u->resolved->no_port = url.no_port;

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

  556.         if (url.no_port) {
  557.             ctx->host = url.host;

  558.         } else {
  559.             ctx->host.len = url.host.len + 1 + url.port_text.len;
  560.             ctx->host.data = url.host.data;
  561.         }

  562.     } else {
  563.         ngx_str_set(&ctx->host, "localhost");
  564.     }

  565.     return NGX_OK;
  566. }


  567. static ngx_int_t
  568. ngx_http_grpc_create_request(ngx_http_request_t *r)
  569. {
  570.     u_char                       *p, *tmp, *key_tmp, *val_tmp, *headers_frame;
  571.     size_t                        len, tmp_len, key_len, val_len, uri_len;
  572.     uintptr_t                     escape;
  573.     ngx_buf_t                    *b;
  574.     ngx_uint_t                    i, next;
  575.     ngx_chain_t                  *cl, *body;
  576.     ngx_list_part_t              *part;
  577.     ngx_table_elt_t              *header;
  578.     ngx_http_grpc_ctx_t          *ctx;
  579.     ngx_http_upstream_t          *u;
  580.     ngx_http_grpc_frame_t        *f;
  581.     ngx_http_script_code_pt       code;
  582.     ngx_http_grpc_loc_conf_t     *glcf;
  583.     ngx_http_script_engine_t      e, le;
  584.     ngx_http_script_len_code_pt   lcode;

  585.     u = r->upstream;

  586.     glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);

  587.     ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);

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

  590.     /* :method header */

  591.     if (r->method == NGX_HTTP_GET || r->method == NGX_HTTP_POST) {
  592.         len += 1;
  593.         tmp_len = 0;

  594.     } else {
  595.         if (r->method_name.len > NGX_HTTP_V2_MAX_FIELD) {
  596.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  597.                           "too long http2 method: \"%V\"", &r->method_name);
  598.             return NGX_ERROR;
  599.         }

  600.         len += 1 + NGX_HTTP_V2_INT_OCTETS + r->method_name.len;
  601.         tmp_len = r->method_name.len;
  602.     }

  603.     /* :scheme header */

  604.     len += 1;

  605.     /* :path header */

  606.     if (r->valid_unparsed_uri) {
  607.         escape = 0;
  608.         uri_len = r->unparsed_uri.len;

  609.     } else {
  610.         escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
  611.                                     NGX_ESCAPE_URI);
  612.         uri_len = r->uri.len + escape + sizeof("?") - 1 + r->args.len;
  613.     }

  614.     if (uri_len > NGX_HTTP_V2_MAX_FIELD) {
  615.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  616.                       "too long http2 URI");
  617.         return NGX_ERROR;
  618.     }

  619.     len += 1 + NGX_HTTP_V2_INT_OCTETS + uri_len;

  620.     if (tmp_len < uri_len) {
  621.         tmp_len = uri_len;
  622.     }

  623.     /* :authority header */

  624.     if (!glcf->host_set) {
  625.         if (ctx->host.len > NGX_HTTP_V2_MAX_FIELD) {
  626.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  627.                           "too long http2 host: \"%V\"", &ctx->host);
  628.             return NGX_ERROR;
  629.         }

  630.         len += 1 + NGX_HTTP_V2_INT_OCTETS + ctx->host.len;

  631.         if (tmp_len < ctx->host.len) {
  632.             tmp_len = ctx->host.len;
  633.         }
  634.     }

  635.     /* other headers */

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

  638.     le.ip = glcf->headers.lengths->elts;
  639.     le.request = r;
  640.     le.flushed = 1;

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

  642.         lcode = *(ngx_http_script_len_code_pt *) le.ip;
  643.         key_len = lcode(&le);

  644.         for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  645.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  646.         }
  647.         le.ip += sizeof(uintptr_t);

  648.         if (val_len == 0) {
  649.             continue;
  650.         }

  651.         if (key_len > NGX_HTTP_V2_MAX_FIELD) {
  652.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  653.                           "too long http2 header name");
  654.             return NGX_ERROR;
  655.         }

  656.         if (val_len > NGX_HTTP_V2_MAX_FIELD) {
  657.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  658.                           "too long http2 header value");
  659.             return NGX_ERROR;
  660.         }

  661.         len += 1 + NGX_HTTP_V2_INT_OCTETS + key_len
  662.                  + NGX_HTTP_V2_INT_OCTETS + val_len;

  663.         if (tmp_len < key_len) {
  664.             tmp_len = key_len;
  665.         }

  666.         if (tmp_len < val_len) {
  667.             tmp_len = val_len;
  668.         }
  669.     }

  670.     if (glcf->upstream.pass_request_headers) {
  671.         part = &r->headers_in.headers.part;
  672.         header = part->elts;

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

  674.             if (i >= part->nelts) {
  675.                 if (part->next == NULL) {
  676.                     break;
  677.                 }

  678.                 part = part->next;
  679.                 header = part->elts;
  680.                 i = 0;
  681.             }

  682.             if (ngx_hash_find(&glcf->headers.hash, header[i].hash,
  683.                               header[i].lowcase_key, header[i].key.len))
  684.             {
  685.                 continue;
  686.             }

  687.             if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
  688.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  689.                               "too long http2 header name: \"%V\"",
  690.                               &header[i].key);
  691.                 return NGX_ERROR;
  692.             }

  693.             if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
  694.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  695.                               "too long http2 header value: \"%V: %V\"",
  696.                               &header[i].key, &header[i].value);
  697.                 return NGX_ERROR;
  698.             }

  699.             len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
  700.                      + NGX_HTTP_V2_INT_OCTETS + header[i].value.len;

  701.             if (tmp_len < header[i].key.len) {
  702.                 tmp_len = header[i].key.len;
  703.             }

  704.             if (tmp_len < header[i].value.len) {
  705.                 tmp_len = header[i].value.len;
  706.             }
  707.         }
  708.     }

  709.     /* continuation frames */

  710.     len += sizeof(ngx_http_grpc_frame_t)
  711.            * (len / NGX_HTTP_V2_DEFAULT_FRAME_SIZE);


  712.     b = ngx_create_temp_buf(r->pool, len);
  713.     if (b == NULL) {
  714.         return NGX_ERROR;
  715.     }

  716.     cl = ngx_alloc_chain_link(r->pool);
  717.     if (cl == NULL) {
  718.         return NGX_ERROR;
  719.     }

  720.     cl->buf = b;
  721.     cl->next = NULL;

  722.     tmp = ngx_palloc(r->pool, tmp_len * 3);
  723.     if (tmp == NULL) {
  724.         return NGX_ERROR;
  725.     }

  726.     key_tmp = tmp + tmp_len;
  727.     val_tmp = tmp + 2 * tmp_len;

  728.     /* connection preface */

  729.     b->last = ngx_copy(b->last, ngx_http_grpc_connection_start,
  730.                        sizeof(ngx_http_grpc_connection_start) - 1);

  731.     /* headers frame */

  732.     headers_frame = b->last;

  733.     f = (ngx_http_grpc_frame_t *) b->last;
  734.     b->last += sizeof(ngx_http_grpc_frame_t);

  735.     f->length_0 = 0;
  736.     f->length_1 = 0;
  737.     f->length_2 = 0;
  738.     f->type = NGX_HTTP_V2_HEADERS_FRAME;
  739.     f->flags = 0;
  740.     f->stream_id_0 = 0;
  741.     f->stream_id_1 = 0;
  742.     f->stream_id_2 = 0;
  743.     f->stream_id_3 = 1;

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

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

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

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

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

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

  759. #if (NGX_HTTP_SSL)
  760.     if (u->ssl) {
  761.         *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);

  762.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  763.                        "grpc header: \":scheme: https\"");
  764.     } else
  765. #endif
  766.     {
  767.         *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX);

  768.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  769.                        "grpc header: \":scheme: http\"");
  770.     }

  771.     if (r->valid_unparsed_uri) {

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

  774.         } else {
  775.             *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
  776.             b->last = ngx_http_v2_write_value(b->last, r->unparsed_uri.data,
  777.                                               r->unparsed_uri.len, tmp);
  778.         }

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

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

  783.         if (escape) {
  784.             p = (u_char *) ngx_escape_uri(p, r->uri.data, r->uri.len,
  785.                                           NGX_ESCAPE_URI);

  786.         } else {
  787.             p = ngx_copy(p, r->uri.data, r->uri.len);
  788.         }

  789.         if (r->args.len > 0) {
  790.             *p++ = '?';
  791.             p = ngx_copy(p, r->args.data, r->args.len);
  792.         }

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

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

  797.     } else {
  798.         *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
  799.         b->last = ngx_http_v2_write_value(b->last, r->uri.data,
  800.                                           r->uri.len, tmp);

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

  804.     if (!glcf->host_set) {
  805.         *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
  806.         b->last = ngx_http_v2_write_value(b->last, ctx->host.data,
  807.                                           ctx->host.len, tmp);

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

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

  812.     e.ip = glcf->headers.values->elts;
  813.     e.request = r;
  814.     e.flushed = 1;

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

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

  817.         lcode = *(ngx_http_script_len_code_pt *) le.ip;
  818.         key_len = lcode(&le);

  819.         for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
  820.             lcode = *(ngx_http_script_len_code_pt *) le.ip;
  821.         }
  822.         le.ip += sizeof(uintptr_t);

  823.         if (val_len == 0) {
  824.             e.skip = 1;

  825.             while (*(uintptr_t *) e.ip) {
  826.                 code = *(ngx_http_script_code_pt *) e.ip;
  827.                 code((ngx_http_script_engine_t *) &e);
  828.             }
  829.             e.ip += sizeof(uintptr_t);

  830.             e.skip = 0;

  831.             continue;
  832.         }

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

  834.         e.pos = key_tmp;

  835.         code = *(ngx_http_script_code_pt *) e.ip;
  836.         code((ngx_http_script_engine_t *) &e);

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

  838.         e.pos = val_tmp;

  839.         while (*(uintptr_t *) e.ip) {
  840.             code = *(ngx_http_script_code_pt *) e.ip;
  841.             code((ngx_http_script_engine_t *) &e);
  842.         }
  843.         e.ip += sizeof(uintptr_t);

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

  845. #if (NGX_DEBUG)
  846.         if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
  847.             ngx_strlow(key_tmp, key_tmp, key_len);

  848.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  849.                            "grpc header: \"%*s: %*s\"",
  850.                            key_len, key_tmp, val_len, val_tmp);
  851.         }
  852. #endif
  853.     }

  854.     if (glcf->upstream.pass_request_headers) {
  855.         part = &r->headers_in.headers.part;
  856.         header = part->elts;

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

  858.             if (i >= part->nelts) {
  859.                 if (part->next == NULL) {
  860.                     break;
  861.                 }

  862.                 part = part->next;
  863.                 header = part->elts;
  864.                 i = 0;
  865.             }

  866.             if (ngx_hash_find(&glcf->headers.hash, header[i].hash,
  867.                               header[i].lowcase_key, header[i].key.len))
  868.             {
  869.                 continue;
  870.             }

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

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

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

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

  879.                 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  880.                                "grpc header: \"%*s: %V\"",
  881.                                header[i].key.len, tmp, &header[i].value);
  882.             }
  883. #endif
  884.         }
  885.     }

  886.     /* update headers frame length */

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

  888.     if (len > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
  889.         len = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
  890.         next = 1;

  891.     } else {
  892.         next = 0;
  893.     }

  894.     f = (ngx_http_grpc_frame_t *) headers_frame;

  895.     f->length_0 = (u_char) ((len >> 16) & 0xff);
  896.     f->length_1 = (u_char) ((len >> 8) & 0xff);
  897.     f->length_2 = (u_char) (len & 0xff);

  898.     /* create additional continuation frames */

  899.     p = headers_frame;

  900.     while (next) {
  901.         p += sizeof(ngx_http_grpc_frame_t) + NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
  902.         len = b->last - p;

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

  905.         if (len > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
  906.             len = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
  907.             next = 1;

  908.         } else {
  909.             next = 0;
  910.         }

  911.         f = (ngx_http_grpc_frame_t *) p;

  912.         f->length_0 = (u_char) ((len >> 16) & 0xff);
  913.         f->length_1 = (u_char) ((len >> 8) & 0xff);
  914.         f->length_2 = (u_char) (len & 0xff);
  915.         f->type = NGX_HTTP_V2_CONTINUATION_FRAME;
  916.         f->flags = 0;
  917.         f->stream_id_0 = 0;
  918.         f->stream_id_1 = 0;
  919.         f->stream_id_2 = 0;
  920.         f->stream_id_3 = 1;
  921.     }

  922.     f->flags |= NGX_HTTP_V2_END_HEADERS_FLAG;

  923.     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  924.                    "grpc header: %*xs%s, len: %uz",
  925.                    (size_t) ngx_min(b->last - b->pos, 256), b->pos,
  926.                    b->last - b->pos > 256 ? "..." : "",
  927.                    b->last - b->pos);

  928.     if (r->request_body_no_buffering) {

  929.         u->request_bufs = cl;

  930.     } else {

  931.         body = u->request_bufs;
  932.         u->request_bufs = cl;

  933.         if (body == NULL) {
  934.             f = (ngx_http_grpc_frame_t *) headers_frame;
  935.             f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;
  936.         }

  937.         while (body) {
  938.             b = ngx_alloc_buf(r->pool);
  939.             if (b == NULL) {
  940.                 return NGX_ERROR;
  941.             }

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

  943.             cl->next = ngx_alloc_chain_link(r->pool);
  944.             if (cl->next == NULL) {
  945.                 return NGX_ERROR;
  946.             }

  947.             cl = cl->next;
  948.             cl->buf = b;

  949.             body = body->next;
  950.         }

  951.         b->last_buf = 1;
  952.     }

  953.     u->output.output_filter = ngx_http_grpc_body_output_filter;
  954.     u->output.filter_ctx = r;

  955.     b->flush = 1;
  956.     cl->next = NULL;

  957.     return NGX_OK;
  958. }


  959. static ngx_int_t
  960. ngx_http_grpc_reinit_request(ngx_http_request_t *r)
  961. {
  962.     ngx_http_grpc_ctx_t  *ctx;

  963.     ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);

  964.     if (ctx == NULL) {
  965.         return NGX_OK;
  966.     }

  967.     ctx->state = 0;
  968.     ctx->header_sent = 0;
  969.     ctx->output_closed = 0;
  970.     ctx->output_blocked = 0;
  971.     ctx->parsing_headers = 0;
  972.     ctx->end_stream = 0;
  973.     ctx->done = 0;
  974.     ctx->status = 0;
  975.     ctx->rst = 0;
  976.     ctx->goaway = 0;
  977.     ctx->connection = NULL;
  978.     ctx->in = NULL;
  979.     ctx->busy = NULL;
  980.     ctx->out = NULL;

  981.     return NGX_OK;
  982. }


  983. static ngx_int_t
  984. ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in)
  985. {
  986.     ngx_http_request_t  *r = data;

  987.     off_t                   file_pos;
  988.     u_char                 *p, *pos, *start;
  989.     size_t                  len, limit;
  990.     ngx_buf_t              *b;
  991.     ngx_int_t               rc;
  992.     ngx_uint_t              next, last;
  993.     ngx_chain_t            *cl, *out, *ln, **ll;
  994.     ngx_http_upstream_t    *u;
  995.     ngx_http_grpc_ctx_t    *ctx;
  996.     ngx_http_grpc_frame_t  *f;

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

  999.     ctx = ngx_http_grpc_get_ctx(r);

  1000.     if (ctx == NULL) {
  1001.         return NGX_ERROR;
  1002.     }

  1003.     if (in) {
  1004.         if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
  1005.             return NGX_ERROR;
  1006.         }
  1007.     }

  1008.     out = NULL;
  1009.     ll = &out;

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

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

  1014.         ctx->header_sent = 1;

  1015.         if (ctx->id != 1) {
  1016.             /*
  1017.              * keepalive connection: skip connection preface,
  1018.              * update stream identifiers
  1019.              */

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

  1022.             p = b->pos;

  1023.             while (p < b->last) {
  1024.                 f = (ngx_http_grpc_frame_t *) p;
  1025.                 p += sizeof(ngx_http_grpc_frame_t);

  1026.                 f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
  1027.                 f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
  1028.                 f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
  1029.                 f->stream_id_3 = (u_char) (ctx->id & 0xff);

  1030.                 p += (f->length_0 << 16) + (f->length_1 << 8) + f->length_2;
  1031.             }
  1032.         }

  1033.         if (ctx->in->buf->last_buf) {
  1034.             ctx->output_closed = 1;
  1035.         }

  1036.         *ll = ctx->in;
  1037.         ll = &ctx->in->next;

  1038.         ctx->in = ctx->in->next;
  1039.     }

  1040.     if (ctx->out) {
  1041.         /* queued control frames */

  1042.         *ll = ctx->out;

  1043.         for (cl = ctx->out, ll = &cl->next; cl; cl = cl->next) {
  1044.             ll = &cl->next;
  1045.         }

  1046.         ctx->out = NULL;
  1047.     }

  1048.     f = NULL;
  1049.     last = 0;

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

  1051.     if (limit > ctx->connection->send_window) {
  1052.         limit = ctx->connection->send_window;
  1053.     }

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

  1057. #if (NGX_SUPPRESS_WARN)
  1058.     file_pos = 0;
  1059.     pos = NULL;
  1060.     cl = NULL;
  1061. #endif

  1062.     in = ctx->in;

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

  1064.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
  1065.                        "grpc output in  l:%d f:%d %p, pos %p, size: %z "
  1066.                        "file: %O, size: %O",
  1067.                        in->buf->last_buf,
  1068.                        in->buf->in_file,
  1069.                        in->buf->start, in->buf->pos,
  1070.                        in->buf->last - in->buf->pos,
  1071.                        in->buf->file_pos,
  1072.                        in->buf->file_last - in->buf->file_pos);

  1073.         if (ngx_buf_special(in->buf)) {
  1074.             goto next;
  1075.         }

  1076.         if (in->buf->in_file) {
  1077.             file_pos = in->buf->file_pos;

  1078.         } else {
  1079.             pos = in->buf->pos;
  1080.         }

  1081.         next = 0;

  1082.         do {

  1083.             cl = ngx_http_grpc_get_buf(r, ctx);
  1084.             if (cl == NULL) {
  1085.                 return NGX_ERROR;
  1086.             }

  1087.             b = cl->buf;

  1088.             f = (ngx_http_grpc_frame_t *) b->last;
  1089.             b->last += sizeof(ngx_http_grpc_frame_t);

  1090.             *ll = cl;
  1091.             ll = &cl->next;

  1092.             cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
  1093.             if (cl == NULL) {
  1094.                 return NGX_ERROR;
  1095.             }

  1096.             b = cl->buf;
  1097.             start = b->start;

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

  1099.             /*
  1100.              * restore b->start to preserve memory allocated in the buffer,
  1101.              * to reuse it later for headers and control frames
  1102.              */

  1103.             b->start = start;

  1104.             if (in->buf->in_file) {
  1105.                 b->file_pos = file_pos;
  1106.                 file_pos += ngx_min(NGX_HTTP_V2_DEFAULT_FRAME_SIZE, limit);

  1107.                 if (file_pos >= in->buf->file_last) {
  1108.                     file_pos = in->buf->file_last;
  1109.                     next = 1;
  1110.                 }

  1111.                 b->file_last = file_pos;
  1112.                 len = (ngx_uint_t) (file_pos - b->file_pos);

  1113.             } else {
  1114.                 b->pos = pos;
  1115.                 pos += ngx_min(NGX_HTTP_V2_DEFAULT_FRAME_SIZE, limit);

  1116.                 if (pos >= in->buf->last) {
  1117.                     pos = in->buf->last;
  1118.                     next = 1;
  1119.                 }

  1120.                 b->last = pos;
  1121.                 len = (ngx_uint_t) (pos - b->pos);
  1122.             }

  1123.             b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
  1124.             b->shadow = in->buf;
  1125.             b->last_shadow = next;

  1126.             b->last_buf = 0;
  1127.             b->last_in_chain = 0;

  1128.             *ll = cl;
  1129.             ll = &cl->next;

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

  1139.             limit -= len;
  1140.             ctx->send_window -= len;
  1141.             ctx->connection->send_window -= len;

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

  1143.         if (!next) {
  1144.             /*
  1145.              * if the buffer wasn't fully sent due to flow control limits,
  1146.              * preserve position for future use
  1147.              */

  1148.             if (in->buf->in_file) {
  1149.                 in->buf->file_pos = file_pos;

  1150.             } else {
  1151.                 in->buf->pos = pos;
  1152.             }

  1153.             break;
  1154.         }

  1155.     next:

  1156.         if (in->buf->last_buf) {
  1157.             last = 1;
  1158.         }

  1159.         ln = in;
  1160.         in = in->next;

  1161.         ngx_free_chain(r->pool, ln);
  1162.     }

  1163.     ctx->in = in;

  1164.     if (last) {

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

  1167.         ctx->output_closed = 1;

  1168.         if (f) {
  1169.             f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;

  1170.         } else {
  1171.             cl = ngx_http_grpc_get_buf(r, ctx);
  1172.             if (cl == NULL) {
  1173.                 return NGX_ERROR;
  1174.             }

  1175.             b = cl->buf;

  1176.             f = (ngx_http_grpc_frame_t *) b->last;
  1177.             b->last += sizeof(ngx_http_grpc_frame_t);

  1178.             f->length_0 = 0;
  1179.             f->length_1 = 0;
  1180.             f->length_2 = 0;
  1181.             f->type = NGX_HTTP_V2_DATA_FRAME;
  1182.             f->flags = NGX_HTTP_V2_END_STREAM_FLAG;
  1183.             f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
  1184.             f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
  1185.             f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
  1186.             f->stream_id_3 = (u_char) (ctx->id & 0xff);

  1187.             *ll = cl;
  1188.             ll = &cl->next;
  1189.         }

  1190.         cl->buf->last_buf = 1;
  1191.     }

  1192.     *ll = NULL;

  1193. #if (NGX_DEBUG)

  1194.     for (cl = out; cl; cl = cl->next) {
  1195.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
  1196.                        "grpc output out l:%d f:%d %p, pos %p, size: %z "
  1197.                        "file: %O, size: %O",
  1198.                        cl->buf->last_buf,
  1199.                        cl->buf->in_file,
  1200.                        cl->buf->start, cl->buf->pos,
  1201.                        cl->buf->last - cl->buf->pos,
  1202.                        cl->buf->file_pos,
  1203.                        cl->buf->file_last - cl->buf->file_pos);
  1204.     }

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

  1208. #endif

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

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

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

  1213.         /* mark original buffers as sent */

  1214.         if (cl->buf->shadow) {
  1215.             if (cl->buf->last_shadow) {
  1216.                 b = cl->buf->shadow;
  1217.                 b->pos = b->last;
  1218.             }

  1219.             cl->buf->shadow = NULL;
  1220.         }
  1221.     }

  1222.     if (rc == NGX_OK && ctx->in) {
  1223.         rc = NGX_AGAIN;
  1224.     }

  1225.     if (rc == NGX_AGAIN) {
  1226.         ctx->output_blocked = 1;

  1227.     } else {
  1228.         ctx->output_blocked = 0;
  1229.     }

  1230.     if (ctx->done) {

  1231.         /*
  1232.          * We have already got the response and were sending some additional
  1233.          * control frames.  Even if there is still something unsent, stop
  1234.          * here anyway.
  1235.          */

  1236.         u = r->upstream;
  1237.         u->length = 0;

  1238.         if (ctx->in == NULL
  1239.             && ctx->out == NULL
  1240.             && ctx->output_closed
  1241.             && !ctx->output_blocked
  1242.             && !ctx->goaway
  1243.             && ctx->state == ngx_http_grpc_st_start)
  1244.         {
  1245.             u->keepalive = 1;
  1246.         }

  1247.         ngx_post_event(u->peer.connection->read, &ngx_posted_events);
  1248.     }

  1249.     return rc;
  1250. }


  1251. static ngx_int_t
  1252. ngx_http_grpc_process_header(ngx_http_request_t *r)
  1253. {
  1254.     ngx_str_t                      *status_line;
  1255.     ngx_int_t                       rc, status;
  1256.     ngx_buf_t                      *b;
  1257.     ngx_table_elt_t                *h;
  1258.     ngx_http_upstream_t            *u;
  1259.     ngx_http_grpc_ctx_t            *ctx;
  1260.     ngx_http_upstream_header_t     *hh;
  1261.     ngx_http_upstream_main_conf_t  *umcf;

  1262.     u = r->upstream;
  1263.     b = &u->buffer;

  1264.     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1265.                    "grpc response: %*xs%s, len: %uz",
  1266.                    (size_t) ngx_min(b->last - b->pos, 256),
  1267.                    b->pos, b->last - b->pos > 256 ? "..." : "",
  1268.                    b->last - b->pos);

  1269.     ctx = ngx_http_grpc_get_ctx(r);

  1270.     if (ctx == NULL) {
  1271.         return NGX_ERROR;
  1272.     }

  1273.     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);

  1274.     for ( ;; ) {

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

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

  1277.             if (rc == NGX_AGAIN) {

  1278.                 /*
  1279.                  * there can be a lot of window update frames,
  1280.                  * so we reset buffer if it is empty and we haven't
  1281.                  * started parsing headers yet
  1282.                  */

  1283.                 if (!ctx->parsing_headers) {
  1284.                     b->pos = b->start;
  1285.                     b->last = b->pos;
  1286.                 }

  1287.                 return NGX_AGAIN;
  1288.             }

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

  1292.             /*
  1293.              * RFC 7540 says that implementations MUST discard frames
  1294.              * that have unknown or unsupported types.  However, extension
  1295.              * frames that appear in the middle of a header block are
  1296.              * not permitted.  Also, for obvious reasons CONTINUATION frames
  1297.              * cannot appear before headers, and DATA frames are not expected
  1298.              * to appear before all headers are parsed.
  1299.              */

  1300.             if (ctx->type == NGX_HTTP_V2_DATA_FRAME
  1301.                 || (ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME
  1302.                     && !ctx->parsing_headers)
  1303.                 || (ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME
  1304.                     && ctx->parsing_headers))
  1305.             {
  1306.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1307.                               "upstream sent unexpected http2 frame: %d",
  1308.                               ctx->type);
  1309.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1310.             }

  1311.             if (ctx->stream_id && ctx->stream_id != ctx->id) {
  1312.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1313.                               "upstream sent frame for unknown stream %ui",
  1314.                               ctx->stream_id);
  1315.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1316.             }
  1317.         }

  1318.         /* frame payload */

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

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

  1321.             if (rc == NGX_AGAIN) {
  1322.                 return NGX_AGAIN;
  1323.             }

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

  1327.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1328.                           "upstream rejected request with error %ui",
  1329.                           ctx->error);

  1330.             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1331.         }

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

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

  1334.             if (rc == NGX_AGAIN) {
  1335.                 return NGX_AGAIN;
  1336.             }

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

  1340.             /*
  1341.              * If stream_id is lower than one we use, our
  1342.              * request won't be processed and needs to be retried.
  1343.              * If stream_id is greater or equal to the one we use,
  1344.              * we can continue normally (except we can't use this
  1345.              * connection for additional requests).  If there is
  1346.              * a real error, the connection will be closed.
  1347.              */

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

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

  1350.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1351.                               "upstream sent goaway with error %ui",
  1352.                               ctx->error);

  1353.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1354.             }

  1355.             ctx->goaway = 1;

  1356.             continue;
  1357.         }

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

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

  1360.             if (rc == NGX_AGAIN) {
  1361.                 return NGX_AGAIN;
  1362.             }

  1363.             if (rc == NGX_ERROR) {
  1364.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1365.             }

  1366.             if (ctx->in) {
  1367.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1368.             }

  1369.             continue;
  1370.         }

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

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

  1373.             if (rc == NGX_AGAIN) {
  1374.                 return NGX_AGAIN;
  1375.             }

  1376.             if (rc == NGX_ERROR) {
  1377.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1378.             }

  1379.             if (ctx->in) {
  1380.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1381.             }

  1382.             continue;
  1383.         }

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

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

  1386.             if (rc == NGX_AGAIN) {
  1387.                 return NGX_AGAIN;
  1388.             }

  1389.             if (rc == NGX_ERROR) {
  1390.                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1391.             }

  1392.             ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1393.             continue;
  1394.         }

  1395.         if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
  1396.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1397.                           "upstream sent unexpected push promise frame");
  1398.             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1399.         }

  1400.         if (ctx->type != NGX_HTTP_V2_HEADERS_FRAME
  1401.             && ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME)
  1402.         {
  1403.             /* priority, unknown frames */

  1404.             if (b->last - b->pos < (ssize_t) ctx->rest) {
  1405.                 ctx->rest -= b->last - b->pos;
  1406.                 b->pos = b->last;
  1407.                 return NGX_AGAIN;
  1408.             }

  1409.             b->pos += ctx->rest;
  1410.             ctx->rest = 0;
  1411.             ctx->state = ngx_http_grpc_st_start;

  1412.             continue;
  1413.         }

  1414.         /* headers */

  1415.         for ( ;; ) {

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

  1417.             if (rc == NGX_AGAIN) {
  1418.                 break;
  1419.             }

  1420.             if (rc == NGX_OK) {

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

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

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

  1426.                     if (ctx->name.len != sizeof(":status") - 1
  1427.                         || ngx_strncmp(ctx->name.data, ":status",
  1428.                                        sizeof(":status") - 1)
  1429.                            != 0)
  1430.                     {
  1431.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1432.                                       "upstream sent invalid header \"%V: %V\"",
  1433.                                       &ctx->name, &ctx->value);
  1434.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1435.                     }

  1436.                     if (ctx->status) {
  1437.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1438.                                       "upstream sent duplicate :status header");
  1439.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1440.                     }

  1441.                     status_line = &ctx->value;

  1442.                     if (status_line->len != 3) {
  1443.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1444.                                       "upstream sent invalid :status \"%V\"",
  1445.                                       status_line);
  1446.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1447.                     }

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

  1449.                     if (status == NGX_ERROR) {
  1450.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1451.                                       "upstream sent invalid :status \"%V\"",
  1452.                                       status_line);
  1453.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1454.                     }

  1455.                     if (status < NGX_HTTP_OK && status != NGX_HTTP_EARLY_HINTS)
  1456.                     {
  1457.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1458.                                       "upstream sent unexpected :status \"%V\"",
  1459.                                       status_line);
  1460.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1461.                     }

  1462.                     u->headers_in.status_n = status;

  1463.                     if (u->state && u->state->status == 0) {
  1464.                         u->state->status = status;
  1465.                     }

  1466.                     ctx->status = 1;

  1467.                     continue;

  1468.                 } else if (!ctx->status) {
  1469.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1470.                                   "upstream sent no :status header");
  1471.                     return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1472.                 }

  1473.                 h = ngx_list_push(&u->headers_in.headers);
  1474.                 if (h == NULL) {
  1475.                     return NGX_ERROR;
  1476.                 }

  1477.                 h->key = ctx->name;
  1478.                 h->value = ctx->value;
  1479.                 h->lowcase_key = h->key.data;
  1480.                 h->hash = ngx_hash_key(h->key.data, h->key.len);

  1481.                 if (u->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
  1482.                     continue;
  1483.                 }

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

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

  1488.                     if (rc != NGX_OK) {
  1489.                         return rc;
  1490.                     }
  1491.                 }

  1492.                 continue;
  1493.             }

  1494.             if (rc == NGX_HTTP_PARSE_HEADER_DONE) {

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

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

  1498.                 if (u->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
  1499.                     if (ctx->end_stream) {
  1500.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1501.                                       "upstream prematurely closed stream");
  1502.                         return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1503.                     }

  1504.                     ctx->status = 0;
  1505.                     return NGX_HTTP_UPSTREAM_EARLY_HINTS;
  1506.                 }

  1507.                 if (ctx->end_stream) {
  1508.                     u->headers_in.content_length_n = 0;

  1509.                     if (ctx->in == NULL
  1510.                         && ctx->out == NULL
  1511.                         && ctx->output_closed
  1512.                         && !ctx->output_blocked
  1513.                         && !ctx->goaway
  1514.                         && b->last == b->pos)
  1515.                     {
  1516.                         u->keepalive = 1;
  1517.                     }
  1518.                 }

  1519.                 return NGX_OK;
  1520.             }

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

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

  1524.             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
  1525.         }

  1526.         /* rc == NGX_AGAIN */

  1527.         if (ctx->rest == 0) {
  1528.             ctx->state = ngx_http_grpc_st_start;
  1529.             continue;
  1530.         }

  1531.         return NGX_AGAIN;
  1532.     }
  1533. }


  1534. static ngx_int_t
  1535. ngx_http_grpc_filter_init(void *data)
  1536. {
  1537.     ngx_http_grpc_ctx_t  *ctx = data;

  1538.     ngx_http_request_t   *r;
  1539.     ngx_http_upstream_t  *u;

  1540.     r = ctx->request;
  1541.     u = r->upstream;

  1542.     if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
  1543.         || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
  1544.         || r->method == NGX_HTTP_HEAD)
  1545.     {
  1546.         ctx->length = 0;

  1547.     } else {
  1548.         ctx->length = u->headers_in.content_length_n;
  1549.     }

  1550.     if (ctx->end_stream) {

  1551.         if (ctx->length > 0) {
  1552.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1553.                           "upstream prematurely closed stream");
  1554.             return NGX_ERROR;
  1555.         }

  1556.         u->length = 0;
  1557.         ctx->done = 1;

  1558.     } else {
  1559.         u->length = 1;
  1560.     }

  1561.     return NGX_OK;
  1562. }


  1563. static ngx_int_t
  1564. ngx_http_grpc_filter(void *data, ssize_t bytes)
  1565. {
  1566.     ngx_http_grpc_ctx_t  *ctx = data;

  1567.     ngx_int_t             rc;
  1568.     ngx_buf_t            *b, *buf;
  1569.     ngx_chain_t          *cl, **ll;
  1570.     ngx_table_elt_t      *h;
  1571.     ngx_http_request_t   *r;
  1572.     ngx_http_upstream_t  *u;

  1573.     r = ctx->request;
  1574.     u = r->upstream;
  1575.     b = &u->buffer;

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

  1578.     b->pos = b->last;
  1579.     b->last += bytes;

  1580.     for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
  1581.         ll = &cl->next;
  1582.     }

  1583.     for ( ;; ) {

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

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

  1586.             if (rc == NGX_AGAIN) {

  1587.                 if (ctx->done) {

  1588.                     if (ctx->length > 0) {
  1589.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1590.                                       "upstream prematurely closed stream");
  1591.                         return NGX_ERROR;
  1592.                     }

  1593.                     /*
  1594.                      * We have finished parsing the response and the
  1595.                      * remaining control frames.  If there are unsent
  1596.                      * control frames, post a write event to send them.
  1597.                      */

  1598.                     if (ctx->out) {
  1599.                         ngx_post_event(u->peer.connection->write,
  1600.                                        &ngx_posted_events);
  1601.                         return NGX_AGAIN;
  1602.                     }

  1603.                     u->length = 0;

  1604.                     if (ctx->in == NULL
  1605.                         && ctx->output_closed
  1606.                         && !ctx->output_blocked
  1607.                         && !ctx->goaway
  1608.                         && ctx->state == ngx_http_grpc_st_start)
  1609.                     {
  1610.                         u->keepalive = 1;
  1611.                     }

  1612.                     break;
  1613.                 }

  1614.                 return NGX_AGAIN;
  1615.             }

  1616.             if (rc == NGX_ERROR) {
  1617.                 return NGX_ERROR;
  1618.             }

  1619.             if ((ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME
  1620.                  && !ctx->parsing_headers)
  1621.                 || (ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME
  1622.                     && ctx->parsing_headers))
  1623.             {
  1624.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1625.                               "upstream sent unexpected http2 frame: %d",
  1626.                               ctx->type);
  1627.                 return NGX_ERROR;
  1628.             }

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

  1630.                 if (ctx->stream_id != ctx->id) {
  1631.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1632.                                   "upstream sent data frame "
  1633.                                   "for unknown stream %ui",
  1634.                                   ctx->stream_id);
  1635.                     return NGX_ERROR;
  1636.                 }

  1637.                 if (ctx->rest > ctx->recv_window) {
  1638.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1639.                                   "upstream violated stream flow control, "
  1640.                                   "received %uz data frame with window %uz",
  1641.                                   ctx->rest, ctx->recv_window);
  1642.                     return NGX_ERROR;
  1643.                 }

  1644.                 if (ctx->rest > ctx->connection->recv_window) {
  1645.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1646.                                   "upstream violated connection flow control, "
  1647.                                   "received %uz data frame with window %uz",
  1648.                                   ctx->rest, ctx->connection->recv_window);
  1649.                     return NGX_ERROR;
  1650.                 }

  1651.                 ctx->recv_window -= ctx->rest;
  1652.                 ctx->connection->recv_window -= ctx->rest;

  1653.                 if (ctx->connection->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4
  1654.                     || ctx->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4)
  1655.                 {
  1656.                     if (ngx_http_grpc_send_window_update(r, ctx) != NGX_OK) {
  1657.                         return NGX_ERROR;
  1658.                     }

  1659.                     ngx_post_event(u->peer.connection->write,
  1660.                                    &ngx_posted_events);
  1661.                 }
  1662.             }

  1663.             if (ctx->stream_id && ctx->stream_id != ctx->id) {
  1664.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1665.                               "upstream sent frame for unknown stream %ui",
  1666.                               ctx->stream_id);
  1667.                 return NGX_ERROR;
  1668.             }

  1669.             if (ctx->stream_id && ctx->done
  1670.                 && ctx->type != NGX_HTTP_V2_RST_STREAM_FRAME
  1671.                 && ctx->type != NGX_HTTP_V2_WINDOW_UPDATE_FRAME)
  1672.             {
  1673.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1674.                               "upstream sent frame for closed stream %ui",
  1675.                               ctx->stream_id);
  1676.                 return NGX_ERROR;
  1677.             }

  1678.             ctx->padding = 0;
  1679.         }

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

  1681.             if (b->last - b->pos < (ssize_t) ctx->rest) {
  1682.                 ctx->rest -= b->last - b->pos;
  1683.                 b->pos = b->last;
  1684.                 return NGX_AGAIN;
  1685.             }

  1686.             b->pos += ctx->rest;
  1687.             ctx->rest = 0;
  1688.             ctx->state = ngx_http_grpc_st_start;

  1689.             if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
  1690.                 ctx->done = 1;
  1691.             }

  1692.             continue;
  1693.         }

  1694.         /* frame payload */

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

  1696.             rc = ngx_http_grpc_parse_rst_stream(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->error || !ctx->done) {
  1704.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1705.                               "upstream rejected request with error %ui",
  1706.                               ctx->error);
  1707.                 return NGX_ERROR;
  1708.             }

  1709.             if (ctx->rst) {
  1710.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1711.                               "upstream sent frame for closed stream %ui",
  1712.                               ctx->stream_id);
  1713.                 return NGX_ERROR;
  1714.             }

  1715.             ctx->rst = 1;

  1716.             continue;
  1717.         }

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

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

  1720.             if (rc == NGX_AGAIN) {
  1721.                 return NGX_AGAIN;
  1722.             }

  1723.             if (rc == NGX_ERROR) {
  1724.                 return NGX_ERROR;
  1725.             }

  1726.             /*
  1727.              * If stream_id is lower than one we use, our
  1728.              * request won't be processed and needs to be retried.
  1729.              * If stream_id is greater or equal to the one we use,
  1730.              * we can continue normally (except we can't use this
  1731.              * connection for additional requests).  If there is
  1732.              * a real error, the connection will be closed.
  1733.              */

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

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

  1736.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1737.                               "upstream sent goaway with error %ui",
  1738.                               ctx->error);

  1739.                 return NGX_ERROR;
  1740.             }

  1741.             ctx->goaway = 1;

  1742.             continue;
  1743.         }

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

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

  1746.             if (rc == NGX_AGAIN) {
  1747.                 return NGX_AGAIN;
  1748.             }

  1749.             if (rc == NGX_ERROR) {
  1750.                 return NGX_ERROR;
  1751.             }

  1752.             if (ctx->in) {
  1753.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1754.             }

  1755.             continue;
  1756.         }

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

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

  1759.             if (rc == NGX_AGAIN) {
  1760.                 return NGX_AGAIN;
  1761.             }

  1762.             if (rc == NGX_ERROR) {
  1763.                 return NGX_ERROR;
  1764.             }

  1765.             if (ctx->in) {
  1766.                 ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1767.             }

  1768.             continue;
  1769.         }

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

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

  1772.             if (rc == NGX_AGAIN) {
  1773.                 return NGX_AGAIN;
  1774.             }

  1775.             if (rc == NGX_ERROR) {
  1776.                 return NGX_ERROR;
  1777.             }

  1778.             ngx_post_event(u->peer.connection->write, &ngx_posted_events);
  1779.             continue;
  1780.         }

  1781.         if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
  1782.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1783.                           "upstream sent unexpected push promise frame");
  1784.             return NGX_ERROR;
  1785.         }

  1786.         if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME
  1787.             || ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME)
  1788.         {
  1789.             for ( ;; ) {

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

  1791.                 if (rc == NGX_AGAIN) {
  1792.                     break;
  1793.                 }

  1794.                 if (rc == NGX_OK) {

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

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

  1799.                     if (ctx->name.len && ctx->name.data[0] == ':') {
  1800.                         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1801.                                       "upstream sent invalid "
  1802.                                       "trailer \"%V: %V\"",
  1803.                                       &ctx->name, &ctx->value);
  1804.                         return NGX_ERROR;
  1805.                     }

  1806.                     h = ngx_list_push(&u->headers_in.trailers);
  1807.                     if (h == NULL) {
  1808.                         return NGX_ERROR;
  1809.                     }

  1810.                     h->key = ctx->name;
  1811.                     h->value = ctx->value;
  1812.                     h->lowcase_key = h->key.data;
  1813.                     h->hash = ngx_hash_key(h->key.data, h->key.len);

  1814.                     continue;
  1815.                 }

  1816.                 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {

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

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

  1820.                     if (ctx->end_stream) {
  1821.                         ctx->done = 1;
  1822.                         break;
  1823.                     }

  1824.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1825.                                   "upstream sent trailer without "
  1826.                                   "end stream flag");
  1827.                     return NGX_ERROR;
  1828.                 }

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

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

  1832.                 return NGX_ERROR;
  1833.             }

  1834.             if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
  1835.                 continue;
  1836.             }

  1837.             /* rc == NGX_AGAIN */

  1838.             if (ctx->rest == 0) {
  1839.                 ctx->state = ngx_http_grpc_st_start;
  1840.                 continue;
  1841.             }

  1842.             return NGX_AGAIN;
  1843.         }

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

  1845.             /* priority, unknown frames */

  1846.             if (b->last - b->pos < (ssize_t) ctx->rest) {
  1847.                 ctx->rest -= b->last - b->pos;
  1848.                 b->pos = b->last;
  1849.                 return NGX_AGAIN;
  1850.             }

  1851.             b->pos += ctx->rest;
  1852.             ctx->rest = 0;
  1853.             ctx->state = ngx_http_grpc_st_start;

  1854.             continue;
  1855.         }

  1856.         /*
  1857.          * data frame:
  1858.          *
  1859.          * +---------------+
  1860.          * |Pad Length? (8)|
  1861.          * +---------------+-----------------------------------------------+
  1862.          * |                            Data (*)                         ...
  1863.          * +---------------------------------------------------------------+
  1864.          * |                           Padding (*)                       ...
  1865.          * +---------------------------------------------------------------+
  1866.          */

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

  1868.             if (ctx->rest == 0) {
  1869.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1870.                               "upstream sent too short http2 frame");
  1871.                 return NGX_ERROR;
  1872.             }

  1873.             if (b->pos == b->last) {
  1874.                 return NGX_AGAIN;
  1875.             }

  1876.             ctx->flags &= ~NGX_HTTP_V2_PADDED_FLAG;
  1877.             ctx->padding = *b->pos++;
  1878.             ctx->rest -= 1;

  1879.             if (ctx->padding > ctx->rest) {
  1880.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1881.                               "upstream sent http2 frame with too long "
  1882.                               "padding: %d in frame %uz",
  1883.                               ctx->padding, ctx->rest);
  1884.                 return NGX_ERROR;
  1885.             }

  1886.             continue;
  1887.         }

  1888.         if (ctx->rest == ctx->padding) {
  1889.             goto done;
  1890.         }

  1891.         if (b->pos == b->last) {
  1892.             return NGX_AGAIN;
  1893.         }

  1894.         cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
  1895.         if (cl == NULL) {
  1896.             return NGX_ERROR;
  1897.         }

  1898.         *ll = cl;
  1899.         ll = &cl->next;

  1900.         buf = cl->buf;

  1901.         buf->flush = 1;
  1902.         buf->memory = 1;

  1903.         buf->pos = b->pos;
  1904.         buf->tag = u->output.tag;

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

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

  1908.             ctx->rest -= b->last - b->pos;
  1909.             b->pos = b->last;
  1910.             buf->last = b->pos;

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

  1912.                 if (buf->last - buf->pos > ctx->length) {
  1913.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1914.                                   "upstream sent response body larger "
  1915.                                   "than indicated content length");
  1916.                     return NGX_ERROR;
  1917.                 }

  1918.                 ctx->length -= buf->last - buf->pos;
  1919.             }

  1920.             return NGX_AGAIN;
  1921.         }

  1922.         b->pos += ctx->rest - ctx->padding;
  1923.         buf->last = b->pos;
  1924.         ctx->rest = ctx->padding;

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

  1926.             if (buf->last - buf->pos > ctx->length) {
  1927.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1928.                               "upstream sent response body larger "
  1929.                               "than indicated content length");
  1930.                 return NGX_ERROR;
  1931.             }

  1932.             ctx->length -= buf->last - buf->pos;
  1933.         }

  1934.     done:

  1935.         if (ctx->padding) {
  1936.             ctx->state = ngx_http_grpc_st_padding;
  1937.             continue;
  1938.         }

  1939.         ctx->state = ngx_http_grpc_st_start;

  1940.         if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
  1941.             ctx->done = 1;
  1942.         }
  1943.     }

  1944.     return NGX_OK;
  1945. }


  1946. static ngx_int_t
  1947. ngx_http_grpc_parse_frame(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  1948.     ngx_buf_t *b)
  1949. {
  1950.     u_char                 ch, *p;
  1951.     ngx_http_grpc_state_e  state;

  1952.     state = ctx->state;

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

  1955. #if 0
  1956.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1957.                        "grpc frame byte: %02Xd, s:%d", ch, state);
  1958. #endif

  1959.         switch (state) {

  1960.         case ngx_http_grpc_st_start:
  1961.             ctx->rest = ch << 16;
  1962.             state = ngx_http_grpc_st_length_2;
  1963.             break;

  1964.         case ngx_http_grpc_st_length_2:
  1965.             ctx->rest |= ch << 8;
  1966.             state = ngx_http_grpc_st_length_3;
  1967.             break;

  1968.         case ngx_http_grpc_st_length_3:
  1969.             ctx->rest |= ch;

  1970.             if (ctx->rest > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
  1971.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1972.                               "upstream sent too large http2 frame: %uz",
  1973.                               ctx->rest);
  1974.                 return NGX_ERROR;
  1975.             }

  1976.             state = ngx_http_grpc_st_type;
  1977.             break;

  1978.         case ngx_http_grpc_st_type:
  1979.             ctx->type = ch;
  1980.             state = ngx_http_grpc_st_flags;
  1981.             break;

  1982.         case ngx_http_grpc_st_flags:
  1983.             ctx->flags = ch;
  1984.             state = ngx_http_grpc_st_stream_id;
  1985.             break;

  1986.         case ngx_http_grpc_st_stream_id:
  1987.             ctx->stream_id = (ch & 0x7f) << 24;
  1988.             state = ngx_http_grpc_st_stream_id_2;
  1989.             break;

  1990.         case ngx_http_grpc_st_stream_id_2:
  1991.             ctx->stream_id |= ch << 16;
  1992.             state = ngx_http_grpc_st_stream_id_3;
  1993.             break;

  1994.         case ngx_http_grpc_st_stream_id_3:
  1995.             ctx->stream_id |= ch << 8;
  1996.             state = ngx_http_grpc_st_stream_id_4;
  1997.             break;

  1998.         case ngx_http_grpc_st_stream_id_4:
  1999.             ctx->stream_id |= ch;

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

  2003.             b->pos = p + 1;

  2004.             ctx->state = ngx_http_grpc_st_payload;
  2005.             ctx->frame_state = 0;

  2006.             return NGX_OK;

  2007.         /* suppress warning */
  2008.         case ngx_http_grpc_st_payload:
  2009.         case ngx_http_grpc_st_padding:
  2010.             break;
  2011.         }
  2012.     }

  2013.     b->pos = p;
  2014.     ctx->state = state;

  2015.     return NGX_AGAIN;
  2016. }


  2017. static ngx_int_t
  2018. ngx_http_grpc_parse_header(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2019.     ngx_buf_t *b)
  2020. {
  2021.     u_char     ch, *p, *last;
  2022.     size_t     min;
  2023.     ngx_int_t  rc;
  2024.     enum {
  2025.         sw_start = 0,
  2026.         sw_padding_length,
  2027.         sw_dependency,
  2028.         sw_dependency_2,
  2029.         sw_dependency_3,
  2030.         sw_dependency_4,
  2031.         sw_weight,
  2032.         sw_fragment,
  2033.         sw_padding
  2034.     } state;

  2035.     state = ctx->frame_state;

  2036.     if (state == sw_start) {

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

  2039.         if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME) {
  2040.             ctx->parsing_headers = 1;
  2041.             ctx->fragment_state = 0;

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

  2044.             if (ctx->rest < min) {
  2045.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2046.                               "upstream sent headers frame "
  2047.                               "with invalid length: %uz",
  2048.                               ctx->rest);
  2049.                 return NGX_ERROR;
  2050.             }

  2051.             if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
  2052.                 ctx->end_stream = 1;
  2053.             }

  2054.             if (ctx->flags & NGX_HTTP_V2_PADDED_FLAG) {
  2055.                 state = sw_padding_length;

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

  2058.             } else {
  2059.                 state = sw_fragment;
  2060.             }

  2061.         } else if (ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME) {
  2062.             state = sw_fragment;
  2063.         }

  2064.         ctx->padding = 0;
  2065.         ctx->frame_state = state;
  2066.     }

  2067.     if (state < sw_fragment) {

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

  2070.         } else {
  2071.             last = b->pos + ctx->rest;
  2072.         }

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

  2075. #if 0
  2076.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2077.                            "grpc header byte: %02Xd s:%d", ch, state);
  2078. #endif

  2079.             /*
  2080.              * headers frame:
  2081.              *
  2082.              * +---------------+
  2083.              * |Pad Length? (8)|
  2084.              * +-+-------------+----------------------------------------------+
  2085.              * |E|                 Stream Dependency? (31)                    |
  2086.              * +-+-------------+----------------------------------------------+
  2087.              * |  Weight? (8)  |
  2088.              * +-+-------------+----------------------------------------------+
  2089.              * |                   Header Block Fragment (*)                ...
  2090.              * +--------------------------------------------------------------+
  2091.              * |                           Padding (*)                      ...
  2092.              * +--------------------------------------------------------------+
  2093.              */

  2094.             switch (state) {

  2095.             case sw_padding_length:

  2096.                 ctx->padding = ch;

  2097.                 if (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG) {
  2098.                     state = sw_dependency;
  2099.                     break;
  2100.                 }

  2101.                 goto fragment;

  2102.             case sw_dependency:
  2103.                 state = sw_dependency_2;
  2104.                 break;

  2105.             case sw_dependency_2:
  2106.                 state = sw_dependency_3;
  2107.                 break;

  2108.             case sw_dependency_3:
  2109.                 state = sw_dependency_4;
  2110.                 break;

  2111.             case sw_dependency_4:
  2112.                 state = sw_weight;
  2113.                 break;

  2114.             case sw_weight:
  2115.                 goto fragment;

  2116.             /* suppress warning */
  2117.             case sw_start:
  2118.             case sw_fragment:
  2119.             case sw_padding:
  2120.                 break;
  2121.             }
  2122.         }

  2123.         ctx->rest -= p - b->pos;
  2124.         b->pos = p;

  2125.         ctx->frame_state = state;
  2126.         return NGX_AGAIN;

  2127.     fragment:

  2128.         p++;
  2129.         ctx->rest -= p - b->pos;
  2130.         b->pos = p;

  2131.         if (ctx->padding > ctx->rest) {
  2132.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2133.                           "upstream sent http2 frame with too long "
  2134.                           "padding: %d in frame %uz",
  2135.                           ctx->padding, ctx->rest);
  2136.             return NGX_ERROR;
  2137.         }

  2138.         state = sw_fragment;
  2139.         ctx->frame_state = state;
  2140.     }

  2141.     if (state == sw_fragment) {

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

  2143.         if (rc == NGX_AGAIN) {
  2144.             return NGX_AGAIN;
  2145.         }

  2146.         if (rc == NGX_ERROR) {
  2147.             return NGX_ERROR;
  2148.         }

  2149.         if (rc == NGX_OK) {
  2150.             return NGX_OK;
  2151.         }

  2152.         /* rc == NGX_DONE */

  2153.         state = sw_padding;
  2154.         ctx->frame_state = state;
  2155.     }

  2156.     if (state == sw_padding) {

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

  2158.             ctx->rest -= b->last - b->pos;
  2159.             b->pos = b->last;

  2160.             return NGX_AGAIN;
  2161.         }

  2162.         b->pos += ctx->rest;
  2163.         ctx->rest = 0;

  2164.         ctx->state = ngx_http_grpc_st_start;

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

  2166.             if (ctx->fragment_state) {
  2167.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2168.                               "upstream sent truncated http2 header");
  2169.                 return NGX_ERROR;
  2170.             }

  2171.             ctx->parsing_headers = 0;

  2172.             return NGX_HTTP_PARSE_HEADER_DONE;
  2173.         }

  2174.         return NGX_AGAIN;
  2175.     }

  2176.     /* unreachable */

  2177.     return NGX_ERROR;
  2178. }


  2179. static ngx_int_t
  2180. ngx_http_grpc_parse_fragment(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2181.     ngx_buf_t *b)
  2182. {
  2183.     u_char      ch, *p, *last;
  2184.     size_t      size;
  2185.     ngx_uint_t  index, size_update;
  2186.     enum {
  2187.         sw_start = 0,
  2188.         sw_index,
  2189.         sw_name_length,
  2190.         sw_name_length_2,
  2191.         sw_name_length_3,
  2192.         sw_name_length_4,
  2193.         sw_name,
  2194.         sw_name_bytes,
  2195.         sw_value_length,
  2196.         sw_value_length_2,
  2197.         sw_value_length_3,
  2198.         sw_value_length_4,
  2199.         sw_value,
  2200.         sw_value_bytes
  2201.     } state;

  2202.     /* header block fragment */

  2203. #if 0
  2204.     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2205.                    "grpc header fragment %p:%p rest:%uz",
  2206.                    b->pos, b->last, ctx->rest);
  2207. #endif

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

  2210.     } else {
  2211.         last = b->pos + ctx->rest - ctx->padding;
  2212.     }

  2213.     state = ctx->fragment_state;

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

  2216. #if 0
  2217.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2218.                        "grpc header byte: %02Xd s:%d", ch, state);
  2219. #endif

  2220.         switch (state) {

  2221.         case sw_start:
  2222.             ctx->index = 0;

  2223.             if ((ch & 0x80) == 0x80) {
  2224.                 /*
  2225.                  * indexed header:
  2226.                  *
  2227.                  *   0   1   2   3   4   5   6   7
  2228.                  * +---+---+---+---+---+---+---+---+
  2229.                  * | 1 |        Index (7+)         |
  2230.                  * +---+---------------------------+
  2231.                  */

  2232.                 index = ch & ~0x80;

  2233.                 if (index == 0 || index > 61) {
  2234.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2235.                                   "upstream sent invalid http2 "
  2236.                                   "table index: %ui", index);
  2237.                     return NGX_ERROR;
  2238.                 }

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

  2241.                 ctx->index = index;
  2242.                 ctx->literal = 0;

  2243.                 goto done;

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

  2270.                 index = ch & ~0xc0;

  2271.                 if (index > 61) {
  2272.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2273.                                   "upstream sent invalid http2 "
  2274.                                   "table index: %ui", index);
  2275.                     return NGX_ERROR;
  2276.                 }

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

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

  2283.                 ctx->index = index;
  2284.                 ctx->literal = 1;

  2285.                 state = sw_value_length;
  2286.                 break;

  2287.             } else if ((ch & 0xe0) == 0x20) {
  2288.                 /*
  2289.                  * dynamic table size update:
  2290.                  *
  2291.                  *   0   1   2   3   4   5   6   7
  2292.                  * +---+---+---+---+---+---+---+---+
  2293.                  * | 0 | 0 | 1 |   Max size (5+)   |
  2294.                  * +---+---------------------------+
  2295.                  */

  2296.                 size_update = ch & ~0xe0;

  2297.                 if (size_update > 0) {
  2298.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2299.                                   "upstream sent invalid http2 "
  2300.                                   "dynamic table size update: %ui",
  2301.                                   size_update);
  2302.                     return NGX_ERROR;
  2303.                 }

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

  2306.                 break;

  2307.             } else if ((ch & 0xf0) == 0x10) {
  2308.                 /*
  2309.                  *  literal header field never indexed:
  2310.                  *
  2311.                  *   0   1   2   3   4   5   6   7
  2312.                  * +---+---+---+---+---+---+---+---+
  2313.                  * | 0 | 0 | 0 | 1 |  Index (4+)   |
  2314.                  * +---+---+-----------------------+
  2315.                  * | H |     Value Length (7+)     |
  2316.                  * +---+---------------------------+
  2317.                  * | Value String (Length octets)  |
  2318.                  * +-------------------------------+
  2319.                  *
  2320.                  *   0   1   2   3   4   5   6   7
  2321.                  * +---+---+---+---+---+---+---+---+
  2322.                  * | 0 | 0 | 0 | 1 |       0       |
  2323.                  * +---+---+-----------------------+
  2324.                  * | H |     Name Length (7+)      |
  2325.                  * +---+---------------------------+
  2326.                  * |  Name String (Length octets)  |
  2327.                  * +---+---------------------------+
  2328.                  * | H |     Value Length (7+)     |
  2329.                  * +---+---------------------------+
  2330.                  * | Value String (Length octets)  |
  2331.                  * +-------------------------------+
  2332.                  */

  2333.                 index = ch & ~0xf0;

  2334.                 if (index == 0x0f) {
  2335.                     ctx->index = index;
  2336.                     ctx->literal = 1;
  2337.                     state = sw_index;
  2338.                     break;
  2339.                 }

  2340.                 if (index == 0) {
  2341.                     state = sw_name_length;
  2342.                     break;
  2343.                 }

  2344.                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2345.                                "grpc literal header never indexed: %ui",
  2346.                                index);

  2347.                 ctx->index = index;
  2348.                 ctx->literal = 1;

  2349.                 state = sw_value_length;
  2350.                 break;

  2351.             } else if ((ch & 0xf0) == 0x00) {
  2352.                 /*
  2353.                  * literal header field without indexing:
  2354.                  *
  2355.                  *   0   1   2   3   4   5   6   7
  2356.                  * +---+---+---+---+---+---+---+---+
  2357.                  * | 0 | 0 | 0 | 0 |  Index (4+)   |
  2358.                  * +---+---+-----------------------+
  2359.                  * | H |     Value Length (7+)     |
  2360.                  * +---+---------------------------+
  2361.                  * | Value String (Length octets)  |
  2362.                  * +-------------------------------+
  2363.                  *
  2364.                  *   0   1   2   3   4   5   6   7
  2365.                  * +---+---+---+---+---+---+---+---+
  2366.                  * | 0 | 0 | 0 | 0 |       0       |
  2367.                  * +---+---+-----------------------+
  2368.                  * | H |     Name Length (7+)      |
  2369.                  * +---+---------------------------+
  2370.                  * |  Name String (Length octets)  |
  2371.                  * +---+---------------------------+
  2372.                  * | H |     Value Length (7+)     |
  2373.                  * +---+---------------------------+
  2374.                  * | Value String (Length octets)  |
  2375.                  * +-------------------------------+
  2376.                  */

  2377.                 index = ch & ~0xf0;

  2378.                 if (index == 0x0f) {
  2379.                     ctx->index = index;
  2380.                     ctx->literal = 1;
  2381.                     state = sw_index;
  2382.                     break;
  2383.                 }

  2384.                 if (index == 0) {
  2385.                     state = sw_name_length;
  2386.                     break;
  2387.                 }

  2388.                 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2389.                                "grpc literal header without indexing: %ui",
  2390.                                index);

  2391.                 ctx->index = index;
  2392.                 ctx->literal = 1;

  2393.                 state = sw_value_length;
  2394.                 break;
  2395.             }

  2396.             /* not reached */

  2397.             return NGX_ERROR;

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

  2400.             if (ch & 0x80) {
  2401.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2402.                               "upstream sent http2 table index "
  2403.                               "with continuation flag");
  2404.                 return NGX_ERROR;
  2405.             }

  2406.             if (ctx->index > 61) {
  2407.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2408.                               "upstream sent invalid http2 "
  2409.                               "table index: %ui", ctx->index);
  2410.                 return NGX_ERROR;
  2411.             }

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

  2414.             state = sw_value_length;
  2415.             break;

  2416.         case sw_name_length:
  2417.             ctx->field_huffman = ch & 0x80 ? 1 : 0;
  2418.             ctx->field_length = ch & ~0x80;

  2419.             if (ctx->field_length == 0x7f) {
  2420.                 state = sw_name_length_2;
  2421.                 break;
  2422.             }

  2423.             if (ctx->field_length == 0) {
  2424.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2425.                               "upstream sent zero http2 "
  2426.                               "header name length");
  2427.                 return NGX_ERROR;
  2428.             }

  2429.             state = sw_name;
  2430.             break;

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

  2433.             if (ch & 0x80) {
  2434.                 state = sw_name_length_3;
  2435.                 break;
  2436.             }

  2437.             state = sw_name;
  2438.             break;

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

  2441.             if (ch & 0x80) {
  2442.                 state = sw_name_length_4;
  2443.                 break;
  2444.             }

  2445.             state = sw_name;
  2446.             break;

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

  2449.             if (ch & 0x80) {
  2450.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2451.                               "upstream sent too large http2 "
  2452.                               "header name length");
  2453.                 return NGX_ERROR;
  2454.             }

  2455.             state = sw_name;
  2456.             break;

  2457.         case sw_name:
  2458.             ctx->name.len = ctx->field_huffman ?
  2459.                             ctx->field_length * 8 / 5 : ctx->field_length;

  2460.             ctx->name.data = ngx_pnalloc(r->pool, ctx->name.len + 1);
  2461.             if (ctx->name.data == NULL) {
  2462.                 return NGX_ERROR;
  2463.             }

  2464.             ctx->field_end = ctx->name.data;
  2465.             ctx->field_rest = ctx->field_length;
  2466.             ctx->field_state = 0;

  2467.             state = sw_name_bytes;

  2468.             /* fall through */

  2469.         case sw_name_bytes:

  2470.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2471.                            "grpc name: len:%uz h:%d last:%uz, rest:%uz",
  2472.                            ctx->field_length,
  2473.                            ctx->field_huffman,
  2474.                            last - p,
  2475.                            ctx->rest - (p - b->pos));

  2476.             size = ngx_min(last - p, (ssize_t) ctx->field_rest);
  2477.             ctx->field_rest -= size;

  2478.             if (ctx->field_huffman) {
  2479.                 if (ngx_http_huff_decode(&ctx->field_state, p, size,
  2480.                                          &ctx->field_end,
  2481.                                          ctx->field_rest == 0,
  2482.                                          r->connection->log)
  2483.                     != NGX_OK)
  2484.                 {
  2485.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2486.                                   "upstream sent invalid encoded header");
  2487.                     return NGX_ERROR;
  2488.                 }

  2489.                 ctx->name.len = ctx->field_end - ctx->name.data;
  2490.                 ctx->name.data[ctx->name.len] = '\0';

  2491.             } else {
  2492.                 ctx->field_end = ngx_cpymem(ctx->field_end, p, size);
  2493.                 ctx->name.data[ctx->name.len] = '\0';
  2494.             }

  2495.             p += size - 1;

  2496.             if (ctx->field_rest == 0) {
  2497.                 state = sw_value_length;
  2498.             }

  2499.             break;

  2500.         case sw_value_length:
  2501.             ctx->field_huffman = ch & 0x80 ? 1 : 0;
  2502.             ctx->field_length = ch & ~0x80;

  2503.             if (ctx->field_length == 0x7f) {
  2504.                 state = sw_value_length_2;
  2505.                 break;
  2506.             }

  2507.             if (ctx->field_length == 0) {
  2508.                 ngx_str_set(&ctx->value, "");
  2509.                 goto done;
  2510.             }

  2511.             state = sw_value;
  2512.             break;

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

  2515.             if (ch & 0x80) {
  2516.                 state = sw_value_length_3;
  2517.                 break;
  2518.             }

  2519.             state = sw_value;
  2520.             break;

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

  2523.             if (ch & 0x80) {
  2524.                 state = sw_value_length_4;
  2525.                 break;
  2526.             }

  2527.             state = sw_value;
  2528.             break;

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

  2531.             if (ch & 0x80) {
  2532.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2533.                               "upstream sent too large http2 "
  2534.                               "header value length");
  2535.                 return NGX_ERROR;
  2536.             }

  2537.             state = sw_value;
  2538.             break;

  2539.         case sw_value:
  2540.             ctx->value.len = ctx->field_huffman ?
  2541.                              ctx->field_length * 8 / 5 : ctx->field_length;

  2542.             ctx->value.data = ngx_pnalloc(r->pool, ctx->value.len + 1);
  2543.             if (ctx->value.data == NULL) {
  2544.                 return NGX_ERROR;
  2545.             }

  2546.             ctx->field_end = ctx->value.data;
  2547.             ctx->field_rest = ctx->field_length;
  2548.             ctx->field_state = 0;

  2549.             state = sw_value_bytes;

  2550.             /* fall through */

  2551.         case sw_value_bytes:

  2552.             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2553.                            "grpc value: len:%uz h:%d last:%uz, rest:%uz",
  2554.                            ctx->field_length,
  2555.                            ctx->field_huffman,
  2556.                            last - p,
  2557.                            ctx->rest - (p - b->pos));

  2558.             size = ngx_min(last - p, (ssize_t) ctx->field_rest);
  2559.             ctx->field_rest -= size;

  2560.             if (ctx->field_huffman) {
  2561.                 if (ngx_http_huff_decode(&ctx->field_state, p, size,
  2562.                                          &ctx->field_end,
  2563.                                          ctx->field_rest == 0,
  2564.                                          r->connection->log)
  2565.                     != NGX_OK)
  2566.                 {
  2567.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2568.                                   "upstream sent invalid encoded header");
  2569.                     return NGX_ERROR;
  2570.                 }

  2571.                 ctx->value.len = ctx->field_end - ctx->value.data;
  2572.                 ctx->value.data[ctx->value.len] = '\0';

  2573.             } else {
  2574.                 ctx->field_end = ngx_cpymem(ctx->field_end, p, size);
  2575.                 ctx->value.data[ctx->value.len] = '\0';
  2576.             }

  2577.             p += size - 1;

  2578.             if (ctx->field_rest == 0) {
  2579.                 goto done;
  2580.             }

  2581.             break;
  2582.         }

  2583.         continue;

  2584.     done:

  2585.         p++;
  2586.         ctx->rest -= p - b->pos;
  2587.         ctx->fragment_state = sw_start;
  2588.         b->pos = p;

  2589.         if (ctx->index) {
  2590.             ctx->name = *ngx_http_v2_get_static_name(ctx->index);
  2591.         }

  2592.         if (ctx->index && !ctx->literal) {
  2593.             ctx->value = *ngx_http_v2_get_static_value(ctx->index);
  2594.         }

  2595.         if (!ctx->index) {
  2596.             if (ngx_http_grpc_validate_header_name(r, &ctx->name) != NGX_OK) {
  2597.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2598.                               "upstream sent invalid header: \"%V: %V\"",
  2599.                               &ctx->name, &ctx->value);
  2600.                 return NGX_ERROR;
  2601.             }
  2602.         }

  2603.         if (!ctx->index || ctx->literal) {
  2604.             if (ngx_http_grpc_validate_header_value(r, &ctx->value) != NGX_OK) {
  2605.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2606.                               "upstream sent invalid header: \"%V: %V\"",
  2607.                               &ctx->name, &ctx->value);
  2608.                 return NGX_ERROR;
  2609.             }
  2610.         }

  2611.         return NGX_OK;
  2612.     }

  2613.     ctx->rest -= p - b->pos;
  2614.     ctx->fragment_state = state;
  2615.     b->pos = p;

  2616.     if (ctx->rest > ctx->padding) {
  2617.         return NGX_AGAIN;
  2618.     }

  2619.     return NGX_DONE;
  2620. }


  2621. static ngx_int_t
  2622. ngx_http_grpc_validate_header_name(ngx_http_request_t *r, ngx_str_t *s)
  2623. {
  2624.     u_char      ch;
  2625.     ngx_uint_t  i;

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

  2628.         if (ch == ':' && i > 0) {
  2629.             return NGX_ERROR;
  2630.         }

  2631.         if (ch >= 'A' && ch <= 'Z') {
  2632.             return NGX_ERROR;
  2633.         }

  2634.         if (ch <= 0x20 || ch == 0x7f) {
  2635.             return NGX_ERROR;
  2636.         }
  2637.     }

  2638.     return NGX_OK;
  2639. }


  2640. static ngx_int_t
  2641. ngx_http_grpc_validate_header_value(ngx_http_request_t *r, ngx_str_t *s)
  2642. {
  2643.     u_char      ch;
  2644.     ngx_uint_t  i;

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

  2647.         if (ch == '\0' || ch == CR || ch == LF) {
  2648.             return NGX_ERROR;
  2649.         }
  2650.     }

  2651.     return NGX_OK;
  2652. }


  2653. static ngx_int_t
  2654. ngx_http_grpc_parse_rst_stream(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_error_2,
  2661.         sw_error_3,
  2662.         sw_error_4
  2663.     } state;

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

  2666.     } else {
  2667.         last = b->pos + ctx->rest;
  2668.     }

  2669.     state = ctx->frame_state;

  2670.     if (state == sw_start) {
  2671.         if (ctx->rest != 4) {
  2672.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2673.                           "upstream sent rst stream frame "
  2674.                           "with invalid length: %uz",
  2675.                           ctx->rest);
  2676.             return NGX_ERROR;
  2677.         }
  2678.     }

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

  2681. #if 0
  2682.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2683.                        "grpc rst byte: %02Xd s:%d", ch, state);
  2684. #endif

  2685.         switch (state) {

  2686.         case sw_start:
  2687.             ctx->error = (ngx_uint_t) ch << 24;
  2688.             state = sw_error_2;
  2689.             break;

  2690.         case sw_error_2:
  2691.             ctx->error |= ch << 16;
  2692.             state = sw_error_3;
  2693.             break;

  2694.         case sw_error_3:
  2695.             ctx->error |= ch << 8;
  2696.             state = sw_error_4;
  2697.             break;

  2698.         case sw_error_4:
  2699.             ctx->error |= ch;
  2700.             state = sw_start;

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

  2703.             break;
  2704.         }
  2705.     }

  2706.     ctx->rest -= p - b->pos;
  2707.     ctx->frame_state = state;
  2708.     b->pos = p;

  2709.     if (ctx->rest > 0) {
  2710.         return NGX_AGAIN;
  2711.     }

  2712.     ctx->state = ngx_http_grpc_st_start;

  2713.     return NGX_OK;
  2714. }


  2715. static ngx_int_t
  2716. ngx_http_grpc_parse_goaway(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2717.     ngx_buf_t *b)
  2718. {
  2719.     u_char  ch, *p, *last;
  2720.     enum {
  2721.         sw_start = 0,
  2722.         sw_last_stream_id_2,
  2723.         sw_last_stream_id_3,
  2724.         sw_last_stream_id_4,
  2725.         sw_error,
  2726.         sw_error_2,
  2727.         sw_error_3,
  2728.         sw_error_4,
  2729.         sw_debug
  2730.     } state;

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

  2733.     } else {
  2734.         last = b->pos + ctx->rest;
  2735.     }

  2736.     state = ctx->frame_state;

  2737.     if (state == sw_start) {

  2738.         if (ctx->stream_id) {
  2739.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2740.                           "upstream sent goaway frame "
  2741.                           "with non-zero stream id: %ui",
  2742.                           ctx->stream_id);
  2743.             return NGX_ERROR;
  2744.         }

  2745.         if (ctx->rest < 8) {
  2746.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2747.                           "upstream sent goaway frame "
  2748.                           "with invalid length: %uz",
  2749.                           ctx->rest);
  2750.             return NGX_ERROR;
  2751.         }
  2752.     }

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

  2755. #if 0
  2756.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2757.                        "grpc goaway byte: %02Xd s:%d", ch, state);
  2758. #endif

  2759.         switch (state) {

  2760.         case sw_start:
  2761.             ctx->stream_id = (ch & 0x7f) << 24;
  2762.             state = sw_last_stream_id_2;
  2763.             break;

  2764.         case sw_last_stream_id_2:
  2765.             ctx->stream_id |= ch << 16;
  2766.             state = sw_last_stream_id_3;
  2767.             break;

  2768.         case sw_last_stream_id_3:
  2769.             ctx->stream_id |= ch << 8;
  2770.             state = sw_last_stream_id_4;
  2771.             break;

  2772.         case sw_last_stream_id_4:
  2773.             ctx->stream_id |= ch;
  2774.             state = sw_error;
  2775.             break;

  2776.         case sw_error:
  2777.             ctx->error = (ngx_uint_t) ch << 24;
  2778.             state = sw_error_2;
  2779.             break;

  2780.         case sw_error_2:
  2781.             ctx->error |= ch << 16;
  2782.             state = sw_error_3;
  2783.             break;

  2784.         case sw_error_3:
  2785.             ctx->error |= ch << 8;
  2786.             state = sw_error_4;
  2787.             break;

  2788.         case sw_error_4:
  2789.             ctx->error |= ch;
  2790.             state = sw_debug;
  2791.             break;

  2792.         case sw_debug:
  2793.             break;
  2794.         }
  2795.     }

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

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

  2802.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2803.                    "grpc goaway: %ui, stream %ui",
  2804.                    ctx->error, ctx->stream_id);

  2805.     ctx->state = ngx_http_grpc_st_start;

  2806.     return NGX_OK;
  2807. }


  2808. static ngx_int_t
  2809. ngx_http_grpc_parse_window_update(ngx_http_request_t *r,
  2810.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b)
  2811. {
  2812.     u_char  ch, *p, *last;
  2813.     enum {
  2814.         sw_start = 0,
  2815.         sw_size_2,
  2816.         sw_size_3,
  2817.         sw_size_4
  2818.     } state;

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

  2821.     } else {
  2822.         last = b->pos + ctx->rest;
  2823.     }

  2824.     state = ctx->frame_state;

  2825.     if (state == sw_start) {
  2826.         if (ctx->rest != 4) {
  2827.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2828.                           "upstream sent window update frame "
  2829.                           "with invalid length: %uz",
  2830.                           ctx->rest);
  2831.             return NGX_ERROR;
  2832.         }
  2833.     }

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

  2836. #if 0
  2837.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2838.                        "grpc window update byte: %02Xd s:%d", ch, state);
  2839. #endif

  2840.         switch (state) {

  2841.         case sw_start:
  2842.             ctx->window_update = (ch & 0x7f) << 24;
  2843.             state = sw_size_2;
  2844.             break;

  2845.         case sw_size_2:
  2846.             ctx->window_update |= ch << 16;
  2847.             state = sw_size_3;
  2848.             break;

  2849.         case sw_size_3:
  2850.             ctx->window_update |= ch << 8;
  2851.             state = sw_size_4;
  2852.             break;

  2853.         case sw_size_4:
  2854.             ctx->window_update |= ch;
  2855.             state = sw_start;
  2856.             break;
  2857.         }
  2858.     }

  2859.     ctx->rest -= p - b->pos;
  2860.     ctx->frame_state = state;
  2861.     b->pos = p;

  2862.     if (ctx->rest > 0) {
  2863.         return NGX_AGAIN;
  2864.     }

  2865.     ctx->state = ngx_http_grpc_st_start;

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

  2868.     if (ctx->stream_id) {

  2869.         if (ctx->window_update > (size_t) NGX_HTTP_V2_MAX_WINDOW
  2870.                                  - ctx->send_window)
  2871.         {
  2872.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2873.                           "upstream sent too large window update");
  2874.             return NGX_ERROR;
  2875.         }

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

  2877.     } else {

  2878.         if (ctx->window_update > NGX_HTTP_V2_MAX_WINDOW
  2879.                                  - ctx->connection->send_window)
  2880.         {
  2881.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2882.                           "upstream sent too large window update");
  2883.             return NGX_ERROR;
  2884.         }

  2885.         ctx->connection->send_window += ctx->window_update;
  2886.     }

  2887.     return NGX_OK;
  2888. }


  2889. static ngx_int_t
  2890. ngx_http_grpc_parse_settings(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
  2891.     ngx_buf_t *b)
  2892. {
  2893.     u_char   ch, *p, *last;
  2894.     ssize_t  window_update;
  2895.     enum {
  2896.         sw_start = 0,
  2897.         sw_id,
  2898.         sw_id_2,
  2899.         sw_value,
  2900.         sw_value_2,
  2901.         sw_value_3,
  2902.         sw_value_4
  2903.     } state;

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

  2906.     } else {
  2907.         last = b->pos + ctx->rest;
  2908.     }

  2909.     state = ctx->frame_state;

  2910.     if (state == sw_start) {

  2911.         if (ctx->stream_id) {
  2912.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2913.                           "upstream sent settings frame "
  2914.                           "with non-zero stream id: %ui",
  2915.                           ctx->stream_id);
  2916.             return NGX_ERROR;
  2917.         }

  2918.         if (ctx->flags & NGX_HTTP_V2_ACK_FLAG) {
  2919.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2920.                            "grpc settings ack");

  2921.             if (ctx->rest != 0) {
  2922.                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2923.                               "upstream sent settings frame "
  2924.                               "with ack flag and non-zero length: %uz",
  2925.                               ctx->rest);
  2926.                 return NGX_ERROR;
  2927.             }

  2928.             ctx->state = ngx_http_grpc_st_start;

  2929.             return NGX_OK;
  2930.         }

  2931.         if (ctx->rest % 6 != 0) {
  2932.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2933.                           "upstream sent settings frame "
  2934.                           "with invalid length: %uz",
  2935.                           ctx->rest);
  2936.             return NGX_ERROR;
  2937.         }

  2938.         if (ctx->free == NULL && ctx->settings++ > 1000) {
  2939.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2940.                           "upstream sent too many settings frames");
  2941.             return NGX_ERROR;
  2942.         }
  2943.     }

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

  2946. #if 0
  2947.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2948.                        "grpc settings byte: %02Xd s:%d", ch, state);
  2949. #endif

  2950.         switch (state) {

  2951.         case sw_start:
  2952.         case sw_id:
  2953.             ctx->setting_id = ch << 8;
  2954.             state = sw_id_2;
  2955.             break;

  2956.         case sw_id_2:
  2957.             ctx->setting_id |= ch;
  2958.             state = sw_value;
  2959.             break;

  2960.         case sw_value:
  2961.             ctx->setting_value = (ngx_uint_t) ch << 24;
  2962.             state = sw_value_2;
  2963.             break;

  2964.         case sw_value_2:
  2965.             ctx->setting_value |= ch << 16;
  2966.             state = sw_value_3;
  2967.             break;

  2968.         case sw_value_3:
  2969.             ctx->setting_value |= ch << 8;
  2970.             state = sw_value_4;
  2971.             break;

  2972.         case sw_value_4:
  2973.             ctx->setting_value |= ch;
  2974.             state = sw_id;

  2975.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2976.                            "grpc setting: %ui %ui",
  2977.                            ctx->setting_id, ctx->setting_value);

  2978.             /*
  2979.              * The following settings are defined by the protocol:
  2980.              *
  2981.              * SETTINGS_HEADER_TABLE_SIZE, SETTINGS_ENABLE_PUSH,
  2982.              * SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE,
  2983.              * SETTINGS_MAX_FRAME_SIZE, SETTINGS_MAX_HEADER_LIST_SIZE
  2984.              *
  2985.              * Only SETTINGS_INITIAL_WINDOW_SIZE seems to be needed in
  2986.              * a simple client.
  2987.              */

  2988.             if (ctx->setting_id == 0x04) {
  2989.                 /* SETTINGS_INITIAL_WINDOW_SIZE */

  2990.                 if (ctx->setting_value > NGX_HTTP_V2_MAX_WINDOW) {
  2991.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  2992.                                   "upstream sent settings frame "
  2993.                                   "with too large initial window size: %ui",
  2994.                                   ctx->setting_value);
  2995.                     return NGX_ERROR;
  2996.                 }

  2997.                 window_update = ctx->setting_value
  2998.                                 - ctx->connection->init_window;
  2999.                 ctx->connection->init_window = ctx->setting_value;

  3000.                 if (ctx->send_window > 0
  3001.                     && window_update > (ssize_t) NGX_HTTP_V2_MAX_WINDOW
  3002.                                        - ctx->send_window)
  3003.                 {
  3004.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3005.                                   "upstream sent settings frame "
  3006.                                   "with too large initial window size: %ui",
  3007.                                   ctx->setting_value);
  3008.                     return NGX_ERROR;
  3009.                 }

  3010.                 ctx->send_window += window_update;
  3011.             }

  3012.             break;
  3013.         }
  3014.     }

  3015.     ctx->rest -= p - b->pos;
  3016.     ctx->frame_state = state;
  3017.     b->pos = p;

  3018.     if (ctx->rest > 0) {
  3019.         return NGX_AGAIN;
  3020.     }

  3021.     ctx->state = ngx_http_grpc_st_start;

  3022.     return ngx_http_grpc_send_settings_ack(r, ctx);
  3023. }


  3024. static ngx_int_t
  3025. ngx_http_grpc_parse_ping(ngx_http_request_t *r,
  3026.     ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b)
  3027. {
  3028.     u_char  ch, *p, *last;
  3029.     enum {
  3030.         sw_start = 0,
  3031.         sw_data_2,
  3032.         sw_data_3,
  3033.         sw_data_4,
  3034.         sw_data_5,
  3035.         sw_data_6,
  3036.         sw_data_7,
  3037.         sw_data_8
  3038.     } state;

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

  3041.     } else {
  3042.         last = b->pos + ctx->rest;
  3043.     }

  3044.     state = ctx->frame_state;

  3045.     if (state == sw_start) {

  3046.         if (ctx->stream_id) {
  3047.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3048.                           "upstream sent ping frame "
  3049.                           "with non-zero stream id: %ui",
  3050.                           ctx->stream_id);
  3051.             return NGX_ERROR;
  3052.         }

  3053.         if (ctx->rest != 8) {
  3054.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3055.                           "upstream sent ping frame "
  3056.                           "with invalid length: %uz",
  3057.                           ctx->rest);
  3058.             return NGX_ERROR;
  3059.         }

  3060.         if (ctx->flags & NGX_HTTP_V2_ACK_FLAG) {
  3061.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3062.                           "upstream sent ping frame with ack flag");
  3063.             return NGX_ERROR;
  3064.         }

  3065.         if (ctx->free == NULL && ctx->pings++ > 1000) {
  3066.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  3067.                           "upstream sent too many ping frames");
  3068.             return NGX_ERROR;
  3069.         }
  3070.     }

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

  3073. #if 0
  3074.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3075.                        "grpc ping byte: %02Xd s:%d", ch, state);
  3076. #endif

  3077.         if (state < sw_data_8) {
  3078.             ctx->ping_data[state] = ch;
  3079.             state++;

  3080.         } else {
  3081.             ctx->ping_data[7] = ch;
  3082.             state = sw_start;

  3083.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3084.                            "grpc ping");
  3085.         }
  3086.     }

  3087.     ctx->rest -= p - b->pos;
  3088.     ctx->frame_state = state;
  3089.     b->pos = p;

  3090.     if (ctx->rest > 0) {
  3091.         return NGX_AGAIN;
  3092.     }

  3093.     ctx->state = ngx_http_grpc_st_start;

  3094.     return ngx_http_grpc_send_ping_ack(r, ctx);
  3095. }


  3096. static ngx_int_t
  3097. ngx_http_grpc_send_settings_ack(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
  3098. {
  3099.     ngx_chain_t            *cl, **ll;
  3100.     ngx_http_grpc_frame_t  *f;

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

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

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

  3110.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3111.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3112.     f->length_0 = 0;
  3113.     f->length_1 = 0;
  3114.     f->length_2 = 0;
  3115.     f->type = NGX_HTTP_V2_SETTINGS_FRAME;
  3116.     f->flags = NGX_HTTP_V2_ACK_FLAG;
  3117.     f->stream_id_0 = 0;
  3118.     f->stream_id_1 = 0;
  3119.     f->stream_id_2 = 0;
  3120.     f->stream_id_3 = 0;

  3121.     *ll = cl;

  3122.     return NGX_OK;
  3123. }


  3124. static ngx_int_t
  3125. ngx_http_grpc_send_ping_ack(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
  3126. {
  3127.     ngx_chain_t            *cl, **ll;
  3128.     ngx_http_grpc_frame_t  *f;

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

  3131.     for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
  3132.         ll = &cl->next;
  3133.     }

  3134.     cl = ngx_http_grpc_get_buf(r, ctx);
  3135.     if (cl == NULL) {
  3136.         return NGX_ERROR;
  3137.     }

  3138.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3139.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3140.     f->length_0 = 0;
  3141.     f->length_1 = 0;
  3142.     f->length_2 = 8;
  3143.     f->type = NGX_HTTP_V2_PING_FRAME;
  3144.     f->flags = NGX_HTTP_V2_ACK_FLAG;
  3145.     f->stream_id_0 = 0;
  3146.     f->stream_id_1 = 0;
  3147.     f->stream_id_2 = 0;
  3148.     f->stream_id_3 = 0;

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

  3150.     *ll = cl;

  3151.     return NGX_OK;
  3152. }


  3153. static ngx_int_t
  3154. ngx_http_grpc_send_window_update(ngx_http_request_t *r,
  3155.     ngx_http_grpc_ctx_t *ctx)
  3156. {
  3157.     size_t                  n;
  3158.     ngx_chain_t            *cl, **ll;
  3159.     ngx_http_grpc_frame_t  *f;

  3160.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3161.                    "grpc send window update: %uz %uz",
  3162.                    ctx->connection->recv_window, ctx->recv_window);

  3163.     for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
  3164.         ll = &cl->next;
  3165.     }

  3166.     cl = ngx_http_grpc_get_buf(r, ctx);
  3167.     if (cl == NULL) {
  3168.         return NGX_ERROR;
  3169.     }

  3170.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3171.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3172.     f->length_0 = 0;
  3173.     f->length_1 = 0;
  3174.     f->length_2 = 4;
  3175.     f->type = NGX_HTTP_V2_WINDOW_UPDATE_FRAME;
  3176.     f->flags = 0;
  3177.     f->stream_id_0 = 0;
  3178.     f->stream_id_1 = 0;
  3179.     f->stream_id_2 = 0;
  3180.     f->stream_id_3 = 0;

  3181.     n = NGX_HTTP_V2_MAX_WINDOW - ctx->connection->recv_window;
  3182.     ctx->connection->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3183.     *cl->buf->last++ = (u_char) ((n >> 24) & 0xff);
  3184.     *cl->buf->last++ = (u_char) ((n >> 16) & 0xff);
  3185.     *cl->buf->last++ = (u_char) ((n >> 8) & 0xff);
  3186.     *cl->buf->last++ = (u_char) (n & 0xff);

  3187.     f = (ngx_http_grpc_frame_t *) cl->buf->last;
  3188.     cl->buf->last += sizeof(ngx_http_grpc_frame_t);

  3189.     f->length_0 = 0;
  3190.     f->length_1 = 0;
  3191.     f->length_2 = 4;
  3192.     f->type = NGX_HTTP_V2_WINDOW_UPDATE_FRAME;
  3193.     f->flags = 0;
  3194.     f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
  3195.     f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
  3196.     f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
  3197.     f->stream_id_3 = (u_char) (ctx->id & 0xff);

  3198.     n = NGX_HTTP_V2_MAX_WINDOW - ctx->recv_window;
  3199.     ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3200.     *cl->buf->last++ = (u_char) ((n >> 24) & 0xff);
  3201.     *cl->buf->last++ = (u_char) ((n >> 16) & 0xff);
  3202.     *cl->buf->last++ = (u_char) ((n >> 8) & 0xff);
  3203.     *cl->buf->last++ = (u_char) (n & 0xff);

  3204.     *ll = cl;

  3205.     return NGX_OK;
  3206. }


  3207. static ngx_chain_t *
  3208. ngx_http_grpc_get_buf(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
  3209. {
  3210.     u_char       *start;
  3211.     ngx_buf_t    *b;
  3212.     ngx_chain_t  *cl;

  3213.     cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
  3214.     if (cl == NULL) {
  3215.         return NULL;
  3216.     }

  3217.     b = cl->buf;
  3218.     start = b->start;

  3219.     if (start == NULL) {

  3220.         /*
  3221.          * each buffer is large enough to hold two window update
  3222.          * frames in a row
  3223.          */

  3224.         start = ngx_palloc(r->pool, 2 * sizeof(ngx_http_grpc_frame_t) + 8);
  3225.         if (start == NULL) {
  3226.             return NULL;
  3227.         }

  3228.     }

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

  3230.     b->start = start;
  3231.     b->pos = start;
  3232.     b->last = start;
  3233.     b->end = start + 2 * sizeof(ngx_http_grpc_frame_t) + 8;

  3234.     b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
  3235.     b->temporary = 1;
  3236.     b->flush = 1;

  3237.     return cl;
  3238. }


  3239. static ngx_http_grpc_ctx_t *
  3240. ngx_http_grpc_get_ctx(ngx_http_request_t *r)
  3241. {
  3242.     ngx_http_grpc_ctx_t  *ctx;
  3243.     ngx_http_upstream_t  *u;

  3244.     ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);

  3245.     if (ctx->connection == NULL) {
  3246.         u = r->upstream;

  3247.         if (ngx_http_grpc_get_connection_data(r, ctx, &u->peer) != NGX_OK) {
  3248.             return NULL;
  3249.         }
  3250.     }

  3251.     return ctx;
  3252. }


  3253. static ngx_int_t
  3254. ngx_http_grpc_get_connection_data(ngx_http_request_t *r,
  3255.     ngx_http_grpc_ctx_t *ctx, ngx_peer_connection_t *pc)
  3256. {
  3257.     ngx_connection_t    *c;
  3258.     ngx_pool_cleanup_t  *cln;

  3259.     c = pc->connection;

  3260.     if (pc->cached) {

  3261.         /*
  3262.          * for cached connections, connection data can be found
  3263.          * in the cleanup handler
  3264.          */

  3265.         for (cln = c->pool->cleanup; cln; cln = cln->next) {
  3266.             if (cln->handler == ngx_http_grpc_cleanup) {
  3267.                 ctx->connection = cln->data;
  3268.                 break;
  3269.             }
  3270.         }

  3271.         if (ctx->connection == NULL) {
  3272.             ngx_log_error(NGX_LOG_ERR, c->log, 0,
  3273.                           "no connection data found for "
  3274.                           "keepalive http2 connection");
  3275.             return NGX_ERROR;
  3276.         }

  3277.         ctx->send_window = ctx->connection->init_window;
  3278.         ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3279.         ctx->connection->last_stream_id += 2;
  3280.         ctx->id = ctx->connection->last_stream_id;

  3281.         return NGX_OK;
  3282.     }

  3283.     cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_http_grpc_conn_t));
  3284.     if (cln == NULL) {
  3285.         return NGX_ERROR;
  3286.     }

  3287.     cln->handler = ngx_http_grpc_cleanup;
  3288.     ctx->connection = cln->data;

  3289.     ctx->connection->init_window = NGX_HTTP_V2_DEFAULT_WINDOW;
  3290.     ctx->connection->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
  3291.     ctx->connection->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3292.     ctx->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
  3293.     ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;

  3294.     ctx->id = 1;
  3295.     ctx->connection->last_stream_id = 1;

  3296.     return NGX_OK;
  3297. }


  3298. static void
  3299. ngx_http_grpc_cleanup(void *data)
  3300. {
  3301. #if 0
  3302.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  3303.                    "grpc cleanup");
  3304. #endif
  3305.     return;
  3306. }


  3307. static void
  3308. ngx_http_grpc_abort_request(ngx_http_request_t *r)
  3309. {
  3310.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3311.                    "abort grpc request");
  3312.     return;
  3313. }


  3314. static void
  3315. ngx_http_grpc_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
  3316. {
  3317.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  3318.                    "finalize grpc request");
  3319.     return;
  3320. }


  3321. static ngx_int_t
  3322. ngx_http_grpc_internal_trailers_variable(ngx_http_request_t *r,
  3323.     ngx_http_variable_value_t *v, uintptr_t data)
  3324. {
  3325.     ngx_table_elt_t  *te;

  3326.     te = r->headers_in.te;

  3327.     if (te == NULL) {
  3328.         v->not_found = 1;
  3329.         return NGX_OK;
  3330.     }

  3331.     if (ngx_strlcasestrn(te->value.data, te->value.data + te->value.len,
  3332.                          (u_char *) "trailers", 8 - 1)
  3333.         == NULL)
  3334.     {
  3335.         v->not_found = 1;
  3336.         return NGX_OK;
  3337.     }

  3338.     v->valid = 1;
  3339.     v->no_cacheable = 0;
  3340.     v->not_found = 0;

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

  3343.     return NGX_OK;
  3344. }


  3345. static ngx_int_t
  3346. ngx_http_grpc_add_variables(ngx_conf_t *cf)
  3347. {
  3348.     ngx_http_variable_t  *var, *v;

  3349.     for (v = ngx_http_grpc_vars; v->name.len; v++) {
  3350.         var = ngx_http_add_variable(cf, &v->name, v->flags);
  3351.         if (var == NULL) {
  3352.             return NGX_ERROR;
  3353.         }

  3354.         var->get_handler = v->get_handler;
  3355.         var->data = v->data;
  3356.     }

  3357.     return NGX_OK;
  3358. }


  3359. static void *
  3360. ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
  3361. {
  3362.     ngx_http_grpc_loc_conf_t  *conf;

  3363.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_grpc_loc_conf_t));
  3364.     if (conf == NULL) {
  3365.         return NULL;
  3366.     }

  3367.     /*
  3368.      * set by ngx_pcalloc():
  3369.      *
  3370.      *     conf->upstream.ignore_headers = 0;
  3371.      *     conf->upstream.next_upstream = 0;
  3372.      *     conf->upstream.hide_headers_hash = { NULL, 0 };
  3373.      *
  3374.      *     conf->headers.lengths = NULL;
  3375.      *     conf->headers.values = NULL;
  3376.      *     conf->headers.hash = { NULL, 0 };
  3377.      *     conf->host = { 0, NULL };
  3378.      *     conf->host_set = 0;
  3379.      *     conf->ssl = 0;
  3380.      *     conf->ssl_protocols = 0;
  3381.      *     conf->ssl_ciphers = { 0, NULL };
  3382.      *     conf->ssl_trusted_certificate = { 0, NULL };
  3383.      *     conf->ssl_crl = { 0, NULL };
  3384.      */

  3385.     conf->upstream.local = NGX_CONF_UNSET_PTR;
  3386.     conf->upstream.socket_keepalive = NGX_CONF_UNSET;
  3387.     conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
  3388.     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
  3389.     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
  3390.     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
  3391.     conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;

  3392.     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;

  3393.     conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
  3394.     conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;

  3395.     conf->upstream.intercept_errors = NGX_CONF_UNSET;

  3396. #if (NGX_HTTP_SSL)
  3397.     conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
  3398.     conf->upstream.ssl_name = NGX_CONF_UNSET_PTR;
  3399.     conf->upstream.ssl_server_name = NGX_CONF_UNSET;
  3400.     conf->upstream.ssl_verify = NGX_CONF_UNSET;
  3401.     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
  3402.     conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR;
  3403.     conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR;
  3404.     conf->upstream.ssl_certificate_cache = NGX_CONF_UNSET_PTR;
  3405.     conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR;
  3406.     conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
  3407. #endif

  3408.     /* the hardcoded values */
  3409.     conf->upstream.cyclic_temp_file = 0;
  3410.     conf->upstream.buffering = 0;
  3411.     conf->upstream.ignore_client_abort = 0;
  3412.     conf->upstream.send_lowat = 0;
  3413.     conf->upstream.bufs.num = 0;
  3414.     conf->upstream.busy_buffers_size = 0;
  3415.     conf->upstream.max_temp_file_size = 0;
  3416.     conf->upstream.temp_file_write_size = 0;
  3417.     conf->upstream.pass_request_headers = 1;
  3418.     conf->upstream.pass_request_body = 1;
  3419.     conf->upstream.force_ranges = 0;
  3420.     conf->upstream.pass_trailers = 1;
  3421.     conf->upstream.pass_early_hints = 1;
  3422.     conf->upstream.preserve_output = 1;

  3423.     conf->headers_source = NGX_CONF_UNSET_PTR;

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

  3425.     return conf;
  3426. }


  3427. static char *
  3428. ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  3429. {
  3430.     ngx_http_grpc_loc_conf_t *prev = parent;
  3431.     ngx_http_grpc_loc_conf_t *conf = child;

  3432.     ngx_int_t                  rc;
  3433.     ngx_hash_init_t            hash;
  3434.     ngx_http_core_loc_conf_t  *clcf;

  3435.     ngx_conf_merge_ptr_value(conf->upstream.local,
  3436.                               prev->upstream.local, NULL);

  3437.     ngx_conf_merge_value(conf->upstream.socket_keepalive,
  3438.                               prev->upstream.socket_keepalive, 0);

  3439.     ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
  3440.                               prev->upstream.next_upstream_tries, 0);

  3441.     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
  3442.                               prev->upstream.connect_timeout, 60000);

  3443.     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
  3444.                               prev->upstream.send_timeout, 60000);

  3445.     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
  3446.                               prev->upstream.read_timeout, 60000);

  3447.     ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
  3448.                               prev->upstream.next_upstream_timeout, 0);

  3449.     ngx_conf_merge_size_value(conf->upstream.buffer_size,
  3450.                               prev->upstream.buffer_size,
  3451.                               (size_t) ngx_pagesize);

  3452.     ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
  3453.                               prev->upstream.ignore_headers,
  3454.                               NGX_CONF_BITMASK_SET);

  3455.     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
  3456.                               prev->upstream.next_upstream,
  3457.                               (NGX_CONF_BITMASK_SET
  3458.                                |NGX_HTTP_UPSTREAM_FT_ERROR
  3459.                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

  3460.     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
  3461.         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
  3462.                                        |NGX_HTTP_UPSTREAM_FT_OFF;
  3463.     }

  3464.     ngx_conf_merge_value(conf->upstream.intercept_errors,
  3465.                               prev->upstream.intercept_errors, 0);

  3466. #if (NGX_HTTP_SSL)

  3467.     if (ngx_http_grpc_merge_ssl(cf, conf, prev) != NGX_OK) {
  3468.         return NGX_CONF_ERROR;
  3469.     }

  3470.     ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
  3471.                               prev->upstream.ssl_session_reuse, 1);

  3472.     ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
  3473.                               (NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));

  3474.     ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
  3475.                              "DEFAULT");

  3476.     ngx_conf_merge_ptr_value(conf->upstream.ssl_name,
  3477.                               prev->upstream.ssl_name, NULL);
  3478.     ngx_conf_merge_value(conf->upstream.ssl_server_name,
  3479.                               prev->upstream.ssl_server_name, 0);
  3480.     ngx_conf_merge_value(conf->upstream.ssl_verify,
  3481.                               prev->upstream.ssl_verify, 0);
  3482.     ngx_conf_merge_uint_value(conf->ssl_verify_depth,
  3483.                               prev->ssl_verify_depth, 1);
  3484.     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
  3485.                               prev->ssl_trusted_certificate, "");
  3486.     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");

  3487.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate,
  3488.                               prev->upstream.ssl_certificate, NULL);
  3489.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key,
  3490.                               prev->upstream.ssl_certificate_key, NULL);
  3491.     ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_cache,
  3492.                               prev->upstream.ssl_certificate_cache, NULL);

  3493.     if (ngx_http_upstream_merge_ssl_passwords(cf, &conf->upstream,
  3494.                                               &prev->upstream)
  3495.         != NGX_OK)
  3496.     {
  3497.         return NGX_CONF_ERROR;
  3498.     }

  3499.     ngx_conf_merge_ptr_value(conf->ssl_conf_commands,
  3500.                               prev->ssl_conf_commands, NULL);

  3501.     if (conf->ssl && ngx_http_grpc_set_ssl(cf, conf) != NGX_OK) {
  3502.         return NGX_CONF_ERROR;
  3503.     }

  3504. #endif

  3505.     hash.max_size = 512;
  3506.     hash.bucket_size = ngx_align(64, ngx_cacheline_size);
  3507.     hash.name = "grpc_headers_hash";

  3508.     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
  3509.             &prev->upstream, ngx_http_grpc_hide_headers, &hash)
  3510.         != NGX_OK)
  3511.     {
  3512.         return NGX_CONF_ERROR;
  3513.     }

  3514.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

  3515.     if (clcf->noname
  3516.         && conf->upstream.upstream == NULL && conf->grpc_lengths == NULL)
  3517.     {
  3518.         conf->upstream.upstream = prev->upstream.upstream;
  3519.         conf->host = prev->host;

  3520.         conf->grpc_lengths = prev->grpc_lengths;
  3521.         conf->grpc_values = prev->grpc_values;

  3522. #if (NGX_HTTP_SSL)
  3523.         conf->ssl = prev->ssl;
  3524. #endif
  3525.     }

  3526.     if (clcf->lmt_excpt && clcf->handler == NULL
  3527.         && (conf->upstream.upstream || conf->grpc_lengths))
  3528.     {
  3529.         clcf->handler = ngx_http_grpc_handler;
  3530.     }

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

  3532.     if (conf->headers_source == prev->headers_source) {
  3533.         conf->headers = prev->headers;
  3534.         conf->host_set = prev->host_set;
  3535.     }

  3536.     rc = ngx_http_grpc_init_headers(cf, conf, &conf->headers,
  3537.                                     ngx_http_grpc_headers);
  3538.     if (rc != NGX_OK) {
  3539.         return NGX_CONF_ERROR;
  3540.     }

  3541.     /*
  3542.      * special handling to preserve conf->headers in the "http" section
  3543.      * to inherit it to all servers
  3544.      */

  3545.     if (prev->headers.hash.buckets == NULL
  3546.         && conf->headers_source == prev->headers_source)
  3547.     {
  3548.         prev->headers = conf->headers;
  3549.         prev->host_set = conf->host_set;
  3550.     }

  3551.     return NGX_CONF_OK;
  3552. }


  3553. static ngx_int_t
  3554. ngx_http_grpc_init_headers(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf,
  3555.     ngx_http_grpc_headers_t *headers, ngx_keyval_t *default_headers)
  3556. {
  3557.     u_char                       *p;
  3558.     size_t                        size;
  3559.     uintptr_t                    *code;
  3560.     ngx_uint_t                    i;
  3561.     ngx_array_t                   headers_names, headers_merged;
  3562.     ngx_keyval_t                 *src, *s, *h;
  3563.     ngx_hash_key_t               *hk;
  3564.     ngx_hash_init_t               hash;
  3565.     ngx_http_script_compile_t     sc;
  3566.     ngx_http_script_copy_code_t  *copy;

  3567.     if (headers->hash.buckets) {
  3568.         return NGX_OK;
  3569.     }

  3570.     if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
  3571.         != NGX_OK)
  3572.     {
  3573.         return NGX_ERROR;
  3574.     }

  3575.     if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
  3576.         != NGX_OK)
  3577.     {
  3578.         return NGX_ERROR;
  3579.     }

  3580.     headers->lengths = ngx_array_create(cf->pool, 64, 1);
  3581.     if (headers->lengths == NULL) {
  3582.         return NGX_ERROR;
  3583.     }

  3584.     headers->values = ngx_array_create(cf->pool, 512, 1);
  3585.     if (headers->values == NULL) {
  3586.         return NGX_ERROR;
  3587.     }

  3588.     if (conf->headers_source) {

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

  3591.             if (src[i].key.len == 4
  3592.                 && ngx_strncasecmp(src[i].key.data, (u_char *) "Host", 4) == 0)
  3593.             {
  3594.                 conf->host_set = 1;
  3595.             }

  3596.             s = ngx_array_push(&headers_merged);
  3597.             if (s == NULL) {
  3598.                 return NGX_ERROR;
  3599.             }

  3600.             *s = src[i];
  3601.         }
  3602.     }

  3603.     h = default_headers;

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

  3605.         src = headers_merged.elts;
  3606.         for (i = 0; i < headers_merged.nelts; i++) {
  3607.             if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
  3608.                 goto next;
  3609.             }
  3610.         }

  3611.         s = ngx_array_push(&headers_merged);
  3612.         if (s == NULL) {
  3613.             return NGX_ERROR;
  3614.         }

  3615.         *s = *h;

  3616.     next:

  3617.         h++;
  3618.     }


  3619.     src = headers_merged.elts;
  3620.     for (i = 0; i < headers_merged.nelts; i++) {

  3621.         hk = ngx_array_push(&headers_names);
  3622.         if (hk == NULL) {
  3623.             return NGX_ERROR;
  3624.         }

  3625.         hk->key = src[i].key;
  3626.         hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
  3627.         hk->value = (void *) 1;

  3628.         if (src[i].value.len == 0) {
  3629.             continue;
  3630.         }

  3631.         copy = ngx_array_push_n(headers->lengths,
  3632.                                 sizeof(ngx_http_script_copy_code_t));
  3633.         if (copy == NULL) {
  3634.             return NGX_ERROR;
  3635.         }

  3636.         copy->code = (ngx_http_script_code_pt) (void *)
  3637.                                                  ngx_http_script_copy_len_code;
  3638.         copy->len = src[i].key.len;

  3639.         size = (sizeof(ngx_http_script_copy_code_t)
  3640.                 + src[i].key.len + sizeof(uintptr_t) - 1)
  3641.                & ~(sizeof(uintptr_t) - 1);

  3642.         copy = ngx_array_push_n(headers->values, size);
  3643.         if (copy == NULL) {
  3644.             return NGX_ERROR;
  3645.         }

  3646.         copy->code = ngx_http_script_copy_code;
  3647.         copy->len = src[i].key.len;

  3648.         p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
  3649.         ngx_memcpy(p, src[i].key.data, src[i].key.len);

  3650.         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  3651.         sc.cf = cf;
  3652.         sc.source = &src[i].value;
  3653.         sc.flushes = &headers->flushes;
  3654.         sc.lengths = &headers->lengths;
  3655.         sc.values = &headers->values;

  3656.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  3657.             return NGX_ERROR;
  3658.         }

  3659.         code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
  3660.         if (code == NULL) {
  3661.             return NGX_ERROR;
  3662.         }

  3663.         *code = (uintptr_t) NULL;

  3664.         code = ngx_array_push_n(headers->values, sizeof(uintptr_t));
  3665.         if (code == NULL) {
  3666.             return NGX_ERROR;
  3667.         }

  3668.         *code = (uintptr_t) NULL;
  3669.     }

  3670.     code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
  3671.     if (code == NULL) {
  3672.         return NGX_ERROR;
  3673.     }

  3674.     *code = (uintptr_t) NULL;


  3675.     hash.hash = &headers->hash;
  3676.     hash.key = ngx_hash_key_lc;
  3677.     hash.max_size = 512;
  3678.     hash.bucket_size = 64;
  3679.     hash.name = "grpc_headers_hash";
  3680.     hash.pool = cf->pool;
  3681.     hash.temp_pool = NULL;

  3682.     return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
  3683. }


  3684. static char *
  3685. ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3686. {
  3687.     ngx_http_grpc_loc_conf_t *glcf = conf;

  3688.     size_t                      add;
  3689.     ngx_str_t                  *value, *url;
  3690.     ngx_url_t                   u;
  3691.     ngx_uint_t                  n;
  3692.     ngx_http_core_loc_conf_t   *clcf;
  3693.     ngx_http_script_compile_t   sc;

  3694.     if (glcf->upstream.upstream || glcf->grpc_lengths) {
  3695.         return "is duplicate";
  3696.     }

  3697.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

  3698.     clcf->handler = ngx_http_grpc_handler;

  3699.     if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
  3700.         clcf->auto_redirect = 1;
  3701.     }

  3702.     value = cf->args->elts;

  3703.     url = &value[1];

  3704.     n = ngx_http_script_variables_count(url);

  3705.     if (n) {

  3706.         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

  3707.         sc.cf = cf;
  3708.         sc.source = url;
  3709.         sc.lengths = &glcf->grpc_lengths;
  3710.         sc.values = &glcf->grpc_values;
  3711.         sc.variables = n;
  3712.         sc.complete_lengths = 1;
  3713.         sc.complete_values = 1;

  3714.         if (ngx_http_script_compile(&sc) != NGX_OK) {
  3715.             return NGX_CONF_ERROR;
  3716.         }

  3717. #if (NGX_HTTP_SSL)
  3718.         glcf->ssl = 1;
  3719. #endif

  3720.         return NGX_CONF_OK;
  3721.     }

  3722.     if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) {
  3723.         add = 7;

  3724.     } else if (ngx_strncasecmp(url->data, (u_char *) "grpcs://", 8) == 0) {

  3725. #if (NGX_HTTP_SSL)
  3726.         glcf->ssl = 1;

  3727.         add = 8;
  3728. #else
  3729.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3730.                            "grpcs protocol requires SSL support");
  3731.         return NGX_CONF_ERROR;
  3732. #endif

  3733.     } else {
  3734.         add = 0;
  3735.     }

  3736.     ngx_memzero(&u, sizeof(ngx_url_t));

  3737.     u.url.len = url->len - add;
  3738.     u.url.data = url->data + add;
  3739.     u.no_resolve = 1;

  3740.     glcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
  3741.     if (glcf->upstream.upstream == NULL) {
  3742.         return NGX_CONF_ERROR;
  3743.     }

  3744.     if (u.family != AF_UNIX) {

  3745.         if (u.no_port) {
  3746.             glcf->host = u.host;

  3747.         } else {
  3748.             glcf->host.len = u.host.len + 1 + u.port_text.len;
  3749.             glcf->host.data = u.host.data;
  3750.         }

  3751.     } else {
  3752.         ngx_str_set(&glcf->host, "localhost");
  3753.     }

  3754.     return NGX_CONF_OK;
  3755. }


  3756. #if (NGX_HTTP_SSL)

  3757. static char *
  3758. ngx_http_grpc_ssl_certificate_cache(ngx_conf_t *cf, ngx_command_t *cmd,
  3759.     void *conf)
  3760. {
  3761.     ngx_http_grpc_loc_conf_t *plcf = conf;

  3762.     time_t       inactive, valid;
  3763.     ngx_str_t   *value, s;
  3764.     ngx_int_t    max;
  3765.     ngx_uint_t   i;

  3766.     if (plcf->upstream.ssl_certificate_cache != NGX_CONF_UNSET_PTR) {
  3767.         return "is duplicate";
  3768.     }

  3769.     value = cf->args->elts;

  3770.     max = 0;
  3771.     inactive = 10;
  3772.     valid = 60;

  3773.     for (i = 1; i < cf->args->nelts; i++) {

  3774.         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {

  3775.             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
  3776.             if (max <= 0) {
  3777.                 goto failed;
  3778.             }

  3779.             continue;
  3780.         }

  3781.         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {

  3782.             s.len = value[i].len - 9;
  3783.             s.data = value[i].data + 9;

  3784.             inactive = ngx_parse_time(&s, 1);
  3785.             if (inactive == (time_t) NGX_ERROR) {
  3786.                 goto failed;
  3787.             }

  3788.             continue;
  3789.         }

  3790.         if (ngx_strncmp(value[i].data, "valid=", 6) == 0) {

  3791.             s.len = value[i].len - 6;
  3792.             s.data = value[i].data + 6;

  3793.             valid = ngx_parse_time(&s, 1);
  3794.             if (valid == (time_t) NGX_ERROR) {
  3795.                 goto failed;
  3796.             }

  3797.             continue;
  3798.         }

  3799.         if (ngx_strcmp(value[i].data, "off") == 0) {

  3800.             plcf->upstream.ssl_certificate_cache = NULL;

  3801.             continue;
  3802.         }

  3803.     failed:

  3804.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3805.                            "invalid parameter \"%V\"", &value[i]);
  3806.         return NGX_CONF_ERROR;
  3807.     }

  3808.     if (plcf->upstream.ssl_certificate_cache == NULL) {
  3809.         return NGX_CONF_OK;
  3810.     }

  3811.     if (max == 0) {
  3812.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  3813.                            "\"grpc_ssl_certificate_cache\" must have "
  3814.                            "the \"max\" parameter");
  3815.         return NGX_CONF_ERROR;
  3816.     }

  3817.     plcf->upstream.ssl_certificate_cache = ngx_ssl_cache_init(cf->pool, max,
  3818.                                                               valid, inactive);
  3819.     if (plcf->upstream.ssl_certificate_cache == NULL) {
  3820.         return NGX_CONF_ERROR;
  3821.     }

  3822.     return NGX_CONF_OK;
  3823. }


  3824. static char *
  3825. ngx_http_grpc_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  3826. {
  3827.     ngx_http_grpc_loc_conf_t *glcf = conf;

  3828.     ngx_str_t  *value;

  3829.     if (glcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) {
  3830.         return "is duplicate";
  3831.     }

  3832.     value = cf->args->elts;

  3833.     glcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);

  3834.     if (glcf->upstream.ssl_passwords == NULL) {
  3835.         return NGX_CONF_ERROR;
  3836.     }

  3837.     return NGX_CONF_OK;
  3838. }


  3839. static char *
  3840. ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
  3841. {
  3842. #ifndef SSL_CONF_FLAG_FILE
  3843.     return "is not supported on this platform";
  3844. #else
  3845.     return NGX_CONF_OK;
  3846. #endif
  3847. }


  3848. static ngx_int_t
  3849. ngx_http_grpc_merge_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf,
  3850.     ngx_http_grpc_loc_conf_t *prev)
  3851. {
  3852.     ngx_uint_t  preserve;

  3853.     if (conf->ssl_protocols == 0
  3854.         && conf->ssl_ciphers.data == NULL
  3855.         && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR
  3856.         && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR
  3857.         && conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR
  3858.         && conf->upstream.ssl_verify == NGX_CONF_UNSET
  3859.         && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT
  3860.         && conf->ssl_trusted_certificate.data == NULL
  3861.         && conf->ssl_crl.data == NULL
  3862.         && conf->upstream.ssl_session_reuse == NGX_CONF_UNSET
  3863.         && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR)
  3864.     {
  3865.         if (prev->upstream.ssl) {
  3866.             conf->upstream.ssl = prev->upstream.ssl;
  3867.             return NGX_OK;
  3868.         }

  3869.         preserve = 1;

  3870.     } else {
  3871.         preserve = 0;
  3872.     }

  3873.     conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
  3874.     if (conf->upstream.ssl == NULL) {
  3875.         return NGX_ERROR;
  3876.     }

  3877.     conf->upstream.ssl->log = cf->log;

  3878.     /*
  3879.      * special handling to preserve conf->upstream.ssl
  3880.      * in the "http" section to inherit it to all servers
  3881.      */

  3882.     if (preserve) {
  3883.         prev->upstream.ssl = conf->upstream.ssl;
  3884.     }

  3885.     return NGX_OK;
  3886. }


  3887. static ngx_int_t
  3888. ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
  3889. {
  3890.     ngx_pool_cleanup_t  *cln;

  3891.     if (glcf->upstream.ssl->ctx) {
  3892.         return NGX_OK;
  3893.     }

  3894.     if (ngx_ssl_create(glcf->upstream.ssl, glcf->ssl_protocols, NULL)
  3895.         != NGX_OK)
  3896.     {
  3897.         return NGX_ERROR;
  3898.     }

  3899.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  3900.     if (cln == NULL) {
  3901.         ngx_ssl_cleanup_ctx(glcf->upstream.ssl);
  3902.         return NGX_ERROR;
  3903.     }

  3904.     cln->handler = ngx_ssl_cleanup_ctx;
  3905.     cln->data = glcf->upstream.ssl;

  3906.     if (ngx_ssl_ciphers(cf, glcf->upstream.ssl, &glcf->ssl_ciphers, 0)
  3907.         != NGX_OK)
  3908.     {
  3909.         return NGX_ERROR;
  3910.     }

  3911.     if (glcf->upstream.ssl_certificate
  3912.         && glcf->upstream.ssl_certificate->value.len)
  3913.     {
  3914.         if (glcf->upstream.ssl_certificate_key == NULL) {
  3915.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  3916.                           "no \"grpc_ssl_certificate_key\" is defined "
  3917.                           "for certificate \"%V\"",
  3918.                           &glcf->upstream.ssl_certificate->value);
  3919.             return NGX_ERROR;
  3920.         }

  3921.         if (glcf->upstream.ssl_certificate->lengths == NULL
  3922.             && glcf->upstream.ssl_certificate_key->lengths == NULL)
  3923.         {
  3924.             if (ngx_ssl_certificate(cf, glcf->upstream.ssl,
  3925.                                     &glcf->upstream.ssl_certificate->value,
  3926.                                     &glcf->upstream.ssl_certificate_key->value,
  3927.                                     glcf->upstream.ssl_passwords)
  3928.                 != NGX_OK)
  3929.             {
  3930.                 return NGX_ERROR;
  3931.             }
  3932.         }
  3933.     }

  3934.     if (glcf->upstream.ssl_verify) {
  3935.         if (glcf->ssl_trusted_certificate.len == 0) {
  3936.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  3937.                       "no grpc_ssl_trusted_certificate for grpc_ssl_verify");
  3938.             return NGX_ERROR;
  3939.         }

  3940.         if (ngx_ssl_trusted_certificate(cf, glcf->upstream.ssl,
  3941.                                         &glcf->ssl_trusted_certificate,
  3942.                                         glcf->ssl_verify_depth)
  3943.             != NGX_OK)
  3944.         {
  3945.             return NGX_ERROR;
  3946.         }

  3947.         if (ngx_ssl_crl(cf, glcf->upstream.ssl, &glcf->ssl_crl) != NGX_OK) {
  3948.             return NGX_ERROR;
  3949.         }
  3950.     }

  3951.     if (ngx_ssl_client_session_cache(cf, glcf->upstream.ssl,
  3952.                                      glcf->upstream.ssl_session_reuse)
  3953.         != NGX_OK)
  3954.     {
  3955.         return NGX_ERROR;
  3956.     }

  3957. #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation

  3958.     if (SSL_CTX_set_alpn_protos(glcf->upstream.ssl->ctx,
  3959.                                 (u_char *) "\x02h2", 3)
  3960.         != 0)
  3961.     {
  3962.         ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
  3963.                       "SSL_CTX_set_alpn_protos() failed");
  3964.         return NGX_ERROR;
  3965.     }

  3966. #endif

  3967.     if (ngx_ssl_conf_commands(cf, glcf->upstream.ssl, glcf->ssl_conf_commands)
  3968.         != NGX_OK)
  3969.     {
  3970.         return NGX_ERROR;
  3971.     }

  3972.     return NGX_OK;
  3973. }

  3974. #endif