summaryrefslogtreecommitdiffstats
path: root/src/quic_tx.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/quic_tx.c77
1 files changed, 37 insertions, 40 deletions
diff --git a/src/quic_tx.c b/src/quic_tx.c
index 39b9176..84e9f32 100644
--- a/src/quic_tx.c
+++ b/src/quic_tx.c
@@ -155,16 +155,27 @@ static void qc_txb_store(struct buffer *buf, uint16_t length,
const size_t hdlen = sizeof(uint16_t) + sizeof(void *);
BUG_ON_HOT(b_contig_space(buf) < hdlen); /* this must not happen */
+ /* If first packet is INITIAL, ensure datagram is sufficiently padded. */
+ BUG_ON(first_pkt->type == QUIC_PACKET_TYPE_INITIAL &&
+ (first_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) &&
+ length < QUIC_INITIAL_PACKET_MINLEN);
+
write_u16(b_tail(buf), length);
write_ptr(b_tail(buf) + sizeof(length), first_pkt);
b_add(buf, hdlen + length);
}
-/* Returns 1 if a packet may be built for <qc> from <qel> encryption level
- * with <frms> as ack-eliciting frame list to send, 0 if not.
- * <cc> must equal to 1 if an immediate close was asked, 0 if not.
- * <probe> must equalt to 1 if a probing packet is required, 0 if not.
- * Also set <*must_ack> to inform the caller if an acknowledgement should be sent.
+/* Reports if data are ready to be sent for <qel> encryption level on <qc>
+ * connection.
+ *
+ * <frms> is the ack-eliciting frames list to send, if any. Other parameters
+ * can be set individually for some special frame types : <cc> for immediate
+ * close, <probe> to emit probing frames.
+ *
+ * This function will also set <must_ack> to inform the caller that an
+ * acknowledgement should be sent.
+ *
+ * Returns true if data to emit else false.
*/
static int qc_may_build_pkt(struct quic_conn *qc, struct list *frms,
struct quic_enc_level *qel, int cc, int probe,
@@ -330,15 +341,7 @@ static int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
for (pkt = first_pkt; pkt; pkt = next_pkt) {
struct quic_cc *cc = &qc->path->cc;
- /* RFC 9000 14.1 Initial datagram size
- * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
- * Initial packets to at least the smallest allowed maximum datagram size of
- * 1200 bytes.
- */
qc->cntrs.sent_pkt++;
- BUG_ON_HOT(pkt->type == QUIC_PACKET_TYPE_INITIAL &&
- (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) &&
- dglen < QUIC_INITIAL_PACKET_MINLEN);
pkt->time_sent = time_sent;
if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) {
@@ -510,7 +513,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
list_for_each_entry_safe(qel, tmp_qel, qels, el_send) {
struct quic_tls_ctx *tls_ctx;
const struct quic_version *ver;
- struct list *frms = qel->send_frms, *next_frms;
+ struct list *frms = qel->send_frms;
struct quic_enc_level *next_qel;
if (qel == qc->eel) {
@@ -521,14 +524,9 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
qc_select_tls_ver(qc, qel, &tls_ctx, &ver);
/* Retrieve next QEL. Set it to NULL if on qels last element. */
- if (qel->el_send.n != qels) {
- next_qel = LIST_ELEM(qel->el_send.n, struct quic_enc_level *, el_send);
- next_frms = next_qel->send_frms;
- }
- else {
- next_qel = NULL;
- next_frms = NULL;
- }
+ next_qel = LIST_NEXT(&qel->el_send, struct quic_enc_level *, el_send);
+ if (&next_qel->el_send == qels)
+ next_qel = NULL;
/* Build as much as datagrams at <qel> encryption level.
* Each datagram is prepended with its length followed by the address
@@ -546,7 +544,9 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
if (!cc)
probe = qel->pktns->tx.pto_probe;
- if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack)) {
+ /* Remove QEL if nothing to send anymore. Padding is only emitted for last QEL. */
+ if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack) &&
+ (!padding || next_qel)) {
/* Remove qel from send_list if nothing to send. */
LIST_DEL_INIT(&qel->el_send);
qel->send_frms = NULL;
@@ -577,30 +577,28 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
}
/* RFC 9000 14.1 Initial datagram size
- * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
- * Initial packets to at least the smallest allowed maximum datagram size of
- * 1200 bytes.
*
- * Ensure that no ack-eliciting packets are sent into too small datagrams
+ * Similarly, a server MUST expand the payload of all UDP
+ * datagrams carrying ack-eliciting Initial packets to at least the
+ * smallest allowed maximum datagram size of 1200 bytes.
*/
- if (qel == qc->iel && !LIST_ISEMPTY(frms)) {
+ if (qel == qc->iel && (!LIST_ISEMPTY(frms) || probe)) {
+ /* Ensure that no ack-eliciting packets are sent into too small datagrams */
if (end - pos < QUIC_INITIAL_PACKET_MINLEN) {
TRACE_PROTO("No more enough room to build an Initial packet",
QUIC_EV_CONN_PHPKTS, qc);
break;
}
- /* Pad this Initial packet if there is no ack-eliciting frames to send from
- * the next packet number space.
- */
- if (!next_frms || LIST_ISEMPTY(next_frms))
- padding = 1;
+ /* padding will be set for last QEL */
+ padding = 1;
}
pkt_type = quic_enc_level_pkt_type(qc, qel);
cur_pkt = qc_build_pkt(&pos, end, qel, tls_ctx, frms,
qc, ver, dglen, pkt_type,
- must_ack, padding, probe, cc, &err);
+ must_ack, padding && !next_qel,
+ probe, cc, &err);
switch (err) {
case -3:
if (first_pkt)
@@ -628,6 +626,10 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
total += cur_pkt->len;
dglen += cur_pkt->len;
+ /* Reset padding if datagram is big enough. */
+ if (dglen >= QUIC_INITIAL_PACKET_MINLEN)
+ padding = 0;
+
if (qc->flags & QUIC_FL_CONN_RETRANS_OLD_DATA)
cur_pkt->flags |= QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA;
@@ -647,12 +649,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
* the same datagram, except if <qel> is the Application data
* encryption level which cannot be selected to do that.
*/
- if (LIST_ISEMPTY(frms) && qel != qc->ael && next_qel) {
- if (qel == qc->iel &&
- (!qc_is_listener(qc) ||
- cur_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING))
- padding = 1;
-
+ if (LIST_ISEMPTY(frms) && next_qel) {
prv_pkt = cur_pkt;
}
else {