summaryrefslogtreecommitdiffstats
path: root/src/hq_interop.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:35:11 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:35:11 +0000
commitda76459dc21b5af2449af2d36eb95226cb186ce2 (patch)
tree542ebb3c1e796fac2742495b8437331727bbbfa0 /src/hq_interop.c
parentInitial commit. (diff)
downloadhaproxy-da76459dc21b5af2449af2d36eb95226cb186ce2.tar.xz
haproxy-da76459dc21b5af2449af2d36eb95226cb186ce2.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.c172
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,
+};