varnish-cache/bin/varnishd/http2/cache_http2_deliver.c
0
/*-
1
 * Copyright (c) 2016 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10 36621
 * are met:
11 0
 * 1. Redistributions of source code must retain the above copyright
12 0
 *    notice, this list of conditions and the following disclaimer.
13 0
 * 2. Redistributions in binary form must reproduce the above copyright
14 0
 *    notice, this list of conditions and the following disclaimer in the
15 0
 *    documentation and/or other materials provided with the distribution.
16 0
 *
17 0
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 0
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 0
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 0
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 0
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 0
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 0
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 36621
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 0
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 0
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 0
 * SUCH DAMAGE.
28 0
 *
29 0
 */
30 0
31 0
#include "config.h"
32 0
33 36621
#include "cache/cache_varnishd.h"
34 0
35 0
#include <ctype.h>
36 0
#include <stdio.h>
37 0
38 0
#include "cache/cache_filter.h"
39 0
#include "cache/cache_transport.h"
40 0
41 0
#include "http2/cache_http2.h"
42 36621
43 36621
#include "vct.h"
44 0
45 0
/**********************************************************************/
46 36621
47 36621
struct hpack_static {
48 36621
        uint8_t                 idx;
49 0
        const char *            name;
50 0
        const char *            val;
51 0
};
52 0
53 36621
static const struct hpack_static hp_static[] = {
54 0
#define HPS(I,N,V) [I] = { I, N ":", V },
55 0
#include "tbl/vhp_static.h"
56 36621
        { 0, "\377:", ""}               // Terminator
57 36621
};
58 0
59 36621
static const struct hpack_static *hp_idx[256];
60 0
61 0
void
62 36621
V2D_Init(void)
63 36621
{
64 0
        int i;
65 0
#define HPS(I,N,V)                                              \
66 36621
        i = hp_static[I].name[0];                               \
67 36621
        if (hp_idx[i] == NULL) hp_idx[i] = &hp_static[I];
68 36621
#include "tbl/vhp_static.h"
69 0
#undef HPS
70 36621
}
71
72
/**********************************************************************/
73
74
static int v_matchproto_(vdp_init_f)
75 1520
h2_init(VRT_CTX, struct vdp_ctx *vdc, void **priv)
76
{
77
        struct h2_req *r2;
78
79 1520
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
80 1520
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
81 1520
        AN(priv);
82 1520
        CAST_OBJ_NOTNULL(r2, *priv, H2_REQ_MAGIC);
83 1520
        (void)r2;
84 1520
        return (0);
85
}
86
87
static int v_matchproto_(vdp_fini_f)
88 1519
h2_fini(struct vdp_ctx *vdc, void **priv)
89
{
90
        struct h2_req *r2;
91
92 1519
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
93 1519
        CHECK_OBJ_NOTNULL(vdc->wrk, WORKER_MAGIC);
94 1519
        TAKE_OBJ_NOTNULL(r2, priv, H2_REQ_MAGIC);
95
96 1519
        if (r2->error)
97 314
                return (0);
98
99 1205
        if (vdc->retval < 0) {
100 68
                r2->error = H2SE_INTERNAL_ERROR; /* XXX: proper error? */
101 68
                H2_Send_Get(vdc->wrk, r2->h2sess, r2);
102 68
                H2_Send_RST(vdc->wrk, r2->h2sess, r2, r2->stream, r2->error);
103 68
                H2_Send_Rel(r2->h2sess, r2);
104 68
                return (0);
105
        }
106
107 1137
        H2_Send_Get(vdc->wrk, r2->h2sess, r2);
108 1137
        H2_Send(vdc->wrk, r2, H2_F_DATA, H2FF_DATA_END_STREAM, 0, "", NULL);
109 1137
        H2_Send_Rel(r2->h2sess, r2);
110 1137
        return (0);
111 1519
}
112
113
static int v_matchproto_(vdp_bytes_f)
114 2480
h2_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv,
115
    const void *ptr, ssize_t len)
