struct quic_transport_params lparams;
struct quic_transport_params rparams;
+ struct buffer txbuf;
struct buffer rxbuf;
};
int conn_send_qstrm(struct connection *conn, struct xprt_qstrm_ctx *ctx, int flag)
{
struct quic_frame frm;
+ struct buffer *buf = &ctx->txbuf;
unsigned char *pos, *old, *end;
+ size_t sent;
int ret;
if (!conn_ctrl_ready(conn))
frm.type = QUIC_FT_QX_TRANSPORT_PARAMETERS;
frm.qmux_transport_params.params = ctx->lparams;
- b_reset(&trash);
- old = pos = (unsigned char *)b_head(&trash);
- end = (unsigned char *)b_wrap(&trash);
- ret = qc_build_frm(&frm, &pos, end, NULL);
- BUG_ON(!ret);
- b_add(&trash, pos - old);
+ /* Small buf is sufficient for our transport parameters. */
+ if (!b_size(buf) && !b_alloc_small(buf))
+ goto fail;
+
+ if (!b_data(buf)) {
+ old = pos = (unsigned char *)b_orig(buf);
+ end = (unsigned char *)b_wrap(buf);
+ ret = qc_build_frm(&frm, &pos, end, NULL);
+ BUG_ON(!ret);
+ b_add(buf, pos - old);
+ }
- ret = ctx->ops_lower->snd_buf(conn, ctx->ctx_lower, &trash, b_data(&trash),
- NULL, 0, 0);
- BUG_ON(!ret || ret != b_data(&trash));
+ sent = ctx->ops_lower->snd_buf(conn, ctx->ctx_lower, buf, b_data(buf),
+ NULL, 0, 0);
+ b_del(buf, sent);
+ if (b_data(buf))
+ goto retry;
conn->flags &= ~flag;
return 1;
+ retry:
+ return 0;
+
fail:
conn->flags |= CO_FL_ERROR;
return 0;
conn->mux->wake(conn);
b_free(&ctx->rxbuf);
+ b_free(&ctx->txbuf);
tasklet_free(ctx->wait_event.tasklet);
pool_free(xprt_qstrm_ctx_pool, ctx);
ctx->ops_lower = NULL;
ctx->rxbuf = BUF_NULL;
+ ctx->txbuf = BUF_NULL;
memset(&ctx->rparams, 0, sizeof(struct quic_transport_params));