Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7748:4cf00c14f11a quic
Safe QUIC stream creation.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 25 Mar 2020 12:56:21 +0300 |
parents | 618a65de08b3 |
children | 2935a11c55b6 |
comparison
equal
deleted
inserted
replaced
7747:618a65de08b3 | 7748:4cf00c14f11a |
---|---|
12 typedef enum { | 12 typedef enum { |
13 NGX_QUIC_ST_INITIAL, /* connection just created */ | 13 NGX_QUIC_ST_INITIAL, /* connection just created */ |
14 NGX_QUIC_ST_HANDSHAKE, /* handshake started */ | 14 NGX_QUIC_ST_HANDSHAKE, /* handshake started */ |
15 NGX_QUIC_ST_APPLICATION /* handshake complete */ | 15 NGX_QUIC_ST_APPLICATION /* handshake complete */ |
16 } ngx_quic_state_t; | 16 } ngx_quic_state_t; |
17 | |
18 | |
19 #define NGX_QUIC_STREAM_BUFSIZE 16384 | |
20 | 17 |
21 | 18 |
22 typedef struct { | 19 typedef struct { |
23 ngx_rbtree_t tree; | 20 ngx_rbtree_t tree; |
24 ngx_rbtree_node_t sentinel; | 21 ngx_rbtree_node_t sentinel; |
120 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, | 117 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, |
121 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); | 118 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); |
122 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, | 119 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, |
123 ngx_uint_t key); | 120 ngx_uint_t key); |
124 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, | 121 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, |
125 ngx_uint_t id); | 122 uint64_t id, size_t rcvbuf_size); |
126 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, | 123 static ssize_t ngx_quic_stream_recv(ngx_connection_t *c, u_char *buf, |
127 size_t size); | 124 size_t size); |
128 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, | 125 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, |
129 size_t size); | 126 size_t size); |
130 static void ngx_quic_stream_cleanup_handler(void *data); | 127 static void ngx_quic_stream_cleanup_handler(void *data); |
1094 | 1091 |
1095 static ngx_int_t | 1092 static ngx_int_t |
1096 ngx_quic_handle_stream_frame(ngx_connection_t *c, | 1093 ngx_quic_handle_stream_frame(ngx_connection_t *c, |
1097 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *f) | 1094 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *f) |
1098 { | 1095 { |
1096 size_t n; | |
1099 ngx_buf_t *b; | 1097 ngx_buf_t *b; |
1100 ngx_event_t *rev; | 1098 ngx_event_t *rev; |
1101 ngx_quic_stream_t *sn; | 1099 ngx_quic_stream_t *sn; |
1102 ngx_quic_connection_t *qc; | 1100 ngx_quic_connection_t *qc; |
1103 | 1101 |
1135 return NGX_OK; | 1133 return NGX_OK; |
1136 } | 1134 } |
1137 | 1135 |
1138 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new"); | 1136 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "stream is new"); |
1139 | 1137 |
1140 sn = ngx_quic_create_stream(c, f->stream_id); | 1138 n = (f->stream_id & NGX_QUIC_STREAM_UNIDIRECTIONAL) |
1139 ? qc->tp.initial_max_stream_data_uni | |
1140 : qc->tp.initial_max_stream_data_bidi_remote; | |
1141 | |
1142 if (n < NGX_QUIC_STREAM_BUFSIZE) { | |
1143 n = NGX_QUIC_STREAM_BUFSIZE; | |
1144 } | |
1145 | |
1146 if (n < f->length) { | |
1147 ngx_log_error(NGX_LOG_INFO, c->log, 0, "no space in stream buffer"); | |
1148 return NGX_ERROR; | |
1149 } | |
1150 | |
1151 sn = ngx_quic_create_stream(c, f->stream_id, n); | |
1141 if (sn == NULL) { | 1152 if (sn == NULL) { |
1142 return NGX_ERROR; | 1153 return NGX_ERROR; |
1143 } | 1154 } |
1144 | 1155 |
1145 b = sn->b; | 1156 b = sn->b; |
1146 | 1157 b->last = ngx_cpymem(b->last, f->data, f->length); |
1147 ngx_memcpy(b->start, f->data, f->length); | 1158 |
1148 b->last = b->start + f->length; | 1159 sn->c->read->ready = 1; |
1149 | 1160 |
1150 qc->streams.handler(sn->c); | 1161 qc->streams.handler(sn->c); |
1151 | 1162 |
1152 return NGX_OK; | 1163 return NGX_OK; |
1153 } | 1164 } |
1417 "creating server uni stream #%ui id %ui", | 1428 "creating server uni stream #%ui id %ui", |
1418 qc->streams.id_counter, id); | 1429 qc->streams.id_counter, id); |
1419 | 1430 |
1420 qc->streams.id_counter++; | 1431 qc->streams.id_counter++; |
1421 | 1432 |
1422 sn = ngx_quic_create_stream(qs->parent, id); | 1433 sn = ngx_quic_create_stream(qs->parent, id, 0); |
1423 if (sn == NULL) { | 1434 if (sn == NULL) { |
1424 return NULL; | 1435 return NULL; |
1425 } | 1436 } |
1426 | 1437 |
1427 return sn->c; | 1438 return sn->c; |
1492 return NULL; | 1503 return NULL; |
1493 } | 1504 } |
1494 | 1505 |
1495 | 1506 |
1496 static ngx_quic_stream_t * | 1507 static ngx_quic_stream_t * |
1497 ngx_quic_create_stream(ngx_connection_t *c, ngx_uint_t id) | 1508 ngx_quic_create_stream(ngx_connection_t *c, uint64_t id, size_t rcvbuf_size) |
1498 { | 1509 { |
1499 size_t n; | 1510 ngx_log_t *log; |
1500 ngx_log_t *log; | 1511 ngx_pool_t *pool; |
1501 ngx_pool_t *pool; | 1512 ngx_quic_stream_t *sn; |
1502 ngx_event_t *rev, *wev; | 1513 ngx_pool_cleanup_t *cln; |
1503 ngx_quic_stream_t *sn; | |
1504 ngx_pool_cleanup_t *cln; | |
1505 ngx_quic_connection_t *qc; | |
1506 | |
1507 qc = c->quic; | |
1508 | |
1509 sn = ngx_pcalloc(c->pool, sizeof(ngx_quic_stream_t)); | |
1510 if (sn == NULL) { | |
1511 return NULL; | |
1512 } | |
1513 | |
1514 sn->c = ngx_get_connection(-1, c->log); // TODO: free on connection termination | |
1515 if (sn->c == NULL) { | |
1516 return NULL; | |
1517 } | |
1518 | 1514 |
1519 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); | 1515 pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, c->log); |
1520 if (pool == NULL) { | 1516 if (pool == NULL) { |
1521 /* XXX free connection */ | 1517 return NULL; |
1522 // TODO: add pool cleanup handdler | 1518 } |
1519 | |
1520 sn = ngx_pcalloc(pool, sizeof(ngx_quic_stream_t)); | |
1521 if (sn == NULL) { | |
1522 ngx_destroy_pool(pool); | |
1523 return NULL; | |
1524 } | |
1525 | |
1526 sn->node.key = id; | |
1527 sn->parent = c; | |
1528 sn->id = id; | |
1529 | |
1530 sn->b = ngx_create_temp_buf(pool, rcvbuf_size); | |
1531 if (sn->b == NULL) { | |
1532 ngx_destroy_pool(pool); | |
1523 return NULL; | 1533 return NULL; |
1524 } | 1534 } |
1525 | 1535 |
1526 log = ngx_palloc(pool, sizeof(ngx_log_t)); | 1536 log = ngx_palloc(pool, sizeof(ngx_log_t)); |
1527 if (log == NULL) { | 1537 if (log == NULL) { |
1528 /* XXX free pool and connection */ | 1538 ngx_destroy_pool(pool); |
1529 return NULL; | 1539 return NULL; |
1530 } | 1540 } |
1531 | 1541 |
1532 *log = *c->log; | 1542 *log = *c->log; |
1533 pool->log = log; | 1543 pool->log = log; |
1534 | 1544 |
1535 sn->c->log = log; | 1545 sn->c = ngx_get_connection(-1, log); |
1546 if (sn->c == NULL) { | |
1547 ngx_destroy_pool(pool); | |
1548 return NULL; | |
1549 } | |
1550 | |
1551 sn->c->qs = sn; | |
1536 sn->c->pool = pool; | 1552 sn->c->pool = pool; |
1537 | 1553 sn->c->ssl = c->ssl; |
1554 sn->c->sockaddr = c->sockaddr; | |
1538 sn->c->listening = c->listening; | 1555 sn->c->listening = c->listening; |
1539 sn->c->sockaddr = c->sockaddr; | 1556 sn->c->addr_text = c->addr_text; |
1540 sn->c->local_sockaddr = c->local_sockaddr; | 1557 sn->c->local_sockaddr = c->local_sockaddr; |
1541 sn->c->addr_text = c->addr_text; | |
1542 sn->c->ssl = c->ssl; | |
1543 | |
1544 rev = sn->c->read; | |
1545 wev = sn->c->write; | |
1546 | |
1547 rev->ready = 1; | |
1548 | |
1549 rev->log = c->log; | |
1550 wev->log = c->log; | |
1551 | |
1552 sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); | 1558 sn->c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); |
1553 | |
1554 n = ngx_max(NGX_QUIC_STREAM_BUFSIZE, | |
1555 qc->tp.initial_max_stream_data_bidi_remote); | |
1556 | |
1557 sn->node.key =id; | |
1558 sn->b = ngx_create_temp_buf(pool, n); | |
1559 if (sn->b == NULL) { | |
1560 return NULL; | |
1561 } | |
1562 | |
1563 ngx_rbtree_insert(&qc->streams.tree, &sn->node); | |
1564 | |
1565 sn->id = id; | |
1566 sn->parent = c; | |
1567 sn->c->qs = sn; | |
1568 | 1559 |
1569 sn->c->recv = ngx_quic_stream_recv; | 1560 sn->c->recv = ngx_quic_stream_recv; |
1570 sn->c->send = ngx_quic_stream_send; | 1561 sn->c->send = ngx_quic_stream_send; |
1571 sn->c->send_chain = ngx_quic_stream_send_chain; | 1562 sn->c->send_chain = ngx_quic_stream_send_chain; |
1563 | |
1564 sn->c->read->log = c->log; | |
1565 sn->c->write->log = c->log; | |
1572 | 1566 |
1573 cln = ngx_pool_cleanup_add(pool, 0); | 1567 cln = ngx_pool_cleanup_add(pool, 0); |
1574 if (cln == NULL) { | 1568 if (cln == NULL) { |
1575 ngx_close_connection(sn->c); | 1569 ngx_close_connection(sn->c); |
1576 ngx_destroy_pool(pool); | 1570 ngx_destroy_pool(pool); |
1578 } | 1572 } |
1579 | 1573 |
1580 cln->handler = ngx_quic_stream_cleanup_handler; | 1574 cln->handler = ngx_quic_stream_cleanup_handler; |
1581 cln->data = sn->c; | 1575 cln->data = sn->c; |
1582 | 1576 |
1577 ngx_rbtree_insert(&c->quic->streams.tree, &sn->node); | |
1578 | |
1583 return sn; | 1579 return sn; |
1584 } | 1580 } |
1585 | 1581 |
1586 | 1582 |
1587 static ssize_t | 1583 static ssize_t |