Mercurial > hg > nginx
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 } |