varnish-cache/bin/varnishd/cache/cache_req_fsm.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2017 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
 * This file contains the request-handling state engine, which is intended to
30
 * (over time) be(ome) protocol agnostic.
31
 * We already use this now with ESI:includes, which are for all relevant
32
 * purposes a different "protocol"
33
 *
34
 * A special complication is the fact that we can suspend processing of
35
 * a request when hash-lookup finds a busy objhdr.
36
 *
37
 */
38
39
#include "config.h"
40
41
#include "cache_varnishd.h"
42
#include "cache_filter.h"
43
#include "cache_objhead.h"
44
#include "cache_transport.h"
45
46
#include "hash/hash_slinger.h"
47
#include "storage/storage.h"
48
#include "common/heritage.h"
49
#include "vcl.h"
50
#include "vsha256.h"
51
#include "vtim.h"
52
53
/*--------------------------------------------------------------------
54
 * Handle "Expect:" and "Connection:" on incoming request
55
 */
56
57
static enum req_fsm_nxt
58 8780
cnt_transport(struct worker *wrk, struct req *req)
59
{
60
        const char *p;
61
62 8780
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
63 8780
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
64 8780
        CHECK_OBJ_NOTNULL(req->http, HTTP_MAGIC);
65 8780
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
66 8780
        assert(req->req_body_status != REQ_BODY_INIT);
67 8780
        AN(req->transport->minimal_response);
68
69 8780
        if (http_GetHdr(req->http, H_Expect, &p)) {
70 48
                if (strcasecmp(p, "100-continue")) {
71 8
                        req->doclose = SC_RX_JUNK;
72 8
                        (void)req->transport->minimal_response(req, 417);
73 8
                        wrk->stats->client_req_417++;
74 8
                        return (REQ_FSM_DONE);
75
                }
76 80
                if (req->http->protover >= 11 &&
77 40
                    req->htc->pipeline_b == NULL)       // XXX: HTTP1 vs 2 ?
78 36
                        req->want100cont = 1;
79 40
                http_Unset(req->http, H_Expect);
80
        }
81
82 8772
        wrk->stats->client_req++;
83
84 8772
        AZ(req->err_code);
85
86 8772
        req->doclose = http_DoConnection(req->http);
87 8772
        if (req->doclose == SC_RX_BAD) {
88 4
                (void)req->transport->minimal_response(req, 400);
89 4
                return (REQ_FSM_DONE);
90
        }
91
92 8768
        if (req->req_body_status < REQ_BODY_TAKEN) {
93 232
                AN(req->transport->req_body != NULL);
94 232
                VFP_Setup(req->vfc, wrk);
95 232
                req->vfc->resp = req->http;             // XXX
96 232
                req->transport->req_body(req);
97
        }
98
99 8768
        req->ws_req = WS_Snapshot(req->ws);
100 8768
        HTTP_Copy(req->http0, req->http);       // For ESI & restart
101 8768
        req->req_step = R_STP_RECV;
102 8768
        return (REQ_FSM_MORE);
103
}
104
105
/*--------------------------------------------------------------------
106
 * Deliver an object to client
107
 */
108
109
static enum req_fsm_nxt
110 8956
cnt_deliver(struct worker *wrk, struct req *req)
111
{
112
113 8956
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
114 8956
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
115 8956
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
116 8956
        CHECK_OBJ_NOTNULL(req->objcore->objhead, OBJHEAD_MAGIC);
117 8956
        AZ(req->stale_oc);
118 8956
        AN(req->vcl);
119
120 8956
        assert(req->objcore->refcnt > 0);
121
122 8956
        ObjTouch(req->wrk, req->objcore, req->t_prev);
123
124 8956
        HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod);
125 8955
        if (HTTP_Decode(req->resp,
126 8955
            ObjGetAttr(req->wrk, req->objcore, OA_HEADERS, NULL))) {
127 4
                (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
128 4
                req->err_code = 500;
129 4
                req->req_step = R_STP_SYNTH;
130 4
                return (REQ_FSM_MORE);
131
        }
132 8952
        http_ForceField(req->resp, HTTP_HDR_PROTO, "HTTP/1.1");
133
134 8952
        if (req->is_hit)
135 5055
                http_PrintfHeader(req->resp,
136 2527
                    "X-Varnish: %u %u", VXID(req->vsl->wid),
137
                    ObjGetXID(wrk, req->objcore));
138
        else
139 6424
                http_PrintfHeader(req->resp,
140 6424
                    "X-Varnish: %u", VXID(req->vsl->wid));
141
142
        /*
143
         * We base Age calculation upon the last timestamp taken during
144
         * client request processing. This gives some inaccuracy, but
145
         * since Age is only full second resolution that shouldn't
146
         * matter. (Last request timestamp could be a Start timestamp
147
         * taken before the object entered into cache leading to negative
148
         * age. Truncate to zero in that case).
149
         */
150 8952
        http_PrintfHeader(req->resp, "Age: %.0f",
151 8952
            floor(fmax(0., req->t_prev - req->objcore->t_origin)));
152
153 8952
        http_SetHeader(req->resp, "Via: 1.1 varnish (Varnish/6.1)");
154
155 17882
        if (cache_param->http_gzip_support &&
156 9363
            ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED) &&
157 432
            !RFC2616_Req_Gzip(req->http))
