comparison src/event/ngx_event_quic.c @ 8286:c7185bc5b4d9 quic

QUIC frames reuse.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 25 Mar 2020 23:40:50 +0300
parents f85749b60e58
children ebd5c71b9f02
comparison
equal deleted inserted replaced
8285:f85749b60e58 8286:c7185bc5b4d9
42 ngx_uint_t appdata_pn; 42 ngx_uint_t appdata_pn;
43 43
44 ngx_quic_secrets_t secrets; 44 ngx_quic_secrets_t secrets;
45 ngx_ssl_t *ssl; 45 ngx_ssl_t *ssl;
46 ngx_quic_frame_t *frames; 46 ngx_quic_frame_t *frames;
47 ngx_quic_frame_t *free_frames;
48
49 #if (NGX_DEBUG)
50 ngx_uint_t nframes;
51 #endif
47 52
48 ngx_quic_streams_t streams; 53 ngx_quic_streams_t streams;
49 ngx_uint_t max_data; 54 ngx_uint_t max_data;
50 55
51 unsigned send_timer_set:1; 56 unsigned send_timer_set:1;
125 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, 130 static ssize_t ngx_quic_stream_send(ngx_connection_t *c, u_char *buf,
126 size_t size); 131 size_t size);
127 static void ngx_quic_stream_cleanup_handler(void *data); 132 static void ngx_quic_stream_cleanup_handler(void *data);
128 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c, 133 static ngx_chain_t *ngx_quic_stream_send_chain(ngx_connection_t *c,
129 ngx_chain_t *in, off_t limit); 134 ngx_chain_t *in, off_t limit);
135 static ngx_quic_frame_t *ngx_quic_alloc_frame(ngx_connection_t *c, size_t size);
136 static void ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame);
130 137
131 138
132 static SSL_QUIC_METHOD quic_method = { 139 static SSL_QUIC_METHOD quic_method = {
133 #if BORINGSSL_API_VERSION >= 10 140 #if BORINGSSL_API_VERSION >= 10
134 ngx_quic_set_read_secret, 141 ngx_quic_set_read_secret,
254 261
255 qc->client_tp_done = 1; 262 qc->client_tp_done = 1;
256 } 263 }
257 } 264 }
258 265
259 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); 266 frame = ngx_quic_alloc_frame(c, len);
260 if (frame == NULL) { 267 if (frame == NULL) {
261 return 0; 268 return 0;
262 } 269 }
263 270
264 p = ngx_pnalloc(c->pool, len); 271 ngx_memcpy(frame->data, data, len);
265 if (p == NULL) {
266 return 0;
267 }
268
269 ngx_memcpy(p, data, len);
270 272
271 frame->level = level; 273 frame->level = level;
272 frame->type = NGX_QUIC_FT_CRYPTO; 274 frame->type = NGX_QUIC_FT_CRYPTO;
273 frame->u.crypto.offset += qc->crypto_offset[level]; 275 frame->u.crypto.offset += qc->crypto_offset[level];
274 frame->u.crypto.len = len; 276 frame->u.crypto.len = len;
275 frame->u.crypto.data = p; 277 frame->u.crypto.data = frame->data;
276 278
277 qc->crypto_offset[level] += len; 279 qc->crypto_offset[level] += len;
278 280
279 ngx_sprintf(frame->info, "crypto, generated by SSL len=%ui level=%d", len, level); 281 ngx_sprintf(frame->info, "crypto, generated by SSL len=%ui level=%d", len, level);
280 282
312 314
313 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 315 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
314 "ngx_quic_send_alert(), lvl=%d, alert=%d", 316 "ngx_quic_send_alert(), lvl=%d, alert=%d",
315 (int) level, (int) alert); 317 (int) level, (int) alert);
316 318
317 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); 319 frame = ngx_quic_alloc_frame(c, 0);
318 if (frame == NULL) { 320 if (frame == NULL) {
319 return 0; 321 return 0;
320 } 322 }
321 323
322 frame->level = level; 324 frame->level = level;
982 c->log->action = "generating acknowledgment"; 984 c->log->action = "generating acknowledgment";
983 985
984 // packet processed, ACK it now if required 986 // packet processed, ACK it now if required
985 // TODO: if (ack_required) ... - currently just ack each packet 987 // TODO: if (ack_required) ... - currently just ack each packet
986 988
987 ack_frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); 989 ack_frame = ngx_quic_alloc_frame(c, 0);
988 if (ack_frame == NULL) { 990 if (ack_frame == NULL) {
989 return NGX_ERROR; 991 return NGX_ERROR;
990 } 992 }
991 993
992 ack_frame->level = pkt->level; 994 ack_frame->level = pkt->level;
1064 1066
1065 #if (NGX_QUIC_DRAFT_VERSION >= 27) 1067 #if (NGX_QUIC_DRAFT_VERSION >= 27)
1066 { 1068 {
1067 ngx_quic_frame_t *frame; 1069 ngx_quic_frame_t *frame;
1068 1070
1069 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); 1071 frame = ngx_quic_alloc_frame(c, 0);
1070 if (frame == NULL) { 1072 if (frame == NULL) {
1071 return NGX_ERROR; 1073 return NGX_ERROR;
1072 } 1074 }
1073 1075
1074 /* 12.4 Frames and frame types, figure 8 */ 1076 /* 12.4 Frames and frame types, figure 8 */
1168 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c, 1170 ngx_quic_handle_streams_blocked_frame(ngx_connection_t *c,
1169 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f) 1171 ngx_quic_header_t *pkt, ngx_quic_streams_blocked_frame_t *f)
1170 { 1172 {
1171 ngx_quic_frame_t *frame; 1173 ngx_quic_frame_t *frame;
1172 1174
1173 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); 1175 frame = ngx_quic_alloc_frame(c, 0);
1174 if (frame == NULL) { 1176 if (frame == NULL) {
1175 return NGX_ERROR; 1177 return NGX_ERROR;
1176 } 1178 }
1177 1179
1178 frame->level = pkt->level; 1180 frame->level = pkt->level;
1210 } 1212 }
1211 1213
1212 b = sn->b; 1214 b = sn->b;
1213 n = (b->pos - b->start) + (b->end - b->last); 1215 n = (b->pos - b->start) + (b->end - b->last);
1214 1216
1215 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t)); 1217 frame = ngx_quic_alloc_frame(c, 0);
1216 if (frame == NULL) { 1218 if (frame == NULL) {
1217 return NGX_ERROR; 1219 return NGX_ERROR;
1218 } 1220 }
1219 1221
1220 frame->level = pkt->level; 1222 frame->level = pkt->level;
1252 static ngx_int_t 1254 static ngx_int_t
1253 ngx_quic_output(ngx_connection_t *c) 1255 ngx_quic_output(ngx_connection_t *c)
1254 { 1256 {
1255 size_t len, hlen, n; 1257 size_t len, hlen, n;
1256 ngx_uint_t lvl; 1258 ngx_uint_t lvl;
1257 ngx_quic_frame_t *f, *start; 1259 ngx_quic_frame_t *f, *start, *next;
1258 ngx_quic_connection_t *qc; 1260 ngx_quic_connection_t *qc;
1259 1261
1260 qc = c->quic; 1262 qc = c->quic;
1261 1263
1262 if (qc->frames == NULL) { 1264 if (qc->frames == NULL) {
1292 1294
1293 if (ngx_quic_frames_send(c, start, f, len) != NGX_OK) { 1295 if (ngx_quic_frames_send(c, start, f, len) != NGX_OK) {
1294 return NGX_ERROR; 1296 return NGX_ERROR;
1295 } 1297 }
1296 1298
1299 while (start != f) {
1300 next = start->next;
1301 ngx_quic_free_frame(c, start);
1302 start = next;
1303 }
1304
1297 if (f == NULL) { 1305 if (f == NULL) {
1298 break; 1306 break;
1299 } 1307 }
1300 1308
1301 lvl = f->level; // TODO: must not decrease (ever, also between calls) 1309 lvl = f->level; // TODO: must not decrease (ever, also between calls)
1302 start = f;
1303 1310
1304 } while (1); 1311 } while (1);
1305 1312
1306 qc->frames = NULL; 1313 qc->frames = NULL;
1307 1314
1619 1626
1620 1627
1621 static ssize_t 1628 static ssize_t
1622 ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size) 1629 ngx_quic_stream_send(ngx_connection_t *c, u_char *buf, size_t size)
1623 { 1630 {
1624 u_char *p;
1625 ngx_connection_t *pc; 1631 ngx_connection_t *pc;
1626 ngx_quic_frame_t *frame; 1632 ngx_quic_frame_t *frame;
1627 ngx_quic_stream_t *qs; 1633 ngx_quic_stream_t *qs;
1628 ngx_quic_connection_t *qc; 1634 ngx_quic_connection_t *qc;
1629 1635
1635 return NGX_ERROR; 1641 return NGX_ERROR;
1636 } 1642 }
1637 1643
1638 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size); 1644 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send: %uz", size);
1639 1645
1640 frame = ngx_pcalloc(pc->pool, sizeof(ngx_quic_frame_t)); 1646 frame = ngx_quic_alloc_frame(pc, size);
1641 if (frame == NULL) { 1647 if (frame == NULL) {
1642 return 0; 1648 return 0;
1643 } 1649 }
1644 1650
1645 p = ngx_pnalloc(pc->pool, size); 1651 ngx_memcpy(frame->data, buf, size);
1646 if (p == NULL) {
1647 return 0;
1648 }
1649
1650 ngx_memcpy(p, buf, size);
1651 1652
1652 frame->level = ssl_encryption_application; 1653 frame->level = ssl_encryption_application;
1653 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */ 1654 frame->type = NGX_QUIC_FT_STREAM6; /* OFF=1 LEN=1 FIN=0 */
1654 frame->u.stream.off = 1; 1655 frame->u.stream.off = 1;
1655 frame->u.stream.len = 1; 1656 frame->u.stream.len = 1;
1657 1658
1658 frame->u.stream.type = frame->type; 1659 frame->u.stream.type = frame->type;
1659 frame->u.stream.stream_id = qs->id; 1660 frame->u.stream.stream_id = qs->id;
1660 frame->u.stream.offset = c->sent; 1661 frame->u.stream.offset = c->sent;
1661 frame->u.stream.length = size; 1662 frame->u.stream.length = size;
1662 frame->u.stream.data = p; 1663 frame->u.stream.data = frame->data;
1663 1664
1664 c->sent += size; 1665 c->sent += size;
1665 1666
1666 ngx_sprintf(frame->info, "stream %xi len=%ui level=%d", 1667 ngx_sprintf(frame->info, "stream %xi len=%ui level=%d",
1667 qs->id, size, frame->level); 1668 qs->id, size, frame->level);
1700 return; 1701 return;
1701 } 1702 }
1702 1703
1703 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send fin"); 1704 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic send fin");
1704 1705
1705 frame = ngx_pcalloc(pc->pool, sizeof(ngx_quic_frame_t)); 1706 frame = ngx_quic_alloc_frame(pc, 0);
1706 if (frame == NULL) { 1707 if (frame == NULL) {
1707 return; 1708 return;
1708 } 1709 }
1709 1710
1710 frame->level = ssl_encryption_application; 1711 frame->level = ssl_encryption_application;
1762 } 1763 }
1763 } 1764 }
1764 1765
1765 return NULL; 1766 return NULL;
1766 } 1767 }
1768
1769
1770 static ngx_quic_frame_t *
1771 ngx_quic_alloc_frame(ngx_connection_t *c, size_t size)
1772 {
1773 u_char *p;
1774 ngx_quic_frame_t *frame;
1775 ngx_quic_connection_t *qc;
1776
1777 if (size) {
1778 p = ngx_alloc(size, c->log);
1779 if (p == NULL) {
1780 return NULL;
1781 }
1782
1783 } else {
1784 p = NULL;
1785 }
1786
1787 qc = c->quic;
1788 frame = qc->free_frames;
1789
1790 if (frame) {
1791 qc->free_frames = frame->next;
1792
1793 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1794 "reuse quic frame n:%ui", qc->nframes);
1795
1796 } else {
1797 frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t));
1798 if (frame == NULL) {
1799 ngx_free(p);
1800 return NULL;
1801 }
1802
1803 #if (NGX_DEBUG)
1804 ++qc->nframes;
1805 #endif
1806
1807 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1808 "alloc quic frame n:%ui", qc->nframes);
1809 }
1810
1811 ngx_memzero(frame, sizeof(ngx_quic_frame_t));
1812
1813 frame->data = p;
1814
1815 return frame;
1816 }
1817
1818
1819 static void
1820 ngx_quic_free_frame(ngx_connection_t *c, ngx_quic_frame_t *frame)
1821 {
1822 ngx_quic_connection_t *qc;
1823
1824 qc = c->quic;
1825
1826 if (frame->data) {
1827 ngx_free(frame->data);
1828 }
1829
1830 frame->next = qc->free_frames;
1831 qc->free_frames = frame;
1832
1833 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1834 "free quic frame n:%ui", qc->nframes);
1835 }