varnish-cache/bin/varnishd/cache/cache_fetch.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include "config.h"
31
32
#include "cache_varnishd.h"
33
#include "cache_filter.h"
34
#include "cache_objhead.h"
35
#include "hash/hash_slinger.h"
36
#include "storage/storage.h"
37
#include "vcl.h"
38
#include "vtim.h"
39
40
/*--------------------------------------------------------------------
41
 * Allocate an object, with fall-back to Transient.
42
 * XXX: This somewhat overlaps the stuff in stevedore.c
43
 * XXX: Should this be merged over there ?
44
 */
45
46
static int
47 4914
vbf_allocobj(struct busyobj *bo, unsigned l)
48
{
49
        struct objcore *oc;
50
        const struct stevedore *stv;
51
        double lifetime;
52
53 4914
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
54 4914
        oc = bo->fetch_objcore;
55 4914
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
56
57 4914
        lifetime = oc->ttl + oc->grace + oc->keep;
58
59 4914
        if (bo->uncacheable || lifetime < cache_param->shortlived)
60 1992
                stv = stv_transient;
61
        else
62 2922
                stv = bo->storage;
63
64 4914
        bo->storage = NULL;
65
66 4914
        if (stv == NULL)
67 3
                return (0);
68
69 4911
        if (STV_NewObject(bo->wrk, bo->fetch_objcore, stv, l))
70 4899
                return (1);
71
72 12
        if (stv == stv_transient)
73 6
                return (0);
74
75
        /*
76
         * Try to salvage the transaction by allocating a shortlived object
77
         * on Transient storage.
78
         */
79
80 6
        if (oc->ttl > cache_param->shortlived)
81 6
                oc->ttl = cache_param->shortlived;
82 6
        oc->grace = 0.0;
83 6
        oc->keep = 0.0;
84 6
        return (STV_NewObject(bo->wrk, bo->fetch_objcore, stv_transient, l));
85
}
86
87
/*--------------------------------------------------------------------
88
 * Turn the beresp into a obj
89
 */
90
91
static int
92 4914
vbf_beresp2obj(struct busyobj *bo)
93
{
94
        unsigned l, l2;
95
        const char *b;
96
        uint8_t *bp;
97 4914
        struct vsb *vary = NULL;
98 4914
        int varyl = 0;
99
100 4914
        l = 0;
101
102
        /* Create Vary instructions */
103 4914
        if (!(bo->fetch_objcore->flags & OC_F_PRIVATE)) {
104 3306
                varyl = VRY_Create(bo, &vary);
105 3306
                if (varyl > 0) {
106 561
                        AN(vary);
107 561
                        assert(varyl == VSB_len(vary));
108 561
                        l += PRNDUP((intptr_t)varyl);
109 2745
                } else if (varyl < 0) {
110
                        /*
111
                         * Vary parse error
112
                         * Complain about it, and make this a pass.
113
                         */
114 15
                        VSLb(bo->vsl, SLT_Error,
115
                            "Illegal 'Vary' header from backend, "
116
                            "making this a pass.");
117 15
                        bo->uncacheable = 1;
118 15
                        AZ(vary);
119
                } else
120
                        /* No vary */
121 2730
                        AZ(vary);
122
        }
123
124 4914
        l2 = http_EstimateWS(bo->beresp,
125 4914
            bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);
126 4914
        l += l2;
127
128 4914
        if (bo->uncacheable)
129 1785
                bo->fetch_objcore->flags |= OC_F_PASS;
130
131 4914
        if (!vbf_allocobj(bo, l)) {
132 9
                if (vary != NULL)
133 0
                        VSB_destroy(&vary);
134 9
                AZ(vary);
135 9
                return (-1);
136
        }
137
138 4905
        if (vary != NULL) {
139 561
                AN(ObjSetAttr(bo->wrk, bo->fetch_objcore, OA_VARY, varyl,
140
                        VSB_data(vary)));
141 561
                VSB_destroy(&vary);
142
        }
143
144 4905
        AZ(ObjSetU32(bo->wrk, bo->fetch_objcore, OA_VXID, VXID(bo->vsl->wid)));
145
146
        /* for HTTP_Encode() VSLH call */
147 4905
        bo->beresp->logtag = SLT_ObjMethod;
148
149
        /* Filter into object */
150 4905
        bp = ObjSetAttr(bo->wrk, bo->fetch_objcore, OA_HEADERS, l2, NULL);
151 4905
        AN(bp);
152 4905
        HTTP_Encode(bo->beresp, bp, l2,
153 4905
            bo->uncacheable ? HTTPH_A_PASS : HTTPH_A_INS);
154
155 4905
        if (http_GetHdr(bo->beresp, H_Last_Modified, &b))
156 102
                AZ(ObjSetDouble(bo->wrk, bo->fetch_objcore, OA_LASTMODIFIED,
157
                    VTIM_parse(b)));
158
        else
159 4803
                AZ(ObjSetDouble(bo->wrk, bo->fetch_objcore, OA_LASTMODIFIED,
160
                    floor(bo->fetch_objcore->t_origin)));
161
162 4905
        return (0);
163
}
164
165
/*--------------------------------------------------------------------
166
 * Copy req->bereq and release req if no body
167
 */