158 136
                RFC2616_Weaken_Etag(req->resp);
159
160 8951
        VCL_deliver_method(req->vcl, wrk, req, NULL, NULL);
161 8948
        VSLb_ts_req(req, "Process", W_TIM_real(wrk));
162
163 8948
        assert(req->restarts <= cache_param->max_restarts);
164
165 8948
        if (wrk->handling != VCL_RET_DELIVER) {
166 320
                (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
167 320
                http_Teardown(req->resp);
168
169 320
                switch (wrk->handling) {
170
                case VCL_RET_RESTART:
171 56
                        req->req_step = R_STP_RESTART;
172 56
                        break;
173
                case VCL_RET_FAIL:
174 244
                        req->req_step = R_STP_VCLFAIL;
175 244
                        break;
176
                case VCL_RET_SYNTH:
177 20
                        req->req_step = R_STP_SYNTH;
178 20
                        break;
179
                default:
180 0
                        WRONG("Illegal return from vcl_deliver{}");
181
                }
182
183 320
                return (REQ_FSM_MORE);
184
        }
185
186 8628
        assert(wrk->handling == VCL_RET_DELIVER);
187
188 16284
        if (req->esi_level == 0 &&
189 14604
            http_IsStatus(req->resp, 200) &&
190 7344
            req->http->conds && RFC2616_Do_Cond(req))
191 120
                http_PutResponse(req->resp, "HTTP/1.1", 304, NULL);
192
193 8628
        req->req_step = R_STP_TRANSMIT;
194 8628
        return (REQ_FSM_MORE);
195
}
196
197
/*--------------------------------------------------------------------
198
 * VCL failed, die horribly
199
 */
200
201
static enum req_fsm_nxt
202 392
cnt_vclfail(const struct worker *wrk, struct req *req)
203
{
204
205 392
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
206 392
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
207
208 392
        AZ(req->objcore);
209 392
        AZ(req->stale_oc);
210
211 392
        Req_Rollback(req);
212
213 392
        req->err_code = 503;
214 392
        req->err_reason = "VCL failed";
215 392
        req->req_step = R_STP_SYNTH;
216 392
        req->doclose = SC_VCL_FAILURE;
217 392
        return (REQ_FSM_MORE);
218
}
219
220
/*--------------------------------------------------------------------
221
 * Emit a synthetic response
222
 */
223
224
static enum req_fsm_nxt
225 1068
cnt_synth(struct worker *wrk, struct req *req)
226
{
227
        struct http *h;
228
        double now;
229
        struct vsb *synth_body;
230
        ssize_t sz, szl;
231
        uint8_t *ptr;
232
233 1068
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
234 1068
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
235
236 1068
        AZ(req->objcore);
237 1068
        AZ(req->stale_oc);
238
239 1068
        wrk->stats->s_synth++;
240
241 1068
        now = W_TIM_real(wrk);
242 1068
        VSLb_ts_req(req, "Process", now);
243
244 1068
        if (req->err_code < 100)
245 0
                req->err_code = 501;
246
247 1068
        HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod);
248 1068
        h = req->resp;
249 1068
        http_TimeHeader(h, "Date: ", now);
250 1068
        http_SetHeader(h, "Server: Varnish");
251 1068
        http_PrintfHeader(req->resp, "X-Varnish: %u", VXID(req->vsl->wid));
252 1068
        http_PutResponse(h, "HTTP/1.1", req->err_code, req->err_reason);
253
254
        /*
255
         * For late 100-continue, we suggest to VCL to close the connection to
256
         * neither send a 100-continue nor drain-read the request. But VCL has
257
         * the option to veto by removing Connection: close
258
         */
259 1068
        if (req->want100cont) {
260 12
                http_SetHeader(h, "Connection: close");
261
        }
262
263 1068
        synth_body = VSB_new_auto();
264 1068
        AN(synth_body);
265
266 1068
        VCL_synth_method(req->vcl, wrk, req, NULL, synth_body);
267
268 1068
        AZ(VSB_finish(synth_body));
269
270 1068
        if (wrk->handling == VCL_RET_FAIL) {
271 12
                VSB_destroy(&synth_body);
272 12
                req->doclose = SC_VCL_FAILURE;
273 12
                VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
274 12
                http_Teardown(req->resp);
275 12
                return (REQ_FSM_DONE);
276
        }
277
278 1056
        if (wrk->handling == VCL_RET_RESTART) {
279
                /*
280
                 * XXX: Should we reset req->doclose = SC_VCL_FAILURE
281
                 * XXX: If so, to what ?
282
                 */
283 24
                HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
284 24
                VSB_destroy(&synth_body);
285 24
                req->req_step = R_STP_RESTART;
286 24
                return (REQ_FSM_MORE);
287
        }
288 1032
        assert(wrk->handling == VCL_RET_DELIVER);
289
290 1032
        http_Unset(h, H_Content_Length);
291 1032
        http_PrintfHeader(req->resp, "Content-Length: %zd",
292
            VSB_len(synth_body));
293
294 1032
        if (!req->doclose && http_HdrIs(req->resp, H_Connection, "close"))
295 12
                req->doclose = SC_RESP_CLOSE;
296
297
        /* Discard any lingering request body before delivery */
