comparison src/event/quic/ngx_event_quic_frames.c @ 8760:6ccf3867959a quic

QUIC: refactored ngx_quic_order_bufs() and ngx_quic_split_bufs(). They are replaced with ngx_quic_write_chain() and ngx_quic_read_chain(). These functions represent the API to data buffering. The first function adds data of given size at given offset to the buffer. Now it returns the unwritten part of the chain similar to c->send_chain(). The second function returns data of given size from the beginning of the buffer. Its second argument and return value are swapped compared to ngx_quic_split_bufs() to better match ngx_quic_write_chain(). Added, returned and stored data are regular ngx_chain_t/ngx_buf_t chains. Missing data is marked with b->sync flag. The functions are now used in both send and recv data chains in QUIC streams.
author Roman Arutyunyan <arut@nginx.com>
date Fri, 24 Dec 2021 18:17:23 +0300
parents 56dec0d4e5b1
children 19e063e955bf
comparison
equal deleted inserted replaced
8759:56dec0d4e5b1 8760:6ccf3867959a
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_event_quic_connection.h> 10 #include <ngx_event_quic_connection.h>
11 11
12 12
13 #define NGX_QUIC_BUFFER_SIZE 4096 13 #define NGX_QUIC_BUFFER_SIZE 4096
14
15
16 static ngx_chain_t *ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in,
17 size_t len);
18 14
19 15
20 ngx_quic_frame_t * 16 ngx_quic_frame_t *
21 ngx_quic_alloc_frame(ngx_connection_t *c) 17 ngx_quic_alloc_frame(ngx_connection_t *c)
22 { 18 {
241 onf = &nf->u.ord; 237 onf = &nf->u.ord;
242 onf->offset += of->length; 238 onf->offset += of->length;
243 onf->length = shrink; 239 onf->length = shrink;
244 nf->len = ngx_quic_create_frame(NULL, nf); 240 nf->len = ngx_quic_create_frame(NULL, nf);
245 241
246 nf->data = ngx_quic_split_bufs(c, f->data, of->length); 242 f->data = ngx_quic_read_chain(c, &nf->data, of->length);
247 if (nf->data == NGX_CHAIN_ERROR) { 243 if (f->data == NGX_CHAIN_ERROR) {
248 return NGX_ERROR; 244 return NGX_ERROR;
249 } 245 }
250 246
251 ngx_queue_insert_after(&f->queue, &nf->queue); 247 ngx_queue_insert_after(&f->queue, &nf->queue);
252 248
253 return NGX_OK; 249 return NGX_OK;
254 } 250 }
255 251
256 252
257 static ngx_chain_t * 253 ngx_chain_t *
258 ngx_quic_split_bufs(ngx_connection_t *c, ngx_chain_t *in, size_t len) 254 ngx_quic_read_chain(ngx_connection_t *c, ngx_chain_t **chain, off_t limit)
259 { 255 {
260 size_t n; 256 off_t n;
261 ngx_buf_t *b; 257 ngx_buf_t *b;
262 ngx_chain_t *out; 258 ngx_chain_t *out, *in, *cl, **ll;
263 ngx_quic_connection_t *qc; 259 ngx_quic_connection_t *qc;
264 260
265 qc = ngx_quic_get_connection(c); 261 qc = ngx_quic_get_connection(c);
266 262
267 while (in) { 263 out = *chain;
268 n = ngx_buf_size(in->buf); 264
269 265 for (ll = &out; *ll; ll = &(*ll)->next) {
270 if (n == len) { 266 b = (*ll)->buf;
271 out = in->next; 267
272 in->next = NULL; 268 if (b->sync) {
273 return out; 269 /* hole */
274 }
275
276 if (n > len) {
277 break; 270 break;
278 } 271 }
279 272
280 len -= n; 273 if (limit == 0) {
281 in = in->next; 274 break;
282 } 275 }
283 276
284 if (in == NULL) { 277 n = b->last - b->pos;
285 return NULL; 278
286 } 279 if (n > limit) {
280 goto split;
281 }
282
283 limit -= n;
284 }
285
286 *chain = *ll;
287 *ll = NULL;
288
289 return out;
290
291 split:
292
293 in = *ll;
287 294
288 /* split in->buf by creating shadow bufs which reference it */ 295 /* split in->buf by creating shadow bufs which reference it */
289 296
290 if (in->buf->shadow == NULL) { 297 if (in->buf->shadow == NULL) {
291 if (qc->free_shadow_bufs) { 298 if (qc->free_shadow_bufs) {
303 b->shadow = in->buf; 310 b->shadow = in->buf;
304 b->last_shadow = 1; 311 b->last_shadow = 1;
305 in->buf = b; 312 in->buf = b;
306 } 313 }
307 314
308 out = ngx_alloc_chain_link(c->pool); 315 cl = ngx_alloc_chain_link(c->pool);
309 if (out == NULL) { 316 if (cl == NULL) {
310 return NGX_CHAIN_ERROR; 317 return NGX_CHAIN_ERROR;
311 } 318 }
312 319
313 if (qc->free_shadow_bufs) { 320 if (qc->free_shadow_bufs) {
314 b = qc->free_shadow_bufs; 321 b = qc->free_shadow_bufs;
315 qc->free_shadow_bufs = b->shadow; 322 qc->free_shadow_bufs = b->shadow;
316 323
317 } else { 324 } else {
318 b = ngx_alloc_buf(c->pool); 325 b = ngx_alloc_buf(c->pool);
319 if (b == NULL) { 326 if (b == NULL) {
320 ngx_free_chain(c->pool, out); 327 ngx_free_chain(c->pool, cl);
321 return NGX_CHAIN_ERROR; 328 return NGX_CHAIN_ERROR;
322 } 329 }
323 } 330 }
324 331
325 out->buf = b; 332 cl->buf = b;
326 out->next = in->next; 333 cl->next = in->next;
327 in->next = NULL; 334 in->next = NULL;
335 *chain = cl;
328 336
329 *b = *in->buf; 337 *b = *in->buf;
330 b->last_shadow = 0; 338 b->last_shadow = 0;
331 b->pos = b->pos + len; 339 b->pos += limit;
332 340
333 in->buf->shadow = b; 341 in->buf->shadow = b;
334 in->buf->last = in->buf->pos + len; 342 in->buf->last = b->pos;
343 in->buf->last_buf = 0;
335 344
336 return out; 345 return out;
337 } 346 }
338 347
339 348
478 487
479 return out; 488 return out;
480 } 489 }
481 490
482 491
483 ngx_int_t 492 ngx_chain_t *
484 ngx_quic_order_bufs(ngx_connection_t *c, ngx_chain_t **out, ngx_chain_t *in, 493 ngx_quic_write_chain(ngx_connection_t *c, ngx_chain_t **chain, ngx_chain_t *in,
485 off_t limit, off_t offset) 494 off_t limit, off_t offset)
486 { 495 {
487 off_t n; 496 off_t n;
488 u_char *p; 497 u_char *p;
489 ngx_buf_t *b; 498 ngx_buf_t *b;
490 ngx_chain_t *cl, *sl; 499 ngx_chain_t *cl, *sl;
491 500
492 while (in && limit) { 501 while (in && limit) {
493 cl = *out; 502 cl = *chain;
494 503
495 if (cl == NULL) { 504 if (cl == NULL) {
496 cl = ngx_quic_alloc_buf(c); 505 cl = ngx_quic_alloc_buf(c);
497 if (cl == NULL) { 506 if (cl == NULL) {
498 return NGX_ERROR; 507 return NGX_CHAIN_ERROR;
499 } 508 }
500 509
501 cl->buf->last = cl->buf->end; 510 cl->buf->last = cl->buf->end;
502 cl->buf->sync = 1; /* hole */ 511 cl->buf->sync = 1; /* hole */
503 cl->next = NULL; 512 cl->next = NULL;
504 *out = cl; 513 *chain = cl;
505 } 514 }
506 515
507 b = cl->buf; 516 b = cl->buf;
508 n = b->last - b->pos; 517 n = b->last - b->pos;
509 518
510 if (n <= offset) { 519 if (n <= offset) {
511 offset -= n; 520 offset -= n;
512 out = &cl->next; 521 chain = &cl->next;
513 continue; 522 continue;
514 } 523 }
515 524
516 if (b->sync && offset > 0) { 525 if (b->sync && offset > 0) {
517 sl = ngx_quic_split_bufs(c, cl, offset); 526 /* split hole at offset */
518 if (sl == NGX_CHAIN_ERROR) { 527
519 return NGX_ERROR; 528 b->sync = 0;
520 } 529
521 530 sl = ngx_quic_read_chain(c, &cl, offset);
522 cl->next = sl; 531 if (cl == NGX_CHAIN_ERROR) {
532 return NGX_CHAIN_ERROR;
533 }
534
535 sl->buf->sync = 1;
536 cl->buf->sync = 1;
537
538 *chain = sl;
539 sl->next = cl;
523 continue; 540 continue;
524 } 541 }
525 542
526 for (p = b->pos + offset; p != b->last && in && limit; /* void */ ) { 543 for (p = b->pos + offset; p != b->last && in && limit; /* void */ ) {
527 n = ngx_min(b->last - p, in->buf->last - in->buf->pos); 544 n = ngx_min(b->last - p, in->buf->last - in->buf->pos);
539 if (in->buf->pos == in->buf->last) { 556 if (in->buf->pos == in->buf->last) {
540 in = in->next; 557 in = in->next;
541 } 558 }
542 } 559 }
543 560
561 if (b->sync && p == b->last) {
562 b->sync = 0;
563 continue;
564 }
565
544 if (b->sync && p != b->pos) { 566 if (b->sync && p != b->pos) {
545 sl = ngx_quic_split_bufs(c, cl, p - b->pos); 567 /* split hole at p - b->pos */
568
569 b->sync = 0;
570
571 sl = ngx_quic_read_chain(c, &cl, p - b->pos);
546 if (sl == NGX_CHAIN_ERROR) { 572 if (sl == NGX_CHAIN_ERROR) {
547 return NGX_ERROR; 573 return NGX_CHAIN_ERROR;
548 } 574 }
549 575
550 cl->next = sl; 576 cl->buf->sync = 1;
551 cl->buf->sync = 0; 577
552 } 578 *chain = sl;
553 } 579 sl->next = cl;
554 580 }
555 return NGX_OK; 581 }
582
583 return in;
556 } 584 }
557 585
558 586
559 #if (NGX_DEBUG) 587 #if (NGX_DEBUG)
560 588