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