298 1032
        (void)VRB_Ignore(req);
299
300 1032
        req->objcore = HSH_Private(wrk);
301 1032
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
302 1032
        szl = -1;
303 1032
        if (STV_NewObject(wrk, req->objcore, stv_transient, 1024)) {
304 1028
                szl = VSB_len(synth_body);
305 1028
                assert(szl >= 0);
306 1028
                sz = szl;
307 2008
                if (sz > 0 &&
308 1960
                    ObjGetSpace(wrk, req->objcore, &sz, &ptr) && sz >= szl) {
309 980
                        memcpy(ptr, VSB_data(synth_body), szl);
310 980
                        ObjExtend(wrk, req->objcore, szl);
311 48
                } else if (sz > 0) {
312 0
                        szl = -1;
313
                }
314
        }
315
316 1032
        if (szl >= 0)
317 1028
                AZ(ObjSetU64(wrk, req->objcore, OA_LEN, szl));
318 1032
        HSH_DerefBoc(wrk, req->objcore);
319 1032
        VSB_destroy(&synth_body);
320
321 1032
        if (szl < 0) {
322 4
                VSLb(req->vsl, SLT_Error, "Could not get storage");
323 4
                req->doclose = SC_OVERLOAD;
324 4
                VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
325 4
                (void)HSH_DerefObjCore(wrk, &req->objcore, 1);
326 4
                http_Teardown(req->resp);
327 4
                return (REQ_FSM_DONE);
328
        }
329
330 1028
        req->req_step = R_STP_TRANSMIT;
331 1028
        return (REQ_FSM_MORE);
332
}
333
334
/*--------------------------------------------------------------------
335
 * The mechanics of sending a response (from deliver or synth)
336
 */
337
338
static enum req_fsm_nxt
339 9656
cnt_transmit(struct worker *wrk, struct req *req)
340
{
341
        struct boc *boc;
342
        const char *r;
343
        uint16_t status;
344
        int err, sendbody, head;
345
        intmax_t clval;
346
347 9656
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
348 9656
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
349 9656
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
350 9656
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
351 9656
        AZ(req->stale_oc);
352
353
        /* Grab a ref to the bo if there is one */
354 9656
        boc = HSH_RefBoc(req->objcore);
355
356 9656
        clval = http_GetContentLength(req->resp);
357 9656
        if (boc != NULL)
358 2842
                req->resp_len = clval;
359
        else
360 6814
                req->resp_len = ObjGetLen(req->wrk, req->objcore);
361
362 9656
        req->res_mode = 0;
363
364
        /* RFC 7230, 3.3.3 */
365 9656
        status = http_GetStatus(req->resp);
366 9656
        head = !strcmp(req->http0->hd[HTTP_HDR_METHOD].b, "HEAD");
367 9656
        if (head) {
368 32
                if (req->objcore->flags & OC_F_PASS)
369 8
                        sendbody = -1;
370
                else
371 24
                        sendbody = 0;
372 9624
        } else if (status < 200 || status == 204 || status == 304) {
373 172
                req->resp_len = -1;
374 172
                sendbody = 0;
375
        } else {
376 9452
                sendbody = 1;
377
        }
378
379 9656
        err = 0;
380 9656
        if (sendbody >= 0) {
381 16548
                if (!req->disable_esi && req->resp_len != 0 &&
382 7312
                    ObjHasAttr(wrk, req->objcore, OA_ESIDATA) &&
383 412
                    VDP_Push(req, &VDP_esi, NULL) < 0)
384 0
                        err++;
385
386 19276
                if (cache_param->http_gzip_support &&
387 10056
                    ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED) &&
388 560
                    !RFC2616_Req_Gzip(req->http) &&
389 132
                    VDP_Push(req, &VDP_gunzip, NULL) < 0)
390 0
                        err++;
391
392 19292
                if (cache_param->http_range_support &&
393 9644
                    http_IsStatus(req->resp, 200)) {
394 8144
                        http_ForceHeader(req->resp, H_Accept_Ranges, "bytes");
395 8144
                        if (sendbody && http_GetHdr(req->http, H_Range, &r))
396 136
                                VRG_dorange(req, r);
397
                }
398
        }
399
400 9656
        if (sendbody < 0 || head) {
401
                /* Don't touch HEAD C-L */
402 32
                sendbody = 0;
403 9624
        } else if (clval >= 0 && clval == req->resp_len) {
404
                /* Reuse C-L header */
405
        } else {
406 1908
                http_Unset(req->resp, H_Content_Length);
407 1908
                if (req->resp_len >= 0 && sendbody)
408 896
                        http_PrintfHeader(req->resp,
409
                            "Content-Length: %jd", req->resp_len);
410
        }
411
412 9656
        if (err == 0) {
413 9656
                if (req->resp_len == 0)
414 2772
                        sendbody = 0;
415 9656
                req->transport->deliver(req, boc, sendbody);
416
        } else {
417 0
                VSLb(req->vsl, SLT_Error, "Failure to push processors");
418 0
                req->doclose = SC_OVERLOAD;
419
        }
420
421 9656
        VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
