blob: a133cd53b440f3d4aff732292ba4847c5bb73c52 [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 Denoyelle154bc7f2021-11-12 16:09:54 +010010
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020011static ssize_t hq_interop_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010012{
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010013 struct htx *htx;
14 struct htx_sl *sl;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010015 struct buffer htx_buf = BUF_NULL;
16 struct ist path;
Amaury Denoyelle62eef852022-06-03 16:40:34 +020017 char *ptr = b_head(b);
18 char *end = b_wrap(b);
19 size_t size = b_size(b);
20 size_t data = b_data(b);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010021
22 b_alloc(&htx_buf);
23 htx = htx_from_buf(&htx_buf);
24
25 /* skip method */
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010026 while (data && HTTP_IS_TOKEN(*ptr)) {
27 if (++ptr == end)
28 ptr -= size;
29 data--;
30 }
31
32 if (!data || !HTTP_IS_SPHT(*ptr)) {
33 fprintf(stderr, "truncated stream\n");
34 return 0;
35 }
36
37 if (++ptr == end)
38 ptr -= size;
39
40 if (!--data) {
41 fprintf(stderr, "truncated stream\n");
42 return 0;
43 }
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010044
45 /* extract path */
46 BUG_ON(HTTP_IS_LWS(*ptr));
47 path.ptr = ptr;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010048 while (data && !HTTP_IS_LWS(*ptr)) {
49 if (++ptr == end)
50 ptr -= size;
51 data--;
52 }
53
54 if (!data) {
55 fprintf(stderr, "truncated stream\n");
56 return 0;
57 }
58
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010059 BUG_ON(!HTTP_IS_LWS(*ptr));
60 path.len = ptr - path.ptr;
61
62 sl = htx_add_stline(htx, HTX_BLK_REQ_SL, 0, ist("GET"), path, ist("HTTP/1.0"));
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010063 if (!sl)
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020064 return -1;
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010065
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010066 sl->flags |= HTX_SL_F_BODYLESS;
67 sl->info.req.meth = find_http_meth("GET", 3);
68
69 htx_add_endof(htx, HTX_BLK_EOH);
70 htx_to_buf(htx, &htx_buf);
71
Amaury Denoyelle8d4ac482022-09-15 11:22:32 +020072 if (!qc_attach_sc(qcs, &htx_buf))
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020073 return -1;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010074
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010075 b_free(&htx_buf);
76
Amaury Denoyelledb443382021-11-30 11:23:29 +010077 if (fin)
78 htx->flags |= HTX_FL_EOM;
79
Amaury Denoyelle1f21ebd2022-06-07 17:30:55 +020080 return b_data(b);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010081}
82
83static struct buffer *mux_get_buf(struct qcs *qcs)
84{
85 if (!b_size(&qcs->tx.buf))
86 b_alloc(&qcs->tx.buf);
87
88 return &qcs->tx.buf;
89}
90
Amaury Denoyelle8d4ac482022-09-15 11:22:32 +020091static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010092 size_t count, int flags)
93{
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010094 struct htx *htx;
95 enum htx_blk_type btype;
96 struct htx_blk *blk;
97 int32_t idx;
98 uint32_t bsize, fsize;
99 struct buffer *res, outbuf;
100 size_t total = 0;
101
102 htx = htx_from_buf(buf);
103 res = mux_get_buf(qcs);
104 outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
105
Amaury Denoyelle84ea8dc2021-12-03 14:40:01 +0100106 while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) {
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100107 /* Not implemented : QUIC on backend side */
108 idx = htx_get_head(htx);
109 blk = htx_get_blk(htx, idx);
110 btype = htx_get_blk_type(blk);
111 fsize = bsize = htx_get_blksz(blk);
112
113 BUG_ON(btype == HTX_BLK_REQ_SL);
114
115 switch (btype) {
116 case HTX_BLK_DATA:
117 if (fsize > count)
118 fsize = count;
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100119
Amaury Denoyelle1ac95442021-12-09 10:07:23 +0100120 if (b_room(&outbuf) < fsize)
121 fsize = b_room(&outbuf);
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100122
123 if (!fsize) {
124 qcs->flags |= QC_SF_BLK_MROOM;
125 goto end;
126 }
127
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100128 b_putblk(&outbuf, htx_get_blk_ptr(htx, blk), fsize);
129 total += fsize;
130 count -= fsize;
131
132 if (fsize == bsize)
133 htx_remove_blk(htx, blk);
134 else
135 htx_cut_data_blk(htx, blk, fsize);
136 break;
137
Ilya Shipitsin5e87bcf2021-12-25 11:45:52 +0500138 /* only body is transferred on HTTP/0.9 */
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100139 case HTX_BLK_RES_SL:
140 case HTX_BLK_TLR:
141 case HTX_BLK_EOT:
142 default:
143 htx_remove_blk(htx, blk);
144 total += bsize;
145 count -= bsize;
146 break;
147 }
148 }
149
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100150 end:
Amaury Denoyellec2025c12021-12-03 15:03:36 +0100151 if ((htx->flags & HTX_FL_EOM) && htx_is_empty(htx))
152 qcs->flags |= QC_SF_FIN_STREAM;
153
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100154 b_add(res, b_data(&outbuf));
155
156 if (total) {
157 if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
158 tasklet_wakeup(qcs->qcc->wait_event.tasklet);
159 }
160
161 return total;
162}
163
Amaury Denoyelle30e260e2022-08-03 11:17:57 +0200164static int hq_interop_attach(struct qcs *qcs, void *conn_ctx)
165{
166 qcs_wait_http_req(qcs);
167 return 0;
168}
169
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100170const struct qcc_app_ops hq_interop_ops = {
171 .decode_qcs = hq_interop_decode_qcs,
172 .snd_buf = hq_interop_snd_buf,
Amaury Denoyelle30e260e2022-08-03 11:17:57 +0200173 .attach = hq_interop_attach,
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100174};