MINOR: mux-quic: standardize h3 settings sending

Use same buffer management to send h3 settings as for streams. This
simplify the code maintenance with unused function removed.
This commit is contained in:
Amaury Denoyelle 2021-10-07 16:26:12 +02:00
parent a543eb1f6f
commit a587136c6f

105
src/h3.c
View File

@ -76,35 +76,6 @@ static inline struct buffer h3_b_dup(struct buffer *b)
return b_make(b->area, b->size, b->head, b->data); return b_make(b->area, b->size, b->head, b->data);
} }
static int qcs_buf_available(void *target)
{
struct h3_uqs *h3_uqs = target;
struct qcs *qcs = h3_uqs->qcs;
if ((qcs->flags & OUQS_SF_TXBUF_MALLOC) && b_alloc(&qcs->tx.buf)) {
qcs->flags &= ~OUQS_SF_TXBUF_MALLOC;
tasklet_wakeup(h3_uqs->wait_event.tasklet);
return 1;
}
return 0;
}
static struct buffer *h3_uqs_get_buf(struct h3_uqs *h3_uqs)
{
struct buffer *buf = NULL;
struct h3 *h3 = h3_uqs->qcs->qcc->ctx;
if (likely(!LIST_INLIST(&h3->buf_wait.list)) &&
unlikely((buf = b_alloc(&h3_uqs->qcs->tx.buf)) == NULL)) {
h3->buf_wait.target = h3_uqs;
h3->buf_wait.wakeup_cb = qcs_buf_available;
LIST_APPEND(&th_ctx->buffer_wq, &h3->buf_wait.list);
}
return buf;
}
/* Decode a h3 frame header made of two QUIC varints from <b> buffer. /* Decode a h3 frame header made of two QUIC varints from <b> buffer.
* Returns the number of bytes consumed if there was enough data in <b>, 0 if not. * Returns the number of bytes consumed if there was enough data in <b>, 0 if not.
* Note that this function update <b> buffer to reflect the number of bytes consumed * Note that this function update <b> buffer to reflect the number of bytes consumed
@ -342,24 +313,15 @@ static int h3_control_recv(struct h3_uqs *h3_uqs, void *ctx)
return 1; return 1;
} }
int h3_txbuf_cpy(struct h3_uqs *h3_uqs, unsigned char *buf, size_t len) /* Returns buffer for data sending.
* May be NULL if the allocation failed.
*/
static struct buffer *mux_get_buf(struct qcs *qcs)
{ {
struct buffer *res = &h3_uqs->qcs->tx.buf; if (!b_size(&qcs->tx.buf))
struct qcc *qcc = h3_uqs->qcs->qcc; b_alloc(&qcs->tx.buf);
int ret;
ret = 0; return &qcs->tx.buf;
if (!h3_uqs_get_buf(h3_uqs)) {
qcc->flags |= OUQS_SF_TXBUF_MALLOC;
goto out;
}
ret = b_istput(res, ist2((char *)buf, len));
if (unlikely(!ret))
qcc->flags |= OUQS_SF_TXBUF_FULL;
out:
return ret;
} }
/* Function used to emit stream data from <h3_uqs> control uni-stream */ /* Function used to emit stream data from <h3_uqs> control uni-stream */
@ -368,14 +330,12 @@ static int h3_control_send(struct h3_uqs *h3_uqs, void *ctx)
int ret; int ret;
struct h3 *h3 = ctx; struct h3 *h3 = ctx;
unsigned char data[(2 + 3) * 2 * QUIC_VARINT_MAX_SIZE]; /* enough for 3 settings */ unsigned char data[(2 + 3) * 2 * QUIC_VARINT_MAX_SIZE]; /* enough for 3 settings */
unsigned char *pos, *end; struct buffer pos, *res;
ret = 0; ret = 0;
pos = data; pos = b_make((char *)data, sizeof(data), 0, 0);
end = pos + sizeof data;
if (!(h3->flags & H3_CF_SETTINGS_SENT)) { if (!(h3->flags & H3_CF_SETTINGS_SENT)) {
struct qcs *qcs = h3_uqs->qcs; struct qcs *qcs = h3_uqs->qcs;
struct buffer *txbuf = &qcs->tx.buf;
size_t frm_len; size_t frm_len;
frm_len = quic_int_getsize(H3_SETTINGS_QPACK_MAX_TABLE_CAPACITY) + frm_len = quic_int_getsize(H3_SETTINGS_QPACK_MAX_TABLE_CAPACITY) +
@ -387,46 +347,37 @@ static int h3_control_send(struct h3_uqs *h3_uqs, void *ctx)
quic_int_getsize(h3_settings_max_field_section_size); quic_int_getsize(h3_settings_max_field_section_size);
} }
quic_enc_int(&pos, end, H3_UNI_STRM_TP_CONTROL_STREAM); b_quic_enc_int(&pos, H3_UNI_STRM_TP_CONTROL_STREAM);
/* Build a SETTINGS frame */ /* Build a SETTINGS frame */
quic_enc_int(&pos, end, H3_FT_SETTINGS); b_quic_enc_int(&pos, H3_FT_SETTINGS);
quic_enc_int(&pos, end, frm_len); b_quic_enc_int(&pos, frm_len);
quic_enc_int(&pos, end, H3_SETTINGS_QPACK_MAX_TABLE_CAPACITY); b_quic_enc_int(&pos, H3_SETTINGS_QPACK_MAX_TABLE_CAPACITY);
quic_enc_int(&pos, end, h3_settings_qpack_max_table_capacity); b_quic_enc_int(&pos, h3_settings_qpack_max_table_capacity);
quic_enc_int(&pos, end, H3_SETTINGS_QPACK_BLOCKED_STREAMS); b_quic_enc_int(&pos, H3_SETTINGS_QPACK_BLOCKED_STREAMS);
quic_enc_int(&pos, end, h3_settings_qpack_blocked_streams); b_quic_enc_int(&pos, h3_settings_qpack_blocked_streams);
if (h3_settings_max_field_section_size) { if (h3_settings_max_field_section_size) {
quic_enc_int(&pos, end, H3_SETTINGS_MAX_FIELD_SECTION_SIZE); b_quic_enc_int(&pos, H3_SETTINGS_MAX_FIELD_SECTION_SIZE);
quic_enc_int(&pos, end, h3_settings_max_field_section_size); b_quic_enc_int(&pos, h3_settings_max_field_section_size);
}
ret = h3_txbuf_cpy(h3_uqs, data, pos - data);
if (ret < 0) {
qc_error(qcs->qcc, H3_INTERNAL_ERROR);
return ret;
} }
res = mux_get_buf(qcs);
if (b_room(res) < b_data(&pos)) {
// TODO the mux should be put in blocked state, with
// the stream in state waiting for settings to be sent
ABORT_NOW();
}
ret = b_force_xfer(res, &pos, b_data(&pos));
if (ret > 0) { if (ret > 0) {
h3->flags |= H3_CF_SETTINGS_SENT; h3->flags |= H3_CF_SETTINGS_SENT;
luqs_snd_buf(h3_uqs->qcs, txbuf, b_data(&qcs->tx.buf), 0); if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
tasklet_wakeup(qcs->qcc->wait_event.tasklet);
} }
if (b_data(&qcs->tx.buf))
qcs->qcc->conn->mux->luqs_subscribe(qcs, SUB_RETRY_SEND, &h3->lctrl.wait_event);
} }
return ret; return ret;
} }
/* Returns buffer for data sending.
* May be NULL if the allocation failed.
*/
static struct buffer *mux_get_buf(struct qcs *qcs)
{
if (!b_size(&qcs->tx.buf))
b_alloc(&qcs->tx.buf);
return &qcs->tx.buf;
}
static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx) static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx)
{ {
struct buffer outbuf; struct buffer outbuf;