116
{
117
        struct h2_req *r2;
118
119 2480
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
120 2480
        CAST_OBJ_NOTNULL(r2, *priv, H2_REQ_MAGIC);
121 2480
        (void)act;
122
123 2480
        if ((r2->h2sess->error || r2->error))
124 263
                return (-1);
125 2217
        if (len == 0)
126 760
                return (0);
127 1457
        H2_Send_Get(vdc->wrk, r2->h2sess, r2);
128 1457
        vdc->bytes_done = 0;
129 1457
        H2_Send(vdc->wrk, r2, H2_F_DATA, H2FF_NONE, len, ptr, &vdc->bytes_done);
130 1457
        H2_Send_Rel(r2->h2sess, r2);
131 1457
        return (0);
132 2480
}
133
134
static const struct vdp h2_vdp = {
135
        .name =         "H2B",
136
        .init =         h2_init,
137
        .bytes =        h2_bytes,
138
        .fini =         h2_fini,
139
};
140
141
static inline size_t
142 4555
h2_status(uint8_t *p, uint16_t status) {
143 4555
        size_t l = 1;
144
145 4555
        switch (status) {
146 2997
        case 200: *p = 0x80 |  8; break;
147 0
        case 204: *p = 0x80 |  9; break;
148 80
        case 206: *p = 0x80 | 10; break;
149 120
        case 304: *p = 0x80 | 11; break;
150 40
        case 400: *p = 0x80 | 12; break;
151 40
        case 404: *p = 0x80 | 13; break;
152 40
        case 500: *p = 0x80 | 14; break;
153
        default:
154 1238
                *p++ = 0x18;
155 1238
                *p++ = 0x03;
156 1238
                l = 2;
157
158 1238
                l += snprintf((char*)p, 4, "%03d", status);
159 1238
                assert(l == 5);
160 1238
                break;
161
        }
162
163 4555
        return (l);
164
}
165
166
int v_matchproto_(vtr_minimal_response_f)
167 1000
h2_minimal_response(struct req *req, uint16_t status)
168
{
169
        struct h2_req *r2;
170
        size_t l;
171
        uint8_t buf[6];
172
173 1000
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
174 1000
        CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
175
176 1000
        assert(status >= 100);
177 1000
        assert(status < 1000);
178
179 1000
        l = h2_status(buf, status);
180 1000
        assert(l < sizeof(buf));
181
182 1000
        VSLb(req->vsl, SLT_RespProtocol, "HTTP/2.0");
183 1000
        VSLb(req->vsl, SLT_RespStatus, "%03d", status);
184 2000
        VSLbs(req->vsl, SLT_RespReason,
185 1000
              TOSTRAND(http_Status2Reason(status, NULL)));
186
187 1000
        if (status >= 400)
188 920
                req->err_code = status;
189
190
        /* XXX return code checking once H2_Send returns anything but 0 */
191 1000
        H2_Send_Get(req->wrk, r2->h2sess, r2);
192 2000
        H2_Send(req->wrk, r2,
193
            H2_F_HEADERS,
194 2000
            H2FF_HEADERS_END_HEADERS |
195 1000
                (status < 200 ? 0 : H2FF_HEADERS_END_STREAM),
196 1000
            l, buf, NULL);
197 1000
        H2_Send_Rel(r2->h2sess, r2);
198 1000
        return (0);
199
}
200
201
static void
202 49003
h2_enc_len(struct vsb *vsb, unsigned bits, unsigned val, uint8_t b0)
203
{
204 49003
        assert(bits < 8);
205 49003
        unsigned mask = (1U << bits) - 1U;
206
207 49003
        if (val >= mask) {
208 20354
                VSB_putc(vsb, b0 | (uint8_t)mask);
209 20354
                val -= mask;
210 20554
                while (val >= 128) {
211 200
                        VSB_putc(vsb, 0x80 | ((uint8_t)val & 0x7f));
212 200
                        val >>= 7;
213
                }
214 20354
        }
215 49003
        VSB_putc(vsb, (uint8_t)val);
216 49003
}
217
218
/*
219
 * Hand-crafted-H2-HEADERS-R-Us:
220
 *
221
 * This is a handbuilt HEADERS frame for when we run out of workspace
222
 * during delivery.
223
 */
