blob: 8126a9390521aa4ee485cc622d669ab27a81600e [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);
Amaury Denoyelle62eef852022-06-03 16:40:34 +020019 size_t data = b_data(b);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010020
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020021 /* hq-interop parser does not support buffer wrapping. */
22 BUG_ON(b_data(b) != b_contig_data(b, 0));
Amaury Denoyelle93dd23c2023-05-11 16:49:28 +020023
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020024 /* hq-interop parser is only done once full message is received. */
25 if (!fin)
Amaury Denoyelle381d8132023-02-17 09:51:20 +010026 return 0;
Amaury Denoyelle381d8132023-02-17 09:51:20 +010027
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010028 b_alloc(&htx_buf);
29 htx = htx_from_buf(&htx_buf);
30
31 /* skip method */
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010032 while (data && HTTP_IS_TOKEN(*ptr)) {
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020033 ptr++;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010034 data--;
35 }
36
37 if (!data || !HTTP_IS_SPHT(*ptr)) {
38 fprintf(stderr, "truncated stream\n");
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020039 return -1;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010040 }
41
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020042 ptr++;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010043 if (!--data) {
44 fprintf(stderr, "truncated stream\n");
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020045 return -1;
46 }
47
48 if (HTTP_IS_LWS(*ptr)) {
49 fprintf(stderr, "malformed stream\n");
50 return -1;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010051 }
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010052
53 /* extract path */
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010054 path.ptr = ptr;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010055 while (data && !HTTP_IS_LWS(*ptr)) {
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020056 ptr++;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010057 data--;
58 }
59
60 if (!data) {
61 fprintf(stderr, "truncated stream\n");
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020062 return -1;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010063 }
64
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010065 path.len = ptr - path.ptr;
66
67 sl = htx_add_stline(htx, HTX_BLK_REQ_SL, 0, ist("GET"), path, ist("HTTP/1.0"));
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010068 if (!sl)
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020069 return -1;
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010070
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010071 sl->flags |= HTX_SL_F_BODYLESS;
72 sl->info.req.meth = find_http_meth("GET", 3);
73
74 htx_add_endof(htx, HTX_BLK_EOH);
Amaury Denoyellec5bc10f2023-10-04 15:46:06 +020075 htx->flags |= HTX_FL_EOM;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010076 htx_to_buf(htx, &htx_buf);
77
Amaury Denoyelled68f8b52023-05-30 15:04:46 +020078 if (!qcs_attach_sc(qcs, &htx_buf, fin))
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020079 return -1;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010080
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010081 b_free(&htx_buf);
82
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020083 return b_data(b);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010084}
85
86static struct buffer *mux_get_buf(struct qcs *qcs)
87{
88 if (!b_size(&qcs->tx.buf))
89 b_alloc(&qcs->tx.buf);
90
91 return &qcs->tx.buf;
92}
93
Amaury Denoyelle9534e592022-09-19 17:14:27 +020094static size_t hq_interop_snd_buf(struct qcs *qcs, struct htx *htx,
95 size_t count)
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010096{
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010097 enum htx_blk_type btype;
98 struct htx_blk *blk;
99 int32_t idx;
100 uint32_t bsize, fsize;
101 struct buffer *res, outbuf;
102 size_t total = 0;
103
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100104 res = mux_get_buf(qcs);
105 outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
106
Amaury Denoyelle84ea8dc2021-12-03 14:40:01 +0100107 while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) {
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100108 /* Not implemented : QUIC on backend side */
109 idx = htx_get_head(htx);
110 blk = htx_get_blk(htx, idx);
111 btype = htx_get_blk_type(blk);
112 fsize = bsize = htx_get_blksz(blk);
113
114 BUG_ON(btype == HTX_BLK_REQ_SL);
115
116 switch (btype) {
117 case HTX_BLK_DATA:
118 if (fsize > count)
119 fsize = count;
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100120
Amaury Denoyelle1ac95442021-12-09 10:07:23 +0100121 if (b_room(&outbuf) < fsize)
122 fsize = b_room(&outbuf);
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100123
124 if (!fsize) {
125 qcs->flags |= QC_SF_BLK_MROOM;
126 goto end;
127 }
128
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100129 b_putblk(&outbuf, htx_get_blk_ptr(htx, blk), fsize);
130 total += fsize;
131 count -= fsize;
132
133 if (fsize == bsize)
134 htx_remove_blk(htx, blk);
135 else
136 htx_cut_data_blk(htx, blk, fsize);
137 break;
138
Ilya Shipitsin5e87bcf2021-12-25 11:45:52 +0500139 /* only body is transferred on HTTP/0.9 */
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100140 case HTX_BLK_RES_SL:
141 case HTX_BLK_TLR:
142 case HTX_BLK_EOT:
143 default:
144 htx_remove_blk(htx, blk);
145 total += bsize;
146 count -= bsize;
147 break;
148 }
149 }
150
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100151 end:
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100152 b_add(res, b_data(&outbuf));
153
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100154 return total;
155}
156
Amaury Denoyelle30e260e2022-08-03 11:17:57 +0200157static int hq_interop_attach(struct qcs *qcs, void *conn_ctx)
158{
159 qcs_wait_http_req(qcs);
160 return 0;
161}
162
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100163const struct qcc_app_ops hq_interop_ops = {
164 .decode_qcs = hq_interop_decode_qcs,
165 .snd_buf = hq_interop_snd_buf,
Amaury Denoyelle30e260e2022-08-03 11:17:57 +0200166 .attach = hq_interop_attach,
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100167};