168
169
static enum fetch_step
170 4902
vbf_stp_mkbereq(struct worker *wrk, struct busyobj *bo)
171
{
172
        const char *q;
173
174 4902
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
175 4902
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
176 4902
        CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC);
177
178 4902
        assert(bo->fetch_objcore->boc->state == BOS_INVALID);
179 4902
        AZ(bo->storage);
180
181 4902
        HTTP_Setup(bo->bereq0, bo->ws, bo->vsl, SLT_BereqMethod);
182 4902
        http_FilterReq(bo->bereq0, bo->req->http,
183 4902
            bo->do_pass ? HTTPH_R_PASS : HTTPH_R_FETCH);
184
185 4902
        if (bo->do_pass)
186 1605
                AZ(bo->stale_oc);
187
        else {
188 3297
                http_ForceField(bo->bereq0, HTTP_HDR_METHOD, "GET");
189 3297
                if (cache_param->http_gzip_support)
190 3282
                        http_ForceHeader(bo->bereq0, H_Accept_Encoding, "gzip");
191
        }
192 4902
        http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1");
193 4902
        http_CopyHome(bo->bereq0);
194
195 5004
        if (bo->stale_oc != NULL &&
196 159
            ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND) &&
197 108
            (bo->stale_oc->boc != NULL || ObjGetLen(wrk, bo->stale_oc) != 0)) {
198 57
                AZ(bo->stale_oc->flags & OC_F_PASS);
199 57
                q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_Last_Modified);
200 57
                if (q != NULL)
201 24
                        http_PrintfHeader(bo->bereq0,
202
                            "If-Modified-Since: %s", q);
203 57
                q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_ETag);
204 57
                if (q != NULL)
205 39
                        http_PrintfHeader(bo->bereq0,
206
                            "If-None-Match: %s", q);
207
        }
208
209 4902
        HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod);
210 4902
        bo->ws_bo = WS_Snapshot(bo->ws);
211 4902
        HTTP_Copy(bo->bereq, bo->bereq0);
212
213 4902
        if (bo->req->req_body_status == REQ_BODY_NONE) {
214 4800
                bo->req = NULL;
215 4800
                ObjSetState(bo->wrk, bo->fetch_objcore, BOS_REQ_DONE);
216
        }
217 4902
        return (F_STP_STARTFETCH);
218
}
219
220
/*--------------------------------------------------------------------
221
 * Start a new VSL transaction and try again
222
 * Prepare the busyobj and fetch processors
223
 */
224
225
static enum fetch_step
226 84
vbf_stp_retry(struct worker *wrk, struct busyobj *bo)
227
{
228 84
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
229 84
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
230
231 84
        assert(bo->fetch_objcore->boc->state <= BOS_REQ_DONE);
232
233 84
        VSLb_ts_busyobj(bo, "Retry", W_TIM_real(wrk));
234
235
        /* VDI_Finish must have been called before */
236 84
        assert(bo->director_state == DIR_S_NULL);
237
238
        /* reset other bo attributes - See VBO_GetBusyObj */
239 84
        bo->storage = NULL;
240 84
        bo->do_esi = 0;
241 84
        bo->do_stream = 1;
242 84
        bo->filter_list = NULL;
243 84
        bo->was_304 = 0;
244
245
        // XXX: BereqEnd + BereqAcct ?
246 84
        VSL_ChgId(bo->vsl, "bereq", "retry", VXID_Get(wrk, VSL_BACKENDMARKER));
247 84
        VSLb_ts_busyobj(bo, "Start", bo->t_prev);
248 84
        http_VSL_log(bo->bereq);
249
250 84
        return (F_STP_STARTFETCH);
251
}
252
253
/*--------------------------------------------------------------------
254
 * Setup bereq from bereq0, run vcl_backend_fetch
255
 */
256
257
static enum fetch_step
258 4986
vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
259
{
260
        int i;
261
        double now;
262
263 4986
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
264 4986
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
265
266 4986
        AZ(bo->storage);
267 4986
        bo->storage = bo->do_pass ? stv_transient : STV_next();
268
269 4986
        if (bo->retries > 0)
270 84
                http_Unset(bo->bereq, "\012X-Varnish:");
271
272 4986
        http_PrintfHeader(bo->bereq, "X-Varnish: %u", VXID(bo->vsl->wid));
273
274 4986
        VCL_backend_fetch_method(bo->vcl, wrk, NULL, bo, NULL);
275
276 4986
        bo->uncacheable = bo->do_pass;
277 4986
        if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL)
278 21
                return (F_STP_FAIL);
279
280 4965
        assert (wrk->handling == VCL_RET_FETCH);
281
282 4965
        HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
283
284 4965
        assert(bo->fetch_objcore->boc->state <= BOS_REQ_DONE);
285
286 4965
        AZ(bo->htc);
287
288 4965
        VFP_Setup(bo->vfc, wrk);
289 4965
        bo->vfc->oc = bo->fetch_objcore;
290 4965
        bo->vfc->resp = bo->beresp;
291 4965
        bo->vfc->req = bo->bereq;
292
293 4965
        i = VDI_GetHdr(bo);
294
295 4965
        now = W_TIM_real(wrk);
296 4965
        VSLb_ts_busyobj(bo, "Beresp", now);
297
298 4965
        if (i) {
299 354
                assert(bo->director_state == DIR_S_NULL);
300 354
                return (F_STP_ERROR);
301
        }
