varnish-cache/bin/varnishd/cache/cache_req_fsm.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2017 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * This file contains the request-handling state engine, which is intended to
31
 * (over time) be(come) protocol agnostic.
32
 * We already use this now with ESI:includes, which are for all relevant
33
 * purposes a different "protocol"
34
 *
35
 * A special complication is the fact that we can suspend processing of
36
 * a request when hash-lookup finds a busy objhdr.
37
 *
38
 */
39
40
#include "config.h"
41
42
#include "cache_varnishd.h"
43
#include "cache_filter.h"
44
#include "cache_objhead.h"
45
#include "cache_transport.h"
46
#include "vcc_interface.h"
47
48
#include "http1/cache_http1.h"
49
#include "storage/storage.h"
50
#include "vcl.h"
51
#include "vct.h"
52
#include "vsha256.h"
53
#include "vtim.h"
54
55
#define REQ_STEPS \
56
  REQ_STEP(transport,           TRANSPORT,      ) \
57
  REQ_STEP(restart,             RESTART,        static) \
58
  REQ_STEP(recv,                RECV,           ) \
59
  REQ_STEP(pipe,                PIPE,           static) \
60
  REQ_STEP(pass,                PASS,           static) \
61
  REQ_STEP(lookup,              LOOKUP,         static) \
62
  REQ_STEP(purge,               PURGE,          static) \
63
  REQ_STEP(miss,                MISS,           static) \
64
  REQ_STEP(fetch,               FETCH,          static) \
65
  REQ_STEP(deliver,             DELIVER,        static) \
66
  REQ_STEP(vclfail,             VCLFAIL,        static) \
67
  REQ_STEP(synth,               SYNTH,          static) \
68
  REQ_STEP(transmit,            TRANSMIT,       static) \
69
  REQ_STEP(finish,              FINISH,         static)
70
71
#define REQ_STEP(l, U, priv) \
72
    static req_state_f cnt_##l; \
73
    priv const struct req_step R_STP_##U[1] = {{ \
74
        .name = "Req Step " #l, \
75
        .func = cnt_##l, \
76
    }};
77
REQ_STEPS
78
#undef REQ_STEP
79
80
/*--------------------------------------------------------------------
81
 * Handle "Expect:" and "Connection:" on incoming request
82
 */
83
84
static enum req_fsm_nxt v_matchproto_(req_state_f)
85 146410
cnt_transport(struct worker *wrk, struct req *req)
86
{
87
        const char *p;
88
89 146410
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
90 146410
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
91 146410
        CHECK_OBJ_NOTNULL(req->http, HTTP_MAGIC);
92 146410
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
93 146410
        AN(req->req_body_status);
94
95 146410
        if (http_GetHdr(req->http, H_Expect, &p)) {
96 480
                if (!http_expect_eq(p, 100-continue)) {
97 80
                        req->doclose = SC_RX_JUNK;
98 80
                        (void)req->transport->minimal_response(req, 417);
99 80
                        wrk->stats->client_req_417++;
100 80
                        return (REQ_FSM_DONE);
101
                }
102 400
                if (req->http->protover >= 11 &&
103 400
                    req->htc->pipeline_b == NULL)       // XXX: HTTP1 vs 2 ?
104 360
                        req->want100cont = 1;
105 400
                http_Unset(req->http, H_Expect);
106 400
        }
107
108 146330
        AZ(req->err_code);
109
110 146330
        req->doclose = http_DoConnection(req->http, SC_REQ_CLOSE);
111 146330
        if (req->doclose == SC_RX_BAD) {
112 120
                wrk->stats->client_req_400++;
113 120
                (void)req->transport->minimal_response(req, 400);
114 120
                return (REQ_FSM_DONE);
115
        }
116
117 146210
        if (req->req_body_status->avail == 1) {
118 4920
                AN(req->transport->req_body != NULL);
119 4920
                VFP_Setup(req->vfc, wrk);
120 4920
                req->vfc->resp = req->http;             // XXX
121 4920
                req->transport->req_body(req);
122 4920
        }
123
124 146210
        req->ws_req = WS_Snapshot(req->ws);
125 146210
        HTTP_Clone(req->http0, req->http);      // For ESI & restart
126 146210
        req->req_step = R_STP_RECV;
127 146210
        return (REQ_FSM_MORE);
128 146410
}
129
130
/*--------------------------------------------------------------------
131
 * Deliver an object to client
132
 */
