src/http/v3/ngx_http_v3_parse.c - nginx source code

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.                 n = n * 8 / 5;
  455.                 st->huffstate = 0;
  456.             }

  457.             st->last = ngx_pnalloc(c->pool, n + 1);
  458.             if (st->last == NULL) {
  459.                 return NGX_ERROR;
  460.             }

  461.             st->value.data = st->last;
  462.             st->state = sw_value;

  463.             /* fall through */

  464.         case sw_value:

  465.             if (b->pos == b->last) {
  466.                 return NGX_AGAIN;
  467.             }

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

  469.             if (st->huffman) {
  470.                 if (ngx_http_huff_decode(&st->huffstate, &ch, 1, &st->last,
  471.                                          st->length == 1, c->log)
  472.                     != NGX_OK)
  473.                 {
  474.                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
  475.                                   "client sent invalid encoded field line");
  476.                     return NGX_ERROR;
  477.                 }

  478.             } else {
  479.                 *st->last++ = ch;
  480.             }

  481.             if (--st->length) {
  482.                 break;
  483.             }

  484.             st->value.len = st->last - st->value.data;
  485.             *st->last = '\0';
  486.             goto done;
  487.         }
  488.     }

  489. done:

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

  492.     st->state = sw_start;
  493.     return NGX_DONE;
  494. }


  495. static ngx_int_t
  496. ngx_http_v3_parse_field_ri(ngx_connection_t *c, ngx_http_v3_parse_field_t *st,
  497.     ngx_buf_t *b)
  498. {
  499.     u_char     ch;
  500.     ngx_int_t  rc;
  501.     enum {
  502.         sw_start = 0,
  503.         sw_index
  504.     };

  505.     for ( ;; ) {

  506.         switch (st->state) {

  507.         case sw_start:

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

  510.             if (b->pos == b->last) {
  511.                 return NGX_AGAIN;
  512.             }

  513.             ch = *b->pos;

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

  516.             /* fall through */

  517.         case sw_index:

  518.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  519.             if (rc != NGX_DONE) {
  520.                 return rc;
  521.             }

  522.             st->index = st->pint.value;
  523.             goto done;
  524.         }
  525.     }

  526. done:

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

  530.     if (st->dynamic) {
  531.         st->index = st->base - st->index - 1;
  532.     }

  533.     rc = ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name,
  534.                                   &st->value);
  535.     if (rc != NGX_OK) {
  536.         return rc;
  537.     }

  538.     st->state = sw_start;
  539.     return NGX_DONE;
  540. }


  541. static ngx_int_t
  542. ngx_http_v3_parse_field_lri(ngx_connection_t *c,
  543.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  544. {
  545.     u_char     ch;
  546.     ngx_int_t  rc;
  547.     enum {
  548.         sw_start = 0,
  549.         sw_index,
  550.         sw_value_len,
  551.         sw_read_value_len,
  552.         sw_value
  553.     };

  554.     for ( ;; ) {

  555.         switch (st->state) {

  556.         case sw_start:

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

  559.             if (b->pos == b->last) {
  560.                 return NGX_AGAIN;
  561.             }

  562.             ch = *b->pos;

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

  565.             /* fall through */

  566.         case sw_index:

  567.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 4, b);
  568.             if (rc != NGX_DONE) {
  569.                 return rc;
  570.             }

  571.             st->index = st->pint.value;
  572.             st->state = sw_value_len;
  573.             break;

  574.         case sw_value_len:

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

  578.             ch = *b->pos;

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

  581.             /* fall through */

  582.         case sw_read_value_len:

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

  587.             st->literal.length = st->pint.value;
  588.             if (st->literal.length == 0) {
  589.                 st->value.data = (u_char *) "";
  590.                 goto done;
  591.             }

  592.             st->state = sw_value;
  593.             break;

  594.         case sw_value:

  595.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  596.             if (rc != NGX_DONE) {
  597.                 return rc;
  598.             }

  599.             st->value = st->literal.value;
  600.             goto done;
  601.         }
  602.     }

  603. done:

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

  608.     if (st->dynamic) {
  609.         st->index = st->base - st->index - 1;
  610.     }

  611.     rc = ngx_http_v3_parse_lookup(c, st->dynamic, st->index, &st->name, NULL);
  612.     if (rc != NGX_OK) {
  613.         return rc;
  614.     }

  615.     st->state = sw_start;
  616.     return NGX_DONE;
  617. }


  618. static ngx_int_t
  619. ngx_http_v3_parse_field_l(ngx_connection_t *c,
  620.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  621. {
  622.     u_char     ch;
  623.     ngx_int_t  rc;
  624.     enum {
  625.         sw_start = 0,
  626.         sw_name_len,
  627.         sw_name,
  628.         sw_value_len,
  629.         sw_read_value_len,
  630.         sw_value
  631.     };

  632.     for ( ;; ) {

  633.         switch (st->state) {

  634.         case sw_start:

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

  637.             if (b->pos == b->last) {
  638.                 return NGX_AGAIN;
  639.             }

  640.             ch = *b->pos;

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

  643.             /* fall through */

  644.         case sw_name_len:

  645.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 3, b);
  646.             if (rc != NGX_DONE) {
  647.                 return rc;
  648.             }

  649.             st->literal.length = st->pint.value;
  650.             if (st->literal.length == 0) {
  651.                 return NGX_ERROR;
  652.             }

  653.             st->state = sw_name;
  654.             break;

  655.         case sw_name:

  656.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  657.             if (rc != NGX_DONE) {
  658.                 return rc;
  659.             }

  660.             st->name = st->literal.value;
  661.             st->state = sw_value_len;
  662.             break;

  663.         case sw_value_len:

  664.             if (b->pos == b->last) {
  665.                 return NGX_AGAIN;
  666.             }

  667.             ch = *b->pos;

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

  670.             /* fall through */

  671.         case sw_read_value_len:

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

  676.             st->literal.length = st->pint.value;
  677.             if (st->literal.length == 0) {
  678.                 st->value.data = (u_char *) "";
  679.                 goto done;
  680.             }

  681.             st->state = sw_value;
  682.             break;

  683.         case sw_value:

  684.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  685.             if (rc != NGX_DONE) {
  686.                 return rc;
  687.             }

  688.             st->value = st->literal.value;
  689.             goto done;
  690.         }
  691.     }

  692. done:

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

  696.     st->state = sw_start;
  697.     return NGX_DONE;
  698. }


  699. static ngx_int_t
  700. ngx_http_v3_parse_field_pbi(ngx_connection_t *c,
  701.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  702. {
  703.     ngx_int_t  rc;
  704.     enum {
  705.         sw_start = 0,
  706.         sw_index
  707.     };

  708.     for ( ;; ) {

  709.         switch (st->state) {

  710.         case sw_start:

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

  713.             st->state = sw_index;

  714.             /* fall through */

  715.         case sw_index:

  716.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 4, b);
  717.             if (rc != NGX_DONE) {
  718.                 return rc;
  719.             }

  720.             st->index = st->pint.value;
  721.             goto done;
  722.         }
  723.     }

  724. done:

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

  727.     rc = ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name,
  728.                                   &st->value);
  729.     if (rc != NGX_OK) {
  730.         return rc;
  731.     }

  732.     st->state = sw_start;
  733.     return NGX_DONE;
  734. }


  735. static ngx_int_t
  736. ngx_http_v3_parse_field_lpbi(ngx_connection_t *c,
  737.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  738. {
  739.     u_char     ch;
  740.     ngx_int_t  rc;
  741.     enum {
  742.         sw_start = 0,
  743.         sw_index,
  744.         sw_value_len,
  745.         sw_read_value_len,
  746.         sw_value
  747.     };

  748.     for ( ;; ) {

  749.         switch (st->state) {

  750.         case sw_start:

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

  753.             st->state = sw_index;

  754.             /* fall through */

  755.         case sw_index:

  756.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 3, b);
  757.             if (rc != NGX_DONE) {
  758.                 return rc;
  759.             }

  760.             st->index = st->pint.value;
  761.             st->state = sw_value_len;
  762.             break;

  763.         case sw_value_len:

  764.             if (b->pos == b->last) {
  765.                 return NGX_AGAIN;
  766.             }

  767.             ch = *b->pos;

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

  770.             /* fall through */

  771.         case sw_read_value_len:

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

  776.             st->literal.length = st->pint.value;
  777.             if (st->literal.length == 0) {
  778.                 st->value.data = (u_char *) "";
  779.                 goto done;
  780.             }

  781.             st->state = sw_value;
  782.             break;

  783.         case sw_value:

  784.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  785.             if (rc != NGX_DONE) {
  786.                 return rc;
  787.             }

  788.             st->value = st->literal.value;
  789.             goto done;
  790.         }
  791.     }

  792. done:

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

  796.     rc = ngx_http_v3_parse_lookup(c, 1, st->base + st->index, &st->name, NULL);
  797.     if (rc != NGX_OK) {
  798.         return rc;
  799.     }

  800.     st->state = sw_start;
  801.     return NGX_DONE;
  802. }


  803. static ngx_int_t
  804. ngx_http_v3_parse_lookup(ngx_connection_t *c, ngx_uint_t dynamic,
  805.     ngx_uint_t index, ngx_str_t *name, ngx_str_t *value)
  806. {
  807.     u_char  *p;

  808.     if (!dynamic) {
  809.         if (ngx_http_v3_lookup_static(c, index, name, value) != NGX_OK) {
  810.             return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
  811.         }

  812.         return NGX_OK;
  813.     }

  814.     if (ngx_http_v3_lookup(c, index, name, value) != NGX_OK) {
  815.         return NGX_HTTP_V3_ERR_DECOMPRESSION_FAILED;
  816.     }

  817.     if (name) {
  818.         p = ngx_pnalloc(c->pool, name->len + 1);
  819.         if (p == NULL) {
  820.             return NGX_ERROR;
  821.         }

  822.         ngx_memcpy(p, name->data, name->len);
  823.         p[name->len] = '\0';
  824.         name->data = p;
  825.     }

  826.     if (value) {
  827.         p = ngx_pnalloc(c->pool, value->len + 1);
  828.         if (p == NULL) {
  829.             return NGX_ERROR;
  830.         }

  831.         ngx_memcpy(p, value->data, value->len);
  832.         p[value->len] = '\0';
  833.         value->data = p;
  834.     }

  835.     return NGX_OK;
  836. }


  837. static ngx_int_t
  838. ngx_http_v3_parse_control(ngx_connection_t *c, ngx_http_v3_parse_control_t *st,
  839.     ngx_buf_t *b)
  840. {
  841.     ngx_buf_t  loc;
  842.     ngx_int_t  rc;
  843.     enum {
  844.         sw_start = 0,
  845.         sw_first_type,
  846.         sw_type,
  847.         sw_length,
  848.         sw_settings,
  849.         sw_skip
  850.     };

  851.     for ( ;; ) {

  852.         switch (st->state) {

  853.         case sw_start:

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

  856.             st->state = sw_first_type;

  857.             /* fall through */

  858.         case sw_first_type:
  859.         case sw_type:

  860.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  861.             if (rc != NGX_DONE) {
  862.                 return rc;
  863.             }

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

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

  867.             if (st->state == sw_first_type
  868.                 && st->type != NGX_HTTP_V3_FRAME_SETTINGS)
  869.             {
  870.                 return NGX_HTTP_V3_ERR_MISSING_SETTINGS;
  871.             }

  872.             if (st->state != sw_first_type
  873.                 && st->type == NGX_HTTP_V3_FRAME_SETTINGS)
  874.             {
  875.                 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
  876.             }

  877.             if (ngx_http_v3_is_v2_frame(st->type)
  878.                 || st->type == NGX_HTTP_V3_FRAME_DATA
  879.                 || st->type == NGX_HTTP_V3_FRAME_HEADERS
  880.                 || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
  881.             {
  882.                 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
  883.             }

  884.             if (st->type == NGX_HTTP_V3_FRAME_CANCEL_PUSH) {
  885.                 return NGX_HTTP_V3_ERR_ID_ERROR;
  886.             }

  887.             st->state = sw_length;
  888.             break;

  889.         case sw_length:

  890.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  891.             if (rc != NGX_DONE) {
  892.                 return rc;
  893.             }

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

  896.             st->length = st->vlint.value;
  897.             if (st->length == 0) {
  898.                 st->state = sw_type;
  899.                 break;
  900.             }

  901.             switch (st->type) {

  902.             case NGX_HTTP_V3_FRAME_SETTINGS:
  903.                 st->state = sw_settings;
  904.                 break;

  905.             default:
  906.                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  907.                                "http3 parse skip unknown frame");
  908.                 st->state = sw_skip;
  909.             }

  910.             break;

  911.         case sw_settings:

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

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

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

  915.             if (st->length == 0 && rc == NGX_AGAIN) {
  916.                 return NGX_HTTP_V3_ERR_SETTINGS_ERROR;
  917.             }

  918.             if (rc != NGX_DONE) {
  919.                 return rc;
  920.             }

  921.             if (st->length == 0) {
  922.                 st->state = sw_type;
  923.             }

  924.             break;

  925.         case sw_skip:

  926.             rc = ngx_http_v3_parse_skip(b, &st->length);
  927.             if (rc != NGX_DONE) {
  928.                 return rc;
  929.             }

  930.             st->state = sw_type;
  931.             break;
  932.         }
  933.     }
  934. }


  935. static ngx_int_t
  936. ngx_http_v3_parse_settings(ngx_connection_t *c,
  937.     ngx_http_v3_parse_settings_t *st, ngx_buf_t *b)
  938. {
  939.     ngx_int_t  rc;
  940.     enum {
  941.         sw_start = 0,
  942.         sw_id,
  943.         sw_value
  944.     };

  945.     for ( ;; ) {

  946.         switch (st->state) {

  947.         case sw_start:

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

  950.             st->state = sw_id;

  951.             /* fall through */

  952.         case sw_id:

  953.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  954.             if (rc != NGX_DONE) {
  955.                 return rc;
  956.             }

  957.             st->id = st->vlint.value;
  958.             st->state = sw_value;
  959.             break;

  960.         case sw_value:

  961.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  962.             if (rc != NGX_DONE) {
  963.                 return rc;
  964.             }

  965.             if (ngx_http_v3_set_param(c, st->id, st->vlint.value) != NGX_OK) {
  966.                 return NGX_HTTP_V3_ERR_SETTINGS_ERROR;
  967.             }

  968.             goto done;
  969.         }
  970.     }

  971. done:

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

  973.     st->state = sw_start;
  974.     return NGX_DONE;
  975. }


  976. static ngx_int_t
  977. ngx_http_v3_parse_encoder(ngx_connection_t *c, ngx_http_v3_parse_encoder_t *st,
  978.     ngx_buf_t *b)
  979. {
  980.     u_char     ch;
  981.     ngx_int_t  rc;
  982.     enum {
  983.         sw_start = 0,
  984.         sw_inr,
  985.         sw_iln,
  986.         sw_capacity,
  987.         sw_duplicate
  988.     };

  989.     for ( ;; ) {

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

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

  993.             if (b->pos == b->last) {
  994.                 return NGX_AGAIN;
  995.             }

  996.             ch = *b->pos;

  997.             if (ch & 0x80) {
  998.                 /* Insert With Name Reference */

  999.                 st->state = sw_inr;

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

  1002.                 st->state = sw_iln;

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

  1005.                 st->state = sw_capacity;

  1006.             } else {
  1007.                 /* Duplicate */

  1008.                 st->state = sw_duplicate;
  1009.             }
  1010.         }

  1011.         switch (st->state) {

  1012.         case sw_inr:

  1013.             rc = ngx_http_v3_parse_field_inr(c, &st->field, b);
  1014.             if (rc != NGX_DONE) {
  1015.                 return rc;
  1016.             }

  1017.             st->state = sw_start;
  1018.             break;

  1019.         case sw_iln:

  1020.             rc = ngx_http_v3_parse_field_iln(c, &st->field, b);
  1021.             if (rc != NGX_DONE) {
  1022.                 return rc;
  1023.             }

  1024.             st->state = sw_start;
  1025.             break;

  1026.         case sw_capacity:

  1027.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, b);
  1028.             if (rc != NGX_DONE) {
  1029.                 return rc;
  1030.             }

  1031.             rc = ngx_http_v3_set_capacity(c, st->pint.value);
  1032.             if (rc != NGX_OK) {
  1033.                 return rc;
  1034.             }

  1035.             st->state = sw_start;
  1036.             break;

  1037.         default: /* sw_duplicate */

  1038.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, b);
  1039.             if (rc != NGX_DONE) {
  1040.                 return rc;
  1041.             }

  1042.             rc = ngx_http_v3_duplicate(c, st->pint.value);
  1043.             if (rc != NGX_OK) {
  1044.                 return rc;
  1045.             }

  1046.             st->state = sw_start;
  1047.             break;
  1048.         }
  1049.     }
  1050. }


  1051. static ngx_int_t
  1052. ngx_http_v3_parse_field_inr(ngx_connection_t *c,
  1053.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  1054. {
  1055.     u_char     ch;
  1056.     ngx_int_t  rc;
  1057.     enum {
  1058.         sw_start = 0,
  1059.         sw_name_index,
  1060.         sw_value_len,
  1061.         sw_read_value_len,
  1062.         sw_value
  1063.     };

  1064.     for ( ;; ) {

  1065.         switch (st->state) {

  1066.         case sw_start:

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

  1069.             if (b->pos == b->last) {
  1070.                 return NGX_AGAIN;
  1071.             }

  1072.             ch = *b->pos;

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

  1075.             /* fall through */

  1076.         case sw_name_index:

  1077.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  1078.             if (rc != NGX_DONE) {
  1079.                 return rc;
  1080.             }

  1081.             st->index = st->pint.value;
  1082.             st->state = sw_value_len;
  1083.             break;

  1084.         case sw_value_len:

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

  1088.             ch = *b->pos;

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

  1091.             /* fall through */

  1092.         case sw_read_value_len:

  1093.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  1094.             if (rc != NGX_DONE) {
  1095.                 return rc;
  1096.             }

  1097.             st->literal.length = st->pint.value;
  1098.             if (st->literal.length == 0) {
  1099.                 st->value.len = 0;
  1100.                 goto done;
  1101.             }

  1102.             st->state = sw_value;
  1103.             break;

  1104.         case sw_value:

  1105.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  1106.             if (rc != NGX_DONE) {
  1107.                 return rc;
  1108.             }

  1109.             st->value = st->literal.value;
  1110.             goto done;
  1111.         }
  1112.     }

  1113. done:

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

  1118.     rc = ngx_http_v3_ref_insert(c, st->dynamic, st->index, &st->value);
  1119.     if (rc != NGX_OK) {
  1120.         return rc;
  1121.     }

  1122.     st->state = sw_start;
  1123.     return NGX_DONE;
  1124. }


  1125. static ngx_int_t
  1126. ngx_http_v3_parse_field_iln(ngx_connection_t *c,
  1127.     ngx_http_v3_parse_field_t *st, ngx_buf_t *b)
  1128. {
  1129.     u_char     ch;
  1130.     ngx_int_t  rc;
  1131.     enum {
  1132.         sw_start = 0,
  1133.         sw_name_len,
  1134.         sw_name,
  1135.         sw_value_len,
  1136.         sw_read_value_len,
  1137.         sw_value
  1138.     };

  1139.     for ( ;; ) {

  1140.         switch (st->state) {

  1141.         case sw_start:

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

  1144.             if (b->pos == b->last) {
  1145.                 return NGX_AGAIN;
  1146.             }

  1147.             ch = *b->pos;

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

  1150.             /* fall through */

  1151.         case sw_name_len:

  1152.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 5, b);
  1153.             if (rc != NGX_DONE) {
  1154.                 return rc;
  1155.             }

  1156.             st->literal.length = st->pint.value;
  1157.             if (st->literal.length == 0) {
  1158.                 return NGX_ERROR;
  1159.             }

  1160.             st->state = sw_name;
  1161.             break;

  1162.         case sw_name:

  1163.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  1164.             if (rc != NGX_DONE) {
  1165.                 return rc;
  1166.             }

  1167.             st->name = st->literal.value;
  1168.             st->state = sw_value_len;
  1169.             break;

  1170.         case sw_value_len:

  1171.             if (b->pos == b->last) {
  1172.                 return NGX_AGAIN;
  1173.             }

  1174.             ch = *b->pos;

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

  1177.             /* fall through */

  1178.         case sw_read_value_len:

  1179.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  1180.             if (rc != NGX_DONE) {
  1181.                 return rc;
  1182.             }

  1183.             st->literal.length = st->pint.value;
  1184.             if (st->literal.length == 0) {
  1185.                 st->value.len = 0;
  1186.                 goto done;
  1187.             }

  1188.             st->state = sw_value;
  1189.             break;

  1190.         case sw_value:

  1191.             rc = ngx_http_v3_parse_literal(c, &st->literal, b);
  1192.             if (rc != NGX_DONE) {
  1193.                 return rc;
  1194.             }

  1195.             st->value = st->literal.value;
  1196.             goto done;
  1197.         }
  1198.     }

  1199. done:

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

  1203.     rc = ngx_http_v3_insert(c, &st->name, &st->value);
  1204.     if (rc != NGX_OK) {
  1205.         return rc;
  1206.     }

  1207.     st->state = sw_start;
  1208.     return NGX_DONE;
  1209. }


  1210. static ngx_int_t
  1211. ngx_http_v3_parse_decoder(ngx_connection_t *c, ngx_http_v3_parse_decoder_t *st,
  1212.     ngx_buf_t *b)
  1213. {
  1214.     u_char     ch;
  1215.     ngx_int_t  rc;
  1216.     enum {
  1217.         sw_start = 0,
  1218.         sw_ack_section,
  1219.         sw_cancel_stream,
  1220.         sw_inc_insert_count
  1221.     };

  1222.     for ( ;; ) {

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

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

  1226.             if (b->pos == b->last) {
  1227.                 return NGX_AGAIN;
  1228.             }

  1229.             ch = *b->pos;

  1230.             if (ch & 0x80) {
  1231.                 /* Section Acknowledgment */

  1232.                 st->state = sw_ack_section;

  1233.             } else if (ch & 0x40) {
  1234.                 /*  Stream Cancellation */

  1235.                 st->state = sw_cancel_stream;

  1236.             }  else {
  1237.                 /*  Insert Count Increment */

  1238.                 st->state = sw_inc_insert_count;
  1239.             }
  1240.         }

  1241.         switch (st->state) {

  1242.         case sw_ack_section:

  1243.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 7, b);
  1244.             if (rc != NGX_DONE) {
  1245.                 return rc;
  1246.             }

  1247.             rc = ngx_http_v3_ack_section(c, st->pint.value);
  1248.             if (rc != NGX_OK) {
  1249.                 return rc;
  1250.             }

  1251.             st->state = sw_start;
  1252.             break;

  1253.         case sw_cancel_stream:

  1254.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  1255.             if (rc != NGX_DONE) {
  1256.                 return rc;
  1257.             }

  1258.             rc = ngx_http_v3_cancel_stream(c, st->pint.value);
  1259.             if (rc != NGX_OK) {
  1260.                 return rc;
  1261.             }

  1262.             st->state = sw_start;
  1263.             break;

  1264.         case sw_inc_insert_count:

  1265.             rc = ngx_http_v3_parse_prefix_int(c, &st->pint, 6, b);
  1266.             if (rc != NGX_DONE) {
  1267.                 return rc;
  1268.             }

  1269.             rc = ngx_http_v3_inc_insert_count(c, st->pint.value);
  1270.             if (rc != NGX_OK) {
  1271.                 return rc;
  1272.             }

  1273.             st->state = sw_start;
  1274.             break;
  1275.         }
  1276.     }
  1277. }


  1278. ngx_int_t
  1279. ngx_http_v3_parse_data(ngx_connection_t *c, ngx_http_v3_parse_data_t *st,
  1280.     ngx_buf_t *b)
  1281. {
  1282.     ngx_int_t  rc;
  1283.     enum {
  1284.         sw_start = 0,
  1285.         sw_type,
  1286.         sw_length,
  1287.         sw_skip
  1288.     };

  1289.     for ( ;; ) {

  1290.         switch (st->state) {

  1291.         case sw_start:

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

  1293.             st->state = sw_type;

  1294.             /* fall through */

  1295.         case sw_type:

  1296.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  1297.             if (rc != NGX_DONE) {
  1298.                 return rc;
  1299.             }

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

  1301.             if (st->type == NGX_HTTP_V3_FRAME_HEADERS) {
  1302.                 /* trailers */
  1303.                 goto done;
  1304.             }

  1305.             if (ngx_http_v3_is_v2_frame(st->type)
  1306.                 || st->type == NGX_HTTP_V3_FRAME_GOAWAY
  1307.                 || st->type == NGX_HTTP_V3_FRAME_SETTINGS
  1308.                 || st->type == NGX_HTTP_V3_FRAME_MAX_PUSH_ID
  1309.                 || st->type == NGX_HTTP_V3_FRAME_CANCEL_PUSH
  1310.                 || st->type == NGX_HTTP_V3_FRAME_PUSH_PROMISE)
  1311.             {
  1312.                 return NGX_HTTP_V3_ERR_FRAME_UNEXPECTED;
  1313.             }

  1314.             st->state = sw_length;
  1315.             break;

  1316.         case sw_length:

  1317.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  1318.             if (rc != NGX_DONE) {
  1319.                 return rc;
  1320.             }

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

  1322.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
  1323.                            "http3 parse data type:%ui, len:%ui",
  1324.                            st->type, st->length);

  1325.             if (st->type != NGX_HTTP_V3_FRAME_DATA && st->length > 0) {
  1326.                 st->state = sw_skip;
  1327.                 break;
  1328.             }

  1329.             st->state = sw_type;
  1330.             return NGX_OK;

  1331.         case sw_skip:

  1332.             rc = ngx_http_v3_parse_skip(b, &st->length);
  1333.             if (rc != NGX_DONE) {
  1334.                 return rc;
  1335.             }

  1336.             st->state = sw_type;
  1337.             break;
  1338.         }
  1339.     }

  1340. done:

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

  1342.     st->state = sw_start;
  1343.     return NGX_DONE;
  1344. }


  1345. ngx_int_t
  1346. ngx_http_v3_parse_uni(ngx_connection_t *c, ngx_http_v3_parse_uni_t *st,
  1347.     ngx_buf_t *b)
  1348. {
  1349.     ngx_int_t  rc;
  1350.     enum {
  1351.         sw_start = 0,
  1352.         sw_type,
  1353.         sw_control,
  1354.         sw_encoder,
  1355.         sw_decoder,
  1356.         sw_unknown
  1357.     };

  1358.     for ( ;; ) {

  1359.         switch (st->state) {
  1360.         case sw_start:

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

  1362.             st->state = sw_type;

  1363.             /* fall through */

  1364.         case sw_type:

  1365.             rc = ngx_http_v3_parse_varlen_int(c, &st->vlint, b);
  1366.             if (rc != NGX_DONE) {
  1367.                 return rc;
  1368.             }

  1369.             rc = ngx_http_v3_register_uni_stream(c, st->vlint.value);
  1370.             if (rc != NGX_OK) {
  1371.                 return rc;
  1372.             }

  1373.             switch (st->vlint.value) {
  1374.             case NGX_HTTP_V3_STREAM_CONTROL:
  1375.                 st->state = sw_control;
  1376.                 break;

  1377.             case NGX_HTTP_V3_STREAM_ENCODER:
  1378.                 st->state = sw_encoder;
  1379.                 break;

  1380.             case NGX_HTTP_V3_STREAM_DECODER:
  1381.                 st->state = sw_decoder;
  1382.                 break;

  1383.             default:
  1384.                 st->state = sw_unknown;
  1385.             }

  1386.             break;

  1387.         case sw_control:

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

  1389.         case sw_encoder:

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

  1391.         case sw_decoder:

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

  1393.         case sw_unknown:

  1394.             b->pos = b->last;
  1395.             return NGX_AGAIN;
  1396.         }
  1397.     }
  1398. }