Mercurial > hg > nginx
comparison src/event/ngx_event_quic_transport.c @ 8657:2dfc5ef29973 quic
QUIC: introduced QUIC buffers.
Buffers are used to hold frame data. They have a fixed size and are reused
after being freed.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 01 Dec 2020 19:11:01 +0000 |
parents | dbad2d6d1898 |
children | 5247461c17e1 |
comparison
equal
deleted
inserted
replaced
8656:43f3574b3e6f | 8657:2dfc5ef29973 |
---|---|
85 static size_t ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out, | 85 static size_t ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out, |
86 size_t pkt_len, u_char **pnp); | 86 size_t pkt_len, u_char **pnp); |
87 | 87 |
88 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt, | 88 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt, |
89 ngx_uint_t frame_type); | 89 ngx_uint_t frame_type); |
90 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack); | 90 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, |
91 ngx_chain_t *ranges); | |
91 static size_t ngx_quic_create_stop_sending(u_char *p, | 92 static size_t ngx_quic_create_stop_sending(u_char *p, |
92 ngx_quic_stop_sending_frame_t *ss); | 93 ngx_quic_stop_sending_frame_t *ss); |
93 static size_t ngx_quic_create_crypto(u_char *p, | 94 static size_t ngx_quic_create_crypto(u_char *p, |
94 ngx_quic_crypto_frame_t *crypto); | 95 ngx_quic_crypto_frame_t *crypto, ngx_chain_t *data); |
95 static size_t ngx_quic_create_hs_done(u_char *p); | 96 static size_t ngx_quic_create_hs_done(u_char *p); |
96 static size_t ngx_quic_create_new_token(u_char *p, | 97 static size_t ngx_quic_create_new_token(u_char *p, |
97 ngx_quic_new_token_frame_t *token); | 98 ngx_quic_new_token_frame_t *token); |
98 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf); | 99 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf, |
100 ngx_chain_t *data); | |
99 static size_t ngx_quic_create_max_streams(u_char *p, | 101 static size_t ngx_quic_create_max_streams(u_char *p, |
100 ngx_quic_max_streams_frame_t *ms); | 102 ngx_quic_max_streams_frame_t *ms); |
101 static size_t ngx_quic_create_max_stream_data(u_char *p, | 103 static size_t ngx_quic_create_max_stream_data(u_char *p, |
102 ngx_quic_max_stream_data_frame_t *ms); | 104 ngx_quic_max_stream_data_frame_t *ms); |
103 static size_t ngx_quic_create_max_data(u_char *p, | 105 static size_t ngx_quic_create_max_data(u_char *p, |
701 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end, | 703 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end, |
702 ngx_quic_frame_t *f) | 704 ngx_quic_frame_t *f) |
703 { | 705 { |
704 u_char *p; | 706 u_char *p; |
705 uint64_t varint; | 707 uint64_t varint; |
708 ngx_buf_t *b; | |
706 ngx_uint_t i; | 709 ngx_uint_t i; |
710 | |
711 b = f->data->buf; | |
707 | 712 |
708 p = start; | 713 p = start; |
709 | 714 |
710 p = ngx_quic_parse_int(p, end, &varint); | 715 p = ngx_quic_parse_int(p, end, &varint); |
711 if (p == NULL) { | 716 if (p == NULL) { |
734 p = ngx_quic_parse_int(p, end, &f->u.crypto.length); | 739 p = ngx_quic_parse_int(p, end, &f->u.crypto.length); |
735 if (p == NULL) { | 740 if (p == NULL) { |
736 goto error; | 741 goto error; |
737 } | 742 } |
738 | 743 |
739 p = ngx_quic_read_bytes(p, end, f->u.crypto.length, &f->u.crypto.data); | 744 p = ngx_quic_read_bytes(p, end, f->u.crypto.length, &b->pos); |
740 if (p == NULL) { | 745 if (p == NULL) { |
741 goto error; | 746 goto error; |
742 } | 747 } |
748 | |
749 b->last = p; | |
743 | 750 |
744 break; | 751 break; |
745 | 752 |
746 case NGX_QUIC_FT_PADDING: | 753 case NGX_QUIC_FT_PADDING: |
747 | 754 |
760 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range)))) | 767 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range)))) |
761 { | 768 { |
762 goto error; | 769 goto error; |
763 } | 770 } |
764 | 771 |
765 f->u.ack.ranges_start = p; | 772 b->pos = p; |
766 | 773 |
767 /* process all ranges to get bounds, values are ignored */ | 774 /* process all ranges to get bounds, values are ignored */ |
768 for (i = 0; i < f->u.ack.range_count; i++) { | 775 for (i = 0; i < f->u.ack.range_count; i++) { |
769 | 776 |
770 p = ngx_quic_parse_int(p, end, &varint); | 777 p = ngx_quic_parse_int(p, end, &varint); |
775 if (p == NULL) { | 782 if (p == NULL) { |
776 goto error; | 783 goto error; |
777 } | 784 } |
778 } | 785 } |
779 | 786 |
780 f->u.ack.ranges_end = p; | 787 b->last = p; |
788 | |
789 f->u.ack.ranges_length = b->last - b->pos; | |
781 | 790 |
782 if (f->type == NGX_QUIC_FT_ACK_ECN) { | 791 if (f->type == NGX_QUIC_FT_ACK_ECN) { |
783 | 792 |
784 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.ect0)) | 793 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.ect0)) |
785 && (p = ngx_quic_parse_int(p, end, &f->u.ack.ect1)) | 794 && (p = ngx_quic_parse_int(p, end, &f->u.ack.ect1)) |
912 | 921 |
913 } else { | 922 } else { |
914 f->u.stream.length = end - p; /* up to packet end */ | 923 f->u.stream.length = end - p; /* up to packet end */ |
915 } | 924 } |
916 | 925 |
917 p = ngx_quic_read_bytes(p, end, f->u.stream.length, | 926 p = ngx_quic_read_bytes(p, end, f->u.stream.length, &b->pos); |
918 &f->u.stream.data); | 927 if (p == NULL) { |
919 if (p == NULL) { | 928 goto error; |
920 goto error; | 929 } |
921 } | 930 |
922 | 931 b->last = p; |
923 break; | 932 break; |
924 | 933 |
925 case NGX_QUIC_FT_MAX_DATA: | 934 case NGX_QUIC_FT_MAX_DATA: |
926 | 935 |
927 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data); | 936 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data); |
1190 f->need_ack = 1; | 1199 f->need_ack = 1; |
1191 | 1200 |
1192 switch (f->type) { | 1201 switch (f->type) { |
1193 case NGX_QUIC_FT_ACK: | 1202 case NGX_QUIC_FT_ACK: |
1194 f->need_ack = 0; | 1203 f->need_ack = 0; |
1195 return ngx_quic_create_ack(p, &f->u.ack); | 1204 return ngx_quic_create_ack(p, &f->u.ack, f->data); |
1196 | 1205 |
1197 case NGX_QUIC_FT_STOP_SENDING: | 1206 case NGX_QUIC_FT_STOP_SENDING: |
1198 return ngx_quic_create_stop_sending(p, &f->u.stop_sending); | 1207 return ngx_quic_create_stop_sending(p, &f->u.stop_sending); |
1199 | 1208 |
1200 case NGX_QUIC_FT_CRYPTO: | 1209 case NGX_QUIC_FT_CRYPTO: |
1201 return ngx_quic_create_crypto(p, &f->u.crypto); | 1210 return ngx_quic_create_crypto(p, &f->u.crypto, f->data); |
1202 | 1211 |
1203 case NGX_QUIC_FT_HANDSHAKE_DONE: | 1212 case NGX_QUIC_FT_HANDSHAKE_DONE: |
1204 return ngx_quic_create_hs_done(p); | 1213 return ngx_quic_create_hs_done(p); |
1205 | 1214 |
1206 case NGX_QUIC_FT_NEW_TOKEN: | 1215 case NGX_QUIC_FT_NEW_TOKEN: |
1212 case NGX_QUIC_FT_STREAM3: | 1221 case NGX_QUIC_FT_STREAM3: |
1213 case NGX_QUIC_FT_STREAM4: | 1222 case NGX_QUIC_FT_STREAM4: |
1214 case NGX_QUIC_FT_STREAM5: | 1223 case NGX_QUIC_FT_STREAM5: |
1215 case NGX_QUIC_FT_STREAM6: | 1224 case NGX_QUIC_FT_STREAM6: |
1216 case NGX_QUIC_FT_STREAM7: | 1225 case NGX_QUIC_FT_STREAM7: |
1217 return ngx_quic_create_stream(p, &f->u.stream); | 1226 return ngx_quic_create_stream(p, &f->u.stream, f->data); |
1218 | 1227 |
1219 case NGX_QUIC_FT_CONNECTION_CLOSE: | 1228 case NGX_QUIC_FT_CONNECTION_CLOSE: |
1220 case NGX_QUIC_FT_CONNECTION_CLOSE_APP: | 1229 case NGX_QUIC_FT_CONNECTION_CLOSE_APP: |
1221 f->need_ack = 0; | 1230 f->need_ack = 0; |
1222 return ngx_quic_create_close(p, &f->u.close); | 1231 return ngx_quic_create_close(p, &f->u.close); |
1245 } | 1254 } |
1246 } | 1255 } |
1247 | 1256 |
1248 | 1257 |
1249 static size_t | 1258 static size_t |
1250 ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack) | 1259 ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, ngx_chain_t *ranges) |
1251 { | 1260 { |
1252 size_t len; | 1261 size_t len; |
1253 u_char *start; | 1262 u_char *start; |
1263 ngx_buf_t *b; | |
1254 | 1264 |
1255 if (p == NULL) { | 1265 if (p == NULL) { |
1256 len = ngx_quic_varint_len(NGX_QUIC_FT_ACK); | 1266 len = ngx_quic_varint_len(NGX_QUIC_FT_ACK); |
1257 len += ngx_quic_varint_len(ack->largest); | 1267 len += ngx_quic_varint_len(ack->largest); |
1258 len += ngx_quic_varint_len(ack->delay); | 1268 len += ngx_quic_varint_len(ack->delay); |
1259 len += ngx_quic_varint_len(ack->range_count); | 1269 len += ngx_quic_varint_len(ack->range_count); |
1260 len += ngx_quic_varint_len(ack->first_range); | 1270 len += ngx_quic_varint_len(ack->first_range); |
1261 len += ack->ranges_end - ack->ranges_start; | 1271 len += ack->ranges_length; |
1262 | 1272 |
1263 return len; | 1273 return len; |
1264 } | 1274 } |
1265 | 1275 |
1266 start = p; | 1276 start = p; |
1268 ngx_quic_build_int(&p, NGX_QUIC_FT_ACK); | 1278 ngx_quic_build_int(&p, NGX_QUIC_FT_ACK); |
1269 ngx_quic_build_int(&p, ack->largest); | 1279 ngx_quic_build_int(&p, ack->largest); |
1270 ngx_quic_build_int(&p, ack->delay); | 1280 ngx_quic_build_int(&p, ack->delay); |
1271 ngx_quic_build_int(&p, ack->range_count); | 1281 ngx_quic_build_int(&p, ack->range_count); |
1272 ngx_quic_build_int(&p, ack->first_range); | 1282 ngx_quic_build_int(&p, ack->first_range); |
1273 p = ngx_cpymem(p, ack->ranges_start, ack->ranges_end - ack->ranges_start); | 1283 |
1284 while (ranges) { | |
1285 b = ranges->buf; | |
1286 p = ngx_cpymem(p, b->pos, b->last - b->pos); | |
1287 ranges = ranges->next; | |
1288 } | |
1274 | 1289 |
1275 return p - start; | 1290 return p - start; |
1276 } | 1291 } |
1277 | 1292 |
1278 | 1293 |
1298 return p - start; | 1313 return p - start; |
1299 } | 1314 } |
1300 | 1315 |
1301 | 1316 |
1302 static size_t | 1317 static size_t |
1303 ngx_quic_create_crypto(u_char *p, ngx_quic_crypto_frame_t *crypto) | 1318 ngx_quic_create_crypto(u_char *p, ngx_quic_crypto_frame_t *crypto, |
1304 { | 1319 ngx_chain_t *data) |
1305 size_t len; | 1320 { |
1306 u_char *start; | 1321 size_t len; |
1322 u_char *start; | |
1323 ngx_buf_t *b; | |
1307 | 1324 |
1308 if (p == NULL) { | 1325 if (p == NULL) { |
1309 len = ngx_quic_varint_len(NGX_QUIC_FT_CRYPTO); | 1326 len = ngx_quic_varint_len(NGX_QUIC_FT_CRYPTO); |
1310 len += ngx_quic_varint_len(crypto->offset); | 1327 len += ngx_quic_varint_len(crypto->offset); |
1311 len += ngx_quic_varint_len(crypto->length); | 1328 len += ngx_quic_varint_len(crypto->length); |
1317 start = p; | 1334 start = p; |
1318 | 1335 |
1319 ngx_quic_build_int(&p, NGX_QUIC_FT_CRYPTO); | 1336 ngx_quic_build_int(&p, NGX_QUIC_FT_CRYPTO); |
1320 ngx_quic_build_int(&p, crypto->offset); | 1337 ngx_quic_build_int(&p, crypto->offset); |
1321 ngx_quic_build_int(&p, crypto->length); | 1338 ngx_quic_build_int(&p, crypto->length); |
1322 p = ngx_cpymem(p, crypto->data, crypto->length); | 1339 |
1340 while (data) { | |
1341 b = data->buf; | |
1342 p = ngx_cpymem(p, b->pos, b->last - b->pos); | |
1343 data = data->next; | |
1344 } | |
1323 | 1345 |
1324 return p - start; | 1346 return p - start; |
1325 } | 1347 } |
1326 | 1348 |
1327 | 1349 |
1365 return p - start; | 1387 return p - start; |
1366 } | 1388 } |
1367 | 1389 |
1368 | 1390 |
1369 static size_t | 1391 static size_t |
1370 ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf) | 1392 ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf, |
1371 { | 1393 ngx_chain_t *data) |
1372 size_t len; | 1394 { |
1373 u_char *start; | 1395 size_t len; |
1396 u_char *start; | |
1397 ngx_buf_t *b; | |
1374 | 1398 |
1375 if (p == NULL) { | 1399 if (p == NULL) { |
1376 len = ngx_quic_varint_len(sf->type); | 1400 len = ngx_quic_varint_len(sf->type); |
1377 | 1401 |
1378 if (sf->off) { | 1402 if (sf->off) { |
1399 } | 1423 } |
1400 | 1424 |
1401 /* length is always present in generated frames */ | 1425 /* length is always present in generated frames */ |
1402 ngx_quic_build_int(&p, sf->length); | 1426 ngx_quic_build_int(&p, sf->length); |
1403 | 1427 |
1404 p = ngx_cpymem(p, sf->data, sf->length); | 1428 while (data) { |
1429 b = data->buf; | |
1430 p = ngx_cpymem(p, b->pos, b->last - b->pos); | |
1431 data = data->next; | |
1432 } | |
1405 | 1433 |
1406 return p - start; | 1434 return p - start; |
1407 } | 1435 } |
1408 | 1436 |
1409 | 1437 |