133
134
int
135 128779
Resp_Setup_Deliver(struct req *req)
136
{
137
        struct http *h;
138
        struct objcore *oc;
139
        const void *hdrs;
140
141 128779
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
142 128779
        oc = req->objcore;
143 128779
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
144
145 128779
        h = req->resp;
146
147 128779
        HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
148
149 128779
        hdrs = ObjGetAttr(req->wrk, oc, OA_HEADERS, NULL);
150 128779
        if (hdrs == NULL || HTTP_Decode(h, hdrs))
151 108
                return (-1);
152
153 128685
        http_ForceField(h, HTTP_HDR_PROTO, "HTTP/1.1");
154
155 128685
        if (req->is_hit)
156 86934
                http_PrintfHeader(h, "X-Varnish: %ju %ju", VXID(req->vsl->wid),
157 43467
                    VXID(ObjGetXID(req->wrk, oc)));
158
        else
159 85218
                http_PrintfHeader(h, "X-Varnish: %ju", VXID(req->vsl->wid));
160
161
        /*
162
         * We base Age calculation upon the last timestamp taken during client
163
         * request processing. This gives some inaccuracy, but since Age is only
164
         * full second resolution that shouldn't matter. (Last request timestamp
165
         * could be a Start timestamp taken before the object entered into cache
166
         * leading to negative age. Truncate to zero in that case).
167
         */
168 257370
        http_PrintfHeader(h, "Age: %.0f",
169 128685
            floor(fmax(0., req->t_prev - oc->t_origin)));
170
171 128685
        http_AppendHeader(h, H_Via, http_ViaHeader());
172
173 138085
        if (cache_param->http_gzip_support &&
174 128493
            ObjCheckFlag(req->wrk, oc, OF_GZIPED) &&
175 9400
            !RFC2616_Req_Gzip(req->http))
176 3040
                RFC2616_Weaken_Etag(h);
177 128685
        return (0);
178 128793
}
179
180
void
181 22118
Resp_Setup_Synth(struct req *req)
182
{
183
        struct http *h;
184
185 22118
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
186
187 22118
        h = req->resp;
188
189 22118
        HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
190
191 22118
        AZ(req->objcore);
192 22118
        http_PutResponse(h, "HTTP/1.1", req->err_code, req->err_reason);
193
194 22118
        http_TimeHeader(h, "Date: ", W_TIM_real(req->wrk));
195 22118
        http_SetHeader(h, "Server: Varnish");
196 22118
        http_PrintfHeader(h, "X-Varnish: %ju", VXID(req->vsl->wid));
197
198
        /*
199
         * For late 100-continue, we suggest to VCL to close the connection to
200
         * neither send a 100-continue nor drain-read the request. But VCL has
201
         * the option to veto by removing Connection: close
202
         */
203 22118
        if (req->want100cont)
204 120
                http_SetHeader(h, "Connection: close");
205 22118
}
206
207
static enum req_fsm_nxt v_matchproto_(req_state_f)
208 128354
cnt_deliver(struct worker *wrk, struct req *req)
209
{
210
        unsigned status;
211
212 128354
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
213 128354
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
214 128354
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
215 128354
        CHECK_OBJ_NOTNULL(req->objcore->objhead, OBJHEAD_MAGIC);
216 128354
        AZ(req->stale_oc);
217 128354
        AN(req->vcl);
218
219 128354
        assert(req->objcore->refcnt > 0);
220
221 128354
        ObjTouch(req->wrk, req->objcore, req->t_prev);
222
223 128354
        if (Resp_Setup_Deliver(req)) {
224 80
                (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
225 80
                req->err_code = 500;
226 80
                req->req_step = R_STP_SYNTH;
227 80
                return (REQ_FSM_MORE);
228
        }
229
230 128274
        status = http_GetStatus(req->resp);
231 128274
        if (cache_param->http_range_support && status == 200 &&
232 114170
            !(req->objcore->flags & OC_F_PRIVATE))
233 92184
                http_ForceHeader(req->resp, H_Accept_Ranges, "bytes");
234
235 128274
        req->t_resp = W_TIM_real(wrk);
236 128274
        VCL_deliver_method(req->vcl, wrk, req, NULL, NULL);
237
238 128274
        assert(req->restarts <= req->max_restarts);
239
240 128274
        if (wrk->vpi->handling != VCL_RET_DELIVER) {
241 5209
                HSH_Cancel(wrk, req->objcore, NULL);
242 5209
                (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
243 5209
                http_Teardown(req->resp);
244
245 5209
                switch (wrk->vpi->handling) {
246
                case VCL_RET_RESTART:
247 1240
                        req->req_step = R_STP_RESTART;
248 1240
                        break;
249
                case VCL_RET_FAIL:
250 3649
                        req->req_step = R_STP_VCLFAIL;
251 3649
                        break;
252
                case VCL_RET_SYNTH:
253 320
                        req->req_step = R_STP_SYNTH;
254 320
                        break;
255
                default:
256 0
                        WRONG("Illegal return from vcl_deliver{}");
257 0
                }
258
259 5209
                return (REQ_FSM_MORE);
260
        }
261
262 123065
        VSLb_ts_req(req, "Process", W_TIM_real(wrk));
263
264 123065
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
265
266 123065
        if (IS_TOPREQ(req) && RFC2616_Do_Cond(req))
267 1200
                http_PutResponse(req->resp, "HTTP/1.1", 304, NULL);
268
269 123065
        req->req_step = R_STP_TRANSMIT;
270 123065
        return (REQ_FSM_MORE);
271 128354
}
272
273
/*--------------------------------------------------------------------
274
 * VCL failed, die horribly
275
 */
276
277
static enum req_fsm_nxt v_matchproto_(req_state_f)
278 6320
cnt_vclfail(struct worker *wrk, struct req *req)
279
{
280
        struct vrt_ctx ctx[1];
281
282 6320
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
283 6320
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
284
285 6320
        AZ(req->objcore);
286 6320
        AZ(req->stale_oc);
287
288 6320
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
289 6320
        VCL_Req2Ctx(ctx, req);
290
291 6320
        Req_Rollback(ctx);
292
293 6320
        if (req->req_reset) {
294 920
                req->err_code = 408;
295 920
                req->err_reason = "Client disconnected";
296 920
        } else {
297 5400
                req->err_code = 503;
298 5400
                req->err_reason = "VCL failed";
299
        }
300 6320
        req->req_step = R_STP_SYNTH;
301 6320
        req->doclose = SC_VCL_FAILURE;
302 6320
        req->vdp_filter_list = NULL;
303 6320
        return (REQ_FSM_MORE);
304
}
305
306
/*--------------------------------------------------------------------
307
 * Emit a synthetic response
308
 */
309
310
static enum req_fsm_nxt v_matchproto_(req_state_f)
311 22040
cnt_synth(struct worker *wrk, struct req *req)
312
{
313
        struct vsb *synth_body;
314
        ssize_t sz, szl;
315
        uint16_t status;
316
        uint8_t *ptr;
317
        const char *body;
318
319 22040
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
320 22040
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
321
322 22040
        AZ(req->objcore);
323 22040
        AZ(req->stale_oc);
324
325 22040
        wrk->stats->s_synth++;
326
327 22040
        if (req->err_code < 100)
328 0
                req->err_code = 501;
329
330 22040
        Resp_Setup_Synth(req);
331
332 22040
        req->vdp_filter_list = NULL;
333 22040
        synth_body = VSB_new_auto();
334 22040
        AN(synth_body);
335
336 22040
        req->t_resp = W_TIM_real(wrk);
337 22040
        VCL_synth_method(req->vcl, wrk, req, NULL, synth_body);
338
339 22040
        AZ(VSB_finish(synth_body));
340
341 22040
        VSLb_ts_req(req, "Process", W_TIM_real(wrk));
342
343 22040
        while (wrk->vpi->handling == VCL_RET_FAIL) {
344 1080
                if (req->esi_level > 0) {
345 40
                        wrk->vpi->handling = VCL_RET_DELIVER;
346 40
                        break;
347
                }
348 1040
                VSB_destroy(&synth_body);
349 1040
                (void)VRB_Ignore(req);
350 1040
                status = req->req_reset ? 408 : 500;
351 1040
                (void)req->transport->minimal_response(req, status);
352 1040
                req->doclose = SC_VCL_FAILURE; // XXX: Not necessary any more ?
353 1040
                VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
354 1040
                http_Teardown(req->resp);
355 1040
                return (REQ_FSM_DONE);
356
        }
357
358 21000
        if (wrk->vpi->handling == VCL_RET_RESTART && req->restarts > req->max_restarts)
359 40
                wrk->vpi->handling = VCL_RET_DELIVER;
360
361 21000
        if (wrk->vpi->handling == VCL_RET_RESTART) {
362
                /*
363
                 * XXX: Should we reset req->doclose = SC_VCL_FAILURE
364
                 * XXX: If so, to what ?
365
                 */
366 440
                HTTP_Setup(req->resp, req->ws, req->vsl, SLT_RespMethod);
367 440
                VSB_destroy(&synth_body);
368 440
                req->req_step = R_STP_RESTART;
369 440
                return (REQ_FSM_MORE);
370
        }
371 20560
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
372
373 20560
        http_Unset(req->resp, H_Content_Length);
374 41120
        http_PrintfHeader(req->resp, "Content-Length: %zd",
375 20560
            VSB_len(synth_body));
376
377 20560
        if (req->doclose == SC_NULL &&
378 15000
            http_HdrIs(req->resp, H_Connection, "close"))
379 120
                req->doclose = SC_RESP_CLOSE;
380
381
        /* Discard any lingering request body before delivery */
382 20560
        (void)VRB_Ignore(req);
383
384 20560
        req->objcore = HSH_Private(wrk);
385 20560
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
386 20560
        szl = -1;
387 20560
        if (STV_NewObject(wrk, req->objcore, stv_transient, 0)) {
388 20480
                body = VSB_data(synth_body);
389 20480
                szl = VSB_len(synth_body);
390 20480
                assert(szl >= 0);
391 39720
                while (szl > 0) {
392 19240
                        sz = szl;
393 19240
                        if (! ObjGetSpace(wrk, req->objcore, &sz, &ptr)) {
394 0
                                szl = -1;
395 0
                                break;
396
                        }
397 19240
                        if (sz > szl)
398 0
                                sz = szl;
399 19240
                        szl -= sz;
400 19240
                        memcpy(ptr, body, sz);
401 19240
                        ObjExtend(wrk, req->objcore, sz, szl == 0 ? 1 : 0);
402 19240
                        body += sz;
403
                }
404 20480
        }
405
406 20560
        if (szl >= 0)
407 20480
                AZ(ObjSetU64(wrk, req->objcore, OA_LEN, VSB_len(synth_body)));
408 20560
        HSH_DerefBoc(wrk, req->objcore);
409 20560
        VSB_destroy(&synth_body);
410
411 20560
        if (szl < 0) {
412 80
                VSLb(req->vsl, SLT_Error, "Could not get storage");
413 80
                req->doclose = SC_OVERLOAD;
414 80
                VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
415 80
                (void)HSH_DerefObjCore(wrk, &req->objcore, 1);
416 80
                http_Teardown(req->resp);
417 80
                return (REQ_FSM_DONE);
418
        }
419
420 20480
        req->req_step = R_STP_TRANSMIT;
421 20480
        return (REQ_FSM_MORE);
422 22040
}
423
424
/*--------------------------------------------------------------------
425
 * The mechanics of sending a response (from deliver or synth)
426
 */
427
428
static enum req_fsm_nxt v_matchproto_(req_state_f)
429 143550
cnt_transmit(struct worker *wrk, struct req *req)
430
{
431 143550
        enum req_fsm_nxt nxt = REQ_FSM_MORE;
432
        enum vtr_deliver_e dnxt;
433
        uint16_t status;
434
        int sendbody, head;
435
        intmax_t clval;
436
437 143550
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
438 143550
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
439 143550
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
440 143550
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
441 143550
        AZ(req->stale_oc);
442 143550
        AZ(req->res_pipe | req->res_esi);
443 143550
        AZ(req->boc);
444 143550
        req->req_step = R_STP_FINISH;
445
446
        /* Grab a ref to the bo if there is one (=streaming) */
447 143550
        req->boc = HSH_RefBoc(req->objcore);
448 143550
        if (req->boc && req->boc->state < BOS_STREAM)
449 0
                ObjWaitState(req->objcore, BOS_STREAM);
450 143550
        clval = http_GetContentLength(req->resp);
451
        /* RFC 7230, 3.3.3 */
452 143550
        status = http_GetStatus(req->resp);
453 143550
        head = http_method_eq(req->http0->hd[HTTP_HDR_METHOD].b, HEAD);
454
455 143550
        if (req->boc != NULL || (req->objcore->flags & (OC_F_FAILED)))
456 33906
                req->resp_len = clval;
457
        else
458 109644
                req->resp_len = ObjGetLen(req->wrk, req->objcore);
459
460 143550
        if (head || status < 200 || status == 204 || status == 304) {
461
                // rfc7230,l,1748,1752
462 6626
                sendbody = 0;
463 6626
        } else {
464 136924
                sendbody = 1;
465
        }
466
467 143550
        VDP_Init(req->vdc, req->wrk, req->vsl, req, NULL, &req->resp_len);
468 143550
        if (req->vdp_filter_list == NULL)
469 132896
                req->vdp_filter_list = resp_Get_Filter_List(req);
470 143550
        if (req->vdp_filter_list == NULL ||
471 143571
            VCL_StackVDP(req->vdc, req->vcl, req->vdp_filter_list, req, NULL)) {
472 2549
                VSLb(req->vsl, SLT_Error, "Failure to push processors");
473 2549
                req->doclose = SC_OVERLOAD;
474 2549
                req->acct.resp_bodybytes +=
475 2549
                        VDP_Close(req->vdc, req->objcore, req->boc);
476 2549
        } else {
477 141051
                if (status < 200 || status == 204) {
478
                        // rfc7230,l,1691,1695
479 919
                        http_Unset(req->resp, H_Content_Length);
480 141051
                } else if (status == 304) {
481
                        // rfc7230,l,1675,1677
482 1360
                        http_Unset(req->resp, H_Content_Length);
483 140132
                } else if (clval >= 0 && clval == req->resp_len) {
484
                        /* Reuse C-L header */
485 138772
                } else if (head && req->objcore->flags & OC_F_HFM) {
486
                        /*
487
                         * Don't touch C-L header (debatable)
488
                         *
489
                         * The only way to do it correctly would be to GET
490
                         * to the backend, and discard the body once the
491
                         * filters have had a chance to chew on it, but that
492
                         * would negate the "pass for huge objects" use case.
493
                         */
494 40
                } else {
495 35117
                        http_Unset(req->resp, H_Content_Length);
496 35117
                        if (req->resp_len >= 0)
497 41328
                                http_PrintfHeader(req->resp,
498 20664
                                    "Content-Length: %jd", req->resp_len);
499
                }
500 141049
                if (req->resp_len == 0)
501 40780
                        sendbody = 0;
502 141049
                dnxt = req->transport->deliver(req, sendbody);
503 141049
                if (dnxt == VTR_D_DISEMBARK)
504 1280
                        nxt = REQ_FSM_DISEMBARK;
505
                else
506 139769
                        assert(dnxt == VTR_D_DONE);
507
        }
508 143598
        return (nxt);
509
}
510
511
static enum req_fsm_nxt v_matchproto_(req_state_f)
512 143533
cnt_finish(struct worker *wrk, struct req *req)
513
{
514
515 143533
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
516 143533
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
517
518 143533
        VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
519
520 143533
        if (req->doclose == SC_NULL && (req->objcore->flags & OC_F_FAILED)) {
521
                /* The object we delivered failed due to a streaming error.
522
                 * Fail the request. */
523 560
                req->doclose = SC_TX_ERROR;
524 560
        }
525
526 143533
        if (req->boc != NULL) {
527 33885
                HSH_DerefBoc(wrk, req->objcore);
528 33885
                req->boc = NULL;
529 33885
        }
530
531 143533
        (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
532 143533
        http_Teardown(req->resp);
533
534 143533
        req->vdp_filter_list = NULL;
535 143533
        req->res_pipe = 0;
536 143533
        req->res_esi = 0;
537 143533
        return (REQ_FSM_DONE);
538
}
539
540
/*--------------------------------------------------------------------
541
 * Initiated a fetch (pass/miss) which we intend to deliver
542
 */
543
544
static enum req_fsm_nxt v_matchproto_(req_state_f)
545 86034
cnt_fetch(struct worker *wrk, struct req *req)
546
{
547
548 86034
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
549 86034
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
550 86034
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
551 86034
        AZ(req->stale_oc);
552
553 86034
        wrk->stats->s_fetch++;
554 86034
        (void)VRB_Ignore(req);
555
556 86034
        if (req->objcore->flags & OC_F_FAILED) {
557 1040
                req->err_code = 503;
558 1040
                req->req_step = R_STP_SYNTH;
559 1040
                (void)HSH_DerefObjCore(wrk, &req->objcore, 1);
560 1040
                AZ(req->objcore);
561 1040
                return (REQ_FSM_MORE);
562
        }
563
564 84994
        req->req_step = R_STP_DELIVER;
565 84994
        return (REQ_FSM_MORE);
566 86034
}
567
568
/*--------------------------------------------------------------------
569
 * Attempt to lookup objhdr from hash.  We disembark and reenter
570
 * this state if we get suspended on a busy objhdr.
571
 */
572
573
static enum req_fsm_nxt v_matchproto_(req_state_f)
574 102695
cnt_lookup(struct worker *wrk, struct req *req)
575
{
576
        struct objcore *oc, *busy;
577
        enum lookup_e lr;
578 102695
        int had_objhead = 0;
579
580 102695
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
581 102695
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
582 102695
        AZ(req->objcore);
583 102695
        AZ(req->stale_oc);
584
585 102695
        AN(req->vcl);
586
587 102695
        VRY_Prep(req);
588
589 102695
        AZ(req->objcore);
590 102695
        if (req->hash_objhead)
591 1879
                had_objhead = 1;
592 102695
        wrk->strangelove = 0;
593 102695
        lr = HSH_Lookup(req, &oc, &busy);
594 102695
        if (lr == HSH_BUSY) {
595
                /*
596
                 * We lost the session to a busy object, disembark the
597
                 * worker thread.   We return to STP_LOOKUP when the busy
598
                 * object has been unbusied, and still have the objhead
599
                 * around to restart the lookup with.
600
                 */
601 1883
                return (REQ_FSM_DISEMBARK);
602
        }
603 100812
        assert(wrk->strangelove >= 0);
604 100812
        if ((unsigned)wrk->strangelove >= cache_param->vary_notice)
605 4960
                VSLb(req->vsl, SLT_Notice, "vsl: High number of variants (%d)",
606 2480
                    wrk->strangelove);
607 100812
        if (had_objhead)
608 1780
                VSLb_ts_req(req, "Waitinglist", W_TIM_real(wrk));
609
610 100812
        if (req->vcf != NULL) {
611 240
                (void)req->vcf->func(req, NULL, NULL, 2);
612 240
                req->vcf = NULL;
613 240
        }
614
615 100812
        if (busy == NULL) {
616 41391
                VRY_Finish(req, DISCARD);
617 41391
        } else {
618 59421
                AN(busy->flags & OC_F_BUSY);
619 59421
                VRY_Finish(req, KEEP);
620
        }
621
622 100812
        AZ(req->objcore);
623 100812
        if (lr == HSH_MISS || lr == HSH_HITMISS) {
624 55740
                AN(busy);
625 55740
                AN(busy->flags & OC_F_BUSY);
626 55740
                req->objcore = busy;
627 55740
                req->stale_oc = oc;
628 55740
                req->req_step = R_STP_MISS;
629 55740
                if (lr == HSH_HITMISS)
630 1480
                        req->is_hitmiss = 1;
631 55740
                return (REQ_FSM_MORE);
632
        }
633 45072
        if (lr == HSH_HITPASS) {
634 440
                AZ(busy);
635 440
                AZ(oc);
636 440
                req->req_step = R_STP_PASS;
637 440
                req->is_hitpass = 1;
638 440
                return (REQ_FSM_MORE);
639
        }
640
641 44632
        assert(lr == HSH_HIT || lr == HSH_GRACE);
642
643 44632
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
644 44632
        AZ(oc->flags & OC_F_BUSY);
645 44632
        req->objcore = oc;
646 44632
        AZ(oc->flags & OC_F_HFM);
647
648 44632
        VCL_hit_method(req->vcl, wrk, req, NULL, NULL);
649
650 44632
        switch (wrk->vpi->handling) {
651
        case VCL_RET_DELIVER:
652 43431
                if (busy != NULL) {
653 3400
                        AZ(oc->flags & OC_F_HFM);
654 3400
                        CHECK_OBJ_NOTNULL(busy->boc, BOC_MAGIC);
655
                        // XXX: shouldn't we go to miss?
656 3400
                        VBF_Fetch(wrk, req, busy, oc, VBF_BACKGROUND);
657 3400
                        wrk->stats->s_fetch++;
658 3400
                        wrk->stats->s_bgfetch++;
659 3400
                } else {
660 40031
                        (void)VRB_Ignore(req);// XXX: handle err
661
                }
662 43431
                wrk->stats->cache_hit++;
663 43431
                req->is_hit = 1;
664 43431
                if (lr == HSH_GRACE)
665 3520
                        wrk->stats->cache_hit_grace++;
666 43431
                req->req_step = R_STP_DELIVER;
667 43431
                return (REQ_FSM_MORE);
668
        case VCL_RET_RESTART:
669 560
                req->req_step = R_STP_RESTART;
670 560
                break;
671
        case VCL_RET_FAIL:
672 201
                req->req_step = R_STP_VCLFAIL;
673 201
                break;
674
        case VCL_RET_SYNTH:
675 360
                req->req_step = R_STP_SYNTH;
676 360
                break;
677
        case VCL_RET_PASS:
678 80
                wrk->stats->cache_hit++;
679 80
                req->is_hit = 1;
680 80
                req->req_step = R_STP_PASS;
681 80
                break;
682
        default:
683 0
                WRONG("Illegal return from vcl_hit{}");
684 0
        }
685
686
        /* Drop our object, we won't need it */
687 1201
        (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
688
689 1201
        if (busy != NULL) {
690 280
                (void)HSH_DerefObjCore(wrk, &busy, 0);
691 280
                VRY_Clear(req);
692 280
        }
693
694 1201
        return (REQ_FSM_MORE);
695 102695
}
696
697
/*--------------------------------------------------------------------
698
 * Cache miss.
699
 */
700
701
static enum req_fsm_nxt v_matchproto_(req_state_f)
702 55702
cnt_miss(struct worker *wrk, struct req *req)
703
{
704
705 55702
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
706 55702
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
707 55702
        AN(req->vcl);
708 55702
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
709 55702
        CHECK_OBJ_ORNULL(req->stale_oc, OBJCORE_MAGIC);
710
711 55702
        VCL_miss_method(req->vcl, wrk, req, NULL, NULL);
712 55702
        switch (wrk->vpi->handling) {
713
        case VCL_RET_FETCH:
714 54960
                wrk->stats->cache_miss++;
715 54960
                VBF_Fetch(wrk, req, req->objcore, req->stale_oc, VBF_NORMAL);
716 54960
                if (req->stale_oc != NULL)
717 2400
                        (void)HSH_DerefObjCore(wrk, &req->stale_oc, 0);
718 54960
                req->req_step = R_STP_FETCH;
719 54960
                return (REQ_FSM_MORE);
720
        case VCL_RET_FAIL:
721 142
                req->req_step = R_STP_VCLFAIL;
722 142
                break;
723
        case VCL_RET_SYNTH:
724 320
                req->req_step = R_STP_SYNTH;
725 320
                break;
726
        case VCL_RET_RESTART:
727 160
                req->req_step = R_STP_RESTART;
728 160
                break;
729
        case VCL_RET_PASS:
730 120
                req->req_step = R_STP_PASS;
731 120
                break;
732
        default:
733 0
                WRONG("Illegal return from vcl_miss{}");
734 0
        }
735 742
        VRY_Clear(req);
736 742
        if (req->stale_oc != NULL)
737 40
                (void)HSH_DerefObjCore(wrk, &req->stale_oc, 0);
738 742
        AZ(HSH_DerefObjCore(wrk, &req->objcore, 1));
739 742
        return (REQ_FSM_MORE);
740 55702
}
741
742
/*--------------------------------------------------------------------
743
 * Pass processing
744
 */
745
746
static enum req_fsm_nxt v_matchproto_(req_state_f)
747 31160
cnt_pass(struct worker *wrk, struct req *req)
748
{
749
750 31160
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
751 31160
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
752 31160
        AN(req->vcl);
753 31160
        AZ(req->objcore);
754 31160
        AZ(req->stale_oc);
755
756 31160
        VCL_pass_method(req->vcl, wrk, req, NULL, NULL);
757 31160
        switch (wrk->vpi->handling) {
758
        case VCL_RET_FAIL:
759 40
                req->req_step = R_STP_VCLFAIL;
760 40
                break;
761
        case VCL_RET_SYNTH:
762 40
                req->req_step = R_STP_SYNTH;
763 40
                break;
764
        case VCL_RET_RESTART:
765 0
                req->req_step = R_STP_RESTART;
766 0
                break;
767
        case VCL_RET_FETCH:
768 31080
                wrk->stats->s_pass++;
769 31080
                req->objcore = HSH_Private(wrk);
770 31080
                CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
771 31080
                VBF_Fetch(wrk, req, req->objcore, NULL, VBF_PASS);
772 31080
                req->req_step = R_STP_FETCH;
773 31080
                break;
774
        default:
775 0
                WRONG("Illegal return from cnt_pass{}");
776 0
        }
777 31160
        return (REQ_FSM_MORE);
778
}
779
780
/*--------------------------------------------------------------------
781
 * Pipe mode
782
 */
783
784
static enum req_fsm_nxt v_matchproto_(req_state_f)
785 1240
cnt_pipe(struct worker *wrk, struct req *req)
786
{
787
        struct busyobj *bo;
788
        enum req_fsm_nxt nxt;
789
790 1240
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
791 1240
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
792 1240
        AZ(req->objcore);
793 1240
        AZ(req->stale_oc);
794 1240
        AN(req->vcl);
795
796 1240
        wrk->stats->s_pipe++;
797 1240
        bo = VBO_GetBusyObj(wrk, req);
798 1240
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
799 1240
        VSLb(bo->vsl, SLT_Begin, "bereq %ju pipe", VXID(req->vsl->wid));
800 1240
        VSLb(req->vsl, SLT_Link, "bereq %ju pipe", VXID(bo->vsl->wid));
801 1240
        VSLb_ts_busyobj(bo, "Start", W_TIM_real(wrk));
802 1240
        THR_SetBusyobj(bo);
803 1240
        bo->sp = req->sp;
804 1240
        SES_Ref(bo->sp);
805
806 1240
        HTTP_Setup(bo->bereq, req->ws, bo->vsl, SLT_BereqMethod);
807 1240
        http_FilterReq(bo->bereq, req->http, 0);        // XXX: 0 ?
808 1240
        http_PrintfHeader(bo->bereq, "X-Varnish: %ju", VXID(req->vsl->wid));
809 1240
        http_ForceHeader(bo->bereq, H_Connection, "close");
810
811 1240
        if (req->want100cont) {
812 0
                http_SetHeader(bo->bereq, "Expect: 100-continue");
813 0
                req->want100cont = 0;
814 0
        }
815
816 1240
        bo->wrk = wrk;
817 1240
        bo->task_deadline = NAN; /* XXX: copy req->task_deadline */
818 1240
        if (WS_Overflowed(req->ws))
819 40
                wrk->vpi->handling = VCL_RET_FAIL;
820
        else
821 1200
                VCL_pipe_method(req->vcl, wrk, req, bo, NULL);
822
823 1240
        switch (wrk->vpi->handling) {
824
        case VCL_RET_SYNTH:
825 120
                req->req_step = R_STP_SYNTH;
826 120
                nxt = REQ_FSM_MORE;
827 120
                break;
828
        case VCL_RET_PIPE:
829 1040
                VSLb_ts_req(req, "Process", W_TIM_real(wrk));
830 1040
                VSLb_ts_busyobj(bo, "Process", wrk->lastused);
831 1040
                if (V1P_Enter() == 0) {
832 1000
                        AZ(bo->req);
833 1000
                        bo->req = req;
834 1000
                        bo->wrk = wrk;
835
                        /* Unless cached, reqbody is not our job */
836 1000
                        if (req->req_body_status != BS_CACHED)
837 960
                                req->req_body_status = BS_NONE;
838 1000
                        SES_Close(req->sp, VDI_Http1Pipe(req, bo));
839 1000
                        nxt = REQ_FSM_DONE;
840 1000
                        V1P_Leave();
841 1000
                        break;
842
                }
843 40
                wrk->stats->pipe_limited++;
844
                /* fall through */
845
        case VCL_RET_FAIL:
846 120
                req->req_step = R_STP_VCLFAIL;
847 120
                nxt = REQ_FSM_MORE;
848 120
                break;
849
        default:
850 0
                WRONG("Illegal return from vcl_pipe{}");
851 0
        }
852 1240
        http_Teardown(bo->bereq);
853 1240
        SES_Rel(bo->sp);
854 1240
        VBO_ReleaseBusyObj(wrk, &bo);
855 1240
        THR_SetBusyobj(NULL);
856 1240
        return (nxt);
857
}
858
859
/*--------------------------------------------------------------------
860
 * Handle restart events
861
 */
862
863
static enum req_fsm_nxt v_matchproto_(req_state_f)
864 2880
cnt_restart(struct worker *wrk, struct req *req)
865
{
866
867 2880
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
868 2880
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
869 2880
        AZ(req->objcore);
870 2880
        AZ(req->stale_oc);
871
872 2880
        if (++req->restarts > req->max_restarts) {
873 400
                VSLb(req->vsl, SLT_VCL_Error, "Too many restarts");
874 400
                req->err_code = 503;
875 400
                req->req_step = R_STP_SYNTH;
876 400
        } else {
877
                // XXX: ReqEnd + ReqAcct ?
878 2480
                VSLb_ts_req(req, "Restart", W_TIM_real(wrk));
879 4960
                VSL_ChgId(req->vsl, "req", "restart",
880 2480
                    VXID_Get(wrk, VSL_CLIENTMARKER));
881 2480
                VSLb_ts_req(req, "Start", req->t_prev);
882 2480
                req->err_code = 0;
883 2480
                req->req_step = R_STP_RECV;
884
        }
885 2880
        return (REQ_FSM_MORE);
886
}
887
888
/*
889
 * prepare the request for vcl_recv, either initially or after a reset
890
 * e.g. due to vcl switching
891
 *
892
 * TODO
893
 * - make restarts == 0 bit re-usable for rollback
894
 * - remove duplication with Req_Cleanup()
895
 */
896
897
static void v_matchproto_(req_state_f)
898 149084
cnt_recv_prep(struct req *req, const char *ci)
899
{
900
901 149084
        if (req->restarts == 0) {
902
                /*
903
                 * This really should be done earlier, but we want to capture
904
                 * it in the VSL log.
905
                 */
906 146605
                http_AppendHeader(req->http, H_X_Forwarded_For, ci);
907 146605
                http_AppendHeader(req->http, H_Via, http_ViaHeader());
908 146605
                http_CollectHdr(req->http, H_Cache_Control);
909
910
                /* By default we use the first backend */
911 293210
                VRT_Assign_Backend(&req->director_hint,
912 146605
                    VCL_DefaultDirector(req->vcl));
913
914 146605
                req->d_ttl = -1;
915 146605
                req->d_grace = -1;
916 146605
                req->disable_esi = 0;
917 146605
                req->hash_always_miss = 0;
918 146605
                req->hash_ignore_busy = 0;
919 146605
                req->hash_ignore_vary = 0;
920 146605
                req->client_identity = NULL;
921 146605
                req->storage = NULL;
922 146605
                req->trace = FEATURE(FEATURE_TRACE);
923 146605
        }
924
925 149084
        req->is_hit = 0;
926 149084
        req->is_hitmiss = 0;
927 149084
        req->is_hitpass = 0;
928 149084
        req->err_code = 0;
929 149084
        req->err_reason = NULL;
930
931 149084
        req->vfp_filter_list = NULL;
932 149084
}
933
934
/*--------------------------------------------------------------------
935
 * We have a complete request, set everything up and start it.
936
 * We can come here both with a request from the client and with
937
 * a interior request during ESI delivery.
938
 */
939
940
static enum req_fsm_nxt v_matchproto_(req_state_f)
941 148531
cnt_recv(struct worker *wrk, struct req *req)
942
{
943
        unsigned recv_handling;
944
        struct VSHA256Context sha256ctx;
945
        const char *ci;
946
947 148531
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
948 148531
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
949 148531
        AN(req->vcl);
950 148531
        AZ(req->objcore);
951 148531
        AZ(req->stale_oc);
952 148531
        AZ(req->err_code);
953
954 148531
        AZ(isnan(req->t_first));
955 148531
        AZ(isnan(req->t_prev));
956 148531
        AZ(isnan(req->t_req));
957
958 148531
        ci = Req_LogStart(wrk, req);
959 148531
        http_VSL_log(req->http);
960
961 148531
        if (http_CountHdr(req->http0, H_Host) > 1) {
962 80
                VSLb(req->vsl, SLT_BogoHeader, "Multiple Host: headers");
963 80
                wrk->stats->client_req_400++;
964 80
                req->doclose = SC_RX_BAD;
965 80
                (void)req->transport->minimal_response(req, 400);
966 80
                return (REQ_FSM_DONE);
967
        }
968
969 148451
        if (http_CountHdr(req->http0, H_Content_Length) > 1) {
970 40
                VSLb(req->vsl, SLT_BogoHeader, "Multiple Content-Length: headers");
971 40
                wrk->stats->client_req_400++;
972 40
                req->doclose = SC_RX_BAD;
973 40
                (void)req->transport->minimal_response(req, 400);
974 40
                return (REQ_FSM_DONE);
975
        }
976
977 148411
        cnt_recv_prep(req, ci);
978
979 148411
        if (req->req_body_status == BS_ERROR) {
980 0
                req->doclose = SC_OVERLOAD;
981 0
                return (REQ_FSM_DONE);
982
        }
983
984 148411
        VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
985
986 148411
        if (wrk->vpi->handling == VCL_RET_FAIL) {
987 1878
                req->req_step = R_STP_VCLFAIL;
988 1878
                return (REQ_FSM_MORE);
989
        }
990
991 146533
        if (wrk->vpi->handling == VCL_RET_VCL && req->restarts == 0) {
992
                // Req_Rollback has happened in VPI_vcl_select
993 520
                assert(WS_Snapshot(req->ws) == req->ws_req);
994 520
                cnt_recv_prep(req, ci);
995 520
                VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
996 520
        }
997
998 146533
        if (req->want100cont && !req->late100cont) {
999 160
                req->want100cont = 0;
1000 160
                if (req->transport->minimal_response(req, 100)) {
1001 0
                        req->doclose = SC_REM_CLOSE;
1002 0
                        return (REQ_FSM_DONE);
1003
                }
1004 160
        }
1005
1006
        /* Attempts to cache req.body may fail */
1007 146533
        if (req->req_body_status == BS_ERROR) {
1008 160
                req->doclose = SC_RX_BODY;
1009 160
                return (REQ_FSM_DONE);
1010
        }
1011
1012 146373
        recv_handling = wrk->vpi->handling;
1013
1014
        /* We wash the A-E header here for the sake of VRY */
1015 291221
        if (cache_param->http_gzip_support &&
1016 146168
             (recv_handling != VCL_RET_PIPE) &&
1017 144848
             (recv_handling != VCL_RET_PASS)) {
1018 114401
                if (RFC2616_Req_Gzip(req->http)) {
1019 8160
                        http_ForceHeader(req->http, H_Accept_Encoding, "gzip");
1020 8160
                } else {
1021 106241
                        http_Unset(req->http, H_Accept_Encoding);
1022
                }
1023 114401
        }
1024
1025 146373
        VSHA256_Init(&sha256ctx);
1026 146373
        VCL_hash_method(req->vcl, wrk, req, NULL, &sha256ctx);
1027 146373
        if (wrk->vpi->handling == VCL_RET_FAIL)
1028 267
                recv_handling = wrk->vpi->handling;
1029
        else
1030 146106
                assert(wrk->vpi->handling == VCL_RET_LOOKUP);
1031 146373
        VSHA256_Final(req->digest, &sha256ctx);
1032
1033 146373
        switch (recv_handling) {
1034
        case VCL_RET_VCL:
1035 320
                VSLb(req->vsl, SLT_VCL_Error,
1036
                    "Illegal return(vcl): %s",
1037 160
                    req->restarts ? "Not after restarts" :
1038
                    "Only from active VCL");
1039 160
                req->err_code = 503;
1040 160
                req->req_step = R_STP_SYNTH;
1041 160
                break;
1042
        case VCL_RET_PURGE:
1043 280
                req->req_step = R_STP_PURGE;
1044 280
                break;
1045
        case VCL_RET_HASH:
1046 100808
                req->req_step = R_STP_LOOKUP;
1047 100808
                break;
1048
        case VCL_RET_PIPE:
1049 1320
                if (!IS_TOPREQ(req)) {
1050 0
                        VSLb(req->vsl, SLT_VCL_Error,
1051
                            "vcl_recv{} returns pipe for ESI included object."
1052
                            "  Doing pass.");
1053 0
                        req->req_step = R_STP_PASS;
1054 1320
                } else if (req->http0->protover > 11) {
1055 80
                        VSLb(req->vsl, SLT_VCL_Error,
1056
                            "vcl_recv{} returns pipe for HTTP/2 request."
1057
                            "  Doing pass.");
1058 80
                        req->req_step = R_STP_PASS;
1059 80
                } else {
1060 1240
                        req->req_step = R_STP_PIPE;
1061
                }
1062 1320
                break;
1063
        case VCL_RET_PASS:
1064 30436
                req->req_step = R_STP_PASS;
1065 30436
                break;
1066
        case VCL_RET_SYNTH:
1067 12759
                req->req_step = R_STP_SYNTH;
1068 12759
                break;
1069
        case VCL_RET_RESTART:
1070 360
                req->req_step = R_STP_RESTART;
1071 360
                break;
1072
        case VCL_RET_FAIL:
1073 250
                req->req_step = R_STP_VCLFAIL;
1074 250
                break;
1075
        default:
1076 0
                WRONG("Illegal return from vcl_recv{}");
1077 0
        }
1078 146373
        return (REQ_FSM_MORE);
1079 148531
}
1080
1081
/*--------------------------------------------------------------------
1082
 * Find the objhead, purge it.
1083
 *
1084
 * In VCL, a restart is necessary to get a new object
1085
 */
1086
1087
static enum req_fsm_nxt v_matchproto_(req_state_f)
1088 280
cnt_purge(struct worker *wrk, struct req *req)
1089
{
1090
        struct objcore *oc, *boc;
1091
        enum lookup_e lr;
1092
1093 280
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1094 280
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1095 280
        AZ(req->objcore);
1096 280
        AZ(req->stale_oc);
1097
1098 280
        AN(req->vcl);
1099
1100 280
        VRY_Prep(req);
1101
1102 280
        AZ(req->objcore);
1103 280
        req->hash_always_miss = 1;
1104 280
        lr = HSH_Lookup(req, &oc, &boc);
1105 280
        assert (lr == HSH_MISS);
1106 280
        AZ(oc);
1107 280
        CHECK_OBJ_NOTNULL(boc, OBJCORE_MAGIC);
1108 280
        VRY_Finish(req, DISCARD);
1109
1110 280
        (void)HSH_Purge(wrk, boc->objhead, req->t_req, 0, 0, 0);
1111
1112 280
        AZ(HSH_DerefObjCore(wrk, &boc, 1));
1113
1114 280
        VCL_purge_method(req->vcl, wrk, req, NULL, NULL);
1115 280
        switch (wrk->vpi->handling) {
1116
        case VCL_RET_RESTART:
1117 120
                req->req_step = R_STP_RESTART;
1118 120
                break;
1119
        case VCL_RET_FAIL:
1120 40
                req->req_step = R_STP_VCLFAIL;
1121 40
                break;
1122
        case VCL_RET_SYNTH:
1123 120
                req->req_step = R_STP_SYNTH;
1124 120
                break;
1125
        default:
1126 0
                WRONG("Illegal return from vcl_purge{}");
1127 0
        }
1128 280
        return (REQ_FSM_MORE);
1129
}
1130
1131
/*--------------------------------------------------------------------
1132
 * Central state engine dispatcher.
1133
 *
1134
 * Kick the session around until it has had enough.
1135
 *
1136
 */
1137
1138
static void v_matchproto_(req_state_f)
1139 8116
cnt_diag(struct req *req, const char *state)
1140
{
1141
1142 8116
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1143
1144 16232
        VSLb(req->vsl,  SLT_Debug, "vxid %ju STP_%s sp %p vcl %p",
1145 8116
            VXID(req->vsl->wid), state, req->sp, req->vcl);
1146 8116
        VSL_Flush(req->vsl, 0);
1147 8116
}
1148
1149
void
1150 150858
CNT_Embark(struct worker *wrk, struct req *req)
1151
{
1152
1153 150858
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1154 150858
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1155
1156
        /* wrk can have changed for restarts */
1157 150858
        req->vfc->wrk = req->wrk = wrk;
1158 150858
        wrk->vsl = req->vsl;
1159 150858
        if (req->req_step == R_STP_TRANSPORT && req->vcl == NULL) {
1160 131734
                VCL_Refresh(&wrk->wpriv->vcl);
1161 131734
                req->vcl = wrk->wpriv->vcl;
1162 131734
                wrk->wpriv->vcl = NULL;
1163 131734
                VSLbs(req->vsl, SLT_VCL_use, TOSTRAND(VCL_Name(req->vcl)));
1164 131734
        }
1165
1166 150858
        AN(req->vcl);
1167 150858
}
1168
1169
enum req_fsm_nxt
1170 149577
CNT_Request(struct req *req)
1171
{
1172
        struct vrt_ctx ctx[1];
1173
        struct worker *wrk;
1174
        enum req_fsm_nxt nxt;
1175
1176 149577
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1177
1178 149577
        wrk = req->wrk;
1179 149577
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1180
1181 149577
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
1182 149577
        AN(req->transport->deliver);
1183 149577
        AN(req->transport->minimal_response);
1184
1185
        /*
1186
         * Possible entrance states
1187
         */
1188 149577
        assert(
1189
            req->req_step == R_STP_LOOKUP ||
1190
            req->req_step == R_STP_FINISH ||
1191
            req->req_step == R_STP_TRANSPORT);
1192
1193 149577
        AN(VXID_TAG(req->vsl->wid) & VSL_CLIENTMARKER);
1194 149577
        AN(req->vcl);
1195
1196 1168215
        for (nxt = REQ_FSM_MORE; nxt == REQ_FSM_MORE; ) {
1197
                /*
1198
                 * This is a good place to be paranoid about the various
1199
                 * pointers still pointing to the things we expect.
1200
                 */
1201 1018638
                CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1202 1018638
                CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
1203 1018638
                CHECK_OBJ_ORNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
1204 1018638
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1205 1018638
                CHECK_OBJ_NOTNULL(req->doclose, STREAM_CLOSE_MAGIC);
1206
1207 1018638
                AN(req->req_step);
1208 1018638
                AN(req->req_step->name);
1209 1018638
                AN(req->req_step->func);
1210 1018638
                if (DO_DEBUG(DBG_REQ_STATE))
1211 8116
                        cnt_diag(req, req->req_step->name);
1212 1018638
                nxt = req->req_step->func(wrk, req);
1213 1018638
                CHECK_OBJ_ORNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
1214
        }
1215 149577
        wrk->vsl = NULL;
1216 149577
        if (nxt == REQ_FSM_DONE) {
1217 146139
                INIT_OBJ(ctx, VRT_CTX_MAGIC);
1218 146139
                VCL_Req2Ctx(ctx, req);
1219 146139
                if (IS_TOPREQ(req)) {
1220 131498
                        VCL_TaskLeave(ctx, req->top->privs);
1221 131498
                        if (req->top->vcl0 != NULL)
1222 480
                                VCL_Recache(wrk, &req->top->vcl0);
1223 131498
                }
1224 146139
                VCL_TaskLeave(ctx, req->privs);
1225 146139
                assert(!IS_NO_VXID(req->vsl->wid));
1226 146139
                VRB_Free(req);
1227 146139
                VRT_Assign_Backend(&req->director_hint, NULL);
1228 146139
                req->wrk = NULL;
1229 146139
        }
1230 149577
        assert(nxt == REQ_FSM_DISEMBARK || !WS_IsReserved(req->ws));
1231 149577
        return (nxt);
1232
}