blob: db4387e8947892b56424cbd25a2257586f992cf1 [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 Denoyelle1290f1e2022-05-13 14:49:05 +020010#include <haproxy/ncbuf.h>
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010011
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{
Amaury Denoyelle1290f1e2022-05-13 14:49:05 +020014 struct ncbuf *rxbuf = &qcs->rx.ncbuf;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010015 struct htx *htx;
16 struct htx_sl *sl;
17 struct conn_stream *cs;
18 struct buffer htx_buf = BUF_NULL;
19 struct ist path;
Amaury Denoyelle1290f1e2022-05-13 14:49:05 +020020 char *ptr = ncb_head(rxbuf);
21 char *end = ncb_wrap(rxbuf);
22 size_t size = ncb_size(rxbuf);
23 size_t data = ncb_data(rxbuf, 0);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010024
25 b_alloc(&htx_buf);
26 htx = htx_from_buf(&htx_buf);
27
28 /* skip method */
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010029 while (data && HTTP_IS_TOKEN(*ptr)) {
30 if (++ptr == end)
31 ptr -= size;
32 data--;
33 }
34
35 if (!data || !HTTP_IS_SPHT(*ptr)) {
36 fprintf(stderr, "truncated stream\n");
37 return 0;
38 }
39
40 if (++ptr == end)
41 ptr -= size;
42
43 if (!--data) {
44 fprintf(stderr, "truncated stream\n");
45 return 0;
46 }
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010047
48 /* extract path */
49 BUG_ON(HTTP_IS_LWS(*ptr));
50 path.ptr = ptr;
Frédéric Lécailleafd373c2021-12-15 22:38:48 +010051 while (data && !HTTP_IS_LWS(*ptr)) {
52 if (++ptr == end)
53 ptr -= size;
54 data--;
55 }
56
57 if (!data) {
58 fprintf(stderr, "truncated stream\n");
59 return 0;
60 }
61
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010062 BUG_ON(!HTTP_IS_LWS(*ptr));
63 path.len = ptr - path.ptr;
64
65 sl = htx_add_stline(htx, HTX_BLK_REQ_SL, 0, ist("GET"), path, ist("HTTP/1.0"));
Amaury Denoyelleb48c59a2021-11-18 14:40:26 +010066 if (!sl)
67 return -1;
68
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010069 sl->flags |= HTX_SL_F_BODYLESS;
70 sl->info.req.meth = find_http_meth("GET", 3);
71
72 htx_add_endof(htx, HTX_BLK_EOH);
73 htx_to_buf(htx, &htx_buf);
74
Amaury Denoyelle846cc042022-04-04 16:13:44 +020075 cs = qc_attach_cs(qcs, &htx_buf);
Frédéric Lécaille1e1fb5d2022-02-15 09:13:05 +010076 if (!cs)
77 return -1;
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010078
Christopher Faulet93882042022-01-19 14:56:50 +010079
Amaury Denoyelle1290f1e2022-05-13 14:49:05 +020080 qcs->rx.offset += ncb_data(rxbuf, 0);
81 ncb_advance(rxbuf, ncb_data(rxbuf, 0));
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010082 b_free(&htx_buf);
83
Amaury Denoyelledb443382021-11-30 11:23:29 +010084 if (fin)
85 htx->flags |= HTX_FL_EOM;
86
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +010087 return 0;
88}
89
90static struct buffer *mux_get_buf(struct qcs *qcs)
91{
92 if (!b_size(&qcs->tx.buf))
93 b_alloc(&qcs->tx.buf);
94
95 return &qcs->tx.buf;
96}
97
98static size_t hq_interop_snd_buf(struct conn_stream *cs, struct buffer *buf,
99 size_t count, int flags)
100{
Christopher Fauletdb90f2a2022-03-22 16:06:25 +0100101 struct qcs *qcs = __cs_mux(cs);
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100102 struct htx *htx;
103 enum htx_blk_type btype;
104 struct htx_blk *blk;
105 int32_t idx;
106 uint32_t bsize, fsize;
107 struct buffer *res, outbuf;
108 size_t total = 0;
109
110 htx = htx_from_buf(buf);
111 res = mux_get_buf(qcs);
112 outbuf = b_make(b_tail(res), b_contig_space(res), 0, 0);
113
Amaury Denoyelle84ea8dc2021-12-03 14:40:01 +0100114 while (count && !htx_is_empty(htx) && !(qcs->flags & QC_SF_BLK_MROOM)) {
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100115 /* Not implemented : QUIC on backend side */
116 idx = htx_get_head(htx);
117 blk = htx_get_blk(htx, idx);
118 btype = htx_get_blk_type(blk);
119 fsize = bsize = htx_get_blksz(blk);
120
121 BUG_ON(btype == HTX_BLK_REQ_SL);
122
123 switch (btype) {
124 case HTX_BLK_DATA:
125 if (fsize > count)
126 fsize = count;
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100127
Amaury Denoyelle1ac95442021-12-09 10:07:23 +0100128 if (b_room(&outbuf) < fsize)
129 fsize = b_room(&outbuf);
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100130
131 if (!fsize) {
132 qcs->flags |= QC_SF_BLK_MROOM;
133 goto end;
134 }
135
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100136 b_putblk(&outbuf, htx_get_blk_ptr(htx, blk), fsize);
137 total += fsize;
138 count -= fsize;
139
140 if (fsize == bsize)
141 htx_remove_blk(htx, blk);
142 else
143 htx_cut_data_blk(htx, blk, fsize);
144 break;
145
Ilya Shipitsin5e87bcf2021-12-25 11:45:52 +0500146 /* only body is transferred on HTTP/0.9 */
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100147 case HTX_BLK_RES_SL:
148 case HTX_BLK_TLR:
149 case HTX_BLK_EOT:
150 default:
151 htx_remove_blk(htx, blk);
152 total += bsize;
153 count -= bsize;
154 break;
155 }
156 }
157
Amaury Denoyelle5ede40b2021-12-07 16:19:03 +0100158 end:
Amaury Denoyellec2025c12021-12-03 15:03:36 +0100159 if ((htx->flags & HTX_FL_EOM) && htx_is_empty(htx))
160 qcs->flags |= QC_SF_FIN_STREAM;
161
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100162 b_add(res, b_data(&outbuf));
163
164 if (total) {
165 if (!(qcs->qcc->wait_event.events & SUB_RETRY_SEND))
166 tasklet_wakeup(qcs->qcc->wait_event.tasklet);
167 }
168
169 return total;
170}
171
Amaury Denoyelle198d35f2022-04-01 17:56:58 +0200172static int hq_is_active(const struct qcc *qcc, void *ctx)
173{
174 if (!eb_is_empty(&qcc->streams_by_id))
175 return 1;
176
177 return 0;
178}
179
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100180const struct qcc_app_ops hq_interop_ops = {
181 .decode_qcs = hq_interop_decode_qcs,
182 .snd_buf = hq_interop_snd_buf,
Amaury Denoyelle198d35f2022-04-01 17:56:58 +0200183 .is_active = hq_is_active,
Amaury Denoyelle154bc7f2021-11-12 16:09:54 +0100184};