302
303 4611
        http_VSL_log(bo->beresp);
304
305 4611
        if (bo->htc->body_status == BS_ERROR) {
306 18
                bo->htc->doclose = SC_RX_BODY;
307 18
                VDI_Finish(bo);
308 18
                VSLb(bo->vsl, SLT_Error, "Body cannot be fetched");
309 18
                assert(bo->director_state == DIR_S_NULL);
310 18
                return (F_STP_ERROR);
311
        }
312
313 4593
        if (!http_GetHdr(bo->beresp, H_Date, NULL)) {
314
                /*
315
                 * RFC 2616 14.18 Date: The Date general-header field
316
                 * represents the date and time at which the message was
317
                 * originated, having the same semantics as orig-date in
318
                 * RFC 822. ... A received message that does not have a
319
                 * Date header field MUST be assigned one by the recipient
320
                 * if the message will be cached by that recipient or
321
                 * gatewayed via a protocol which requires a Date.
322
                 *
323
                 * If we didn't get a Date header, we assign one here.
324
                 */
325 4563
                http_TimeHeader(bo->beresp, "Date: ", now);
326
        }
327
328
        /*
329
         * These two headers can be spread over multiple actual headers
330
         * and we rely on their content outside of VCL, so collect them
331
         * into one line here.
332
         */
333 4593
        http_CollectHdr(bo->beresp, H_Cache_Control);
334 4593
        http_CollectHdr(bo->beresp, H_Vary);
335
336 4593
        if (bo->fetch_objcore->flags & OC_F_PRIVATE) {
337
                /* private objects have negative TTL */
338 1416
                bo->fetch_objcore->t_origin = now;
339 1416
                bo->fetch_objcore->ttl = -1.;
340 1416
                bo->fetch_objcore->grace = 0;
341 1416
                bo->fetch_objcore->keep = 0;
342
        } else {
343
                /* What does RFC2616 think about TTL ? */
344 12708
                RFC2616_Ttl(bo, now,
345 3177
                    &bo->fetch_objcore->t_origin,
346 3177
                    &bo->fetch_objcore->ttl,
347 3177
                    &bo->fetch_objcore->grace,
348 3177
                    &bo->fetch_objcore->keep
349
                    );
350
        }
351
352 4593
        AZ(bo->do_esi);
353 4593
        AZ(bo->was_304);
354
355 4593
        if (http_IsStatus(bo->beresp, 304)) {
356 120
                if (bo->stale_oc != NULL &&
357 54
                    ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND)) {
358 51
                        if (ObjCheckFlag(bo->wrk, bo->stale_oc, OF_CHGGZIP)) {
359
                                /*
360
                                 * If we changed the gzip status of the object
361
                                 * the stored Content_Encoding controls we
362
                                 * must weaken any new ETag we get.
363
                                 */
364 6
                                http_Unset(bo->beresp, H_Content_Encoding);
365 6
                                RFC2616_Weaken_Etag(bo->beresp);
366
                        }
367 51
                        http_Unset(bo->beresp, H_Content_Length);
368 51
                        HTTP_Merge(bo->wrk, bo->stale_oc, bo->beresp);
369 51
                        assert(http_IsStatus(bo->beresp, 200));
370 51
                        bo->was_304 = 1;
371 15
                } else if (!bo->do_pass) {
372
                        /*
373
                         * Backend sent unallowed 304
374
                         */
375 3
                        VSLb(bo->vsl, SLT_Error,
376
                            "304 response but not conditional fetch");
377 3
                        bo->htc->doclose = SC_RX_BAD;
378 3
                        VDI_Finish(bo);
379 3
                        return (F_STP_ERROR);
380
                }
381
        }
382
383 4590
        VCL_backend_response_method(bo->vcl, wrk, NULL, bo, NULL);
384
385 4587
        if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL) {
386 15
                bo->htc->doclose = SC_RESP_CLOSE;
387 15
                VDI_Finish(bo);
388 15
                return (F_STP_FAIL);
389
        }
390
391 4572
        if (wrk->handling == VCL_RET_RETRY) {
392 60
                if (bo->htc->body_status != BS_NONE)
393 21
                        bo->htc->doclose = SC_RESP_CLOSE;
394 60
                if (bo->director_state != DIR_S_NULL)
395 60
                        VDI_Finish(bo);
396
397 60
                if (bo->retries++ < cache_param->max_retries)
398 57
                        return (F_STP_RETRY);
399
400 3
                VSLb(bo->vsl, SLT_VCL_Error,
401
                    "Too many retries, delivering 503");
402 3
                assert(bo->director_state == DIR_S_NULL);
403 3
                return (F_STP_ERROR);
404
        }
405
406 4512
        assert(bo->fetch_objcore->boc->state <= BOS_REQ_DONE);
407 4512
        if (bo->fetch_objcore->boc->state != BOS_REQ_DONE) {
408 69
                bo->req = NULL;
409 69
                ObjSetState(wrk, bo->fetch_objcore, BOS_REQ_DONE);
410
        }
411
412 4512
        if (bo->do_esi)
413 525
                bo->do_stream = 0;
414 4512
        if (wrk->handling == VCL_RET_PASS) {
415 30
                bo->fetch_objcore->flags |= OC_F_HFP;
416 30
                bo->uncacheable = 1;
417 30
                wrk->handling = VCL_RET_DELIVER;
418
        }
