blob: f34657854bc03a740b2ee862170b0fb08f6d3f2e [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>
Amaury Denoyelle846cc042022-04-04 16:13:44 +02009#include <haproxy/mux_quic.h>
Amaury Denoyelle381d8132023-02-17 09:51:20 +010010#include <haproxy/qmux_http.h>
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010011
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020012static ssize_t hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010013{
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010014 struct htx *htx;
15 struct htx_sl *sl;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010016 struct buffer htx_buf = BUF_NULL;
17 struct ist path;
Amaury Denoyelle62eef852022-06-03 16:40:34 +020018 char *ptr = b_head(b);
19 char *end = b_wrap(b);
20 size_t size = b_size(b);
21 size_t data = b_data(b);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010022
Amaury Denoyelle381d8132023-02-17 09:51:20 +010023 if (!data && fin) {
Amaury Denoyelle93dd23c2023-05-11 16:49:28 +020024 struct buffer *appbuf;
25 struct htx *htx;
26
Amaury Denoyelle381d8132023-02-17 09:51:20 +010027 /* FIN is notified with an empty STREAM frame. */
28 BUG_ON(!qcs->sd); /* sd must already be attached here */
Amaury Denoyelle93dd23c2023-05-11 16:49:28 +020029
30 if (!(appbuf = qc_get_buf(qcs, &qcs->rx.app_buf)))
31 return -1;
32
33 htx = htx_from_buf(appbuf);
34 if (!htx_set_eom(htx))
35 return -1;
36 htx_to_buf(htx, appbuf);
37
Amaury Denoyelle381d8132023-02-17 09:51:20 +010038 return 0;
39 }
40
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010041 b_alloc(&htx_buf);
42 htx = htx_from_buf(&htx_buf);
43
44 /* skip method */
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010045 while (data && HTTP_IS_TOKEN(*ptr)) {
46 if (++ptr == end)
47 ptr -= size;
48 data--;
49 }
50
51 if (!data || !HTTP_IS_SPHT(*ptr)) {
52 fprintf(stderr, "truncated stream\n");
53 return 0;
54 }
55
56 if (++ptr == end)
57 ptr -= size;
58
59 if (!--data) {
60 fprintf(stderr, "truncated stream\n");
61 return 0;
62 }
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010063
64 /* extract path */
65 BUG_ON(HTTP_IS_LWS(*ptr));
66 path.ptr = ptr;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010067 while (data && !HTTP_IS_LWS(*ptr)) {
68 if (++ptr == end)
69 ptr -= size;
70 data--;
71 }
72
73 if (!data) {
74 fprintf(stderr, "truncated stream\n");
75 return 0;
76 }
77
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010078 BUG_ON(!HTTP_IS_LWS(*ptr));
79 path.len = ptr - path.ptr;
80
81 sl = htx_add_stline(htx, HTX_BLK_REQ_SL, 0, ist("GET"), path, ist("HTTP/1.0"));
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010082 if (!sl)
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020083 return -1;
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010084
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010085 sl->flags |= HTX_SL_F_BODYLESS;
86 sl->info.req.meth = find_http_meth("GET", 3);
87
88 htx_add_endof(htx, HTX_BLK_EOH);
89 htx_to_buf(htx, &htx_buf);
90
Amaury Denoyellebf86d892023-05-12 18:16:31 +020091 if (!qc_attach_sc(qcs, &htx_buf, fin))
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020092 return -1;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010093
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010094 b_free(&htx_buf);
95
Amaury Denoyelledb443382021-11-30 11:23:29 +010096 if (fin)
97 htx->flags |= HTX_FL_EOM;
98
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020099 return b_data(b);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100100}
101
102static struct buffer *mux_get_buf(struct qcs *qcs)
103{
104 if (!b_size(&qcs->tx.buf))
105 b_alloc(&qcs->tx.buf);
106
107 return &qcs->tx.buf;
108}
109
Amaury Denoyelle9534e592022-09-19 17:14:27 +0200110static size_t hq_interop_snd_buf(struct qcs *qcs, struct htx *htx,
111 size_t count)
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100112{
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100113 enum htx_blk_type btype;
114 struct htx_blk *blk;
115 int32_t idx;
116 uint32_t bsize, fsize;
117 struct buffer *res, outbuf;
118 size_t total = 0;
119
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100120 res = mux_get_buf(qcs);
121 outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
122
Amaury Denoyelle84ea8dc2021-12-03 14:40:01 +0100123 while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) {
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100124 /* Not implemented : QUIC on backend side */
125 idx = htx_get_head(htx);
126 blk = htx_get_blk(htx, idx);
127 btype = htx_get_blk_type(blk);
128 fsize = bsize = htx_get_blksz(blk);
129
130 BUG_ON(btype == HTX_BLK_REQ_SL);
131
132 switch (btype) {
133 case HTX_BLK_DATA:
134 if (fsize > count)
135 fsize = count;
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100136
Amaury Denoyelle1ac95442021-12-09 10:07:23 +0100137 if (b_room(&outbuf) < fsize)
138 fsize = b_room(&outbuf);
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100139
140 if (!fsize) {
141 qcs->flags |= QC_SF_BLK_MROOM;
142 goto end;
143 }
144
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100145 b_putblk(&outbuf, htx_get_blk_ptr(htx, blk), fsize);
146 total += fsize;
147 count -= fsize;
148
149 if (fsize == bsize)
150 htx_remove_blk(htx, blk);
151 else
152 htx_cut_data_blk(htx, blk, fsize);
153 break;
154
Ilya Shipitsin5e87bcf2021-12-25 11:45:52 +0500155 /* only body is transferred on HTTP/0.9 */
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100156 case HTX_BLK_RES_SL:
157 case HTX_BLK_TLR:
158 case HTX_BLK_EOT:
159 default:
160 htx_remove_blk(htx, blk);
161 total += bsize;
162 count -= bsize;
163 break;
164 }
165 }
166
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100167 end:
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100168 b_add(res, b_data(&outbuf));
169
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100170 return total;
171}
172
Amaury Denoyelle30e260e2022-08-03 11:17:57 +0200173static int hq_interop_attach(struct qcs *qcs, void *conn_ctx)
174{
175 qcs_wait_http_req(qcs);
176 return 0;
177}
178
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100179const struct qcc_app_ops hq_interop_ops = {
180 .decode_qcs = hq_interop_decode_qcs,
181 .snd_buf = hq_interop_snd_buf,
Amaury Denoyelle30e260e2022-08-03 11:17:57 +0200182 .attach = hq_interop_attach,
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100183};