static struct quic_tx_packet *qc_build_pkt(unsigned char **pos, const unsigned char *buf_end,
struct quic_enc_level *qel,
- struct quic_conn *qc, int pkt_type,
- int ack, int nb_pto_dgrams, int *err);
+ struct quic_conn *qc, size_t dglen, int pkt_type,
+ int padding, int ack, int nb_pto_dgrams, int *err);
/* Add traces to <buf> depending on <frm> TX frame type. */
static inline void chunk_tx_frm_appendf(struct buffer *buf,
/* length of datagrams */
uint16_t dglen;
size_t total;
+ int padding;
/* Each datagram is prepended with its length followed by the
* address of the first packet in the datagram.
*/
}
start:
- total = 0;
dglen = 0;
+ total = 0;
+ padding = 0;
qel = &qc->els[tel];
cbuf = qr->cbuf;
spos = pos = cb_wr(cbuf);
end = pos + qc->path->mtu;
}
- cur_pkt = qc_build_pkt(&pos, end, qel, qc, pkt_type, ack, nb_ptos, &err);
+ cur_pkt = qc_build_pkt(&pos, end, qel, qc, dglen, padding,
+ pkt_type, ack, nb_ptos, &err);
/* Restore the PTO dgrams counter if a packet could not be built */
if (err < 0) {
if (!prv_pkt && nb_ptos)
qc_set_timer(ctx);
HA_ATOMIC_STORE(&qc->state, QUIC_HS_ST_CLIENT_HANDSHAKE);
}
- /* Special case for Initial packets: when they have all
- * been sent, select the next level.
+ /* If the data for the current encryption level have all been sent,
+ * select the next level.
*/
if ((tel == QUIC_TLS_ENC_LEVEL_INITIAL || tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE) &&
(MT_LIST_ISEMPTY(&qel->pktns->tx.frms) ||
qel = &qc->els[tel];
if (!MT_LIST_ISEMPTY(&qel->pktns->tx.frms)) {
/* If there is data for the next level, do not
- * consume a datagram. This is the case for a client
- * which sends only one Initial packet, then wait
- * for additional CRYPTO data from the server to enter the
- * next level.
+ * consume a datagram.
*/
prv_pkt = cur_pkt;
}
qc_set_dg(cbuf, dglen, first_pkt);
first_pkt = NULL;
dglen = 0;
+ padding = 0;
+ }
+ else if (prv_pkt->type == QUIC_TLS_ENC_LEVEL_INITIAL &&
+ (objt_server(qc->conn->target) ||
+ prv_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
+ padding = 1;
}
}
* Always succeeds: this is the responsibility of the caller to ensure there is
* enough room to build a packet.
*/
-static void qc_do_build_pkt(unsigned char *pos, const unsigned char *end,
- struct quic_tx_packet *pkt, int ack, int nb_pto_dgrams,
+static void qc_do_build_pkt(unsigned char *pos, const unsigned char *end, int padding,
+ size_t dglen, struct quic_tx_packet *pkt, int ack, int nb_pto_dgrams,
int64_t pn, size_t *pn_len, unsigned char **buf_pn,
struct quic_enc_level *qel, struct quic_conn *conn)
{
unsigned char *beg;
- size_t len, len_frms, padding_len;
+ size_t len, len_sz, len_frms, padding_len;
struct quic_frame frm = { .type = QUIC_FT_CRYPTO, };
struct quic_frame ack_frm = { .type = QUIC_FT_ACK, };
- size_t ack_frm_len;
+ size_t ack_frm_len, head_len;
int64_t largest_acked_pn;
int add_ping_frm;
/* XXX FIXME XXX Encode the token length (0) for an Initial packet. */
if (pkt->type == QUIC_PACKET_TYPE_INITIAL)
*pos++ = 0;
+ head_len = pos - beg;
/* Ensure there is enough room for the TLS encryption tag */
end -= QUIC_TLS_TAG_LEN;
/* Build an ACK frame if required. */
conn->conn, NULL, NULL, &room);
}
+ /* Length (of the remaining data). Must not fail because, the buffer size
+ * has been checked above. Note that we have reserved QUIC_TLS_TAG_LEN bytes
+ * for the encryption tag. It must be taken into an account for the length
+ * of this packet.
+ */
+ if (len_frms)
+ len = len_frms + QUIC_TLS_TAG_LEN;
+ else
+ len += QUIC_TLS_TAG_LEN;
+
add_ping_frm = 0;
padding_len = 0;
- if (objt_server(conn->conn->target) &&
- pkt->type == QUIC_PACKET_TYPE_INITIAL &&
- len < QUIC_INITIAL_PACKET_MINLEN) {
- len += padding_len = QUIC_INITIAL_PACKET_MINLEN - len;
+ len_sz = quic_int_getsize(len);
+ /* Add this packet size to <dglen> */
+ dglen += head_len + len_sz + len;
+ if (padding && dglen < QUIC_INITIAL_PACKET_MINLEN) {
+ /* This is a maximum padding size */
+ padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen;
+ /* The length field value is of this packet is <len> + <padding_len>
+ * the size of which may be greater than the initial computed size
+ * <len_sz>. So, let's deduce the difference betwen these to packet
+ * sizes from <padding_len>.
+ */
+ padding_len -= quic_int_getsize(len + padding_len) - len_sz;
+ len += padding_len;
}
else if (LIST_ISEMPTY(&pkt->frms) || len_frms == len) {
if (qel->pktns->tx.pto_probe) {
len += padding_len = QUIC_PACKET_PN_MAXLEN - *pn_len;
}
- /* Length (of the remaining data). Must not fail because, the buffer size
- * has been checked above. Note that we have reserved QUIC_TLS_TAG_LEN bytes
- * for the encryption tag. It must be taken into an account for the length
- * of this packet.
- */
- if (len_frms)
- len = len_frms + QUIC_TLS_TAG_LEN;
- else
- len += QUIC_TLS_TAG_LEN;
if (pkt->type != QUIC_PACKET_TYPE_SHORT)
quic_enc_int(&pos, end, len);
static struct quic_tx_packet *qc_build_pkt(unsigned char **pos,
const unsigned char *buf_end,
struct quic_enc_level *qel,
- struct quic_conn *qc, int pkt_type,
- int ack, int nb_pto_dgrams, int *err)
+ struct quic_conn *qc, size_t dglen, int padding,
+ int pkt_type, int ack, int nb_pto_dgrams, int *err)
{
/* The pointer to the packet number field. */
unsigned char *buf_pn;
/* Consume a packet number. */
pn = HA_ATOMIC_ADD_FETCH(&qel->pktns->tx.next_pn, 1);
- qc_do_build_pkt(*pos, buf_end, pkt, ack, nb_pto_dgrams, pn, &pn_len, &buf_pn, qel, qc);
+ qc_do_build_pkt(*pos, buf_end, padding, dglen, pkt, ack, nb_pto_dgrams,
+ pn, &pn_len, &buf_pn, qel, qc);
end = beg + pkt->len;
payload = buf_pn + pn_len;