422
423 9656
        if (req->objcore->flags & (OC_F_PRIVATE | OC_F_PASS | OC_F_HFP)) {
424 3384
                if (req->objcore->flags & OC_F_HFP)
425 44
                        AN(req->objcore->flags & OC_F_PASS);
426 3384
                if (boc != NULL) {
427 1301
                        HSH_Abandon(req->objcore);
428 1301
                        ObjWaitState(req->objcore, BOS_FINISHED);
429
                }
430 3384
                ObjSlim(wrk, req->objcore);
431
        }
432
433 9656
        if (boc != NULL)
434 2842
                HSH_DerefBoc(wrk, req->objcore);
435
436 9656
        (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
437 9656
        http_Teardown(req->resp);
438
439 9656
        return (REQ_FSM_DONE);
440
}
441
442
/*--------------------------------------------------------------------
443
 * Initiated a fetch (pass/miss) which we intend to deliver
444
 */
445
446
static enum req_fsm_nxt
447 6500
cnt_fetch(struct worker *wrk, struct req *req)
448
{
449
450 6500
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
451 6500
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
452 6500
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
453 6500
        AZ(req->stale_oc);
454
455 6500
        wrk->stats->s_fetch++;
456 6500
        (void)VRB_Ignore(req);
457
458 6499
        if (req->objcore->flags & OC_F_FAILED) {
459 68
                req->err_code = 503;
460 68
                req->req_step = R_STP_SYNTH;
461 68
                (void)HSH_DerefObjCore(wrk, &req->objcore, 1);
462 68
                AZ(req->objcore);
463 68
                return (REQ_FSM_MORE);
464
        }
465
466 6431
        req->req_step = R_STP_DELIVER;
467 6431
        return (REQ_FSM_MORE);
468
}
469
470
/*--------------------------------------------------------------------
471
 * Attempt to lookup objhdr from hash.  We disembark and reenter
472
 * this state if we get suspended on a busy objhdr.
473
 */