419 4512
        if (bo->do_pass || bo->uncacheable)
420 1554
                bo->fetch_objcore->flags |= OC_F_PASS;
421
422 4512
        assert(wrk->handling == VCL_RET_DELIVER);
423
424 4512
        return (bo->was_304 ? F_STP_CONDFETCH : F_STP_FETCH);
425
}
426
427
/*--------------------------------------------------------------------
428
 */
429
430
static enum fetch_step
431 2751
vbf_stp_fetchbody(struct worker *wrk, struct busyobj *bo)
432
{
433
        ssize_t l;
434
        uint8_t *ptr;
435 2751
        enum vfp_status vfps = VFP_ERROR;
436
        ssize_t est;
437
        struct vfp_ctx *vfc;
438
439 2751
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
440 2751
        vfc = bo->vfc;
441 2751
        CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
442
443 2751
        AN(vfc->vfp_nxt);
444
445 2751
        est = bo->htc->content_length;
446 2751
        if (est < 0)
447 363
                est = 0;
448
449
        do {
450 165294
                if (vfc->oc->flags & OC_F_ABANDON) {
451
                        /*
452
                         * A pass object and delivery was terminated
453
                         * We don't fail the fetch, in order for hit-for-pass
454
                         * objects to be created.
455
                         */
456 3
                        AN(vfc->oc->flags & OC_F_PASS);
457 3
                        VSLb(wrk->vsl, SLT_Debug,
458
                            "Fetch: Pass delivery abandoned");
459 3
                        bo->htc->doclose = SC_RX_BODY;
460 3
                        break;
461
                }
462 165291
                AZ(vfc->failed);
463 165291
                l = est;
464 165291
                assert(l >= 0);
465 165291
                if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK) {
466 9
                        bo->htc->doclose = SC_RX_BODY;
467 9
                        break;
468
                }
469
470 165282
                AZ(vfc->failed);
471 165282
                vfps = VFP_Suck(vfc, ptr, &l);
472 165282
                if (l > 0 && vfps != VFP_ERROR) {
473 163421
                        bo->acct.beresp_bodybytes += l;
474 163421
                        VFP_Extend(vfc, l);
475 163421
                        if (est >= l)
476 4169
                                est -= l;
477
                        else
478 159252
                                est = 0;
479
                }
480 165282
        } while (vfps == VFP_OK);
481
482 2751
        if (vfc->failed) {
483 90
                (void)VFP_Error(vfc, "Fetch pipeline failed to process");
484 90
                bo->htc->doclose = SC_RX_BODY;
485 90
                VFP_Close(vfc);
486 90
                VDI_Finish(bo);
487 90
                if (!bo->do_stream) {
488 60
                        assert(bo->fetch_objcore->boc->state < BOS_STREAM);
489
                        // XXX: doclose = ?
490 60
                        return (F_STP_ERROR);
491
                } else {
492 30
                        wrk->stats->fetch_failed++;
493 30
                        return (F_STP_FAIL);
494
                }
495
        }
496
497 2661
        ObjTrimStore(wrk, vfc->oc);
498 2661
        return (F_STP_FETCHEND);
499
}
500
501
/*--------------------------------------------------------------------
502
 */
