comparison src/event/ngx_event_quic.c @ 8211: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
8210:b761ca7df7d0 8211: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