474
475
static enum req_fsm_nxt
476 7163
cnt_lookup(struct worker *wrk, struct req *req)
477
{
478
        struct objcore *oc, *busy;
479
        enum lookup_e lr;
480 7163
        int had_objhead = 0;
481
482 7163
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
483 7163
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
484 7163
        AZ(req->objcore);
485 7163
        AZ(req->stale_oc);
486
487 7163
        AN(req->vcl);
488
489 7163
        VRY_Prep(req);
490
491 7163
        AZ(req->objcore);
492 7163
        if (req->hash_objhead)
493 111
                had_objhead = 1;
494 7163
        lr = HSH_Lookup(req, &oc, &busy, req->hash_always_miss ? 1 : 0);
495 7163
        if (lr == HSH_BUSY) {
496
                /*
497
                 * We lost the session to a busy object, disembark the
498
                 * worker thread.   We return to STP_LOOKUP when the busy
499
                 * object has been unbusied, and still have the objhead
500
                 * around to restart the lookup with.
501
                 */
502 111
                return (REQ_FSM_DISEMBARK);
503
        }
504 7052
        if (had_objhead)
505 64
                VSLb_ts_req(req, "Waitinglist", W_TIM_real(wrk));
506
507 7052
        if (busy == NULL) {
508 2552
                VRY_Finish(req, DISCARD);
509
        } else {
510 4500
                AN(busy->flags & OC_F_BUSY);
511 4500
                VRY_Finish(req, KEEP);
512
        }
513
514 7052
        AZ(req->objcore);
515 7052
        if (lr == HSH_MISS) {
516 4456
                if (busy != NULL) {
517
                        /* hitmiss, out-of-grace or ordinary miss */
518 4440
                        AN(busy->flags & OC_F_BUSY);
519 4440
                        req->objcore = busy;
520 4440
                        req->stale_oc = oc;
521 4440
                        req->req_step = R_STP_MISS;
522
                } else {
523
                        /* hitpass */
524 16
                        AZ(oc);
525 16
                        req->req_step = R_STP_PASS;
526
                }
527 4456
                return (REQ_FSM_MORE);
528
        }
529
530 2596
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
531 2596
        AZ(oc->flags & OC_F_BUSY);
532 2596
        req->objcore = oc;
533 2596
        AZ(oc->flags & OC_F_PASS);
534
535 7788
        VSLb(req->vsl, SLT_Hit, "%u %.6f %.6f %.6f",
536
            ObjGetXID(wrk, req->objcore),
537 2596
            EXP_Dttl(req, req->objcore),
538 2596
            req->objcore->grace,
539 2596
            req->objcore->keep);
540
541 2596
        VCL_hit_method(req->vcl, wrk, req, NULL, NULL);
542
543 2596
        switch (wrk->handling) {
544
        case VCL_RET_DELIVER:
545 2524
                if (busy != NULL) {
546 60
                        AZ(oc->flags & OC_F_PASS);
547 60
                        CHECK_OBJ_NOTNULL(busy->boc, BOC_MAGIC);
548
                        // XXX: shouldn't we go to miss?
549 60
                        VBF_Fetch(wrk, req, busy, oc, VBF_BACKGROUND);
550
                } else {
551 2464
                        (void)VRB_Ignore(req);// XXX: handle err
552
                }
553 2523
                wrk->stats->cache_hit++;
554 2523
                req->is_hit = 1;
555 2523
                if (lr == HSH_EXP || lr == HSH_EXPBUSY)
556 71
                        wrk->stats->cache_hit_grace++;
557 2523
                req->req_step = R_STP_DELIVER;
558 2523
                return (REQ_FSM_MORE);
559
        case VCL_RET_MISS:
560 4
                if (busy != NULL) {
561 0
                        req->objcore = busy;
562 0
                        req->stale_oc = oc;
563 0
                        req->req_step = R_STP_MISS;
564
                } else {
565 4
                        (void)HSH_DerefObjCore(wrk, &req->objcore,
566
                            HSH_RUSH_POLICY);
567
                        /*
568
                         * We don't have a busy object, so treat this
569
                         * like a pass
570
                         */
571 4
                        VSLb(req->vsl, SLT_VCL_Error,
572
                            "vcl_hit{} returns miss without busy object."
573
                            "  Doing pass.");
574 4
                        req->req_step = R_STP_PASS;
575
                }
576 4
                return (REQ_FSM_MORE);
577
        case VCL_RET_RESTART:
578 52
                req->req_step = R_STP_RESTART;
579 52
                break;
580
        case VCL_RET_FAIL:
581 4
                req->req_step = R_STP_VCLFAIL;
582 4
                break;
583
        case VCL_RET_SYNTH:
584 4
                req->req_step = R_STP_SYNTH;
585 4
                break;
586
        case VCL_RET_PASS:
587 8
                wrk->stats->cache_hit++;
588 8
                req->is_hit = 1;
589 8
                req->req_step = R_STP_PASS;
590 8
                break;
591
        default:
592 0
                WRONG("Illegal return from vcl_hit{}");
593
        }
594
595
        /* Drop our object, we won't need it */
596 68
        (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
597
598 68
        if (busy != NULL) {
599 0
                (void)HSH_DerefObjCore(wrk, &busy, 0);
600 0
                VRY_Clear(req);
601
        }
602
603 68
        return (REQ_FSM_MORE);
604
}
605
606
/*--------------------------------------------------------------------
607
 * Cache miss.
608
 */
609
610
static enum req_fsm_nxt
611 4440
cnt_miss(struct worker *wrk, struct req *req)
612
{
613
614 4440
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
615 4440
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
616 4440
        AN(req->vcl);
617 4440
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
618 4440
        CHECK_OBJ_ORNULL(req->stale_oc, OBJCORE_MAGIC);
619
620 4440
        VCL_miss_method(req->vcl, wrk, req, NULL, NULL);
621 4440
        switch (wrk->handling) {
622
        case VCL_RET_FETCH:
623 4356
                wrk->stats->cache_miss++;
624 4356
                VBF_Fetch(wrk, req, req->objcore, req->stale_oc, VBF_NORMAL);
625 4352
                if (req->stale_oc != NULL)
626 156
                        (void)HSH_DerefObjCore(wrk, &req->stale_oc, 0);
627 4352
                req->req_step = R_STP_FETCH;
628 4352
                return (REQ_FSM_MORE);
629
        case VCL_RET_FAIL:
630 28
                req->req_step = R_STP_VCLFAIL;
631 28
                break;
632
        case VCL_RET_SYNTH:
633 32
                req->req_step = R_STP_SYNTH;
634 32
                break;
635
        case VCL_RET_RESTART:
636 16
                req->req_step = R_STP_RESTART;
637 16
                break;
638
        case VCL_RET_PASS:
639 8
                req->req_step = R_STP_PASS;
640 8
                break;
641
        default:
642 0
                WRONG("Illegal return from vcl_miss{}");
643
        }
644 84
        VRY_Clear(req);
645 84
        if (req->stale_oc != NULL)
646 0
                (void)HSH_DerefObjCore(wrk, &req->stale_oc, 0);
647 84
        AZ(HSH_DerefObjCore(wrk, &req->objcore, 1));
648 84
        return (REQ_FSM_MORE);
649
}
650
651
/*--------------------------------------------------------------------
652
 * Pass processing
653
 */
654
655
static enum req_fsm_nxt
656 2160
cnt_pass(struct worker *wrk, struct req *req)
657
{
658
659 2160
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
660 2160
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
661 2160
        AN(req->vcl);
662 2160
        AZ(req->objcore);
663 2160
        AZ(req->stale_oc);
664
665 2160
        VCL_pass_method(req->vcl, wrk, req, NULL, NULL);
666 2159
        switch (wrk->handling) {
667
        case VCL_RET_FAIL:
668 8
                req->req_step = R_STP_VCLFAIL;
669 8
                break;
670
        case VCL_RET_SYNTH:
671 4
                req->req_step = R_STP_SYNTH;
672 4
                break;
673
        case VCL_RET_RESTART:
674 0
                req->req_step = R_STP_RESTART;
675 0
                break;
676
        case VCL_RET_FETCH:
677 2147
                wrk->stats->s_pass++;
678 2147
                req->objcore = HSH_Private(wrk);
679 2148
                CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
680 2148
                VBF_Fetch(wrk, req, req->objcore, NULL, VBF_PASS);
681 2148
                req->req_step = R_STP_FETCH;
682 2148
                break;
683
        default:
684 0
                WRONG("Illegal return from cnt_pass{}");
685
        }
686 2160
        return (REQ_FSM_MORE);
687
}
688
689
/*--------------------------------------------------------------------
690
 * Pipe mode
691
 */
692
693
static enum req_fsm_nxt
694 56
cnt_pipe(struct worker *wrk, struct req *req)
695
{
696
        struct busyobj *bo;
697
        enum req_fsm_nxt nxt;
698
699 56
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
700 56
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
701 56
        AZ(req->objcore);
702 56
        AZ(req->stale_oc);
703 56
        AN(req->vcl);
704
705 56
        wrk->stats->s_pipe++;
706 56
        bo = VBO_GetBusyObj(wrk, req);
707 56
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
708 56
        VSLb(bo->vsl, SLT_Begin, "bereq %u pipe", VXID(req->vsl->wid));
709 56
        VSLb(req->vsl, SLT_Link, "bereq %u pipe", VXID(bo->vsl->wid));
710 56
        THR_SetBusyobj(bo);
711 56
        bo->sp = req->sp;
712 56
        SES_Ref(bo->sp);
713
714 56
        HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod);
715 56
        http_FilterReq(bo->bereq, req->http, 0);        // XXX: 0 ?
716 56
        http_PrintfHeader(bo->bereq, "X-Varnish: %u", VXID(req->vsl->wid));
717 56
        http_ForceHeader(bo->bereq, H_Connection, "close");
718
719 56
        if (req->want100cont) {
720 0
                http_SetHeader(bo->bereq, "Expect: 100-continue");
721 0
                req->want100cont = 0;
722
        }
723
724 56
        VCL_pipe_method(req->vcl, wrk, req, bo, NULL);
725
726 56
        switch (wrk->handling) {
727
        case VCL_RET_FAIL:
728 4
                req->req_step = R_STP_VCLFAIL;
729 4
                nxt = REQ_FSM_MORE;
730 4
                break;
731
        case VCL_RET_SYNTH:
732 4
                req->req_step = R_STP_SYNTH;
733 4
                nxt = REQ_FSM_MORE;
734 4
                break;
735
        case VCL_RET_PIPE:
736 48
                AZ(bo->req);
737 48
                bo->req = req;
738 48
                bo->wrk = wrk;
739 48
                SES_Close(req->sp, VDI_Http1Pipe(req, bo));
740 48
                nxt = REQ_FSM_DONE;
741 48
                break;
742
        default:
743 0
                WRONG("Illegal return from vcl_pipe{}");
744
        }
745 56
        http_Teardown(bo->bereq);
746 56
        SES_Rel(bo->sp);
747 56
        VBO_ReleaseBusyObj(wrk, &bo);
748 56
        THR_SetBusyobj(NULL);
749 56
        return (nxt);
750
}
751
752
/*--------------------------------------------------------------------
753
 * Handle restart events
754
 */