503
504
static void
505 2829
vbf_default_filter_list(const struct busyobj *bo, struct vsb *vsb)
506
{
507
        const char *p;
508 2829
        int do_gzip = bo->do_gzip;
509 2829
        int do_gunzip = bo->do_gunzip;
510 2829
        int is_gzip = 0, is_gunzip = 0;
511
512
        /*
513
         * The VCL variables beresp.do_g[un]zip tells us how we want the
514
         * object processed before it is stored.
515
         *
516
         * The backend Content-Encoding header tells us what we are going
517
         * to receive, which we classify in the following three classes:
518
         *
519
         *      "Content-Encoding: gzip"        --> object is gzip'ed.
520
         *      no Content-Encoding             --> object is not gzip'ed.
521
         *      anything else                   --> do nothing wrt gzip
522
         */
523
524
        /* No body -> done */
525 2829
        if (bo->htc->body_status == BS_NONE || bo->htc->content_length == 0)
526 519
                return;
527
528 2829
        if (!cache_param->http_gzip_support)
529 12
                do_gzip = do_gunzip = 0;
530
531 2829
        if (http_GetHdr(bo->beresp, H_Content_Encoding, &p))
532 255
                is_gzip = !strcasecmp(p, "gzip");
533
        else
534 2574
                is_gunzip = 1;
535
536
        /* We won't gunzip unless it is gzip'ed */
537 2829
        if (do_gunzip && !is_gzip)
538 6
                do_gunzip = 0;
539
540
        /* We wont gzip unless if it already is gzip'ed */
541 2829
        if (do_gzip && !is_gunzip)
542 0
                do_gzip = 0;
543
544 2829
        if (do_gunzip || (is_gzip && bo->do_esi))
545 138
                VSB_cat(vsb, " gunzip");
546
547 2829
        if (bo->do_esi && (do_gzip || (is_gzip && !do_gunzip))) {
548 138
                VSB_cat(vsb, " esi_gzip");
549 138
                return;
550
        }
551
552 2691
        if (bo->do_esi) {
553 381
                VSB_cat(vsb, " esi");
554 381
                return;
555
        }
556
557 2310
        if (do_gzip)
558 42
                VSB_cat(vsb, " gzip");
559
560 2310
        if (is_gzip && !do_gunzip)
561 117
                VSB_cat(vsb, " testgunzip");
562
}
563
564
const char *
565 2835
VBF_Get_Filter_List(struct busyobj *bo)
566
{
567
        unsigned u;
568
        struct vsb vsb[1];
569
570 2835
        u = WS_Reserve(bo->ws, 0);
571 2835
        if (u == 0) {
572 6
                WS_Release(bo->ws, 0);
573 6
                WS_MarkOverflow(bo->ws);
574 6
                return (NULL);
575
        }
576 2829
        AN(VSB_new(vsb, bo->ws->f, u, VSB_FIXEDLEN));
577 2829
        vbf_default_filter_list(bo, vsb);
578 2829
        if (VSB_finish(vsb)) {
579 0
                WS_Release(bo->ws, 0);
580 0
                WS_MarkOverflow(bo->ws);
581 0
                return (NULL);
582
        }
583 2829
        if (VSB_len(vsb)) {
584 699
                WS_Release(bo->ws, VSB_len(vsb) + 1);
585 699
                return (VSB_data(vsb) + 1);
586
        }
587 2130
        WS_Release(bo->ws, 0);
588 2130
        return ("");
589
}
590
591
static enum fetch_step
592 4464
vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
593
{
594
        const char *p;
595
596 4464
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
597 4464
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
598 4464
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
599
600 4464
        assert(wrk->handling == VCL_RET_DELIVER);
601
602
        /* No body -> done */
603 4464
        if (bo->htc->body_status == BS_NONE || bo->htc->content_length == 0) {
604 1701
                http_Unset(bo->beresp, H_Content_Encoding);
605 1701
                bo->do_gzip = bo->do_gunzip = 0;
606 1701
                bo->do_stream = 0;
607 1701
                bo->filter_list = "";
608 2763
        } else if (bo->filter_list == NULL) {
609 2757
                bo->filter_list = VBF_Get_Filter_List(bo);
610
        }
611
612 8922
        if (bo->filter_list == NULL ||
613 4458
            VCL_StackVFP(bo->vfc, bo->vcl, bo->filter_list)) {
614 9
                (bo)->htc->doclose = SC_OVERLOAD;
615 9
                VDI_Finish(bo);
616 9
                return (F_STP_ERROR);
617
        }
618
619 4455
        if (bo->fetch_objcore->flags & OC_F_PRIVATE)
620 1386
                AN(bo->uncacheable);
621
622 4455
        bo->fetch_objcore->boc->len_so_far = 0;
623
624 4455
        if (VFP_Open(bo->vfc)) {
625 3
                (void)VFP_Error(bo->vfc, "Fetch pipeline failed to open");
626 3
                bo->htc->doclose = SC_RX_BODY;
627 3
                VDI_Finish(bo);
628 3
                return (F_STP_ERROR);
629
        }
630
631 4452
        if (vbf_beresp2obj(bo)) {
632 6
                (void)VFP_Error(bo->vfc, "Could not get storage");
633 6
                bo->htc->doclose = SC_RX_BODY;
634 6
                VFP_Close(bo->vfc);
635 6
                VDI_Finish(bo);
636 6
                return (F_STP_ERROR);
637
        }
638
639
#define OBJ_FLAG(U, l, v)                                               \
640
        if (bo->vfc->obj_flags & OF_##U)                                \
641
                ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_##U, 1);
642
#include "tbl/obj_attr.h"
643
644 7335
        if (!(bo->fetch_objcore->flags & OC_F_PASS) &&
645 5730
            http_IsStatus(bo->beresp, 200) && (
646 5625
              http_GetHdr(bo->beresp, H_Last_Modified, &p) ||
647 2784
              http_GetHdr(bo->beresp, H_ETag, &p)))
648 120
                ObjSetFlag(bo->wrk, bo->fetch_objcore, OF_IMSCAND, 1);
649
650 4446
        assert(bo->fetch_objcore->boc->refcount >= 1);
651
652 4446
        assert(bo->fetch_objcore->boc->state == BOS_REQ_DONE);
653
654 4446
        if (bo->do_stream) {
655 2091
                ObjSetState(wrk, bo->fetch_objcore, BOS_PREP_STREAM);
656 2091
                HSH_Unbusy(wrk, bo->fetch_objcore);
657 2091
                ObjSetState(wrk, bo->fetch_objcore, BOS_STREAM);
658
        }
659
660 13338
        VSLb(bo->vsl, SLT_Fetch_Body, "%u %s %s",
661 8892
            bo->htc->body_status, body_status_2str(bo->htc->body_status),
662 4446
            bo->do_stream ? "stream" : "-");
663
664 4446
        if (bo->htc->body_status != BS_NONE) {
665 2751
                assert(bo->htc->body_status != BS_ERROR);
666 2751
                return (F_STP_FETCHBODY);
667
        }
668 1695
        AZ(bo->vfc->failed);
669 1695
        return (F_STP_FETCHEND);
670
}
671
672
static enum fetch_step
673 4401
vbf_stp_fetchend(struct worker *wrk, struct busyobj *bo)
674
{
675
676 4401
        AZ(bo->vfc->failed);
677 4401
        VFP_Close(bo->vfc);
678
679 4401
        AZ(ObjSetU64(wrk, bo->fetch_objcore, OA_LEN,
680
            bo->fetch_objcore->boc->len_so_far));
681
682 4401
        if (bo->do_stream)
683 2103
                assert(bo->fetch_objcore->boc->state == BOS_STREAM);
684
        else {
685 2298
                assert(bo->fetch_objcore->boc->state == BOS_REQ_DONE);
686 2298
                HSH_Unbusy(wrk, bo->fetch_objcore);
687
        }
688
689
        /* Recycle the backend connection before setting BOS_FINISHED to
690
           give predictable backend reuse behavior for varnishtest */
691 4401
        VDI_Finish(bo);
692
693 4401
        ObjSetState(wrk, bo->fetch_objcore, BOS_FINISHED);
694 4401
        VSLb_ts_busyobj(bo, "BerespBody", W_TIM_real(wrk));
695 4401
        if (bo->stale_oc != NULL)
696 81
                HSH_Kill(bo->stale_oc);
697 4401
        return (F_STP_DONE);
698
}
699
700
/*--------------------------------------------------------------------
701
 */
702
703
static int
704 54
vbf_objiterator(void *priv, int flush, const void *ptr, ssize_t len)
705
{
706
        struct busyobj *bo;
707
        ssize_t l;
708 54
        const uint8_t *ps = ptr;
709
        uint8_t *pd;
710
711
        (void)flush;
712 54
        CAST_OBJ_NOTNULL(bo, priv, BUSYOBJ_MAGIC);
713
714 162
        while (len > 0) {
715 54
                l = len;
716 54
                if (VFP_GetStorage(bo->vfc, &l, &pd) != VFP_OK)
717 0
                        return (1);
718 54
                if (len < l)
719 0
                        l = len;
720 54
                memcpy(pd, ps, l);
721 54
                VFP_Extend(bo->vfc, l);
722 54
                ps += l;
723 54
                len -= l;
724
        }
725 54
        return (0);
726
}
727
728
static enum fetch_step
729 48
vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo)
730
{
731
732 48
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
733 48
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
734
735 48
        AZ(vbf_beresp2obj(bo));
736
737 48
        if (ObjHasAttr(bo->wrk, bo->stale_oc, OA_ESIDATA))
738 3
                AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc,
739
                    OA_ESIDATA));
