diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:35:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:35:11 +0000 |
commit | da76459dc21b5af2449af2d36eb95226cb186ce2 (patch) | |
tree | 542ebb3c1e796fac2742495b8437331727bbbfa0 /src/hq_interop.c | |
parent | Initial commit. (diff) | |
download | haproxy-upstream.tar.xz haproxy-upstream.zip |
Adding upstream version 2.6.12.upstream/2.6.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/hq_interop.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/hq_interop.c b/src/hq_interop.c new file mode 100644 index 0000000..175b92d --- /dev/null +++ b/src/hq_interop.c @@ -0,0 +1,172 @@ +#include <haproxy/hq_interop.h> + +#include <import/ist.h> +#include <haproxy/buf.h> +#include <haproxy/connection.h> +#include <haproxy/dynbuf.h> +#include <haproxy/htx.h> +#include <haproxy/http.h> +#include <haproxy/mux_quic.h> +#include <haproxy/qmux_http.h> + +static ssize_t hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin) +{ + struct htx *htx; + struct htx_sl *sl; + struct buffer htx_buf = BUF_NULL; + struct ist path; + char *ptr = b_head(b); + char *end = b_wrap(b); + size_t size = b_size(b); + size_t data = b_data(b); + + if (!data && fin) { + /* FIN is notified with an empty STREAM frame. */ + BUG_ON(!qcs->sd); /* sd must already be attached here */ + qcs_http_handle_standalone_fin(qcs); + return 0; + } + + b_alloc(&htx_buf); + htx = htx_from_buf(&htx_buf); + + /* skip method */ + while (data && HTTP_IS_TOKEN(*ptr)) { + if (++ptr == end) + ptr -= size; + data--; + } + + if (!data || !HTTP_IS_SPHT(*ptr)) { + fprintf(stderr, "truncated stream\n"); + return 0; + } + + if (++ptr == end) + ptr -= size; + + if (!--data) { + fprintf(stderr, "truncated stream\n"); + return 0; + } + + /* extract path */ + BUG_ON(HTTP_IS_LWS(*ptr)); + path.ptr = ptr; + while (data && !HTTP_IS_LWS(*ptr)) { + if (++ptr == end) + ptr -= size; + data--; + } + + if (!data) { + fprintf(stderr, "truncated stream\n"); + return 0; + } + + BUG_ON(!HTTP_IS_LWS(*ptr)); + path.len = ptr - path.ptr; + + sl = htx_add_stline(htx, HTX_BLK_REQ_SL, 0, ist("GET"), path, ist("HTTP/1.0")); + if (!sl) + return -1; + + sl->flags |= HTX_SL_F_BODYLESS; + sl->info.req.meth = find_http_meth("GET", 3); + + htx_add_endof(htx, HTX_BLK_EOH); + htx_to_buf(htx, &htx_buf); + + if (!qc_attach_sc(qcs, &htx_buf)) + return -1; + + b_free(&htx_buf); + + if (fin) + htx->flags |= HTX_FL_EOM; + + return b_data(b); +} + +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 size_t hq_interop_snd_buf(struct qcs *qcs, struct htx *htx, + size_t count) +{ + enum htx_blk_type btype; + struct htx_blk *blk; + int32_t idx; + uint32_t bsize, fsize; + struct buffer *res, outbuf; + size_t total = 0; + + res = mux_get_buf(qcs); + outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0); + + while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) { + /* Not implemented : QUIC on backend side */ + idx = htx_get_head(htx); + blk = htx_get_blk(htx, idx); + btype = htx_get_blk_type(blk); + fsize = bsize = htx_get_blksz(blk); + + BUG_ON(btype == HTX_BLK_REQ_SL); + + switch (btype) { + case HTX_BLK_DATA: + if (fsize > count) + fsize = count; + + if (b_room(&outbuf) < fsize) + fsize = b_room(&outbuf); + + if (!fsize) { + qcs->flags |= QC_SF_BLK_MROOM; + goto end; + } + + b_putblk(&outbuf, htx_get_blk_ptr(htx, blk), fsize); + total += fsize; + count -= fsize; + + if (fsize == bsize) + htx_remove_blk(htx, blk); + else + htx_cut_data_blk(htx, blk, fsize); + break; + + /* only body is transferred on HTTP/0.9 */ + case HTX_BLK_RES_SL: + case HTX_BLK_TLR: + case HTX_BLK_EOT: + default: + htx_remove_blk(htx, blk); + total += bsize; + count -= bsize; + break; + } + } + + end: + b_add(res, b_data(&outbuf)); + + return total; +} + +static int hq_interop_attach(struct qcs *qcs, void *conn_ctx) +{ + qcs_wait_http_req(qcs); + return 0; +} + +const struct qcc_app_ops hq_interop_ops = { + .decode_qcs = hq_interop_decode_qcs, + .snd_buf = hq_interop_snd_buf, + .attach = hq_interop_attach, +}; |