blob: 9d0d566353190c8fb38c0d9e8d198978e30e87b8 [file] [log] [blame]
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +01001#include <haproxy/hq_interop.h>
2
3#include <import/ist.h>
4#include <haproxy/buf.h>
5#include <haproxy/connection.h>
6#include <haproxy/dynbuf.h>
7#include <haproxy/htx.h>
8#include <haproxy/http.h>
9#include <haproxy/mux_quic-t.h>
10#include <haproxy/stream.h>
11
Amaury Denoyelledb443382021-11-30 11:23:29 +010012static int hq_interop_decode_qcs(struct qcs *qcs, int fin, void *ctx)
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010013{
14 struct buffer *rxbuf = &qcs->rx.buf;
15 struct htx *htx;
16 struct htx_sl *sl;
17 struct conn_stream *cs;
18 struct buffer htx_buf = BUF_NULL;
19 struct ist path;
20 char *ptr;
21
22 b_alloc(&htx_buf);
23 htx = htx_from_buf(&htx_buf);
24
25 /* skip method */
26 ptr = b_orig(rxbuf);
27 while (HTTP_IS_TOKEN(*ptr))
28 ++ptr;
29 BUG_ON(!HTTP_IS_SPHT(*ptr));
30 ++ptr;
31
32 /* extract path */
33 BUG_ON(HTTP_IS_LWS(*ptr));
34 path.ptr = ptr;
35 while (!HTTP_IS_LWS(*ptr))
36 ++ptr;
37 BUG_ON(!HTTP_IS_LWS(*ptr));
38 path.len = ptr - path.ptr;
39
40 sl = htx_add_stline(htx, HTX_BLK_REQ_SL, 0, ist("GET"), path, ist("HTTP/1.0"));
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010041 if (!sl)
42 return -1;
43
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010044 sl->flags |= HTX_SL_F_BODYLESS;
45 sl->info.req.meth = find_http_meth("GET", 3);
46
47 htx_add_endof(htx, HTX_BLK_EOH);
48 htx_to_buf(htx, &htx_buf);
49
50 cs = cs_new(qcs->qcc->conn, qcs->qcc->conn->target);
51 cs->ctx = qcs;
52 stream_create_from_cs(cs, &htx_buf);
53
54 b_del(rxbuf, b_data(rxbuf));
55 b_free(&htx_buf);
56
Amaury Denoyelledb443382021-11-30 11:23:29 +010057 if (fin)
58 htx->flags |= HTX_FL_EOM;
59
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010060 return 0;
61}
62
63static struct buffer *mux_get_buf(struct qcs *qcs)
64{
65 if (!b_size(&qcs->tx.buf))
66 b_alloc(&qcs->tx.buf);
67
68 return &qcs->tx.buf;
69}
70
71static size_t hq_interop_snd_buf(struct conn_stream *cs, struct buffer *buf,
72 size_t count, int flags)
73{
74 struct qcs *qcs = cs->ctx;
75 struct htx *htx;
76 enum htx_blk_type btype;
77 struct htx_blk *blk;
78 int32_t idx;
79 uint32_t bsize, fsize;
80 struct buffer *res, outbuf;
81 size_t total = 0;
82
83 htx = htx_from_buf(buf);
84 res = mux_get_buf(qcs);
85 outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
86
Amaury Denoyelle84ea8dc2021-12-03 14:40:01 +010087 while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) {
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010088 /* Not implemented : QUIC on backend side */
89 idx = htx_get_head(htx);
90 blk = htx_get_blk(htx, idx);
91 btype = htx_get_blk_type(blk);
92 fsize = bsize = htx_get_blksz(blk);
93
94 BUG_ON(btype == HTX_BLK_REQ_SL);
95
96 switch (btype) {
97 case HTX_BLK_DATA:
98 if (fsize > count)
99 fsize = count;
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100100
101 if (b_size(&outbuf) < fsize)
102 fsize = b_size(&outbuf);
103
104 if (!fsize) {
105 qcs->flags |= QC_SF_BLK_MROOM;
106 goto end;
107 }
108
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100109 b_putblk(&outbuf, htx_get_blk_ptr(htx, blk), fsize);
110 total += fsize;
111 count -= fsize;
112
113 if (fsize == bsize)
114 htx_remove_blk(htx, blk);
115 else
116 htx_cut_data_blk(htx, blk, fsize);
117 break;
118
119 /* only body is transfered on HTTP/0.9 */
120 case HTX_BLK_RES_SL:
121 case HTX_BLK_TLR:
122 case HTX_BLK_EOT:
123 default:
124 htx_remove_blk(htx, blk);
125 total += bsize;
126 count -= bsize;
127 break;
128 }
129 }
130
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100131 end:
Amaury Denoyellec2025c12021-12-03 15:03:36 +0100132 if ((htx->flags & HTX_FL_EOM) && htx_is_empty(htx))
133 qcs->flags |= QC_SF_FIN_STREAM;
134
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100135 b_add(res, b_data(&outbuf));
136
137 if (total) {
138 if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
139 tasklet_wakeup(qcs->qcc->wait_event.tasklet);
140 }
141
142 return total;
143}
144
145const struct qcc_app_ops hq_interop_ops = {
146 .decode_qcs = hq_interop_decode_qcs,
147 .snd_buf = hq_interop_snd_buf,
148};