755
756
static enum req_fsm_nxt
757 196
cnt_restart(struct worker *wrk, struct req *req)
758
{
759
760 196
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
761 196
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
762 196
        AZ(req->objcore);
763 196
        AZ(req->stale_oc);
764
765 196
        if (++req->restarts > cache_param->max_restarts) {
766 32
                VSLb(req->vsl, SLT_VCL_Error, "Too many restarts");
767 32
                req->err_code = 503;
768 32
                req->req_step = R_STP_SYNTH;
769
        } else {
770
                // XXX: ReqEnd + ReqAcct ?
771 164
                VSLb_ts_req(req, "Restart", W_TIM_real(wrk));
772 164
                VSL_ChgId(req->vsl, "req", "restart",
773
                    VXID_Get(wrk, VSL_CLIENTMARKER));
774 164
                VSLb_ts_req(req, "Start", req->t_prev);
775 164
                req->err_code = 0;
776 164
                req->req_step = R_STP_RECV;
777
        }
778 196
        return (REQ_FSM_MORE);
779
}
780
781
/*
782
 * prepare the request for vcl_recv, either initially or after a reset
783
 * e.g. due to vcl switching
784
 *
785
 * TODO
786
 * - make restarts == 0 bit re-usable for rollback
787
 * - remove duplicatation with Req_Cleanup()
788
 */
789
790
static void
791 9944
cnt_recv_prep(struct req *req, const char *ci)
792
{
793
        const char *xff;
794
795 9944
        if (req->restarts == 0) {
796
                /*
797
                 * This really should be done earlier, but we want to capture
798
                 * it in the VSL log.
799
                 */
800 9780
                http_CollectHdr(req->http, H_X_Forwarded_For);
801 9779
                if (http_GetHdr(req->http, H_X_Forwarded_For, &xff)) {
802 36
                        http_Unset(req->http, H_X_Forwarded_For);
803 36
                        http_PrintfHeader(req->http, "X-Forwarded-For: %s, %s",
804
                            xff, ci);
805
                } else {
806 9743
                        http_PrintfHeader(req->http, "X-Forwarded-For: %s", ci);
807
                }
808 9780
                http_CollectHdr(req->http, H_Cache_Control);
809
810
                /* By default we use the first backend */
811 9780
                req->director_hint = VCL_DefaultDirector(req->vcl);
812 9780
                AN(req->director_hint);
813
814 9780
                req->d_ttl = -1;
815 9780
                req->d_grace = -1;
816 9780
                req->disable_esi = 0;
817 9780
                req->hash_always_miss = 0;
818 9780
                req->hash_ignore_busy = 0;
819 9780
                req->client_identity = NULL;
820 9780
                req->storage = NULL;
821
        }
822
823 9944
        req->vdc->retval = 0;
824 9944
        req->is_hit = 0;
825 9944
}
826
/*--------------------------------------------------------------------
827
 * We have a complete request, set everything up and start it.
828
 * We can come here both with a request from the client and with
829
 * a interior request during ESI delivery.
830
 */
