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