740
741 48
        AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_FLAGS));
742 48
        AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_GZIPBITS));
743
744 48
        if (bo->do_stream) {
745 45
                ObjSetState(wrk, bo->fetch_objcore, BOS_PREP_STREAM);
746 45
                HSH_Unbusy(wrk, bo->fetch_objcore);
747 45
                ObjSetState(wrk, bo->fetch_objcore, BOS_STREAM);
748
        }
749
750 48
        if (ObjIterate(wrk, bo->stale_oc, bo, vbf_objiterator, 0))
751 3
                (void)VFP_Error(bo->vfc, "Template object failed");
752
753 48
        if (bo->stale_oc->flags & OC_F_FAILED)
754 3
                (void)VFP_Error(bo->vfc, "Template object failed");
755 48
        if (bo->vfc->failed) {
756 3
                VDI_Finish(bo);
757 3
                wrk->stats->fetch_failed++;
758 3
                return (F_STP_FAIL);
759
        }
760 45
        return (F_STP_FETCHEND);
761
}
762
763
/*--------------------------------------------------------------------
764
 * Create synth object
765
 */
766
767
static enum fetch_step
768 456
vbf_stp_error(struct worker *wrk, struct busyobj *bo)
769
{
770
        ssize_t l, ll, o;
771
        double now;
772
        uint8_t *ptr;
773
        struct vsb *synth_body;
774
775 456
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
776 456
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
777 456
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
778 456
        AN(bo->fetch_objcore->flags & OC_F_BUSY);
779 456
        assert(bo->director_state == DIR_S_NULL);
780
781 456
        wrk->stats->fetch_failed++;
782
783 456
        now = W_TIM_real(wrk);
784 456
        VSLb_ts_busyobj(bo, "Error", now);
785
786 456
        if (bo->fetch_objcore->stobj->stevedore != NULL)
787 60
                ObjFreeObj(bo->wrk, bo->fetch_objcore);
788
789 456
        if (bo->storage == NULL)
790 66
                bo->storage = STV_next();
791
792
        // XXX: reset all beresp flags ?
793
794 456
        HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod);
