|
22 | 22 | #include <haproxy/api.h> |
23 | 23 | #include <haproxy/buf.h> |
24 | 24 | #include <haproxy/connection.h> |
| 25 | +#include <haproxy/dynbuf.h> |
25 | 26 | #include <haproxy/fd.h> |
26 | 27 | #include <haproxy/freq_ctr.h> |
27 | 28 | #include <haproxy/global-t.h> |
@@ -487,84 +488,14 @@ void quic_lstnr_sock_fd_iocb(int fd) |
487 | 488 | /* FD-owned quic-conn socket callback. */ |
488 | 489 | static void quic_conn_sock_fd_iocb(int fd) |
489 | 490 | { |
490 | | - struct quic_conn *qc; |
| 491 | + struct quic_conn *qc = fdtab[fd].owner; |
491 | 492 |
|
492 | | - struct sockaddr_storage saddr = {0}, daddr = {0}; |
493 | | - struct quic_receiver_buf *rxbuf; |
494 | | - struct quic_transport_params *params; |
495 | | - struct quic_dgram *new_dgram; |
496 | | - struct buffer *buf; |
497 | | - size_t max_sz; |
498 | | - size_t cspace; |
499 | | - unsigned char *dgram_buf; |
500 | | - struct listener *l; |
501 | | - ssize_t ret = 0; |
502 | | - |
503 | | - qc = fdtab[fd].owner; |
504 | | - l = qc->li; |
505 | 493 | TRACE_ENTER(QUIC_EV_CONN_RCV, qc); |
506 | 494 |
|
507 | | - new_dgram = NULL; |
508 | | - rxbuf = MT_LIST_POP(&l->rx.rxbuf_list, typeof(rxbuf), rxbuf_el); |
509 | | - if (!rxbuf) |
510 | | - return; |
511 | | - |
512 | | - buf = &rxbuf->buf; |
513 | | - new_dgram = quic_rxbuf_purge_dgrams(rxbuf); |
514 | | - |
515 | | - params = &l->bind_conf->quic_params; |
516 | | - max_sz = params->max_udp_payload_size; |
517 | | - cspace = b_contig_space(buf); |
518 | | - if (cspace < max_sz) { |
519 | | - struct quic_dgram *dgram; |
520 | | - |
521 | | - /* Do no mark <buf> as full, and do not try to consume it |
522 | | - * if the contiguous remaining space is not at the end |
523 | | - */ |
524 | | - if (b_tail(buf) + cspace < b_wrap(buf)) |
525 | | - goto end; |
526 | | - |
527 | | - /* Allocate a fake datagram, without data to locate |
528 | | - * the end of the RX buffer (required during purging). |
529 | | - */ |
530 | | - dgram = pool_alloc(pool_head_quic_dgram); |
531 | | - if (!dgram) |
532 | | - goto end; |
533 | | - |
534 | | - /* Initialize only the useful members of this fake datagram. */ |
535 | | - dgram->buf = NULL; |
536 | | - dgram->len = cspace; |
537 | | - /* Append this datagram only to the RX buffer list. It will |
538 | | - * not be treated by any datagram handler. |
539 | | - */ |
540 | | - LIST_APPEND(&rxbuf->dgram_list, &dgram->recv_list); |
541 | | - |
542 | | - /* Consume the remaining space */ |
543 | | - b_add(buf, cspace); |
544 | | - if (b_contig_space(buf) < max_sz) |
545 | | - goto end; |
546 | | - } |
547 | | - |
548 | | - dgram_buf = (unsigned char *)b_tail(buf); |
549 | | - ret = quic_recv(qc->fd, dgram_buf, max_sz, |
550 | | - (struct sockaddr *)&saddr, sizeof(saddr), |
551 | | - (struct sockaddr *)&daddr, sizeof(daddr), |
552 | | - get_net_port(&qc->local_addr)); |
553 | | - if (ret <= 0) |
554 | | - goto end; |
555 | | - |
556 | | - b_add(buf, ret); |
557 | | - if (!quic_lstnr_dgram_dispatch(dgram_buf, ret, l, &qc->peer_addr, &qc->local_addr, |
558 | | - new_dgram, &rxbuf->dgram_list)) { |
559 | | - b_del(buf, ret); |
560 | | - } |
561 | | - new_dgram = NULL; |
| 495 | + tasklet_wakeup_after(NULL, qc->wait_event.tasklet); |
| 496 | + fd_stop_recv(fd); |
562 | 497 |
|
563 | | - end: |
564 | | - pool_free(pool_head_quic_dgram, new_dgram); |
565 | | - MT_LIST_APPEND(&l->rx.rxbuf_list, &rxbuf->rxbuf_el); |
566 | 498 | TRACE_LEAVE(QUIC_EV_CONN_RCV, qc); |
567 | | - return; |
568 | 499 | } |
569 | 500 |
|
570 | 501 | /* Send a datagram stored into <buf> buffer with <sz> as size. |
@@ -627,6 +558,96 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz, |
627 | 558 | return 0; |
628 | 559 | } |
629 | 560 |
|
| 561 | +/* Receive datagram on <qc> FD-owned socket. |
| 562 | + * |
| 563 | + * Returns the total number of bytes read or a negative value on error. |
| 564 | + */ |
| 565 | +int qc_rcv_buf(struct quic_conn *qc) |
| 566 | +{ |
| 567 | + struct sockaddr_storage saddr = {0}, daddr = {0}; |
| 568 | + struct quic_transport_params *params; |
| 569 | + struct quic_dgram *new_dgram = NULL; |
| 570 | + struct buffer buf = BUF_NULL; |
| 571 | + size_t max_sz; |
| 572 | + unsigned char *dgram_buf; |
| 573 | + struct listener *l; |
| 574 | + ssize_t ret = 0; |
| 575 | + |
| 576 | + /* Do not call this if quic-conn FD is uninitialized. */ |
| 577 | + BUG_ON(qc->fd < 0); |
| 578 | + |
| 579 | + TRACE_ENTER(QUIC_EV_CONN_RCV, qc); |
| 580 | + l = qc->li; |
| 581 | + |
| 582 | + params = &l->bind_conf->quic_params; |
| 583 | + max_sz = params->max_udp_payload_size; |
| 584 | + |
| 585 | + do { |
| 586 | + if (!b_alloc(&buf)) |
| 587 | + break; /* TODO subscribe for memory again available. */ |
| 588 | + |
| 589 | + b_reset(&buf); |
| 590 | + BUG_ON(b_contig_space(&buf) < max_sz); |
| 591 | + |
| 592 | + /* Allocate datagram on first loop or after requeuing. */ |
| 593 | + if (!new_dgram && !(new_dgram = pool_alloc(pool_head_quic_dgram))) |
| 594 | + break; /* TODO subscribe for memory again available. */ |
| 595 | + |
| 596 | + dgram_buf = (unsigned char *)b_tail(&buf); |
| 597 | + ret = quic_recv(qc->fd, dgram_buf, max_sz, |
| 598 | + (struct sockaddr *)&saddr, sizeof(saddr), |
| 599 | + (struct sockaddr *)&daddr, sizeof(daddr), |
| 600 | + get_net_port(&qc->local_addr)); |
| 601 | + if (ret <= 0) { |
| 602 | + /* Subscribe FD for future reception. */ |
| 603 | + fd_want_recv(qc->fd); |
| 604 | + break; |
| 605 | + } |
| 606 | + |
| 607 | + b_add(&buf, ret); |
| 608 | + |
| 609 | + new_dgram->buf = dgram_buf; |
| 610 | + new_dgram->len = ret; |
| 611 | + new_dgram->dcid_len = 0; |
| 612 | + new_dgram->dcid = NULL; |
| 613 | + new_dgram->saddr = saddr; |
| 614 | + new_dgram->daddr = daddr; |
| 615 | + new_dgram->qc = NULL; /* set later via quic_dgram_parse() */ |
| 616 | + |
| 617 | + TRACE_DEVEL("read datagram", QUIC_EV_CONN_RCV, qc, new_dgram); |
| 618 | + |
| 619 | + if (!quic_get_dgram_dcid(new_dgram->buf, |
| 620 | + new_dgram->buf + new_dgram->len, |
| 621 | + &new_dgram->dcid, &new_dgram->dcid_len)) { |
| 622 | + continue; |
| 623 | + } |
| 624 | + |
| 625 | + if (!qc_check_dcid(qc, new_dgram->dcid, new_dgram->dcid_len)) { |
| 626 | + /* Datagram received by error on the connection FD, dispatch it |
| 627 | + * to its associated quic-conn. |
| 628 | + * |
| 629 | + * TODO count redispatch datagrams. |
| 630 | + */ |
| 631 | + TRACE_STATE("wrong datagram on quic-conn socket, prepare to requeue it", QUIC_EV_CONN_RCV, qc); |
| 632 | + ABORT_NOW(); |
| 633 | + } |
| 634 | + |
| 635 | + quic_dgram_parse(new_dgram, qc, qc->li); |
| 636 | + /* A datagram must always be consumed after quic_parse_dgram(). */ |
| 637 | + BUG_ON(new_dgram->buf); |
| 638 | + } while (ret > 0); |
| 639 | + |
| 640 | + pool_free(pool_head_quic_dgram, new_dgram); |
| 641 | + |
| 642 | + if (b_size(&buf)) { |
| 643 | + b_free(&buf); |
| 644 | + offer_buffers(NULL, 1); |
| 645 | + } |
| 646 | + |
| 647 | + TRACE_LEAVE(QUIC_EV_CONN_RCV, qc); |
| 648 | + return ret; |
| 649 | +} |
| 650 | + |
630 | 651 | /* Allocate a socket file-descriptor specific for QUIC connection <qc>. |
631 | 652 | * Endpoint addresses are specified by the two following arguments : <src> is |
632 | 653 | * the local address and <dst> is the remote one. |
|
0 commit comments