224
225
static const uint8_t h2_500_resp[] = {
226
        // :status 500
227
        0x8e,
228
229
        // content-length 0
230
        0x1f, 0x0d, 0x01, 0x30,
231
232
        // server Varnish
233
        0x1f, 0x27, 0x07, 'V', 'a', 'r', 'n', 'i', 's', 'h',
234
};
235
236
static void
237 3560
h2_build_headers(struct vsb *resp, struct req *req)
238
{
239
        unsigned u, l;
240
        int i;
241
        struct http *hp;
242
        const char *r;
243
        const struct hpack_static *hps;
244
        uint8_t buf[6];
245
        ssize_t sz, sz1;
246
247 3560
        assert(req->resp->status % 1000 >= 100);
248 3560
        l = h2_status(buf, req->resp->status % 1000);
249 3560
        VSB_bcat(resp, buf, l);
250
251 3560
        hp = req->resp;
252 28190
        for (u = HTTP_HDR_FIRST; u < hp->nhd && !VSB_error(resp); u++) {
253 24630
                r = strchr(hp->hd[u].b, ':');
254 24630
                AN(r);
255
256 24630
                if (http_IsFiltered(hp, u, HTTPH_C_SPECIFIC))
257 120
                        continue; //rfc7540,l,2999,3006
258
259 24510
                hps = hp_idx[tolower(*hp->hd[u].b)];
260 24510
                sz = 1 + r - hp->hd[u].b;
261 24510
                assert(sz > 0);
262 73070
                while (hps != NULL && hps->idx > 0) {
263 69395
                        i = strncasecmp(hps->name, hp->hd[u].b, sz);
264 69395
                        if (i < 0) {
265 48560
                                hps++;
266 48560
                                continue;
267
                        }
268 20835
                        if (i > 0)
269 680
                                hps = NULL;
270 20835
                        break;
271
                }
272 24510
                if (hps != NULL) {
273 40302
                        VSLb(req->vsl, SLT_Debug,
274
                            "HP {%d, \"%s\", \"%s\"} <%s>",
275 20151
                            hps->idx, hps->name, hps->val, hp->hd[u].b);
276 20151
                        h2_enc_len(resp, 4, hps->idx, 0x10);
277 20151
                } else {
278 4359
                        VSB_putc(resp, 0x10);
279 4359
                        sz--;
280 4359
                        h2_enc_len(resp, 7, sz, 0);
281 64580
                        for (sz1 = 0; sz1 < sz; sz1++)
282 60221
                                VSB_putc(resp, tolower(hp->hd[u].b[sz1]));
283
284
                }
285
286 49020
                while (vct_islws(*++r))
287 24510
                        continue;
288 24510
                sz = hp->hd[u].e - r;
289 24510
                h2_enc_len(resp, 7, sz, 0);
290 24510
                VSB_bcat(resp, r, sz);
291 24510
        }
292 3560
}
293
294
void v_matchproto_(vtr_deliver_f)
295 3560
h2_deliver(struct req *req, struct boc *boc, int sendbody)
296
{
297
        size_t sz;
298
        const char *r;
299
        struct sess *sp;
300
        struct h2_req *r2;
301
        struct vsb resp[1];
302
        struct vrt_ctx ctx[1];
303
        uintptr_t ss;
304
305 3560
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
306 3560
        CHECK_OBJ_ORNULL(boc, BOC_MAGIC);
307 3560
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
308 3560
        CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
309 3560
        sp = req->sp;
310 3560
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
311
312 3560
        VSLb(req->vsl, SLT_RespProtocol, "HTTP/2.0");
313
314 3560
        (void)http_DoConnection(req->resp, SC_RESP_CLOSE);
315
316 3560
        ss = WS_Snapshot(req->ws);
317
318 3560
        WS_VSB_new(resp, req->ws);
319 3560
        h2_build_headers(resp, req);
320 3560
        r = WS_VSB_finish(resp, req->ws, &sz);
321
322 3560
        if (r == NULL) {
323 40
                VSLb(req->vsl, SLT_Error, "workspace_client overflow");
324 40
                VSLb(req->vsl, SLT_RespStatus, "500");
325 40
                VSLb(req->vsl, SLT_RespReason, "Internal Server Error");
326 40
                req->wrk->stats->client_resp_500++;
327
328 40
                r = (const char*)h2_500_resp;
329 40
                sz = sizeof h2_500_resp;
330 40
                sendbody = 0;
331 40
        }
332
333 3560
        AZ(req->wrk->v1l);
334
335 3560
        r2->t_send = req->t_prev;
336
337 3560
        H2_Send_Get(req->wrk, r2->h2sess, r2);
338 7120
        H2_Send(req->wrk, r2, H2_F_HEADERS,
339 3560
            (sendbody ? 0 : H2FF_HEADERS_END_STREAM) | H2FF_HEADERS_END_HEADERS,
340 3560
            sz, r, &req->acct.resp_hdrbytes);
341 3560
        H2_Send_Rel(r2->h2sess, r2);
342
343 3560
        WS_Reset(req->ws, ss);
344
345
        /* XXX someone into H2 please add appropriate error handling */
346 3560
        if (sendbody) {
347 1520
                INIT_OBJ(ctx, VRT_CTX_MAGIC);
348 1520
                VCL_Req2Ctx(ctx, req);
349 1520
                if (! VDP_Push(ctx, req->vdc, req->ws, &h2_vdp, r2))
350 1520
                        (void)VDP_DeliverObj(req->vdc, req->objcore);
351 1520
        }
352
353 3560
        AZ(req->wrk->v1l);
354 3560
        req->acct.resp_bodybytes += VDP_Close(req->vdc, req->objcore, boc);
355 3560
}