795 456
        http_PutResponse(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed");
796 456
        http_TimeHeader(bo->beresp, "Date: ", now);
797 456
        http_SetHeader(bo->beresp, "Server: Varnish");
798
799 456
        bo->fetch_objcore->t_origin = now;
800 456
        if (!VTAILQ_EMPTY(&bo->fetch_objcore->objhead->waitinglist)) {
801
                /*
802
                 * If there is a waitinglist, it means that there is no
803
                 * grace-able object, so cache the error return for a
804
                 * short time, so the waiting list can drain, rather than
805
                 * each objcore on the waiting list sequentially attempt
806
                 * to fetch from the backend.
807
                 */
808 0
                bo->fetch_objcore->ttl = 1;
809 0
                bo->fetch_objcore->grace = 5;
810 0
                bo->fetch_objcore->keep = 5;
811
        } else {
812 456
                bo->fetch_objcore->ttl = 0;
813 456
                bo->fetch_objcore->grace = 0;
814 456
                bo->fetch_objcore->keep = 0;
815
        }
816
817 456
        synth_body = VSB_new_auto();
818 456
        AN(synth_body);
819
820 456
        VCL_backend_error_method(bo->vcl, wrk, NULL, bo, synth_body);
821
822 456
        AZ(VSB_finish(synth_body));
823
824 456
        if (wrk->handling == VCL_RET_ABANDON || wrk->handling == VCL_RET_FAIL) {
825 9
                VSB_destroy(&synth_body);
826 9
                return (F_STP_FAIL);
827
        }
828
829 447
        if (wrk->handling == VCL_RET_RETRY) {
830 33
                VSB_destroy(&synth_body);
831 33
                if (bo->retries++ < cache_param->max_retries)
832 27
                        return (F_STP_RETRY);
833 6
                VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, failing");
834 6
                return (F_STP_FAIL);
835
        }
836
837 414
        assert(wrk->handling == VCL_RET_DELIVER);
838
839 414
        assert(bo->vfc->wrk == bo->wrk);
840 414
        assert(bo->vfc->oc == bo->fetch_objcore);
841 414
        assert(bo->vfc->resp == bo->beresp);
842 414
        assert(bo->vfc->req == bo->bereq);
843
844 414
        if (vbf_beresp2obj(bo)) {
845 3
                (void)VFP_Error(bo->vfc, "Could not get storage");
846 3
                VSB_destroy(&synth_body);
847 3
                return (F_STP_FAIL);
848
        }
849
850 411
        ll = VSB_len(synth_body);
851 411
        o = 0;
852 1227
        while (ll > 0) {
853 405
                l = ll;
854 405
                if (VFP_GetStorage(bo->vfc, &l, &ptr) != VFP_OK)
855 0
                        break;
856 405
                if (l > ll)
857 3
                        l = ll;
858 405
                memcpy(ptr, VSB_data(synth_body) + o, l);
859 405
                VFP_Extend(bo->vfc, l);
860 405
                ll -= l;
861 405
                o += l;
862
        }
863 411
        AZ(ObjSetU64(wrk, bo->fetch_objcore, OA_LEN, o));
864 411
        VSB_destroy(&synth_body);
865 411
        HSH_Unbusy(wrk, bo->fetch_objcore);
866 411
        ObjSetState(wrk, bo->fetch_objcore, BOS_FINISHED);
867 411
        return (F_STP_DONE);
868
}
869
870
/*--------------------------------------------------------------------
871
 */
872
873
static enum fetch_step
874 87
vbf_stp_fail(struct worker *wrk, const struct busyobj *bo)
875
{
876 87
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
877 87
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
878 87
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
879
880 87
        assert(bo->fetch_objcore->boc->state < BOS_FINISHED);
881 87
        HSH_Fail(bo->fetch_objcore);
882 87
        if (!(bo->fetch_objcore->flags & OC_F_BUSY))
883 33
                HSH_Kill(bo->fetch_objcore);
884 87
        ObjSetState(wrk, bo->fetch_objcore, BOS_FAILED);
885 87
        return (F_STP_DONE);
886
}
887
888
/*--------------------------------------------------------------------
889
 */
890
891
static enum fetch_step
892 0
vbf_stp_done(void)
893
{
894 0
        WRONG("Just plain wrong");
895
        NEEDLESS(return(F_STP_DONE));
896
}
897
898
static void v_matchproto_(task_func_t)
899 4902
vbf_fetch_thread(struct worker *wrk, void *priv)
900
{
901
        struct busyobj *bo;
902
        enum fetch_step stp;
903
904 4902
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
905 4902
        CAST_OBJ_NOTNULL(bo, priv, BUSYOBJ_MAGIC);
906 4902
        CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC);
907 4902
        CHECK_OBJ_NOTNULL(bo->fetch_objcore, OBJCORE_MAGIC);
908
909 4902
        THR_SetBusyobj(bo);
910 4902
        stp = F_STP_MKBEREQ;
911 4902
        assert(isnan(bo->t_first));
912 4902
        assert(isnan(bo->t_prev));
913 4902
        VSLb_ts_busyobj(bo, "Start", W_TIM_real(wrk));
914
915 4902
        bo->wrk = wrk;
916 4902
        wrk->vsl = bo->vsl;
