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