src/http/v3/ngx_http_v3_parse.c - nginx

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Roman Arutyunyan
  3. * Copyright (C) Nginx, Inc.
  4. */


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


  8. #define ngx_http_v3_is_v2_frame(type)                                         \
  9.     ((type) == 0x02 || (type) == 0x06 || (type) == 0x08 || (type) == 0x09)


  10. static void ngx_http_v3_parse_start_local(ngx_buf_t *b, ngx_buf_t *loc,
  11.     ngx_uint_t n);
  12. static void ngx_http_v3_parse_end_local(ngx_buf_t *b, ngx_buf_t *loc,
  13.     ngx_uint_t *n);
  14. static ngx_int_t ngx_http_v3_parse_skip(ngx_buf_t *b, ngx_uint_t *length);

  15. static ngx_int_t ngx_http_v3_parse_varlen_int(ngx_connection_t *c,
  16.     ngx_http_v3_parse_varlen_int_t *st, ngx_buf_t *b);
  17. static ngx_int_t ngx_http_v3_parse_prefix_int(ngx_connection_t *c,
  18.     ngx_http_v3_parse_prefix_int_t *st, ngx_uint_t prefix, ngx_buf_t *b);

  19. static ngx_int_t ngx_http_v3_parse_field_section_prefix(ngx_connection_t *c,
  20.     ngx_http_v3_parse_field_section_prefix_t *st, ngx_buf_t *b);
  21. static ngx_int_t ngx_http_v3_parse_field_rep(ngx_connection_t *c,
  22.     ngx_http_v3_parse_field_rep_t *st, ngx_uint_t base, ngx_buf_t *b);
  23. static ngx_int_t ngx_http_v3_parse_literal(ngx_connection_t *c,
  24.     ngx_http_v3_parse_literal_t *st, ngx_buf_t *b);
  25. static ngx_int_t ngx_http_v3_parse_field_ri(ngx_connection_t *c,
  26.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b);
  27. static ngx_int_t ngx_http_v3_parse_field_lri(ngx_connection_t *c,
  28.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b);
  29. static ngx_int_t ngx_http_v3_parse_field_l(ngx_connection_t *c,
  30.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b);
  31. static ngx_int_t ngx_http_v3_parse_field_pbi(ngx_connection_t *c,
  32.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b);
  33. static ngx_int_t ngx_http_v3_parse_field_lpbi(ngx_connection_t *c,
  34.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b);

  35. static ngx_int_t ngx_http_v3_parse_control(ngx_connection_t *c,
  36.     ngx_http_v3_parse_control_t *st, ngx_buf_t *b);
  37. static ngx_int_t ngx_http_v3_parse_settings(ngx_connection_t *c,
  38.     ngx_http_v3_parse_settings_t *st, ngx_buf_t *b);

  39. static ngx_int_t ngx_http_v3_parse_encoder(ngx_connection_t *c,
  40.     ngx_http_v3_parse_encoder_t *st, ngx_buf_t *b);
  41. static ngx_int_t ngx_http_v3_parse_field_inr(ngx_connection_t *c,
  42.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b);
  43. static ngx_int_t ngx_http_v3_parse_field_iln(ngx_connection_t *c,
  44.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b);

  45. static ngx_int_t ngx_http_v3_parse_decoder(ngx_connection_t *c,
  46.     ngx_http_v3_parse_decoder_t *st, ngx_buf_t *b);

  47. static ngx_int_t ngx_http_v3_parse_lookup(ngx_connection_t *c,
  48.     ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *name, ngx_str_t *value);


  49. static void
  50. ngx_http_v3_parse_start_local(ngx_buf_t *b, ngx_buf_t *loc, ngx_uint_t n)
  51. {
  52.     *loc = *b;

  53.     if ((size_t) (loc->last - loc->pos) > n) {
  54.         loc->last = loc->pos + n;
  55.     }
  56. }


  57. static void
  58. ngx_http_v3_parse_end_local(ngx_buf_t *b, ngx_buf_t *loc, ngx_uint_t *pn)
  59. {
  60.     *pn -= loc->pos - b->pos;
  61.     b->pos = loc->pos;
  62. }


  63. static ngx_int_t
  64. ngx_http_v3_parse_skip(ngx_buf_t *b, ngx_uint_t *length)
  65. {
  66.     if ((size_t) (b->last - b->pos) < *length) {
  67.         *length -= b->last - b->pos;
  68.         b->pos = b->last;
  69.         return NGX_AGAIN;
  70.     }

  71.     b->pos += *length;
  72.     return NGX_DONE;
  73. }


  74. static ngx_int_t
  75. ngx_http_v3_parse_varlen_int(ngx_connection_t *c,
  76.     ngx_http_v3_parse_varlen_int_t *st, ngx_buf_t *b)
  77. {
  78.     u_char  ch;
  79.     enum {
  80.         sw_start = 0,
  81.         sw_length_2,
  82.         sw_length_3,
  83.         sw_length_4,
  84.         sw_length_5,
  85.         sw_length_6,
  86.         sw_length_7,
  87.         sw_length_8
  88.     };

  89.     for ( ;; ) {

  90.         if (b->pos == b->last) {
  91.             return NGX_AGAIN;
  92.         }

  93.         ch = *b->pos++;

  94.         switch (st->state) {

  95.         case sw_start:

  96.             st->value = ch;
  97.             if (st->value & 0xc0) {
  98.                 st->state = sw_length_2;
  99.                 break;
  100.             }

  101.             goto done;

  102.         case sw_length_2:

  103.             st->value = (st->value << 8) + ch;
  104.             if ((st->value & 0xc000) == 0x4000) {
  105.                 st->value &= 0x3fff;
  106.                 goto done;
  107.             }

  108.             st->state = sw_length_3;
  109.             break;

  110.         case sw_length_4:

  111.             st->value = (st->value << 8) + ch;
  112.             if ((st->value & 0xc0000000) == 0x80000000) {
  113.                 st->value &= 0x3fffffff;
  114.                 goto done;
  115.             }

  116.             st->state = sw_length_5;
  117.             break;

  118.         case sw_length_3:
  119.         case sw_length_5:
  120.         case sw_length_6:
  121.         case sw_length_7:

  122.             st->value = (st->value << 8) + ch;
  123.             st->state++;
  124.             break;

  125.         case sw_length_8:

  126.             st->value = (st->value << 8) + ch;
  127.             st->value &= 0x3fffffffffffffff;
  128.             goto done;
  129.         }
  130.     }

  131. done:

  132.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  133.                    "http3 parse varlen int %uL", st->value);

  134.     st->state = sw_start;
  135.     return NGX_DONE;
  136. }


  137. static ngx_int_t
  138. ngx_http_v3_parse_prefix_int(ngx_connection_t *c,
  139.     ngx_http_v3_parse_prefix_int_t *st, ngx_uint_t prefix, ngx_buf_t *b)
  140. {
  141.     u_char      ch;
  142.     ngx_uint_t  mask;
  143.     enum {
  144.         sw_start = 0,
  145.         sw_value
  146.     };

  147.     for ( ;; ) {

  148.         if (b->pos == b->last) {
  149.             return NGX_AGAIN;
  150.         }

  151.         ch = *b->pos++;

  152.         switch (st->state) {

  153.         case sw_start:

  154.             mask = (1 << prefix) - 1;
  155.             st->value = ch & mask;

  156.             if (st->value != mask) {
  157.                 goto done;
  158.             }

  159.             st->shift = 0;
  160.             st->state = sw_value;
  161.             break;

  162.         case sw_value:

  163.             st->value += (uint64_t) (ch & 0x7f) << st->shift;

  164.             if (st->shift == 56
  165.                 && ((ch & 0x80) || (st->value & 0xc000000000000000)))
  166.             {
  167.                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
  168.                               "client exceeded integer size limit");
  169.                 return NGX_HTTP_V3_ERR_EXCESSIVE_LOAD;
  170.             }

  171.             if (ch & 0x80) {
  172.                 st->shift += 7;
  173.                 break;
  174.             }

  175.             goto done;
  176.         }
  177.     }

  178. done:

  179.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  180.                    "http3 parse prefix int %uL", st->value);

  181.     st->state = sw_start;
  182.     return NGX_DONE;
  183. }


  184. ngx_int_t
  185. ngx_http_v3_parse_headers(ngx_connection_t *c, ngx_http_v3_parse_headers_t *st,
  186.     ngx_buf_t *b)
  187. {
  188.     ngx_buf_t  loc;
  189.     ngx_int_t  rc;
  190.     enum {
  191.         sw_start = 0,
  192.         sw_type,
  193.         sw_length,
  194.         sw_skip,
  195.         sw_prefix,
  196.         sw_verify,
  197.         sw_field_rep,
  198.         sw_done
  199.     };

  200.     for ( ;; ) {

  201.         switch (st->state) {

  202.         case sw_start:

  203.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  204.                            "http3 parse headers");

  205.             st->state = sw_type;

  206.             /* fall through */

  207.         case sw_type:

  208.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  209.             if (rc != NGX_DONE) {
  210.                 return rc;
  211.             }

  212.             st->type = st->vlint.value;

  213.             if (ngx_http_v3_is_v2_frame(st->type)
  214.                 || st->type == NGX_HTTP_V3_FRAME_DATA
  215.                 || st->type == NGX_HTTP_V3_FRAME_GOAWAY
  216.                 || st->type == NGX_HTTP_V3_FRAME_SETTINGS
  217.                 || st->type == NGX_HTTP_V3_FRAME_MAX_PUSH_ID
  218.                 || st->type == NGX_HTTP_V3_FRAME_CANCEL_PUSH
  219.                 || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
  220.             {
  221.                 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
  222.             }

  223.             st->state = sw_length;
  224.             break;

  225.         case sw_length:

  226.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  227.             if (rc != NGX_DONE) {
  228.                 return rc;
  229.             }

  230.             st->length = st->vlint.value;

  231.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  232.                            "http3 parse headers type:%ui, len:%ui",
  233.                            st->type, st->length);

  234.             if (st->type != NGX_HTTP_V3_FRAME_HEADERS) {
  235.                 st->state = st->length > 0 ? sw_skip : sw_type;
  236.                 break;
  237.             }

  238.             if (st->length == 0) {
  239.                 return NGX_HTTP_V3_ERR_FRAME_ERROR;
  240.             }

  241.             st->state = sw_prefix;
  242.             break;

  243.         case sw_skip:

  244.             rc = ngx_http_v3_parse_skip(b, &st->length);
  245.             if (rc != NGX_DONE) {
  246.                 return rc;
  247.             }

  248.             st->state = sw_type;
  249.             break;

  250.         case sw_prefix:

  251.             ngx_http_v3_parse_start_local(b, &loc, st->length);

  252.             rc = ngx_http_v3_parse_field_section_prefix(c, &st->prefix, &loc);

  253.             ngx_http_v3_parse_end_local(b, &loc, &st->length);

  254.             if (st->length == 0 && rc == NGX_AGAIN) {
  255.                 return NGX_HTTP_V3_ERR_FRAME_ERROR;
  256.             }

  257.             if (rc != NGX_DONE) {
  258.                 return rc;
  259.             }

  260.             st->state = sw_verify;
  261.             break;

  262.         case sw_verify:

  263.             rc = ngx_http_v3_check_insert_count(c, st->prefix.insert_count);
  264.             if (rc != NGX_OK) {
  265.                 return rc;
  266.             }

  267.             st->state = sw_field_rep;

  268.             /* fall through */

  269.         case sw_field_rep:

  270.             ngx_http_v3_parse_start_local(b, &loc, st->length);

  271.             rc = ngx_http_v3_parse_field_rep(c, &st->field_rep, st->prefix.base,
  272.                                              &loc);

  273.             ngx_http_v3_parse_end_local(b, &loc, &st->length);

  274.             if (st->length == 0 && rc == NGX_AGAIN) {
  275.                 return NGX_HTTP_V3_ERR_FRAME_ERROR;
  276.             }

  277.             if (rc != NGX_DONE) {
  278.                 return rc;
  279.             }

  280.             if (st->length == 0) {
  281.                 goto done;
  282.             }

  283.             return NGX_OK;
  284.         }
  285.     }

  286. done:

  287.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse headers done");

  288.     if (st->prefix.insert_count > 0) {
  289.         if (ngx_http_v3_send_ack_section(c, c->quic->id) != NGX_OK) {
  290.             return NGX_ERROR;
  291.         }

  292.         ngx_http_v3_ack_insert_count(c, st->prefix.insert_count);
  293.     }

  294.     st->state = sw_start;
  295.     return NGX_DONE;
  296. }


  297. static ngx_int_t
  298. ngx_http_v3_parse_field_section_prefix(ngx_connection_t *c,
  299.     ngx_http_v3_parse_field_section_prefix_t *st, ngx_buf_t *b)
  300. {
  301.     u_char     ch;
  302.     ngx_int_t  rc;
  303.     enum {
  304.         sw_start = 0,
  305.         sw_req_insert_count,
  306.         sw_delta_base,
  307.         sw_read_delta_base
  308.     };

  309.     for ( ;; ) {

  310.         switch (st->state) {

  311.         case sw_start:

  312.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  313.                            "http3 parse field section prefix");

  314.             st->state = sw_req_insert_count;

  315.             /* fall through */

  316.         case sw_req_insert_count:

  317.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 8, b);
  318.             if (rc != NGX_DONE) {
  319.                 return rc;
  320.             }

  321.             st->insert_count = st->pint.value;
  322.             st->state = sw_delta_base;
  323.             break;

  324.         case sw_delta_base:

  325.             if (b->pos == b->last) {
  326.                 return NGX_AGAIN;
  327.             }

  328.             ch = *b->pos;

  329.             st->sign = (ch & 0x80) ? 1 : 0;
  330.             st->state = sw_read_delta_base;

  331.             /* fall through */

  332.         case sw_read_delta_base:

  333.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  334.             if (rc != NGX_DONE) {
  335.                 return rc;
  336.             }

  337.             st->delta_base = st->pint.value;
  338.             goto done;
  339.         }
  340.     }

  341. done:

  342.     rc = ngx_http_v3_decode_insert_count(c, &st->insert_count);
  343.     if (rc != NGX_OK) {
  344.         return rc;
  345.     }

  346.     if (st->sign) {
  347.         if (st->insert_count <= st->delta_base) {
  348.             ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent negative base");
  349.             return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
  350.         }

  351.         st->base = st->insert_count - st->delta_base - 1;

  352.     } else {
  353.         st->base = st->insert_count + st->delta_base;
  354.     }

  355.     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0,
  356.                   "http3 parse field section prefix done "
  357.                   "insert_count:%ui, sign:%ui, delta_base:%ui, base:%ui",
  358.                   st->insert_count, st->sign, st->delta_base, st->base);

  359.     st->state = sw_start;
  360.     return NGX_DONE;
  361. }


  362. static ngx_int_t
  363. ngx_http_v3_parse_field_rep(ngx_connection_t *c,
  364.     ngx_http_v3_parse_field_rep_t *st, ngx_uint_t base, ngx_buf_t *b)
  365. {
  366.     u_char     ch;
  367.     ngx_int_t  rc;
  368.     enum {
  369.         sw_start = 0,
  370.         sw_field_ri,
  371.         sw_field_lri,
  372.         sw_field_l,
  373.         sw_field_pbi,
  374.         sw_field_lpbi
  375.     };

  376.     if (st->state == sw_start) {

  377.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  378.                        "http3 parse field representation");

  379.         if (b->pos == b->last) {
  380.             return NGX_AGAIN;
  381.         }

  382.         ch = *b->pos;

  383.         ngx_memzero(&st->field, sizeof(ngx_http_v3_parse_field_t));

  384.         st->field.base = base;

  385.         if (ch & 0x80) {
  386.             /* Indexed Field Line */

  387.             st->state = sw_field_ri;

  388.         } else if (ch & 0x40) {
  389.             /* Literal Field Line With Name Reference */

  390.             st->state = sw_field_lri;

  391.         } else if (ch & 0x20) {
  392.             /* Literal Field Line With Literal Name */

  393.             st->state = sw_field_l;

  394.         } else if (ch & 0x10) {
  395.             /* Indexed Field Line With Post-Base Index */

  396.             st->state = sw_field_pbi;

  397.         } else {
  398.             /* Literal Field Line With Post-Base Name Reference */

  399.             st->state = sw_field_lpbi;
  400.         }
  401.     }

  402.     switch (st->state) {

  403.     case sw_field_ri:
  404.         rc = ngx_http_v3_parse_field_ri(c, &st->field, b);
  405.         break;

  406.     case sw_field_lri:
  407.         rc = ngx_http_v3_parse_field_lri(c, &st->field, b);
  408.         break;

  409.     case sw_field_l:
  410.         rc = ngx_http_v3_parse_field_l(c, &st->field, b);
  411.         break;

  412.     case sw_field_pbi:
  413.         rc = ngx_http_v3_parse_field_pbi(c, &st->field, b);
  414.         break;

  415.     case sw_field_lpbi:
  416.         rc = ngx_http_v3_parse_field_lpbi(c, &st->field, b);
  417.         break;

  418.     default:
  419.         rc = NGX_OK;
  420.     }

  421.     if (rc != NGX_DONE) {
  422.         return rc;
  423.     }

  424.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  425.                    "http3 parse field representation done");

  426.     st->state = sw_start;
  427.     return NGX_DONE;
  428. }


  429. static ngx_int_t
  430. ngx_http_v3_parse_literal(ngx_connection_t *c, ngx_http_v3_parse_literal_t *st,
  431.     ngx_buf_t *b)
  432. {
  433.     u_char                     ch;
  434.     ngx_uint_t                 n;
  435.     ngx_http_core_srv_conf_t  *cscf;
  436.     enum {
  437.         sw_start = 0,
  438.         sw_value
  439.     };

  440.     for ( ;; ) {

  441.         switch (st->state) {

  442.         case sw_start:

  443.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  444.                            "http3 parse literal huff:%ui, len:%ui",
  445.                            st->huffman, st->length);

  446.             n = st->length;

  447.             cscf = ngx_http_v3_get_module_srv_conf(c, ngx_http_core_module);

  448.             if (n > cscf->large_client_header_buffers.size) {
  449.                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
  450.                               "client sent too large field line");
  451.                 return NGX_HTTP_V3_ERR_EXCESSIVE_LOAD;
  452.             }

  453.             if (st->huffman) {
  454.                 if (n > NGX_MAX_INT_T_VALUE / 8) {
  455.                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
  456.                                   "client sent too large field line");
  457.                     return NGX_HTTP_V3_ERR_EXCESSIVE_LOAD;
  458.                 }

  459.                 n = n * 8 / 5;
  460.                 st->huffstate = 0;
  461.             }

  462.             if (st->buf) {
  463.                 if ((size_t) (st->buf->end - st->buf->last) < n + 1) {
  464.                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
  465.                                   "not enough dynamic table capacity");

  466.                     st->last = NULL;
  467.                     return NGX_ERROR;
  468.                 }

  469.                 st->last = st->buf->last;
  470.                 st->buf->last += n + 1;

  471.             } else {
  472.                 st->last = ngx_pnalloc(c->pool, n + 1);
  473.                 if (st->last == NULL) {
  474.                     return NGX_ERROR;
  475.                 }
  476.             }

  477.             st->value.data = st->last;
  478.             st->state = sw_value;

  479.             /* fall through */

  480.         case sw_value:

  481.             if (b->pos == b->last) {
  482.                 return NGX_AGAIN;
  483.             }

  484.             ch = *b->pos++;

  485.             if (st->huffman) {
  486.                 if (ngx_http_huff_decode(&st->huffstate, &ch, 1, &st->last,
  487.                                          st->length == 1, c->log)
  488.                     != NGX_OK)
  489.                 {
  490.                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
  491.                                   "client sent invalid encoded field line");
  492.                     return NGX_ERROR;
  493.                 }

  494.             } else {
  495.                 *st->last++ = ch;
  496.             }

  497.             if (--st->length) {
  498.                 break;
  499.             }

  500.             st->value.len = st->last - st->value.data;
  501.             *st->last = '\0';
  502.             goto done;
  503.         }
  504.     }

  505. done:

  506.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  507.                    "http3 parse literal done \"%V\"", &st->value);

  508.     st->state = sw_start;
  509.     return NGX_DONE;
  510. }


  511. static ngx_int_t
  512. ngx_http_v3_parse_field_ri(ngx_connection_t *c, ngx_http_v3_parse_field_t *st,
  513.     ngx_buf_t *b)
  514. {
  515.     u_char     ch;
  516.     ngx_int_t  rc;
  517.     enum {
  518.         sw_start = 0,
  519.         sw_index
  520.     };

  521.     for ( ;; ) {

  522.         switch (st->state) {

  523.         case sw_start:

  524.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  525.                            "http3 parse field ri");

  526.             if (b->pos == b->last) {
  527.                 return NGX_AGAIN;
  528.             }

  529.             ch = *b->pos;

  530.             st->dynamic = (ch & 0x40) ? 0 : 1;
  531.             st->state = sw_index;

  532.             /* fall through */

  533.         case sw_index:

  534.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  535.             if (rc != NGX_DONE) {
  536.                 return rc;
  537.             }

  538.             st->index = st->pint.value;
  539.             goto done;
  540.         }
  541.     }

  542. done:

  543.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  544.                    "http3 parse field ri done %s%ui]",
  545.                    st->dynamic ? "dynamic[-" : "static[", st->index);

  546.     if (st->dynamic) {
  547.         st->index = st->base - st->index - 1;
  548.     }

  549.     rc = ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name,
  550.                                   &st->value);
  551.     if (rc != NGX_OK) {
  552.         return rc;
  553.     }

  554.     st->state = sw_start;
  555.     return NGX_DONE;
  556. }


  557. static ngx_int_t
  558. ngx_http_v3_parse_field_lri(ngx_connection_t *c,
  559.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  560. {
  561.     u_char     ch;
  562.     ngx_int_t  rc;
  563.     enum {
  564.         sw_start = 0,
  565.         sw_index,
  566.         sw_value_len,
  567.         sw_read_value_len,
  568.         sw_value
  569.     };

  570.     for ( ;; ) {

  571.         switch (st->state) {

  572.         case sw_start:

  573.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  574.                            "http3 parse field lri");

  575.             if (b->pos == b->last) {
  576.                 return NGX_AGAIN;
  577.             }

  578.             ch = *b->pos;

  579.             st->dynamic = (ch & 0x10) ? 0 : 1;
  580.             st->state = sw_index;

  581.             /* fall through */

  582.         case sw_index:

  583.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 4, b);
  584.             if (rc != NGX_DONE) {
  585.                 return rc;
  586.             }

  587.             st->index = st->pint.value;
  588.             st->state = sw_value_len;
  589.             break;

  590.         case sw_value_len:

  591.             if (b->pos == b->last) {
  592.                 return NGX_AGAIN;
  593.             }

  594.             ch = *b->pos;

  595.             st->literal.huffman = (ch & 0x80) ? 1 : 0;
  596.             st->state = sw_read_value_len;

  597.             /* fall through */

  598.         case sw_read_value_len:

  599.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  600.             if (rc != NGX_DONE) {
  601.                 return rc;
  602.             }

  603.             st->literal.length = st->pint.value;
  604.             if (st->literal.length == 0) {
  605.                 st->value.data = (u_char *) "";
  606.                 goto done;
  607.             }

  608.             st->state = sw_value;
  609.             break;

  610.         case sw_value:

  611.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  612.             if (rc != NGX_DONE) {
  613.                 return rc;
  614.             }

  615.             st->value = st->literal.value;
  616.             goto done;
  617.         }
  618.     }

  619. done:

  620.     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
  621.                    "http3 parse field lri done %s%ui] \"%V\"",
  622.                    st->dynamic ? "dynamic[-" : "static[",
  623.                    st->index, &st->value);

  624.     if (st->dynamic) {
  625.         st->index = st->base - st->index - 1;
  626.     }

  627.     rc = ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, NULL);
  628.     if (rc != NGX_OK) {
  629.         return rc;
  630.     }

  631.     st->state = sw_start;
  632.     return NGX_DONE;
  633. }


  634. static ngx_int_t
  635. ngx_http_v3_parse_field_l(ngx_connection_t *c,
  636.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  637. {
  638.     u_char     ch;
  639.     ngx_int_t  rc;
  640.     enum {
  641.         sw_start = 0,
  642.         sw_name_len,
  643.         sw_name,
  644.         sw_value_len,
  645.         sw_read_value_len,
  646.         sw_value
  647.     };

  648.     for ( ;; ) {

  649.         switch (st->state) {

  650.         case sw_start:

  651.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  652.                            "http3 parse field l");

  653.             if (b->pos == b->last) {
  654.                 return NGX_AGAIN;
  655.             }

  656.             ch = *b->pos;

  657.             st->literal.huffman = (ch & 0x08) ? 1 : 0;
  658.             st->state = sw_name_len;

  659.             /* fall through */

  660.         case sw_name_len:

  661.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 3, b);
  662.             if (rc != NGX_DONE) {
  663.                 return rc;
  664.             }

  665.             st->literal.length = st->pint.value;
  666.             if (st->literal.length == 0) {
  667.                 return NGX_ERROR;
  668.             }

  669.             st->state = sw_name;
  670.             break;

  671.         case sw_name:

  672.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  673.             if (rc != NGX_DONE) {
  674.                 return rc;
  675.             }

  676.             st->name = st->literal.value;
  677.             st->state = sw_value_len;
  678.             break;

  679.         case sw_value_len:

  680.             if (b->pos == b->last) {
  681.                 return NGX_AGAIN;
  682.             }

  683.             ch = *b->pos;

  684.             st->literal.huffman = (ch & 0x80) ? 1 : 0;
  685.             st->state = sw_read_value_len;

  686.             /* fall through */

  687.         case sw_read_value_len:

  688.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  689.             if (rc != NGX_DONE) {
  690.                 return rc;
  691.             }

  692.             st->literal.length = st->pint.value;
  693.             if (st->literal.length == 0) {
  694.                 st->value.data = (u_char *) "";
  695.                 goto done;
  696.             }

  697.             st->state = sw_value;
  698.             break;

  699.         case sw_value:

  700.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  701.             if (rc != NGX_DONE) {
  702.                 return rc;
  703.             }

  704.             st->value = st->literal.value;
  705.             goto done;
  706.         }
  707.     }

  708. done:

  709.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  710.                    "http3 parse field l done \"%V\" \"%V\"",
  711.                    &st->name, &st->value);

  712.     st->state = sw_start;
  713.     return NGX_DONE;
  714. }


  715. static ngx_int_t
  716. ngx_http_v3_parse_field_pbi(ngx_connection_t *c,
  717.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  718. {
  719.     ngx_int_t  rc;
  720.     enum {
  721.         sw_start = 0,
  722.         sw_index
  723.     };

  724.     for ( ;; ) {

  725.         switch (st->state) {

  726.         case sw_start:

  727.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  728.                            "http3 parse field pbi");

  729.             st->state = sw_index;

  730.             /* fall through */

  731.         case sw_index:

  732.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 4, b);
  733.             if (rc != NGX_DONE) {
  734.                 return rc;
  735.             }

  736.             st->index = st->pint.value;
  737.             goto done;
  738.         }
  739.     }

  740. done:

  741.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  742.                    "http3 parse field pbi done dynamic[+%ui]", st->index);

  743.     rc = ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name,
  744.                                   &st->value);
  745.     if (rc != NGX_OK) {
  746.         return rc;
  747.     }

  748.     st->state = sw_start;
  749.     return NGX_DONE;
  750. }


  751. static ngx_int_t
  752. ngx_http_v3_parse_field_lpbi(ngx_connection_t *c,
  753.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  754. {
  755.     u_char     ch;
  756.     ngx_int_t  rc;
  757.     enum {
  758.         sw_start = 0,
  759.         sw_index,
  760.         sw_value_len,
  761.         sw_read_value_len,
  762.         sw_value
  763.     };

  764.     for ( ;; ) {

  765.         switch (st->state) {

  766.         case sw_start:

  767.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  768.                            "http3 parse field lpbi");

  769.             st->state = sw_index;

  770.             /* fall through */

  771.         case sw_index:

  772.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 3, b);
  773.             if (rc != NGX_DONE) {
  774.                 return rc;
  775.             }

  776.             st->index = st->pint.value;
  777.             st->state = sw_value_len;
  778.             break;

  779.         case sw_value_len:

  780.             if (b->pos == b->last) {
  781.                 return NGX_AGAIN;
  782.             }

  783.             ch = *b->pos;

  784.             st->literal.huffman = (ch & 0x80) ? 1 : 0;
  785.             st->state = sw_read_value_len;

  786.             /* fall through */

  787.         case sw_read_value_len:

  788.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  789.             if (rc != NGX_DONE) {
  790.                 return rc;
  791.             }

  792.             st->literal.length = st->pint.value;
  793.             if (st->literal.length == 0) {
  794.                 st->value.data = (u_char *) "";
  795.                 goto done;
  796.             }

  797.             st->state = sw_value;
  798.             break;

  799.         case sw_value:

  800.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  801.             if (rc != NGX_DONE) {
  802.                 return rc;
  803.             }

  804.             st->value = st->literal.value;
  805.             goto done;
  806.         }
  807.     }

  808. done:

  809.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  810.                    "http3 parse field lpbi done dynamic[+%ui] \"%V\"",
  811.                    st->index, &st->value);

  812.     rc = ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, NULL);
  813.     if (rc != NGX_OK) {
  814.         return rc;
  815.     }

  816.     st->state = sw_start;
  817.     return NGX_DONE;
  818. }


  819. static ngx_int_t
  820. ngx_http_v3_parse_lookup(ngx_connection_t *c, ngx_uint_t dynamic,
  821.     ngx_uint_t index, ngx_str_t *name, ngx_str_t *value)
  822. {
  823.     u_char  *p;

  824.     if (!dynamic) {
  825.         if (ngx_http_v3_lookup_static(c, index, name, value) != NGX_OK) {
  826.             return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
  827.         }

  828.         return NGX_OK;
  829.     }

  830.     if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) {
  831.         return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
  832.     }

  833.     if (name) {
  834.         p = ngx_pnalloc(c->pool, name->len + 1);
  835.         if (p == NULL) {
  836.             return NGX_ERROR;
  837.         }

  838.         ngx_memcpy(p, name->data, name->len);
  839.         p[name->len] = '\0';
  840.         name->data = p;
  841.     }

  842.     if (value) {
  843.         p = ngx_pnalloc(c->pool, value->len + 1);
  844.         if (p == NULL) {
  845.             return NGX_ERROR;
  846.         }

  847.         ngx_memcpy(p, value->data, value->len);
  848.         p[value->len] = '\0';
  849.         value->data = p;
  850.     }

  851.     return NGX_OK;
  852. }


  853. static ngx_int_t
  854. ngx_http_v3_parse_control(ngx_connection_t *c, ngx_http_v3_parse_control_t *st,
  855.     ngx_buf_t *b)
  856. {
  857.     ngx_buf_t  loc;
  858.     ngx_int_t  rc;
  859.     enum {
  860.         sw_start = 0,
  861.         sw_first_type,
  862.         sw_type,
  863.         sw_length,
  864.         sw_settings,
  865.         sw_skip
  866.     };

  867.     for ( ;; ) {

  868.         switch (st->state) {

  869.         case sw_start:

  870.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  871.                            "http3 parse control");

  872.             st->state = sw_first_type;

  873.             /* fall through */

  874.         case sw_first_type:
  875.         case sw_type:

  876.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  877.             if (rc != NGX_DONE) {
  878.                 return rc;
  879.             }

  880.             st->type = st->vlint.value;

  881.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  882.                            "http3 parse frame type:%ui", st->type);

  883.             if (st->state == sw_first_type
  884.                 && st->type != NGX_HTTP_V3_FRAME_SETTINGS)
  885.             {
  886.                 return NGX_HTTP_V3_ERR_MISSING_SETTINGS;
  887.             }

  888.             if (st->state != sw_first_type
  889.                 && st->type == NGX_HTTP_V3_FRAME_SETTINGS)
  890.             {
  891.                 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
  892.             }

  893.             if (ngx_http_v3_is_v2_frame(st->type)
  894.                 || st->type == NGX_HTTP_V3_FRAME_DATA
  895.                 || st->type == NGX_HTTP_V3_FRAME_HEADERS
  896.                 || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
  897.             {
  898.                 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
  899.             }

  900.             if (st->type == NGX_HTTP_V3_FRAME_CANCEL_PUSH) {
  901.                 return NGX_HTTP_V3_ERR_ID_ERROR;
  902.             }

  903.             st->state = sw_length;
  904.             break;

  905.         case sw_length:

  906.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  907.             if (rc != NGX_DONE) {
  908.                 return rc;
  909.             }

  910.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  911.                            "http3 parse frame len:%uL", st->vlint.value);

  912.             st->length = st->vlint.value;
  913.             if (st->length == 0) {
  914.                 st->state = sw_type;
  915.                 break;
  916.             }

  917.             switch (st->type) {

  918.             case NGX_HTTP_V3_FRAME_SETTINGS:
  919.                 st->state = sw_settings;
  920.                 break;

  921.             default:
  922.                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  923.                                "http3 parse skip unknown frame");
  924.                 st->state = sw_skip;
  925.             }

  926.             break;

  927.         case sw_settings:

  928.             ngx_http_v3_parse_start_local(b, &loc, st->length);

  929.             rc = ngx_http_v3_parse_settings(c, &st->settings, &loc);

  930.             ngx_http_v3_parse_end_local(b, &loc, &st->length);

  931.             if (st->length == 0 && rc == NGX_AGAIN) {
  932.                 return NGX_HTTP_V3_ERR_SETTINGS_ERROR;
  933.             }

  934.             if (rc != NGX_DONE) {
  935.                 return rc;
  936.             }

  937.             if (st->length == 0) {
  938.                 st->state = sw_type;
  939.             }

  940.             break;

  941.         case sw_skip:

  942.             rc = ngx_http_v3_parse_skip(b, &st->length);
  943.             if (rc != NGX_DONE) {
  944.                 return rc;
  945.             }

  946.             st->state = sw_type;
  947.             break;
  948.         }
  949.     }
  950. }


  951. static ngx_int_t
  952. ngx_http_v3_parse_settings(ngx_connection_t *c,
  953.     ngx_http_v3_parse_settings_t *st, ngx_buf_t *b)
  954. {
  955.     ngx_int_t  rc;
  956.     enum {
  957.         sw_start = 0,
  958.         sw_id,
  959.         sw_value
  960.     };

  961.     for ( ;; ) {

  962.         switch (st->state) {

  963.         case sw_start:

  964.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  965.                            "http3 parse settings");

  966.             st->state = sw_id;

  967.             /* fall through */

  968.         case sw_id:

  969.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  970.             if (rc != NGX_DONE) {
  971.                 return rc;
  972.             }

  973.             st->id = st->vlint.value;
  974.             st->state = sw_value;
  975.             break;

  976.         case sw_value:

  977.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  978.             if (rc != NGX_DONE) {
  979.                 return rc;
  980.             }

  981.             if (ngx_http_v3_set_param(c, st->id, st->vlint.value) != NGX_OK) {
  982.                 return NGX_HTTP_V3_ERR_SETTINGS_ERROR;
  983.             }

  984.             goto done;
  985.         }
  986.     }

  987. done:

  988.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse settings done");

  989.     st->state = sw_start;
  990.     return NGX_DONE;
  991. }


  992. static ngx_int_t
  993. ngx_http_v3_parse_encoder(ngx_connection_t *c, ngx_http_v3_parse_encoder_t *st,
  994.     ngx_buf_t *b)
  995. {
  996.     u_char     ch;
  997.     ngx_int_t  rc;
  998.     enum {
  999.         sw_start = 0,
  1000.         sw_inr,
  1001.         sw_iln,
  1002.         sw_capacity,
  1003.         sw_duplicate
  1004.     };

  1005.     for ( ;; ) {

  1006.         if (st->state == sw_start) {

  1007.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1008.                            "http3 parse encoder instruction");

  1009.             if (b->pos == b->last) {
  1010.                 return NGX_AGAIN;
  1011.             }

  1012.             ch = *b->pos;

  1013.             if (ch & 0x80) {
  1014.                 /* Insert With Name Reference */

  1015.                 st->state = sw_inr;

  1016.             } else if (ch & 0x40) {
  1017.                 /* Insert With Literal Name */

  1018.                 st->state = sw_iln;

  1019.             } else if (ch & 0x20) {
  1020.                 /* Set Dynamic Table Capacity */

  1021.                 st->state = sw_capacity;

  1022.             } else {
  1023.                 /* Duplicate */

  1024.                 st->state = sw_duplicate;
  1025.             }
  1026.         }

  1027.         switch (st->state) {

  1028.         case sw_inr:

  1029.             rc = ngx_http_v3_parse_field_inr(c, &st->field, b);
  1030.             if (rc != NGX_DONE) {
  1031.                 return rc;
  1032.             }

  1033.             st->state = sw_start;
  1034.             break;

  1035.         case sw_iln:

  1036.             rc = ngx_http_v3_parse_field_iln(c, &st->field, b);
  1037.             if (rc != NGX_DONE) {
  1038.                 return rc;
  1039.             }

  1040.             st->state = sw_start;
  1041.             break;

  1042.         case sw_capacity:

  1043.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, b);
  1044.             if (rc != NGX_DONE) {
  1045.                 return rc;
  1046.             }

  1047.             rc = ngx_http_v3_set_capacity(c, st->pint.value);
  1048.             if (rc != NGX_OK) {
  1049.                 return rc;
  1050.             }

  1051.             st->state = sw_start;
  1052.             break;

  1053.         default: /* sw_duplicate */

  1054.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, b);
  1055.             if (rc != NGX_DONE) {
  1056.                 return rc;
  1057.             }

  1058.             rc = ngx_http_v3_duplicate(c, st->pint.value);
  1059.             if (rc != NGX_OK) {
  1060.                 return rc;
  1061.             }

  1062.             st->state = sw_start;
  1063.             break;
  1064.         }
  1065.     }
  1066. }


  1067. static ngx_int_t
  1068. ngx_http_v3_parse_field_inr(ngx_connection_t *c,
  1069.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  1070. {
  1071.     u_char     ch;
  1072.     ngx_int_t  rc;
  1073.     enum {
  1074.         sw_start = 0,
  1075.         sw_name_index,
  1076.         sw_value_len,
  1077.         sw_read_value_len,
  1078.         sw_value
  1079.     };

  1080.     for ( ;; ) {

  1081.         switch (st->state) {

  1082.         case sw_start:

  1083.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1084.                            "http3 parse field inr");

  1085.             if (b->pos == b->last) {
  1086.                 return NGX_AGAIN;
  1087.             }

  1088.             ch = *b->pos;

  1089.             st->literal.buf = ngx_http_v3_get_insert_buffer(c);
  1090.             if (st->literal.buf == NULL) {
  1091.                 return NGX_ERROR;
  1092.             }

  1093.             st->dynamic = (ch & 0x40) ? 0 : 1;
  1094.             st->state = sw_name_index;

  1095.             /* fall through */

  1096.         case sw_name_index:

  1097.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  1098.             if (rc != NGX_DONE) {
  1099.                 return rc;
  1100.             }

  1101.             st->index = st->pint.value;
  1102.             st->state = sw_value_len;
  1103.             break;

  1104.         case sw_value_len:

  1105.             if (b->pos == b->last) {
  1106.                 return NGX_AGAIN;
  1107.             }

  1108.             ch = *b->pos;

  1109.             st->literal.huffman = (ch & 0x80) ? 1 : 0;
  1110.             st->state = sw_read_value_len;

  1111.             /* fall through */

  1112.         case sw_read_value_len:

  1113.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  1114.             if (rc != NGX_DONE) {
  1115.                 return rc;
  1116.             }

  1117.             st->literal.length = st->pint.value;
  1118.             if (st->literal.length == 0) {
  1119.                 st->value.len = 0;
  1120.                 goto done;
  1121.             }

  1122.             st->state = sw_value;
  1123.             break;

  1124.         case sw_value:

  1125.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  1126.             if (rc != NGX_DONE) {
  1127.                 return rc;
  1128.             }

  1129.             st->value = st->literal.value;
  1130.             goto done;
  1131.         }
  1132.     }

  1133. done:

  1134.     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1135.                    "http3 parse field inr done %s[%ui] \"%V\"",
  1136.                    st->dynamic ? "dynamic" : "static",
  1137.                    st->index, &st->value);

  1138.     rc = ngx_http_v3_ref_insert(c, st->dynamic, st->index, &st->value);
  1139.     if (rc != NGX_OK) {
  1140.         return rc;
  1141.     }

  1142.     st->state = sw_start;
  1143.     return NGX_DONE;
  1144. }


  1145. static ngx_int_t
  1146. ngx_http_v3_parse_field_iln(ngx_connection_t *c,
  1147.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  1148. {
  1149.     u_char     ch;
  1150.     ngx_int_t  rc;
  1151.     enum {
  1152.         sw_start = 0,
  1153.         sw_name_len,
  1154.         sw_name,
  1155.         sw_value_len,
  1156.         sw_read_value_len,
  1157.         sw_value
  1158.     };

  1159.     for ( ;; ) {

  1160.         switch (st->state) {

  1161.         case sw_start:

  1162.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1163.                            "http3 parse field iln");

  1164.             if (b->pos == b->last) {
  1165.                 return NGX_AGAIN;
  1166.             }

  1167.             ch = *b->pos;

  1168.             st->literal.buf = ngx_http_v3_get_insert_buffer(c);
  1169.             if (st->literal.buf == NULL) {
  1170.                 return NGX_ERROR;
  1171.             }

  1172.             st->literal.huffman = (ch & 0x20) ? 1 : 0;
  1173.             st->state = sw_name_len;

  1174.             /* fall through */

  1175.         case sw_name_len:

  1176.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, b);
  1177.             if (rc != NGX_DONE) {
  1178.                 return rc;
  1179.             }

  1180.             st->literal.length = st->pint.value;
  1181.             if (st->literal.length == 0) {
  1182.                 return NGX_ERROR;
  1183.             }

  1184.             st->state = sw_name;
  1185.             break;

  1186.         case sw_name:

  1187.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  1188.             if (rc != NGX_DONE) {
  1189.                 return rc;
  1190.             }

  1191.             st->name = st->literal.value;
  1192.             st->state = sw_value_len;
  1193.             break;

  1194.         case sw_value_len:

  1195.             if (b->pos == b->last) {
  1196.                 return NGX_AGAIN;
  1197.             }

  1198.             ch = *b->pos;

  1199.             st->literal.huffman = (ch & 0x80) ? 1 : 0;
  1200.             st->state = sw_read_value_len;

  1201.             /* fall through */

  1202.         case sw_read_value_len:

  1203.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  1204.             if (rc != NGX_DONE) {
  1205.                 return rc;
  1206.             }

  1207.             st->literal.length = st->pint.value;
  1208.             if (st->literal.length == 0) {
  1209.                 st->value.len = 0;
  1210.                 goto done;
  1211.             }

  1212.             st->state = sw_value;
  1213.             break;

  1214.         case sw_value:

  1215.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  1216.             if (rc != NGX_DONE) {
  1217.                 return rc;
  1218.             }

  1219.             st->value = st->literal.value;
  1220.             goto done;
  1221.         }
  1222.     }

  1223. done:

  1224.     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1225.                    "http3 parse field iln done \"%V\":\"%V\"",
  1226.                    &st->name, &st->value);

  1227.     rc = ngx_http_v3_insert(c, &st->name, &st->value);
  1228.     if (rc != NGX_OK) {
  1229.         return rc;
  1230.     }

  1231.     st->state = sw_start;
  1232.     return NGX_DONE;
  1233. }


  1234. static ngx_int_t
  1235. ngx_http_v3_parse_decoder(ngx_connection_t *c, ngx_http_v3_parse_decoder_t *st,
  1236.     ngx_buf_t *b)
  1237. {
  1238.     u_char     ch;
  1239.     ngx_int_t  rc;
  1240.     enum {
  1241.         sw_start = 0,
  1242.         sw_ack_section,
  1243.         sw_cancel_stream,
  1244.         sw_inc_insert_count
  1245.     };

  1246.     for ( ;; ) {

  1247.         if (st->state == sw_start) {

  1248.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1249.                            "http3 parse decoder instruction");

  1250.             if (b->pos == b->last) {
  1251.                 return NGX_AGAIN;
  1252.             }

  1253.             ch = *b->pos;

  1254.             if (ch & 0x80) {
  1255.                 /* Section Acknowledgment */

  1256.                 st->state = sw_ack_section;

  1257.             } else if (ch & 0x40) {
  1258.                 /*  Stream Cancellation */

  1259.                 st->state = sw_cancel_stream;

  1260.             }  else {
  1261.                 /*  Insert Count Increment */

  1262.                 st->state = sw_inc_insert_count;
  1263.             }
  1264.         }

  1265.         switch (st->state) {

  1266.         case sw_ack_section:

  1267.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  1268.             if (rc != NGX_DONE) {
  1269.                 return rc;
  1270.             }

  1271.             rc = ngx_http_v3_ack_section(c, st->pint.value);
  1272.             if (rc != NGX_OK) {
  1273.                 return rc;
  1274.             }

  1275.             st->state = sw_start;
  1276.             break;

  1277.         case sw_cancel_stream:

  1278.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  1279.             if (rc != NGX_DONE) {
  1280.                 return rc;
  1281.             }

  1282.             rc = ngx_http_v3_cancel_stream(c, st->pint.value);
  1283.             if (rc != NGX_OK) {
  1284.                 return rc;
  1285.             }

  1286.             st->state = sw_start;
  1287.             break;

  1288.         case sw_inc_insert_count:

  1289.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  1290.             if (rc != NGX_DONE) {
  1291.                 return rc;
  1292.             }

  1293.             rc = ngx_http_v3_inc_insert_count(c, st->pint.value);
  1294.             if (rc != NGX_OK) {
  1295.                 return rc;
  1296.             }

  1297.             st->state = sw_start;
  1298.             break;
  1299.         }
  1300.     }
  1301. }


  1302. ngx_int_t
  1303. ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st,
  1304.     ngx_buf_t *b)
  1305. {
  1306.     ngx_int_t  rc;
  1307.     enum {
  1308.         sw_start = 0,
  1309.         sw_type,
  1310.         sw_length,
  1311.         sw_skip
  1312.     };

  1313.     for ( ;; ) {

  1314.         switch (st->state) {

  1315.         case sw_start:

  1316.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse data");

  1317.             st->state = sw_type;

  1318.             /* fall through */

  1319.         case sw_type:

  1320.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  1321.             if (rc != NGX_DONE) {
  1322.                 return rc;
  1323.             }

  1324.             st->type = st->vlint.value;

  1325.             if (st->type == NGX_HTTP_V3_FRAME_HEADERS) {
  1326.                 /* trailers */
  1327.                 goto done;
  1328.             }

  1329.             if (ngx_http_v3_is_v2_frame(st->type)
  1330.                 || st->type == NGX_HTTP_V3_FRAME_GOAWAY
  1331.                 || st->type == NGX_HTTP_V3_FRAME_SETTINGS
  1332.                 || st->type == NGX_HTTP_V3_FRAME_MAX_PUSH_ID
  1333.                 || st->type == NGX_HTTP_V3_FRAME_CANCEL_PUSH
  1334.                 || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
  1335.             {
  1336.                 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
  1337.             }

  1338.             st->state = sw_length;
  1339.             break;

  1340.         case sw_length:

  1341.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  1342.             if (rc != NGX_DONE) {
  1343.                 return rc;
  1344.             }

  1345.             st->length = st->vlint.value;

  1346.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1347.                            "http3 parse data type:%ui, len:%ui",
  1348.                            st->type, st->length);

  1349.             if (st->type != NGX_HTTP_V3_FRAME_DATA && st->length > 0) {
  1350.                 st->state = sw_skip;
  1351.                 break;
  1352.             }

  1353.             st->state = sw_type;
  1354.             return NGX_OK;

  1355.         case sw_skip:

  1356.             rc = ngx_http_v3_parse_skip(b, &st->length);
  1357.             if (rc != NGX_DONE) {
  1358.                 return rc;
  1359.             }

  1360.             st->state = sw_type;
  1361.             break;
  1362.         }
  1363.     }

  1364. done:

  1365.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse data done");

  1366.     st->state = sw_start;
  1367.     return NGX_DONE;
  1368. }


  1369. ngx_int_t
  1370. ngx_http_v3_parse_uni(ngx_connection_t *c, ngx_http_v3_parse_uni_t *st,
  1371.     ngx_buf_t *b)
  1372. {
  1373.     ngx_int_t  rc;
  1374.     enum {
  1375.         sw_start = 0,
  1376.         sw_type,
  1377.         sw_control,
  1378.         sw_encoder,
  1379.         sw_decoder,
  1380.         sw_unknown
  1381.     };

  1382.     for ( ;; ) {

  1383.         switch (st->state) {
  1384.         case sw_start:

  1385.             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse uni");

  1386.             st->state = sw_type;

  1387.             /* fall through */

  1388.         case sw_type:

  1389.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  1390.             if (rc != NGX_DONE) {
  1391.                 return rc;
  1392.             }

  1393.             rc = ngx_http_v3_register_uni_stream(c, st->vlint.value);
  1394.             if (rc != NGX_OK) {
  1395.                 return rc;
  1396.             }

  1397.             switch (st->vlint.value) {
  1398.             case NGX_HTTP_V3_STREAM_CONTROL:
  1399.                 st->state = sw_control;
  1400.                 break;

  1401.             case NGX_HTTP_V3_STREAM_ENCODER:
  1402.                 st->state = sw_encoder;
  1403.                 break;

  1404.             case NGX_HTTP_V3_STREAM_DECODER:
  1405.                 st->state = sw_decoder;
  1406.                 break;

  1407.             default:
  1408.                 st->state = sw_unknown;
  1409.             }

  1410.             break;

  1411.         case sw_control:

  1412.             return ngx_http_v3_parse_control(c, &st->u.control, b);

  1413.         case sw_encoder:

  1414.             return ngx_http_v3_parse_encoder(c, &st->u.encoder, b);

  1415.         case sw_decoder:

  1416.             return ngx_http_v3_parse_decoder(c, &st->u.decoder, b);

  1417.         case sw_unknown:

  1418.             b->pos = b->last;
  1419.             return NGX_AGAIN;
  1420.         }
  1421.     }
  1422. }