917
918
#if 0
919
        if (bo->stale_oc != NULL) {
920
                CHECK_OBJ_NOTNULL(bo->stale_oc, OBJCORE_MAGIC);
921
                /* We don't want the oc/stevedore ops in fetching thread */
922
                if (!ObjCheckFlag(wrk, bo->stale_oc, OF_IMSCAND))
923
                        (void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
924
        }
925
#endif
926
927 31979
        while (stp != F_STP_DONE) {
928 22178
                CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
929 22179
                assert(bo->fetch_objcore->boc->refcount >= 1);
930 22179
                if (bo->fetch_objcore->boc->state < BOS_REQ_DONE)
931 5066
                        AN(bo->req);
932
                else
933 17113
                        AZ(bo->req);
934 22179
                switch (stp) {
935
#define FETCH_STEP(l, U, arg)                                           \
936
                case F_STP_##U:                                         \
937
                        stp = vbf_stp_##l arg;                          \
938
                        break;
939
#include "tbl/steps.h"
940
                default:
941 0
                        WRONG("Illegal fetch_step");
942
                }
943
        }
944
945 4899
        assert(bo->director_state == DIR_S_NULL);
946
947 4899
        http_Teardown(bo->bereq);
948 4899
        http_Teardown(bo->beresp);
949
950 4899
        if (bo->fetch_objcore->boc->state == BOS_FINISHED) {
951 4812
                AZ(bo->fetch_objcore->flags & OC_F_FAILED);
952 4812
                VSLb(bo->vsl, SLT_Length, "%ju",
953 4812
                    (uintmax_t)ObjGetLen(bo->wrk, bo->fetch_objcore));
954
        }
955
        // AZ(bo->fetch_objcore->boc);  // XXX
956
957 4899
        if (bo->stale_oc != NULL)
958 102
                (void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
959
960 4899
        wrk->vsl = NULL;
961 4899
        HSH_DerefBoc(wrk, bo->fetch_objcore);
962 4899
        SES_Rel(bo->sp);
963 4899
        VBO_ReleaseBusyObj(wrk, &bo);
964 4899
        THR_SetBusyobj(NULL);
965 4899
}
966
967
/*--------------------------------------------------------------------
968
 */
969
970
void
971 4902
VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
972
    struct objcore *oldoc, enum vbf_fetch_mode_e mode)
973
{
974
        struct boc *boc;
975
        struct busyobj *bo;
976
        const char *how;
977
978 4902
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
979 4902
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
980 4902
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
981 4902
        AN(oc->flags & OC_F_BUSY);
982 4902
        CHECK_OBJ_ORNULL(oldoc, OBJCORE_MAGIC);
983
984 4902
        bo = VBO_GetBusyObj(wrk, req);
985 4902
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
986
987 4902
        boc = HSH_RefBoc(oc);
988 4902
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
989
990 4902
        switch (mode) {
991
        case VBF_PASS:
992 1605
                how = "pass";
993 1605
                bo->do_pass = 1;
994 1605
                break;
995
        case VBF_NORMAL:
996 3252
                how = "fetch";
997 3252
                break;
998
        case VBF_BACKGROUND:
999 45
                how = "bgfetch";
1000 45
                bo->is_bgfetch = 1;
1001 45
                break;
1002
        default:
1003 0
                WRONG("Wrong fetch mode");
1004
        }
1005
1006 4902
        VSLb(bo->vsl, SLT_Begin, "bereq %u %s", VXID(req->vsl->wid), how);
1007 4902
        VSLb(req->vsl, SLT_Link, "bereq %u %s", VXID(bo->vsl->wid), how);
1008
1009 4902
        THR_SetBusyobj(bo);
1010
1011 4902
        bo->sp = req->sp;
1012 4902
        SES_Ref(bo->sp);
1013
1014 4901
        AN(bo->vcl);
1015
1016 4901
        oc->boc->vary = req->vary_b;
1017 4901
        req->vary_b = NULL;
1018
1019 4901
        HSH_Ref(oc);
1020 4902
        AZ(bo->fetch_objcore);
1021 4902
        bo->fetch_objcore = oc;
1022
1023 4902
        AZ(bo->stale_oc);
1024 4902
        if (oldoc != NULL) {
1025 102
                assert(oldoc->refcnt > 0);
1026 102
                HSH_Ref(oldoc);
1027 102
                bo->stale_oc = oldoc;
1028
        }
1029
1030 4902
        AZ(bo->req);
1031 4902
        bo->req = req;
1032
1033 4902
        bo->fetch_task.priv = bo;
1034 4902
        bo->fetch_task.func = vbf_fetch_thread;
1035
1036 4902
        if (Pool_Task(wrk->pool, &bo->fetch_task, TASK_QUEUE_BO)) {
1037 0
                wrk->stats->fetch_no_thread++;
1038 0
                (void)vbf_stp_fail(req->wrk, bo);
1039 0
                if (bo->stale_oc != NULL)
1040 0
                        (void)HSH_DerefObjCore(wrk, &bo->stale_oc, 0);
1041 0
                HSH_DerefBoc(wrk, oc);
1042 0
                SES_Rel(bo->sp);
1043 0
                VBO_ReleaseBusyObj(wrk, &bo);
1044
        } else {
1045 4902
                bo = NULL; /* ref transferred to fetch thread */
1046 4902
                if (mode == VBF_BACKGROUND) {
1047 45
                        ObjWaitState(oc, BOS_REQ_DONE);
1048 45
                        (void)VRB_Ignore(req);
1049
                } else {
1050 4857
                        ObjWaitState(oc, BOS_STREAM);
1051 4854
                        if (oc->boc->state == BOS_FAILED) {
1052 51
                                AN((oc->flags & OC_F_FAILED));
1053
                        } else {
1054 4803
                                AZ(oc->flags & OC_F_BUSY);
1055
                        }
1056
                }
1057
        }
1058 4899
        AZ(bo);
1059 4899
        VSLb_ts_req(req, "Fetch", W_TIM_real(wrk));
1060 4899
        assert(oc->boc == boc);
1061 4899
        HSH_DerefBoc(wrk, oc);
1062 4899
        if (mode == VBF_BACKGROUND)
1063 45
                (void)HSH_DerefObjCore(wrk, &oc, HSH_RUSH_POLICY);
1064 4899
        THR_SetBusyobj(NULL);
1065 4899
}