831
832
static enum req_fsm_nxt
833 9916
cnt_recv(struct worker *wrk, struct req *req)
834
{
835
        unsigned recv_handling;
836
        struct VSHA256Context sha256ctx;
837
        const char *ci, *cp, *endpname;
838
839 9916
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
840 9916
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
841 9916
        AN(req->vcl);
842 9916
        AZ(req->objcore);
843 9916
        AZ(req->stale_oc);
844 9916
        AZ(req->err_code);
845
846 9916
        AZ(isnan(req->t_first));
847 9914
        AZ(isnan(req->t_prev));
848 9914
        AZ(isnan(req->t_req));
849
850 9914
        ci = SES_Get_String_Attr(req->sp, SA_CLIENT_IP);
851 9915
        cp = SES_Get_String_Attr(req->sp, SA_CLIENT_PORT);
852 9915
        CHECK_OBJ_NOTNULL(req->sp->listen_sock, LISTEN_SOCK_MAGIC);
853 9915
        endpname = req->sp->listen_sock->name;
854 9915
        AN(endpname);
855 9915
        VSLb(req->vsl, SLT_ReqStart, "%s %s %s", ci, cp, endpname);
856
857 9916
        http_VSL_log(req->http);
858
859 9915
        cnt_recv_prep(req, ci);
860
861 9916
        if (req->req_body_status == REQ_BODY_FAIL) {
862 0
                req->doclose = SC_OVERLOAD;
863 0
                return (REQ_FSM_DONE);
864
        }
865
866 9916
        VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
867 9904
        if (wrk->handling == VCL_RET_VCL && req->restarts == 0) {
868 28
                Req_Rollback(req);
869 28
                cnt_recv_prep(req, ci);
870 28
                VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
871
        }
872
873 9904
        if (req->want100cont && !req->late100cont) {
874 16
                req->want100cont = 0;
875 16
                if (req->transport->minimal_response(req, 100)) {
876 0
                        req->doclose = SC_REM_CLOSE;
877 0
                        return (REQ_FSM_DONE);
878
                }
879
        }
880
881
        /* Attempts to cache req.body may fail */
882 9904
        if (req->req_body_status == REQ_BODY_FAIL) {
883 12
                req->doclose = SC_RX_BODY;
884 12
                return (REQ_FSM_DONE);
885
        }
886
887 9892
        recv_handling = wrk->handling;
888
889
        /* We wash the A-E header here for the sake of VRY */
890 9892
        if (cache_param->http_gzip_support &&
891 9808
             (recv_handling != VCL_RET_PIPE) &&
892
             (recv_handling != VCL_RET_PASS)) {
893 7692
                if (RFC2616_Req_Gzip(req->http)) {
894 440
                        http_ForceHeader(req->http, H_Accept_Encoding, "gzip");
895
                } else {
896 7252
                        http_Unset(req->http, H_Accept_Encoding);
897
                }
898
        }
899
900 9892
        VSHA256_Init(&sha256ctx);
901 9892
        VCL_hash_method(req->vcl, wrk, req, NULL, &sha256ctx);
902 9892
        if (wrk->handling == VCL_RET_FAIL)
903 8
                recv_handling = wrk->handling;
904
        else
905 9884
                assert(wrk->handling == VCL_RET_LOOKUP);
906 9892
        VSHA256_Final(req->digest, &sha256ctx);
907
908 9892
        switch (recv_handling) {
909
        case VCL_RET_VCL:
910 12
                VSLb(req->vsl, SLT_VCL_Error,
911
                    "Illegal return(vcl): %s",
912 12
                    req->restarts ? "Not after restarts" :
913
                    "Only from active VCL");
914 12
                req->err_code = 503;
915 12
                req->req_step = R_STP_SYNTH;
916 12
                break;
917
        case VCL_RET_PURGE:
918 32
                req->req_step = R_STP_PURGE;
919 32
                break;
920
        case VCL_RET_HASH:
921 7052
                req->req_step = R_STP_LOOKUP;
922 7052
                break;
923
        case VCL_RET_PIPE:
924 64
                if (req->esi_level > 0) {
925 0
                        VSLb(req->vsl, SLT_VCL_Error,
926
                            "vcl_recv{} returns pipe for ESI included object."
927
                            "  Doing pass.");
928 0
                        req->req_step = R_STP_PASS;
929 64
                } else if (req->http0->protover > 11) {
930 8
                        VSLb(req->vsl, SLT_VCL_Error,
931
                            "vcl_recv{} returns pipe for HTTP/2 request."
932
                            "  Doing pass.");
933 8
                        req->req_step = R_STP_PASS;
934
                } else {
935 56
                        req->req_step = R_STP_PIPE;
936
                }
937 64
                break;
938
        case VCL_RET_PASS:
939 2116
                req->req_step = R_STP_PASS;
940 2116
                break;
941
        case VCL_RET_SYNTH:
942 484
                req->req_step = R_STP_SYNTH;
943 484
                break;
944
        case VCL_RET_RESTART:
945 36
                req->req_step = R_STP_RESTART;
946 36
                break;
947
        case VCL_RET_FAIL:
948 96
                req->req_step = R_STP_VCLFAIL;
949 96
                break;
950
        default:
951 0
                WRONG("Illegal return from vcl_recv{}");
952
        }
953 9892
        return (REQ_FSM_MORE);
954
}
955
956
/*--------------------------------------------------------------------
957
 * Find the objhead, purge it.
958
 *
959
 * In VCL, a restart is necessary to get a new object
960
 */
