Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7677:6bc18966b8c1 quic
Stream "connection" read/write methods.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Fri, 13 Mar 2020 14:39:23 +0300 |
parents | 36fe31ce9582 |
children | e3c0b19a3a8a |
comparison
equal
deleted
inserted
replaced
7676:b761ca7df7d0 | 7677:6bc18966b8c1 |
---|---|
58 | 58 |
59 #define ngx_quic_write_uint32_aligned(p, s) \ | 59 #define ngx_quic_write_uint32_aligned(p, s) \ |
60 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) | 60 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) |
61 | 61 |
62 #define ngx_quic_varint_len(value) \ | 62 #define ngx_quic_varint_len(value) \ |
63 ((value) <= 63 ? 1 : (value) <= 16383 ? 2 : (value) <= 1073741823 ? 4 : 8) | 63 ((value) <= 63 ? 1 : ((uint32_t)value) <= 16383 ? 2 : ((uint64_t)value) <= 1073741823 ? 4 : 8) |
64 | 64 |
65 | 65 |
66 #if (NGX_DEBUG) | 66 #if (NGX_DEBUG) |
67 | 67 |
68 #define ngx_quic_hexdump(log, fmt, data, len, ...) \ | 68 #define ngx_quic_hexdump(log, fmt, data, len, ...) \ |
103 #define NGX_QUIC_FT_ACK_ECN 0x03 | 103 #define NGX_QUIC_FT_ACK_ECN 0x03 |
104 #define NGX_QUIC_FT_RESET_STREAM 0x04 | 104 #define NGX_QUIC_FT_RESET_STREAM 0x04 |
105 #define NGX_QUIC_FT_STOP_SENDING 0x05 | 105 #define NGX_QUIC_FT_STOP_SENDING 0x05 |
106 #define NGX_QUIC_FT_CRYPTO 0x06 | 106 #define NGX_QUIC_FT_CRYPTO 0x06 |
107 #define NGX_QUIC_FT_NEW_TOKEN 0x07 | 107 #define NGX_QUIC_FT_NEW_TOKEN 0x07 |
108 #define NGX_QUIC_FT_STREAM 0x08 | 108 #define NGX_QUIC_FT_STREAM0 0x08 |
109 #define NGX_QUIC_FT_STREAM1 0x09 | 109 #define NGX_QUIC_FT_STREAM1 0x09 |
110 #define NGX_QUIC_FT_STREAM2 0x0A | 110 #define NGX_QUIC_FT_STREAM2 0x0A |
111 #define NGX_QUIC_FT_STREAM3 0x0B | 111 #define NGX_QUIC_FT_STREAM3 0x0B |
112 #define NGX_QUIC_FT_STREAM4 0x0C | 112 #define NGX_QUIC_FT_STREAM4 0x0C |
113 #define NGX_QUIC_FT_STREAM5 0x0D | 113 #define NGX_QUIC_FT_STREAM5 0x0D |
128 #define NGX_QUIC_FT_CONNECTION_CLOSE 0x1c | 128 #define NGX_QUIC_FT_CONNECTION_CLOSE 0x1c |
129 #define NGX_QUIC_FT_CONNECTION_CLOSE2 0x1d // XXX | 129 #define NGX_QUIC_FT_CONNECTION_CLOSE2 0x1d // XXX |
130 #define NGX_QUIC_FT_HANDSHAKE_DONE 0x1e | 130 #define NGX_QUIC_FT_HANDSHAKE_DONE 0x1e |
131 | 131 |
132 | 132 |
133 #define ngx_quic_stream_bit_off(val) (((val) & 0x04) ? 1 : 0) | |
134 #define ngx_quic_stream_bit_len(val) (((val) & 0x02) ? 1 : 0) | |
135 #define ngx_quic_stream_bit_fin(val) (((val) & 0x01) ? 1 : 0) | |
136 | |
137 | |
138 | |
133 /* TODO: real states, these are stubs */ | 139 /* TODO: real states, these are stubs */ |
134 typedef enum { | 140 typedef enum { |
135 NGX_QUIC_ST_INITIAL, | 141 NGX_QUIC_ST_INITIAL, |
136 NGX_QUIC_ST_HANDSHAKE, | 142 NGX_QUIC_ST_HANDSHAKE, |
137 NGX_QUIC_ST_APP_DATA | 143 NGX_QUIC_ST_APP_DATA |
182 u_char srt[16]; | 188 u_char srt[16]; |
183 } ngx_quic_ncid_t; | 189 } ngx_quic_ncid_t; |
184 | 190 |
185 | 191 |
186 typedef struct { | 192 typedef struct { |
193 uint8_t type; | |
187 uint64_t stream_id; | 194 uint64_t stream_id; |
188 uint64_t offset; | 195 uint64_t offset; |
189 uint64_t length; | 196 uint64_t length; |
190 u_char *data; | 197 u_char *data; |
191 } ngx_quic_stream_frame_t; | 198 } ngx_quic_stream_frame_t; |
348 ngx_quic_secret_t *s, u_char *out, u_char *in); | 355 ngx_quic_secret_t *s, u_char *out, u_char *in); |
349 | 356 |
350 static ngx_int_t ngx_quic_ciphers(ngx_connection_t *c, | 357 static ngx_int_t ngx_quic_ciphers(ngx_connection_t *c, |
351 ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level); | 358 ngx_quic_ciphers_t *ciphers, enum ssl_encryption_level_t level); |
352 | 359 |
360 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, | |
361 size_t size); | |
362 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, | |
363 size_t size); | |
364 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c, | |
365 ngx_chain_t *in, off_t limit); | |
366 | |
353 static SSL_QUIC_METHOD quic_method = { | 367 static SSL_QUIC_METHOD quic_method = { |
354 #if BORINGSSL_API_VERSION >= 10 | 368 #if BORINGSSL_API_VERSION >= 10 |
355 ngx_quic_set_read_secret, | 369 ngx_quic_set_read_secret, |
356 ngx_quic_set_write_secret, | 370 ngx_quic_set_write_secret, |
357 #else | 371 #else |
638 p = ngx_cpymem(p, crypto->data, crypto->len); | 652 p = ngx_cpymem(p, crypto->data, crypto->len); |
639 | 653 |
640 return p - start; | 654 return p - start; |
641 } | 655 } |
642 | 656 |
657 | |
658 static size_t | |
659 ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf) | |
660 { | |
661 size_t len; | |
662 u_char *start; | |
663 | |
664 if (!ngx_quic_stream_bit_len(sf->type)) { | |
665 #if 0 | |
666 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
667 "attempt to generate a stream frame without length"); | |
668 #endif | |
669 // XXX: handle error in caller | |
670 return NGX_ERROR; | |
671 } | |
672 | |
673 if (p == NULL) { | |
674 len = ngx_quic_varint_len(sf->type); | |
675 | |
676 if (ngx_quic_stream_bit_off(sf->type)) { | |
677 len += ngx_quic_varint_len(sf->offset); | |
678 } | |
679 | |
680 len += ngx_quic_varint_len(sf->stream_id); | |
681 | |
682 /* length is always present in generated frames */ | |
683 len += ngx_quic_varint_len(sf->length); | |
684 | |
685 len += sf->length; | |
686 | |
687 return len; | |
688 } | |
689 | |
690 start = p; | |
691 | |
692 ngx_quic_build_int(&p, sf->type); | |
693 ngx_quic_build_int(&p, sf->stream_id); | |
694 | |
695 if (ngx_quic_stream_bit_off(sf->type)) { | |
696 ngx_quic_build_int(&p, sf->offset); | |
697 } | |
698 | |
699 /* length is always present in generated frames */ | |
700 ngx_quic_build_int(&p, sf->length); | |
701 | |
702 p = ngx_cpymem(p, sf->data, sf->length); | |
703 | |
704 return p - start; | |
705 } | |
706 | |
707 | |
643 size_t | 708 size_t |
644 ngx_quic_frame_len(ngx_quic_frame_t *frame) | 709 ngx_quic_frame_len(ngx_quic_frame_t *frame) |
645 { | 710 { |
646 switch (frame->type) { | 711 switch (frame->type) { |
647 case NGX_QUIC_FT_ACK: | 712 case NGX_QUIC_FT_ACK: |
648 return ngx_quic_create_ack(NULL, &frame->u.ack); | 713 return ngx_quic_create_ack(NULL, &frame->u.ack); |
649 case NGX_QUIC_FT_CRYPTO: | 714 case NGX_QUIC_FT_CRYPTO: |
650 return ngx_quic_create_crypto(NULL, &frame->u.crypto); | 715 return ngx_quic_create_crypto(NULL, &frame->u.crypto); |
716 | |
717 case NGX_QUIC_FT_STREAM0: | |
718 case NGX_QUIC_FT_STREAM1: | |
719 case NGX_QUIC_FT_STREAM2: | |
720 case NGX_QUIC_FT_STREAM3: | |
721 case NGX_QUIC_FT_STREAM4: | |
722 case NGX_QUIC_FT_STREAM5: | |
723 case NGX_QUIC_FT_STREAM6: | |
724 case NGX_QUIC_FT_STREAM7: | |
725 return ngx_quic_create_stream(NULL, &frame->u.stream); | |
651 default: | 726 default: |
652 /* BUG: unsupported frame type generated */ | 727 /* BUG: unsupported frame type generated */ |
653 return 0; | 728 return 0; |
654 } | 729 } |
655 } | 730 } |
683 p += ngx_quic_create_ack(p, &f->u.ack); | 758 p += ngx_quic_create_ack(p, &f->u.ack); |
684 break; | 759 break; |
685 | 760 |
686 case NGX_QUIC_FT_CRYPTO: | 761 case NGX_QUIC_FT_CRYPTO: |
687 p += ngx_quic_create_crypto(p, &f->u.crypto); | 762 p += ngx_quic_create_crypto(p, &f->u.crypto); |
763 break; | |
764 | |
765 case NGX_QUIC_FT_STREAM0: | |
766 case NGX_QUIC_FT_STREAM1: | |
767 case NGX_QUIC_FT_STREAM2: | |
768 case NGX_QUIC_FT_STREAM3: | |
769 case NGX_QUIC_FT_STREAM4: | |
770 case NGX_QUIC_FT_STREAM5: | |
771 case NGX_QUIC_FT_STREAM6: | |
772 case NGX_QUIC_FT_STREAM7: | |
773 p += ngx_quic_create_stream(p, &f->u.stream); | |
688 break; | 774 break; |
689 | 775 |
690 default: | 776 default: |
691 /* BUG: unsupported frame type generated */ | 777 /* BUG: unsupported frame type generated */ |
692 return NGX_ERROR; | 778 return NGX_ERROR; |
1651 | 1737 |
1652 // TODO: parse connection close here | 1738 // TODO: parse connection close here |
1653 return NGX_ERROR; | 1739 return NGX_ERROR; |
1654 break; | 1740 break; |
1655 | 1741 |
1656 case NGX_QUIC_FT_STREAM: | 1742 case NGX_QUIC_FT_STREAM0: |
1657 case NGX_QUIC_FT_STREAM1: | 1743 case NGX_QUIC_FT_STREAM1: |
1658 case NGX_QUIC_FT_STREAM2: | 1744 case NGX_QUIC_FT_STREAM2: |
1659 case NGX_QUIC_FT_STREAM3: | 1745 case NGX_QUIC_FT_STREAM3: |
1660 case NGX_QUIC_FT_STREAM4: | 1746 case NGX_QUIC_FT_STREAM4: |
1661 case NGX_QUIC_FT_STREAM5: | 1747 case NGX_QUIC_FT_STREAM5: |
1662 case NGX_QUIC_FT_STREAM6: | 1748 case NGX_QUIC_FT_STREAM6: |
1663 case NGX_QUIC_FT_STREAM7: | 1749 case NGX_QUIC_FT_STREAM7: |
1664 | 1750 |
1665 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1751 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1666 "STREAM frame, type: 0x%xi", frame->type); | 1752 "STREAM frame, type: 0x%xi", frame->type); |
1753 | |
1754 frame->u.stream.type = frame->type; | |
1667 | 1755 |
1668 frame->u.stream.stream_id = ngx_quic_parse_int(&p); | 1756 frame->u.stream.stream_id = ngx_quic_parse_int(&p); |
1669 if (frame->type & 0x04) { | 1757 if (frame->type & 0x04) { |
1670 frame->u.stream.offset = ngx_quic_parse_int(&p); | 1758 frame->u.stream.offset = ngx_quic_parse_int(&p); |
1671 } else { | 1759 } else { |
1795 | 1883 |
1796 return NGX_OK; | 1884 return NGX_OK; |
1797 } | 1885 } |
1798 | 1886 |
1799 | 1887 |
1888 static ssize_t | |
1889 ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, size_t size) | |
1890 { | |
1891 ssize_t len; | |
1892 ngx_buf_t *b; | |
1893 ngx_quic_stream_t *qs; | |
1894 ngx_quic_connection_t *qc; | |
1895 ngx_quic_stream_node_t *sn; | |
1896 | |
1897 qs = c->qs; | |
1898 qc = qs->parent->quic; | |
1899 | |
1900 // XXX: get direct pointer from stream structure? | |
1901 sn = ngx_quic_stream_lookup(&qc->stree, qs->id); | |
1902 | |
1903 if (sn == NULL) { | |
1904 return NGX_ERROR; | |
1905 } | |
1906 | |
1907 // XXX: how to return EOF? | |
1908 | |
1909 b = sn->b; | |
1910 | |
1911 if (b->last - b->pos == 0) { | |
1912 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1913 "quic recv() not ready"); | |
1914 return NGX_AGAIN; // ? | |
1915 } | |
1916 | |
1917 len = ngx_min(b->last - b->pos, (ssize_t) size); | |
1918 | |
1919 ngx_memcpy(buf, b->pos, len); | |
1920 | |
1921 b->pos += len; | |
1922 | |
1923 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1924 "quic recv: %z of %uz", len, size); | |
1925 | |
1926 return len; | |
1927 } | |
1928 | |
1929 | |
1930 static ssize_t | |
1931 ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size) | |
1932 { | |
1933 u_char *p; | |
1934 ngx_quic_frame_t *frame; | |
1935 ngx_quic_stream_t *qs; | |
1936 ngx_quic_connection_t *qc; | |
1937 ngx_quic_stream_node_t *sn; | |
1938 | |
1939 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size); | |
1940 | |
1941 qs = c->qs; | |
1942 qc = qs->parent->quic; | |
1943 | |
1944 | |
1945 // XXX: get direct pointer from stream structure? | |
1946 sn = ngx_quic_stream_lookup(&qc->stree, qs->id); | |
1947 | |
1948 if (sn == NULL) { | |
1949 return NGX_ERROR; | |
1950 } | |
1951 | |
1952 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); | |
1953 if (frame == NULL) { | |
1954 return 0; | |
1955 } | |
1956 | |
1957 p = ngx_pnalloc(c->pool, size); | |
1958 if (p == NULL) { | |
1959 return 0; | |
1960 } | |
1961 | |
1962 ngx_memcpy(p, buf, size); | |
1963 | |
1964 frame->level = ssl_encryption_application; | |
1965 frame->type = NGX_QUIC_FT_STREAM2; /* OFF=0 LEN=1 FIN=0 */ | |
1966 | |
1967 frame->u.stream.type = frame->type; | |
1968 frame->u.stream.stream_id = qs->id; | |
1969 frame->u.stream.offset = 0; | |
1970 frame->u.stream.length = size; | |
1971 frame->u.stream.data = p; | |
1972 | |
1973 ngx_sprintf(frame->info, "stream %xi len=%ui level=%d", | |
1974 qs->id, size, frame->level); | |
1975 | |
1976 ngx_quic_queue_frame(qc, frame); | |
1977 | |
1978 return size; | |
1979 } | |
1980 | |
1981 | |
1982 static ngx_chain_t * | |
1983 ngx_quic_stream_send_chain(ngx_connection_t *c, ngx_chain_t *in, | |
1984 off_t limit) | |
1985 { | |
1986 // TODO | |
1987 return NULL; | |
1988 } | |
1989 | |
1990 | |
1800 /* process all payload from the current packet and generate ack if required */ | 1991 /* process all payload from the current packet and generate ack if required */ |
1801 static ngx_int_t | 1992 static ngx_int_t |
1802 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1993 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1803 { | 1994 { |
1804 u_char *end, *p; | 1995 u_char *end, *p; |
1805 ssize_t len; | 1996 ssize_t len; |
1806 ngx_buf_t *b; | 1997 ngx_buf_t *b; |
1807 ngx_uint_t ack_this; | 1998 ngx_uint_t ack_this; |
1999 ngx_pool_t *pool; | |
2000 ngx_event_t *rev, *wev; | |
1808 ngx_quic_frame_t frame, *ack_frame; | 2001 ngx_quic_frame_t frame, *ack_frame; |
1809 ngx_quic_connection_t *qc; | 2002 ngx_quic_connection_t *qc; |
1810 ngx_quic_stream_node_t *sn; | 2003 ngx_quic_stream_node_t *sn; |
1811 | 2004 |
1812 qc = c->quic; | 2005 qc = c->quic; |
1871 frame.u.ncid.seqnum, | 2064 frame.u.ncid.seqnum, |
1872 frame.u.ncid.retire, | 2065 frame.u.ncid.retire, |
1873 frame.u.ncid.len); | 2066 frame.u.ncid.len); |
1874 continue; | 2067 continue; |
1875 | 2068 |
1876 case NGX_QUIC_FT_STREAM: | 2069 case NGX_QUIC_FT_STREAM0: |
1877 case NGX_QUIC_FT_STREAM1: | 2070 case NGX_QUIC_FT_STREAM1: |
1878 case NGX_QUIC_FT_STREAM2: | 2071 case NGX_QUIC_FT_STREAM2: |
1879 case NGX_QUIC_FT_STREAM3: | 2072 case NGX_QUIC_FT_STREAM3: |
1880 case NGX_QUIC_FT_STREAM4: | 2073 case NGX_QUIC_FT_STREAM4: |
1881 case NGX_QUIC_FT_STREAM5: | 2074 case NGX_QUIC_FT_STREAM5: |
1882 case NGX_QUIC_FT_STREAM6: | 2075 case NGX_QUIC_FT_STREAM6: |
1883 case NGX_QUIC_FT_STREAM7: | 2076 case NGX_QUIC_FT_STREAM7: |
1884 | 2077 |
1885 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2078 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1886 "STREAM frame 0x%xi id 0x%xi off 0x%xi len 0x%xi", | 2079 "STREAM frame 0x%xi id 0x%xi offset 0x%xi len 0x%xi bits:off=%d len=%d fin=%d", |
1887 frame.type, | 2080 frame.type, |
1888 frame.u.stream.stream_id, | 2081 frame.u.stream.stream_id, |
1889 frame.u.stream.offset, | 2082 frame.u.stream.offset, |
1890 frame.u.stream.length); | 2083 frame.u.stream.length, |
2084 ngx_quic_stream_bit_off(frame.u.stream.type), | |
2085 ngx_quic_stream_bit_len(frame.u.stream.type), | |
2086 ngx_quic_stream_bit_fin(frame.u.stream.type)); | |
1891 | 2087 |
1892 | 2088 |
1893 sn = ngx_quic_stream_lookup(&qc->stree, frame.u.stream.stream_id); | 2089 sn = ngx_quic_stream_lookup(&qc->stree, frame.u.stream.stream_id); |
1894 if (sn == NULL) { | 2090 if (sn == NULL) { |
1895 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new"); | 2091 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new"); |
1897 sn = ngx_pcalloc(c->pool, sizeof(ngx_quic_stream_node_t)); | 2093 sn = ngx_pcalloc(c->pool, sizeof(ngx_quic_stream_node_t)); |
1898 if (sn == NULL) { | 2094 if (sn == NULL) { |
1899 return NGX_ERROR; | 2095 return NGX_ERROR; |
1900 } | 2096 } |
1901 | 2097 |
2098 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); | |
2099 if (pool == NULL) { | |
2100 return NGX_ERROR; | |
2101 } | |
2102 | |
1902 sn->c = ngx_get_connection(-1, c->log); // TODO: free on connection termination | 2103 sn->c = ngx_get_connection(-1, c->log); // TODO: free on connection termination |
1903 if (sn->c == NULL) { | 2104 if (sn->c == NULL) { |
1904 return NGX_ERROR; | 2105 return NGX_ERROR; |
1905 } | 2106 } |
1906 | 2107 |
2108 sn->c->pool = pool; | |
2109 | |
2110 rev = sn->c->read; | |
2111 wev = sn->c->write; | |
2112 | |
2113 rev->log = c->log; | |
2114 wev->log = c->log; | |
2115 | |
2116 sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); | |
2117 | |
1907 sn->node.key = frame.u.stream.stream_id; | 2118 sn->node.key = frame.u.stream.stream_id; |
1908 sn->b = ngx_create_temp_buf(c->pool, 16 * 1024); // XXX enough for everyone | 2119 sn->b = ngx_create_temp_buf(pool, 16 * 1024); // XXX enough for everyone |
1909 if (sn->b == NULL) { | 2120 if (sn->b == NULL) { |
1910 return NGX_ERROR; | 2121 return NGX_ERROR; |
1911 } | 2122 } |
1912 b = sn->b; | 2123 b = sn->b; |
1913 | 2124 |
1915 b->last = b->start + frame.u.stream.length; | 2126 b->last = b->start + frame.u.stream.length; |
1916 | 2127 |
1917 ngx_rbtree_insert(&qc->stree, &sn->node); | 2128 ngx_rbtree_insert(&qc->stree, &sn->node); |
1918 | 2129 |
1919 sn->s.id = frame.u.stream.stream_id; | 2130 sn->s.id = frame.u.stream.stream_id; |
2131 sn->s.unidirectional = (sn->s.id & 0x02) ? 1 : 0; | |
1920 sn->s.parent = c; | 2132 sn->s.parent = c; |
1921 sn->c->qs = &sn->s; | 2133 sn->c->qs = &sn->s; |
2134 | |
2135 sn->c->recv = ngx_quic_stream_recv; | |
2136 sn->c->send = ngx_quic_stream_send; | |
2137 sn->c->send_chain = ngx_quic_stream_send_chain; | |
1922 | 2138 |
1923 qc->stream_handler(sn->c); | 2139 qc->stream_handler(sn->c); |
1924 | 2140 |
1925 } else { | 2141 } else { |
1926 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "existing stream"); | 2142 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "existing stream"); |
1971 | 2187 |
1972 ack_frame->level = pkt->level; | 2188 ack_frame->level = pkt->level; |
1973 ack_frame->type = NGX_QUIC_FT_ACK; | 2189 ack_frame->type = NGX_QUIC_FT_ACK; |
1974 ack_frame->u.ack.pn = pkt->pn; | 2190 ack_frame->u.ack.pn = pkt->pn; |
1975 | 2191 |
1976 ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler", pkt->pn); | 2192 ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, pkt->level); |
1977 ngx_quic_queue_frame(qc, ack_frame); | 2193 ngx_quic_queue_frame(qc, ack_frame); |
1978 | 2194 |
1979 return ngx_quic_output(c); | 2195 return ngx_quic_output(c); |
1980 } | 2196 } |
1981 | 2197 |