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