961
962
static enum req_fsm_nxt
963 32
cnt_purge(struct worker *wrk, struct req *req)
964
{
965
        struct objcore *oc, *boc;
966
        enum lookup_e lr;
967
968 32
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
969 32
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
970 32
        AZ(req->objcore);
971 32
        AZ(req->stale_oc);
972
973 32
        AN(req->vcl);
974
975 32
        VRY_Prep(req);
976
977 32
        AZ(req->objcore);
978 32
        lr = HSH_Lookup(req, &oc, &boc, 1);
979 32
        assert (lr == HSH_MISS);
980 32
        AZ(oc);
981 32
        CHECK_OBJ_NOTNULL(boc, OBJCORE_MAGIC);
982 32
        VRY_Finish(req, DISCARD);
983
984 32
        (void)HSH_Purge(wrk, boc->objhead, req->t_req, 0, 0, 0);
985
986 32
        AZ(HSH_DerefObjCore(wrk, &boc, 1));
987
988 32
        VCL_purge_method(req->vcl, wrk, req, NULL, NULL);
989 32
        switch (wrk->handling) {
990
        case VCL_RET_RESTART:
991 12
                req->req_step = R_STP_RESTART;
992 12
                break;
993
        case VCL_RET_FAIL:
994 8
                req->req_step = R_STP_VCLFAIL;
995 8
                break;
996
        case VCL_RET_SYNTH:
997 12
                req->req_step = R_STP_SYNTH;
998 12
                break;
999
        default:
1000 0
                WRONG("Illegal return from vcl_purge{}");
1001
        }
1002 32
        return (REQ_FSM_MORE);
1003
}
1004
1005
/*--------------------------------------------------------------------
1006
 * Central state engine dispatcher.
1007
 *
1008
 * Kick the session around until it has had enough.
1009
 *
1010
 */
1011
1012
static void
1013 28
cnt_diag(struct req *req, const char *state)
1014
{
1015
1016 28
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1017
1018 28
        VSLb(req->vsl,  SLT_Debug, "vxid %u STP_%s sp %p vcl %p",
1019
            req->vsl->wid, state, req->sp, req->vcl);
1020 28
        VSL_Flush(req->vsl, 0);
1021 28
}
1022
1023
enum req_fsm_nxt
1024 9875
CNT_Request(struct worker *wrk, struct req *req)
1025
{
1026
        enum req_fsm_nxt nxt;
1027
1028 9875
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1029 9875
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1030 9875
        AN(req->vcl);
1031
1032
        /*
1033
         * Possible entrance states
1034
         */
1035 9875
        assert(
1036
            req->req_step == R_STP_LOOKUP ||
1037
            req->req_step == R_STP_TRANSPORT ||
1038
            req->req_step == R_STP_RECV);
1039
1040 9875
        AN(req->vsl->wid & VSL_CLIENTMARKER);
1041
1042
        /* wrk can have changed for restarts */
1043 9875
        req->vfc->wrk = req->wrk = wrk;
1044 9875
        wrk->vsl = req->vsl;
1045 9875
        if (req->req_step != R_STP_LOOKUP)
1046 9764
                VCL_TaskEnter(req->vcl, req->privs);
1047 79019
        for (nxt = REQ_FSM_MORE; nxt == REQ_FSM_MORE; ) {
1048
                /*
1049
                 * This is a good place to be paranoid about the various
1050
                 * pointers still pointing to the things we expect.
1051
                 */
1052 59289
                CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1053 59314
                CHECK_OBJ_ORNULL(wrk->nobjhead, OBJHEAD_MAGIC);
1054 59314
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1055
1056 59314
                switch (req->req_step) {
1057
#define REQ_STEP(l,u,arg) \
1058
                    case R_STP_##u: \
1059
                        if (DO_DEBUG(DBG_REQ_STATE)) \
1060
                                cnt_diag(req, #u); \
1061
                        nxt = cnt_##l arg; \
1062
                        break;
1063
#include "tbl/steps.h"
1064
                default:
1065 0
                        WRONG("State engine misfire");
1066
                }
1067 59269
                CHECK_OBJ_ORNULL(wrk->nobjhead, OBJHEAD_MAGIC);
1068
        }
1069 9855
        wrk->vsl = NULL;
1070 9855
        if (nxt == REQ_FSM_DONE) {
1071 9744
                VCL_TaskLeave(req->vcl, req->privs);
1072 9744
                AN(req->vsl->wid);
1073 9744
                VRB_Free(req);
1074 9744
                req->wrk = NULL;
1075
        }
1076 9855
        assert(nxt == REQ_FSM_DISEMBARK || req->ws->r == NULL);
1077 9855
        return (nxt);
1078
}