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
70
#define REQ_STEP(l, U, priv) \
71
    static req_state_f cnt_##l; \
72
    priv const struct req_step R_STP_##U[1] = {{ \
73
        .name = "Req Step " #l, \
74
        .func = cnt_##l, \
75
    }};
76
REQ_STEPS
77
#undef REQ_STEP
78
79
/*--------------------------------------------------------------------
80
 * Handle "Expect:" and "Connection:" on incoming request
81
 */
82
83
static enum req_fsm_nxt v_matchproto_(req_state_f)
84 142569
cnt_transport(struct worker *wrk, struct req *req)
85
{
86
        const char *p;
87
88 142569
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
89 142569
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
90 142569
        CHECK_OBJ_NOTNULL(req->http, HTTP_MAGIC);
91 142569
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
92 142569
        AN(req->req_body_status);
93
94 142569
        if (http_GetHdr(req->http, H_Expect, &p)) {
95 480
                if (!http_expect_eq(p, 100-continue)) {
96 80
                        req->doclose = SC_RX_JUNK;
97 80
                        (void)req->transport->minimal_response(req, 417);
98 80
                        wrk->stats->client_req_417++;
99 80
                        return (REQ_FSM_DONE);
100
                }
101 400
                if (req->http->protover >= 11 &&
102 400
                    req->htc->pipeline_b == NULL)       // XXX: HTTP1 vs 2 ?
103 360
                        req->want100cont = 1;
104 400
                http_Unset(req->http, H_Expect);
105 400
        }
106
107 142489
        AZ(req->err_code);
108
109 142489
        req->doclose = http_DoConnection(req->http, SC_REQ_CLOSE);
110 142489
        if (req->doclose == SC_RX_BAD) {
111 120
                wrk->stats->client_req_400++;
112 120
                (void)req->transport->minimal_response(req, 400);
113 120
                return (REQ_FSM_DONE);
114
        }
115
116 142369
        if (req->req_body_status->avail == 1) {
117 4800
                AN(req->transport->req_body != NULL);
118 4800
                VFP_Setup(req->vfc, wrk);
119 4800
                req->vfc->resp = req->http;             // XXX
120 4800
                req->transport->req_body(req);
121 4800
        }
122
123 142369
        req->ws_req = WS_Snapshot(req->ws);
124 142369
        HTTP_Clone(req->http0, req->http);      // For ESI & restart
125 142369
        req->req_step = R_STP_RECV;
126 142369
        return (REQ_FSM_MORE);
127 142569
}
128
129
/*--------------------------------------------------------------------
130
 * Deliver an object to client
131
 */
132
133
int
134 124854
Resp_Setup_Deliver(struct req *req)
135
{
136
        struct http *h;
137
        struct objcore *oc;
138
        const void *hdrs;
139
140 124854
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
141 124854
        oc = req->objcore;
142 124854
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
143
144 124854
        h = req->resp;
145
146 124854
        HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
147
148 124854
        hdrs = ObjGetAttr(req->wrk, oc, OA_HEADERS, NULL);
149 124854
        if (hdrs == NULL || HTTP_Decode(h, hdrs))
150 94
                return (-1);
151
152 124764
        http_ForceField(h, HTTP_HDR_PROTO, "HTTP/1.1");
153
154 124764
        if (req->is_hit)
155 82206
                http_PrintfHeader(h, "X-Varnish: %ju %ju", VXID(req->vsl->wid),
156 41103
                    VXID(ObjGetXID(req->wrk, oc)));
157
        else
158 83661
                http_PrintfHeader(h, "X-Varnish: %ju", VXID(req->vsl->wid));
159
160
        /*
161
         * We base Age calculation upon the last timestamp taken during client
162
         * request processing. This gives some inaccuracy, but since Age is only
163
         * full second resolution that shouldn't matter. (Last request timestamp
164
         * could be a Start timestamp taken before the object entered into cache
165
         * leading to negative age. Truncate to zero in that case).
166
         */
167 249528
        http_PrintfHeader(h, "Age: %.0f",
168 124764
            floor(fmax(0., req->t_prev - oc->t_origin)));
169
170 124764
        http_AppendHeader(h, H_Via, http_ViaHeader());
171
172 134164
        if (cache_param->http_gzip_support &&
173 124562
            ObjCheckFlag(req->wrk, oc, OF_GZIPED) &&
174 9400
            !RFC2616_Req_Gzip(req->http))
175 3040
                RFC2616_Weaken_Etag(h);
176 124764
        return (0);
177 124858
}
178
179
void
180 22038
Resp_Setup_Synth(struct req *req)
181
{
182
        struct http *h;
183
184 22038
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
185
186 22038
        h = req->resp;
187
188 22038
        HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
189
190 22038
        AZ(req->objcore);
191 22038
        http_PutResponse(h, "HTTP/1.1", req->err_code, req->err_reason);
192
193 22038
        http_TimeHeader(h, "Date: ", W_TIM_real(req->wrk));
194 22038
        http_SetHeader(h, "Server: Varnish");
195 22038
        http_PrintfHeader(h, "X-Varnish: %ju", VXID(req->vsl->wid));
196
197
        /*
198
         * For late 100-continue, we suggest to VCL to close the connection to
199
         * neither send a 100-continue nor drain-read the request. But VCL has
200
         * the option to veto by removing Connection: close
201
         */
202 22038
        if (req->want100cont)
203 120
                http_SetHeader(h, "Connection: close");
204 22038
}
205
206
static enum req_fsm_nxt v_matchproto_(req_state_f)
207 124443
cnt_deliver(struct worker *wrk, struct req *req)
208
{
209
        unsigned status;
210
211 124443
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
212 124443
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
213 124443
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
214 124443
        CHECK_OBJ_NOTNULL(req->objcore->objhead, OBJHEAD_MAGIC);
215 124443
        AZ(req->stale_oc);
216 124443
        AN(req->vcl);
217
218 124443
        assert(req->objcore->refcnt > 0);
219
220 124443
        ObjTouch(req->wrk, req->objcore, req->t_prev);
221
222 124443
        if (Resp_Setup_Deliver(req)) {
223 80
                (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
224 80
                req->err_code = 500;
225 80
                req->req_step = R_STP_SYNTH;
226 80
                return (REQ_FSM_MORE);
227
        }
228
229 124363
        status = http_GetStatus(req->resp);
230 124363
        if (cache_param->http_range_support && status == 200 &&
231 110411
            !(req->objcore->flags & OC_F_PRIVATE))
232 88742
                http_ForceHeader(req->resp, H_Accept_Ranges, "bytes");
233
234 124363
        req->t_resp = W_TIM_real(wrk);
235 124363
        VCL_deliver_method(req->vcl, wrk, req, NULL, NULL);
236
237 124363
        assert(req->restarts <= cache_param->max_restarts);
238
239 124363
        if (wrk->vpi->handling != VCL_RET_DELIVER) {
240 5043
                HSH_Cancel(wrk, req->objcore, NULL);
241 5043
                (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
242 5043
                http_Teardown(req->resp);
243
244 5043
                switch (wrk->vpi->handling) {
245
                case VCL_RET_RESTART:
246 1080
                        req->req_step = R_STP_RESTART;
247 1080
                        break;
248
                case VCL_RET_FAIL:
249 3643
                        req->req_step = R_STP_VCLFAIL;
250 3643
                        break;
251
                case VCL_RET_SYNTH:
252 320
                        req->req_step = R_STP_SYNTH;
253 320
                        break;
254
                default:
255 0
                        WRONG("Illegal return from vcl_deliver{}");
256 0
                }
257
258 5043
                return (REQ_FSM_MORE);
259
        }
260
261 119320
        VSLb_ts_req(req, "Process", W_TIM_real(wrk));
262
263 119320
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
264
265 119320
        if (IS_TOPREQ(req) && RFC2616_Do_Cond(req))
266 1200
                http_PutResponse(req->resp, "HTTP/1.1", 304, NULL);
267
268 119320
        req->req_step = R_STP_TRANSMIT;
269 119320
        return (REQ_FSM_MORE);
270 124443
}
271
272
/*--------------------------------------------------------------------
273
 * VCL failed, die horribly
274
 */
275
276
static enum req_fsm_nxt v_matchproto_(req_state_f)
277 6279
cnt_vclfail(struct worker *wrk, struct req *req)
278
{
279
        struct vrt_ctx ctx[1];
280
281 6279
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
282 6279
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
283
284 6279
        AZ(req->objcore);
285 6279
        AZ(req->stale_oc);
286
287 6279
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
288 6279
        VCL_Req2Ctx(ctx, req);
289
290 6279
        Req_Rollback(ctx);
291
292 6279
        if (req->req_reset) {
293 879
                req->err_code = 408;
294 879
                req->err_reason = "Client disconnected";
295 879
        } else {
296 5400
                req->err_code = 503;
297 5400
                req->err_reason = "VCL failed";
298
        }
299 6279
        req->req_step = R_STP_SYNTH;
300 6279
        req->doclose = SC_VCL_FAILURE;
301 6279
        req->vdp_filter_list = NULL;
302 6279
        return (REQ_FSM_MORE);
303
}
304
305
/*--------------------------------------------------------------------
306
 * Emit a synthetic response
307
 */
308
309
static enum req_fsm_nxt v_matchproto_(req_state_f)
310 21959
cnt_synth(struct worker *wrk, struct req *req)
311
{
312
        struct vsb *synth_body;
313
        ssize_t sz, szl;
314
        uint16_t status;
315
        uint8_t *ptr;
316
        const char *body;
317
318 21959
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
319 21959
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
320
321 21959
        AZ(req->objcore);
322 21959
        AZ(req->stale_oc);
323
324 21959
        wrk->stats->s_synth++;
325
326 21959
        if (req->err_code < 100)
327 0
                req->err_code = 501;
328
329 21959
        Resp_Setup_Synth(req);
330
331 21959
        req->vdp_filter_list = NULL;
332 21959
        synth_body = VSB_new_auto();
333 21959
        AN(synth_body);
334
335 21959
        req->t_resp = W_TIM_real(wrk);
336 21959
        VCL_synth_method(req->vcl, wrk, req, NULL, synth_body);
337
338 21959
        AZ(VSB_finish(synth_body));
339
340 21959
        VSLb_ts_req(req, "Process", W_TIM_real(wrk));
341
342 21959
        while (wrk->vpi->handling == VCL_RET_FAIL) {
343 1039
                if (req->esi_level > 0) {
344 40
                        wrk->vpi->handling = VCL_RET_DELIVER;
345 40
                        break;
346
                }
347 999
                VSB_destroy(&synth_body);
348 999
                (void)VRB_Ignore(req);
349 999
                status = req->req_reset ? 408 : 500;
350 999
                (void)req->transport->minimal_response(req, status);
351 999
                req->doclose = SC_VCL_FAILURE; // XXX: Not necessary any more ?
352 999
                VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
353 999
                http_Teardown(req->resp);
354 999
                return (REQ_FSM_DONE);
355
        }
356
357 20960
        if (wrk->vpi->handling == VCL_RET_RESTART &&
358 480
            req->restarts > cache_param->max_restarts)
359 40
                wrk->vpi->handling = VCL_RET_DELIVER;
360
361 20960
        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 20520
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
372
373 20520
        http_Unset(req->resp, H_Content_Length);
374 41040
        http_PrintfHeader(req->resp, "Content-Length: %zd",
375 20520
            VSB_len(synth_body));
376
377 20520
        if (req->doclose == SC_NULL &&
378 14960
            http_HdrIs(req->resp, H_Connection, "close"))
379 120
                req->doclose = SC_RESP_CLOSE;
380
381
        /* Discard any lingering request body before delivery */
382 20520
        (void)VRB_Ignore(req);
383
384 20520
        req->objcore = HSH_Private(wrk);
385 20520
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
386 20520
        szl = -1;
387 20520
        if (STV_NewObject(wrk, req->objcore, stv_transient, 0)) {
388 20440
                body = VSB_data(synth_body);
389 20440
                szl = VSB_len(synth_body);
390 20440
                assert(szl >= 0);
391 39640
                while (szl > 0) {
392 19200
                        sz = szl;
393 19200
                        if (! ObjGetSpace(wrk, req->objcore, &sz, &ptr)) {
394 0
                                szl = -1;
395 0
                                break;
396
                        }
397 19200
                        if (sz > szl)
398 0
                                sz = szl;
399 19200
                        szl -= sz;
400 19200
                        memcpy(ptr, body, sz);
401 19200
                        ObjExtend(wrk, req->objcore, sz, szl == 0 ? 1 : 0);
402 19200
                        body += sz;
403
                }
404 20440
        }
405
406 20520
        if (szl >= 0)
407 20440
                AZ(ObjSetU64(wrk, req->objcore, OA_LEN, VSB_len(synth_body)));
408 20520
        HSH_DerefBoc(wrk, req->objcore);
409 20520
        VSB_destroy(&synth_body);
410
411 20520
        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 20440
        req->req_step = R_STP_TRANSMIT;
421 20440
        return (REQ_FSM_MORE);
422 21959
}
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 139785
cnt_transmit(struct worker *wrk, struct req *req)
430
{
431
        struct boc *boc;
432
        uint16_t status;
433
        int sendbody, head;
434
        intmax_t clval;
435
436 139785
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
437 139785
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
438 139785
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
439 139785
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
440 139785
        AZ(req->stale_oc);
441 139785
        AZ(req->res_mode);
442
443
        /* Grab a ref to the bo if there is one (=streaming) */
444 139785
        boc = HSH_RefBoc(req->objcore);
445 139785
        if (boc && boc->state < BOS_STREAM)
446 2
                ObjWaitState(req->objcore, BOS_STREAM);
447 139785
        clval = http_GetContentLength(req->resp);
448
        /* RFC 7230, 3.3.3 */
449 139785
        status = http_GetStatus(req->resp);
450 139785
        head = http_method_eq(req->http0->hd[HTTP_HDR_METHOD].b, HEAD);
451
452 139785
        if (boc != NULL || (req->objcore->flags & (OC_F_FAILED)))
453 33510
                req->resp_len = clval;
454
        else
455 106275
                req->resp_len = ObjGetLen(req->wrk, req->objcore);
456
457 139785
        if (head || status < 200 || status == 204 || status == 304) {
458
                // rfc7230,l,1748,1752
459 6494
                sendbody = 0;
460 6494
        } else {
461 133291
                sendbody = 1;
462
        }
463
464 139785
        VDP_Init(req->vdc, req->wrk, req->vsl, req, NULL, &req->resp_len);
465 139785
        if (req->vdp_filter_list == NULL)
466 129731
                req->vdp_filter_list = resp_Get_Filter_List(req);
467 139785
        if (req->vdp_filter_list == NULL ||
468 139768
            VCL_StackVDP(req->vdc, req->vcl, req->vdp_filter_list, req, NULL)) {
469 2508
                VSLb(req->vsl, SLT_Error, "Failure to push processors");
470 2508
                req->doclose = SC_OVERLOAD;
471 2508
                req->acct.resp_bodybytes +=
472 2508
                        VDP_Close(req->vdc, req->objcore, boc);
473 2508
        } else {
474 137277
                if (status < 200 || status == 204) {
475
                        // rfc7230,l,1691,1695
476 800
                        http_Unset(req->resp, H_Content_Length);
477 137277
                } else if (status == 304) {
478
                        // rfc7230,l,1675,1677
479 1360
                        http_Unset(req->resp, H_Content_Length);
480 136477
                } else if (clval >= 0 && clval == req->resp_len) {
481
                        /* Reuse C-L header */
482 135117
                } else if (head && req->objcore->flags & OC_F_HFM) {
483
                        /*
484
                         * Don't touch C-L header (debatable)
485
                         *
486
                         * The only way to do it correctly would be to GET
487
                         * to the backend, and discard the body once the
488
                         * filters have had a chance to chew on it, but that
489
                         * would negate the "pass for huge objects" use case.
490
                         */
491 40
                } else {
492 34193
                        http_Unset(req->resp, H_Content_Length);
493 34193
                        if (req->resp_len >= 0)
494 40788
                                http_PrintfHeader(req->resp,
495 20394
                                    "Content-Length: %jd", req->resp_len);
496
                }
497 137277
                if (req->resp_len == 0)
498 39060
                        sendbody = 0;
499 137277
                req->transport->deliver(req, boc, sendbody);
500
        }
501
502 139757
        VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
503
504 139757
        if (req->doclose == SC_NULL && (req->objcore->flags & OC_F_FAILED)) {
505
                /* The object we delivered failed due to a streaming error.
506
                 * Fail the request. */
507 560
                req->doclose = SC_TX_ERROR;
508 560
        }
509
510 139757
        if (boc != NULL)
511 33458
                HSH_DerefBoc(wrk, req->objcore);
512
513 139757
        (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
514 139757
        http_Teardown(req->resp);
515
516 139757
        req->vdp_filter_list = NULL;
517 139757
        req->res_mode = 0;
518 139757
        return (REQ_FSM_DONE);
519
}
520
521
/*--------------------------------------------------------------------
522
 * Initiated a fetch (pass/miss) which we intend to deliver
523
 */
524
525
static enum req_fsm_nxt v_matchproto_(req_state_f)
526 84472
cnt_fetch(struct worker *wrk, struct req *req)
527
{
528
529 84472
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
530 84472
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
531 84472
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
532 84472
        AZ(req->stale_oc);
533
534 84472
        wrk->stats->s_fetch++;
535 84472
        (void)VRB_Ignore(req);
536
537 84472
        if (req->objcore->flags & OC_F_FAILED) {
538 1040
                req->err_code = 503;
539 1040
                req->req_step = R_STP_SYNTH;
540 1040
                (void)HSH_DerefObjCore(wrk, &req->objcore, 1);
541 1040
                AZ(req->objcore);
542 1040
                return (REQ_FSM_MORE);
543
        }
544
545 83432
        req->req_step = R_STP_DELIVER;
546 83432
        return (REQ_FSM_MORE);
547 84472
}
548
549
/*--------------------------------------------------------------------
550
 * Attempt to lookup objhdr from hash.  We disembark and reenter
551
 * this state if we get suspended on a busy objhdr.
552
 */
553
554
static enum req_fsm_nxt v_matchproto_(req_state_f)
555 99035
cnt_lookup(struct worker *wrk, struct req *req)
556
{
557
        struct objcore *oc, *busy;
558
        enum lookup_e lr;
559 99035
        int had_objhead = 0;
560
561 99035
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
562 99035
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
563 99035
        AZ(req->objcore);
564 99035
        AZ(req->stale_oc);
565
566 99035
        AN(req->vcl);
567
568 99035
        VRY_Prep(req);
569
570 99035
        AZ(req->objcore);
571 99035
        if (req->hash_objhead)
572 1854
                had_objhead = 1;
573 99035
        wrk->strangelove = 0;
574 99035
        lr = HSH_Lookup(req, &oc, &busy);
575 99035
        if (lr == HSH_BUSY) {
576
                /*
577
                 * We lost the session to a busy object, disembark the
578
                 * worker thread.   We return to STP_LOOKUP when the busy
579
                 * object has been unbusied, and still have the objhead
580
                 * around to restart the lookup with.
581
                 */
582 1861
                return (REQ_FSM_DISEMBARK);
583
        }
584 97174
        assert(wrk->strangelove >= 0);
585 97174
        if ((unsigned)wrk->strangelove >= cache_param->vary_notice)
586 4960
                VSLb(req->vsl, SLT_Notice, "vsl: High number of variants (%d)",
587 2480
                    wrk->strangelove);
588 97174
        if (had_objhead)
589 1755
                VSLb_ts_req(req, "Waitinglist", W_TIM_real(wrk));
590
591 97174
        if (req->vcf != NULL) {
592 240
                (void)req->vcf->func(req, NULL, NULL, 2);
593 240
                req->vcf = NULL;
594 240
        }
595
596 97174
        if (busy == NULL) {
597 38983
                VRY_Finish(req, DISCARD);
598 38983
        } else {
599 58191
                AN(busy->flags & OC_F_BUSY);
600 58191
                VRY_Finish(req, KEEP);
601
        }
602
603 97174
        AZ(req->objcore);
604 97174
        if (lr == HSH_MISS || lr == HSH_HITMISS) {
605 54510
                AN(busy);
606 54510
                AN(busy->flags & OC_F_BUSY);
607 54510
                req->objcore = busy;
608 54510
                req->stale_oc = oc;
609 54510
                req->req_step = R_STP_MISS;
610 54510
                if (lr == HSH_HITMISS)
611 1400
                        req->is_hitmiss = 1;
612 54510
                return (REQ_FSM_MORE);
613
        }
614 42664
        if (lr == HSH_HITPASS) {
615 399
                AZ(busy);
616 399
                AZ(oc);
617 399
                req->req_step = R_STP_PASS;
618 399
                req->is_hitpass = 1;
619 399
                return (REQ_FSM_MORE);
620
        }
621
622 42265
        assert(lr == HSH_HIT || lr == HSH_GRACE);
623
624 42265
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
625 42265
        AZ(oc->flags & OC_F_BUSY);
626 42265
        req->objcore = oc;
627 42265
        AZ(oc->flags & OC_F_HFM);
628
629 42265
        VCL_hit_method(req->vcl, wrk, req, NULL, NULL);
630
631 42265
        switch (wrk->vpi->handling) {
632
        case VCL_RET_DELIVER:
633 41062
                if (busy != NULL) {
634 3400
                        AZ(oc->flags & OC_F_HFM);
635 3400
                        CHECK_OBJ_NOTNULL(busy->boc, BOC_MAGIC);
636
                        // XXX: shouldn't we go to miss?
637 3400
                        VBF_Fetch(wrk, req, busy, oc, VBF_BACKGROUND);
638 3400
                        wrk->stats->s_fetch++;
639 3400
                        wrk->stats->s_bgfetch++;
640 3400
                } else {
641 37662
                        (void)VRB_Ignore(req);// XXX: handle err
642
                }
643 41062
                wrk->stats->cache_hit++;
644 41062
                req->is_hit = 1;
645 41062
                if (lr == HSH_GRACE)
646 3520
                        wrk->stats->cache_hit_grace++;
647 41062
                req->req_step = R_STP_DELIVER;
648 41062
                return (REQ_FSM_MORE);
649
        case VCL_RET_RESTART:
650 560
                req->req_step = R_STP_RESTART;
651 560
                break;
652
        case VCL_RET_FAIL:
653 203
                req->req_step = R_STP_VCLFAIL;
654 203
                break;
655
        case VCL_RET_SYNTH:
656 360
                req->req_step = R_STP_SYNTH;
657 360
                break;
658
        case VCL_RET_PASS:
659 80
                wrk->stats->cache_hit++;
660 80
                req->is_hit = 1;
661 80
                req->req_step = R_STP_PASS;
662 80
                break;
663
        default:
664 0
                WRONG("Illegal return from vcl_hit{}");
665 0
        }
666
667
        /* Drop our object, we won't need it */
668 1203
        (void)HSH_DerefObjCore(wrk, &req->objcore, HSH_RUSH_POLICY);
669
670 1203
        if (busy != NULL) {
671 280
                (void)HSH_DerefObjCore(wrk, &busy, 0);
672 280
                VRY_Clear(req);
673 280
        }
674
675 1203
        return (REQ_FSM_MORE);
676 99035
}
677
678
/*--------------------------------------------------------------------
679
 * Cache miss.
680
 */
681
682
static enum req_fsm_nxt v_matchproto_(req_state_f)
683 54471
cnt_miss(struct worker *wrk, struct req *req)
684
{
685
686 54471
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
687 54471
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
688 54471
        AN(req->vcl);
689 54471
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
690 54471
        CHECK_OBJ_ORNULL(req->stale_oc, OBJCORE_MAGIC);
691
692 54471
        VCL_miss_method(req->vcl, wrk, req, NULL, NULL);
693 54471
        switch (wrk->vpi->handling) {
694
        case VCL_RET_FETCH:
695 53760
                wrk->stats->cache_miss++;
696 53760
                VBF_Fetch(wrk, req, req->objcore, req->stale_oc, VBF_NORMAL);
697 53760
                if (req->stale_oc != NULL)
698 2360
                        (void)HSH_DerefObjCore(wrk, &req->stale_oc, 0);
699 53760
                req->req_step = R_STP_FETCH;
700 53760
                return (REQ_FSM_MORE);
701
        case VCL_RET_FAIL:
702 151
                req->req_step = R_STP_VCLFAIL;
703 151
                break;
704
        case VCL_RET_SYNTH:
705 320
                req->req_step = R_STP_SYNTH;
706 320
                break;
707
        case VCL_RET_RESTART:
708 160
                req->req_step = R_STP_RESTART;
709 160
                break;
710
        case VCL_RET_PASS:
711 80
                req->req_step = R_STP_PASS;
712 80
                break;
713
        default:
714 0
                WRONG("Illegal return from vcl_miss{}");
715 0
        }
716 711
        VRY_Clear(req);
717 711
        if (req->stale_oc != NULL)
718 0
                (void)HSH_DerefObjCore(wrk, &req->stale_oc, 0);
719 711
        AZ(HSH_DerefObjCore(wrk, &req->objcore, 1));
720 711
        return (REQ_FSM_MORE);
721 54471
}
722
723
/*--------------------------------------------------------------------
724
 * Pass processing
725
 */
726
727
static enum req_fsm_nxt v_matchproto_(req_state_f)
728 30800
cnt_pass(struct worker *wrk, struct req *req)
729
{
730
731 30800
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
732 30800
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
733 30800
        AN(req->vcl);
734 30800
        AZ(req->objcore);
735 30800
        AZ(req->stale_oc);
736
737 30800
        VCL_pass_method(req->vcl, wrk, req, NULL, NULL);
738 30800
        switch (wrk->vpi->handling) {
739
        case VCL_RET_FAIL:
740 40
                req->req_step = R_STP_VCLFAIL;
741 40
                break;
742
        case VCL_RET_SYNTH:
743 40
                req->req_step = R_STP_SYNTH;
744 40
                break;
745
        case VCL_RET_RESTART:
746 0
                req->req_step = R_STP_RESTART;
747 0
                break;
748
        case VCL_RET_FETCH:
749 30720
                wrk->stats->s_pass++;
750 30720
                req->objcore = HSH_Private(wrk);
751 30720
                CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
752 30720
                VBF_Fetch(wrk, req, req->objcore, NULL, VBF_PASS);
753 30720
                req->req_step = R_STP_FETCH;
754 30720
                break;
755
        default:
756 0
                WRONG("Illegal return from cnt_pass{}");
757 0
        }
758 30800
        return (REQ_FSM_MORE);
759
}
760
761
/*--------------------------------------------------------------------
762
 * Pipe mode
763
 */
764
765
static enum req_fsm_nxt v_matchproto_(req_state_f)
766 1240
cnt_pipe(struct worker *wrk, struct req *req)
767
{
768
        struct busyobj *bo;
769
        enum req_fsm_nxt nxt;
770
771 1240
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
772 1240
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
773 1240
        AZ(req->objcore);
774 1240
        AZ(req->stale_oc);
775 1240
        AN(req->vcl);
776
777 1240
        wrk->stats->s_pipe++;
778 1240
        bo = VBO_GetBusyObj(wrk, req);
779 1240
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
780 1240
        VSLb(bo->vsl, SLT_Begin, "bereq %ju pipe", VXID(req->vsl->wid));
781 1240
        VSLb(req->vsl, SLT_Link, "bereq %ju pipe", VXID(bo->vsl->wid));
782 1240
        VSLb_ts_busyobj(bo, "Start", W_TIM_real(wrk));
783 1240
        THR_SetBusyobj(bo);
784 1240
        bo->sp = req->sp;
785 1240
        SES_Ref(bo->sp);
786
787 1240
        HTTP_Setup(bo->bereq, req->ws, bo->vsl, SLT_BereqMethod);
788 1240
        http_FilterReq(bo->bereq, req->http, 0);        // XXX: 0 ?
789 1240
        http_PrintfHeader(bo->bereq, "X-Varnish: %ju", VXID(req->vsl->wid));
790 1240
        http_ForceHeader(bo->bereq, H_Connection, "close");
791
792 1240
        if (req->want100cont) {
793 0
                http_SetHeader(bo->bereq, "Expect: 100-continue");
794 0
                req->want100cont = 0;
795 0
        }
796
797 1240
        bo->wrk = wrk;
798 1240
        bo->task_deadline = NAN; /* XXX: copy req->task_deadline */
799 1240
        if (WS_Overflowed(req->ws))
800 40
                wrk->vpi->handling = VCL_RET_FAIL;
801
        else
802 1200
                VCL_pipe_method(req->vcl, wrk, req, bo, NULL);
803
804 1240
        switch (wrk->vpi->handling) {
805
        case VCL_RET_SYNTH:
806 120
                req->req_step = R_STP_SYNTH;
807 120
                nxt = REQ_FSM_MORE;
808 120
                break;
809
        case VCL_RET_PIPE:
810 1040
                VSLb_ts_req(req, "Process", W_TIM_real(wrk));
811 1040
                VSLb_ts_busyobj(bo, "Process", wrk->lastused);
812 1040
                if (V1P_Enter() == 0) {
813 1000
                        AZ(bo->req);
814 1000
                        bo->req = req;
815 1000
                        bo->wrk = wrk;
816
                        /* Unless cached, reqbody is not our job */
817 1000
                        if (req->req_body_status != BS_CACHED)
818 960
                                req->req_body_status = BS_NONE;
819 1000
                        SES_Close(req->sp, VDI_Http1Pipe(req, bo));
820 1000
                        nxt = REQ_FSM_DONE;
821 1000
                        V1P_Leave();
822 1000
                        break;
823
                }
824 40
                wrk->stats->pipe_limited++;
825
                /* fall through */
826
        case VCL_RET_FAIL:
827 120
                req->req_step = R_STP_VCLFAIL;
828 120
                nxt = REQ_FSM_MORE;
829 120
                break;
830
        default:
831 0
                WRONG("Illegal return from vcl_pipe{}");
832 0
        }
833 1240
        http_Teardown(bo->bereq);
834 1240
        SES_Rel(bo->sp);
835 1240
        VBO_ReleaseBusyObj(wrk, &bo);
836 1240
        THR_SetBusyobj(NULL);
837 1240
        return (nxt);
838
}
839
840
/*--------------------------------------------------------------------
841
 * Handle restart events
842
 */
843
844
static enum req_fsm_nxt v_matchproto_(req_state_f)
845 2720
cnt_restart(struct worker *wrk, struct req *req)
846
{
847
848 2720
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
849 2720
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
850 2720
        AZ(req->objcore);
851 2720
        AZ(req->stale_oc);
852
853 2720
        if (++req->restarts > cache_param->max_restarts) {
854 400
                VSLb(req->vsl, SLT_VCL_Error, "Too many restarts");
855 400
                req->err_code = 503;
856 400
                req->req_step = R_STP_SYNTH;
857 400
        } else {
858
                // XXX: ReqEnd + ReqAcct ?
859 2320
                VSLb_ts_req(req, "Restart", W_TIM_real(wrk));
860 4640
                VSL_ChgId(req->vsl, "req", "restart",
861 2320
                    VXID_Get(wrk, VSL_CLIENTMARKER));
862 2320
                VSLb_ts_req(req, "Start", req->t_prev);
863 2320
                req->err_code = 0;
864 2320
                req->req_step = R_STP_RECV;
865
        }
866 2720
        return (REQ_FSM_MORE);
867
}
868
869
/*
870
 * prepare the request for vcl_recv, either initially or after a reset
871
 * e.g. due to vcl switching
872
 *
873
 * TODO
874
 * - make restarts == 0 bit re-usable for rollback
875
 * - remove duplication with Req_Cleanup()
876
 */
877
878
static void v_matchproto_(req_state_f)
879 145092
cnt_recv_prep(struct req *req, const char *ci)
880
{
881
882 145092
        if (req->restarts == 0) {
883
                /*
884
                 * This really should be done earlier, but we want to capture
885
                 * it in the VSL log.
886
                 */
887 142771
                http_AppendHeader(req->http, H_X_Forwarded_For, ci);
888 142771
                http_AppendHeader(req->http, H_Via, http_ViaHeader());
889 142771
                http_CollectHdr(req->http, H_Cache_Control);
890
891
                /* By default we use the first backend */
892 285542
                VRT_Assign_Backend(&req->director_hint,
893 142771
                    VCL_DefaultDirector(req->vcl));
894
895 142771
                req->d_ttl = -1;
896 142771
                req->d_grace = -1;
897 142771
                req->disable_esi = 0;
898 142771
                req->hash_always_miss = 0;
899 142771
                req->hash_ignore_busy = 0;
900 142771
                req->hash_ignore_vary = 0;
901 142771
                req->client_identity = NULL;
902 142771
                req->storage = NULL;
903 142771
                req->trace = FEATURE(FEATURE_TRACE);
904 142771
        }
905
906 145092
        req->is_hit = 0;
907 145092
        req->is_hitmiss = 0;
908 145092
        req->is_hitpass = 0;
909 145092
        req->err_code = 0;
910 145092
        req->err_reason = NULL;
911
912 145092
        req->vfp_filter_list = NULL;
913 145092
}
914
915
/*--------------------------------------------------------------------
916
 * We have a complete request, set everything up and start it.
917
 * We can come here both with a request from the client and with
918
 * a interior request during ESI delivery.
919
 */
920
921
static enum req_fsm_nxt v_matchproto_(req_state_f)
922 144523
cnt_recv(struct worker *wrk, struct req *req)
923
{
924
        unsigned recv_handling;
925
        struct VSHA256Context sha256ctx;
926
        const char *ci;
927
928 144523
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
929 144523
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
930 144523
        AN(req->vcl);
931 144523
        AZ(req->objcore);
932 144523
        AZ(req->stale_oc);
933 144523
        AZ(req->err_code);
934
935 144523
        AZ(isnan(req->t_first));
936 144523
        AZ(isnan(req->t_prev));
937 144523
        AZ(isnan(req->t_req));
938
939 144523
        ci = Req_LogStart(wrk, req);
940 144523
        http_VSL_log(req->http);
941
942 144523
        if (http_CountHdr(req->http0, H_Host) > 1) {
943 80
                VSLb(req->vsl, SLT_BogoHeader, "Multiple Host: headers");
944 80
                wrk->stats->client_req_400++;
945 80
                (void)req->transport->minimal_response(req, 400);
946 80
                return (REQ_FSM_DONE);
947
        }
948
949 144443
        if (http_CountHdr(req->http0, H_Content_Length) > 1) {
950 40
                VSLb(req->vsl, SLT_BogoHeader, "Multiple Content-Length: headers");
951 40
                wrk->stats->client_req_400++;
952 40
                (void)req->transport->minimal_response(req, 400);
953 40
                return (REQ_FSM_DONE);
954
        }
955
956 144403
        cnt_recv_prep(req, ci);
957
958 144403
        if (req->req_body_status == BS_ERROR) {
959 0
                req->doclose = SC_OVERLOAD;
960 0
                return (REQ_FSM_DONE);
961
        }
962
963 144403
        VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
964
965 144403
        if (wrk->vpi->handling == VCL_RET_FAIL) {
966 1839
                req->req_step = R_STP_VCLFAIL;
967 1839
                return (REQ_FSM_MORE);
968
        }
969
970 142564
        if (wrk->vpi->handling == VCL_RET_VCL && req->restarts == 0) {
971
                // Req_Rollback has happened in VPI_vcl_select
972 520
                assert(WS_Snapshot(req->ws) == req->ws_req);
973 520
                cnt_recv_prep(req, ci);
974 520
                VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
975 520
        }
976
977 142564
        if (req->want100cont && !req->late100cont) {
978 160
                req->want100cont = 0;
979 160
                if (req->transport->minimal_response(req, 100)) {
980 0
                        req->doclose = SC_REM_CLOSE;
981 0
                        return (REQ_FSM_DONE);
982
                }
983 160
        }
984
985
        /* Attempts to cache req.body may fail */
986 142564
        if (req->req_body_status == BS_ERROR) {
987 160
                req->doclose = SC_RX_BODY;
988 160
                return (REQ_FSM_DONE);
989
        }
990
991 142404
        recv_handling = wrk->vpi->handling;
992
993
        /* We wash the A-E header here for the sake of VRY */
994 283286
        if (cache_param->http_gzip_support &&
995 142202
             (recv_handling != VCL_RET_PIPE) &&
996 140882
             (recv_handling != VCL_RET_PASS)) {
997 110729
                if (RFC2616_Req_Gzip(req->http)) {
998 8160
                        http_ForceHeader(req->http, H_Accept_Encoding, "gzip");
999 8160
                } else {
1000 102569
                        http_Unset(req->http, H_Accept_Encoding);
1001
                }
1002 110729
        }
1003
1004 142404
        VSHA256_Init(&sha256ctx);
1005 142404
        VCL_hash_method(req->vcl, wrk, req, NULL, &sha256ctx);
1006 142404
        if (wrk->vpi->handling == VCL_RET_FAIL)
1007 248
                recv_handling = wrk->vpi->handling;
1008
        else
1009 142156
                assert(wrk->vpi->handling == VCL_RET_LOOKUP);
1010 142404
        VSHA256_Final(req->digest, &sha256ctx);
1011
1012 142404
        switch (recv_handling) {
1013
        case VCL_RET_VCL:
1014 320
                VSLb(req->vsl, SLT_VCL_Error,
1015
                    "Illegal return(vcl): %s",
1016 160
                    req->restarts ? "Not after restarts" :
1017
                    "Only from active VCL");
1018 160
                req->err_code = 503;
1019 160
                req->req_step = R_STP_SYNTH;
1020 160
                break;
1021
        case VCL_RET_PURGE:
1022 280
                req->req_step = R_STP_PURGE;
1023 280
                break;
1024
        case VCL_RET_HASH:
1025 97164
                req->req_step = R_STP_LOOKUP;
1026 97164
                break;
1027
        case VCL_RET_PIPE:
1028 1320
                if (!IS_TOPREQ(req)) {
1029 0
                        VSLb(req->vsl, SLT_VCL_Error,
1030
                            "vcl_recv{} returns pipe for ESI included object."
1031
                            "  Doing pass.");
1032 0
                        req->req_step = R_STP_PASS;
1033 1320
                } else if (req->http0->protover > 11) {
1034 80
                        VSLb(req->vsl, SLT_VCL_Error,
1035
                            "vcl_recv{} returns pipe for HTTP/2 request."
1036
                            "  Doing pass.");
1037 80
                        req->req_step = R_STP_PASS;
1038 80
                } else {
1039 1240
                        req->req_step = R_STP_PIPE;
1040
                }
1041 1320
                break;
1042
        case VCL_RET_PASS:
1043 30157
                req->req_step = R_STP_PASS;
1044 30157
                break;
1045
        case VCL_RET_SYNTH:
1046 12720
                req->req_step = R_STP_SYNTH;
1047 12720
                break;
1048
        case VCL_RET_RESTART:
1049 360
                req->req_step = R_STP_RESTART;
1050 360
                break;
1051
        case VCL_RET_FAIL:
1052 243
                req->req_step = R_STP_VCLFAIL;
1053 243
                break;
1054
        default:
1055 0
                WRONG("Illegal return from vcl_recv{}");
1056 0
        }
1057 142404
        return (REQ_FSM_MORE);
1058 144523
}
1059
1060
/*--------------------------------------------------------------------
1061
 * Find the objhead, purge it.
1062
 *
1063
 * In VCL, a restart is necessary to get a new object
1064
 */
1065
1066
static enum req_fsm_nxt v_matchproto_(req_state_f)
1067 280
cnt_purge(struct worker *wrk, struct req *req)
1068
{
1069
        struct objcore *oc, *boc;
1070
        enum lookup_e lr;
1071
1072 280
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1073 280
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1074 280
        AZ(req->objcore);
1075 280
        AZ(req->stale_oc);
1076
1077 280
        AN(req->vcl);
1078
1079 280
        VRY_Prep(req);
1080
1081 280
        AZ(req->objcore);
1082 280
        req->hash_always_miss = 1;
1083 280
        lr = HSH_Lookup(req, &oc, &boc);
1084 280
        assert (lr == HSH_MISS);
1085 280
        AZ(oc);
1086 280
        CHECK_OBJ_NOTNULL(boc, OBJCORE_MAGIC);
1087 280
        VRY_Finish(req, DISCARD);
1088
1089 280
        (void)HSH_Purge(wrk, boc->objhead, req->t_req, 0, 0, 0);
1090
1091 280
        AZ(HSH_DerefObjCore(wrk, &boc, 1));
1092
1093 280
        VCL_purge_method(req->vcl, wrk, req, NULL, NULL);
1094 280
        switch (wrk->vpi->handling) {
1095
        case VCL_RET_RESTART:
1096 120
                req->req_step = R_STP_RESTART;
1097 120
                break;
1098
        case VCL_RET_FAIL:
1099 40
                req->req_step = R_STP_VCLFAIL;
1100 40
                break;
1101
        case VCL_RET_SYNTH:
1102 120
                req->req_step = R_STP_SYNTH;
1103 120
                break;
1104
        default:
1105 0
                WRONG("Illegal return from vcl_purge{}");
1106 0
        }
1107 280
        return (REQ_FSM_MORE);
1108
}
1109
1110
/*--------------------------------------------------------------------
1111
 * Central state engine dispatcher.
1112
 *
1113
 * Kick the session around until it has had enough.
1114
 *
1115
 */
1116
1117
static void v_matchproto_(req_state_f)
1118 280
cnt_diag(struct req *req, const char *state)
1119
{
1120
1121 280
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1122
1123 560
        VSLb(req->vsl,  SLT_Debug, "vxid %ju STP_%s sp %p vcl %p",
1124 280
            VXID(req->vsl->wid), state, req->sp, req->vcl);
1125 280
        VSL_Flush(req->vsl, 0);
1126 280
}
1127
1128
void
1129 144438
CNT_Embark(struct worker *wrk, struct req *req)
1130
{
1131
1132 144438
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1133 144438
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1134
1135
        /* wrk can have changed for restarts */
1136 144438
        req->vfc->wrk = req->wrk = wrk;
1137 144438
        wrk->vsl = req->vsl;
1138 144438
        if (req->req_step == R_STP_TRANSPORT && req->vcl == NULL) {
1139 127918
                VCL_Refresh(&wrk->wpriv->vcl);
1140 127918
                req->vcl = wrk->wpriv->vcl;
1141 127918
                wrk->wpriv->vcl = NULL;
1142 127918
                VSLbs(req->vsl, SLT_VCL_use, TOSTRAND(VCL_Name(req->vcl)));
1143 127918
        }
1144
1145 144438
        AN(req->vcl);
1146 144438
}
1147
1148
enum req_fsm_nxt
1149 144439
CNT_Request(struct req *req)
1150
{
1151
        struct vrt_ctx ctx[1];
1152
        struct worker *wrk;
1153
        enum req_fsm_nxt nxt;
1154
1155 144439
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1156
1157 144439
        wrk = req->wrk;
1158 144439
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1159
1160 144439
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
1161 144439
        AN(req->transport->deliver);
1162 144439
        AN(req->transport->minimal_response);
1163
1164
        /*
1165
         * Possible entrance states
1166
         */
1167 144439
        assert(
1168
            req->req_step == R_STP_LOOKUP ||
1169
            req->req_step == R_STP_TRANSPORT);
1170
1171 144439
        AN(VXID_TAG(req->vsl->wid) & VSL_CLIENTMARKER);
1172 144439
        AN(req->vcl);
1173
1174 996927
        for (nxt = REQ_FSM_MORE; nxt == REQ_FSM_MORE; ) {
1175
                /*
1176
                 * This is a good place to be paranoid about the various
1177
                 * pointers still pointing to the things we expect.
1178
                 */
1179 852488
                CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1180 852488
                CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
1181 852488
                CHECK_OBJ_ORNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
1182 852488
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1183 852488
                CHECK_OBJ_NOTNULL(req->doclose, STREAM_CLOSE_MAGIC);
1184
1185 852488
                AN(req->req_step);
1186 852488
                AN(req->req_step->name);
1187 852488
                AN(req->req_step->func);
1188 852488
                if (DO_DEBUG(DBG_REQ_STATE))
1189 280
                        cnt_diag(req, req->req_step->name);
1190 852488
                nxt = req->req_step->func(wrk, req);
1191 852488
                CHECK_OBJ_ORNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
1192
        }
1193 144439
        wrk->vsl = NULL;
1194 144439
        if (nxt == REQ_FSM_DONE) {
1195 142295
                INIT_OBJ(ctx, VRT_CTX_MAGIC);
1196 142295
                VCL_Req2Ctx(ctx, req);
1197 142295
                if (IS_TOPREQ(req)) {
1198 127657
                        VCL_TaskLeave(ctx, req->top->privs);
1199 127657
                        if (req->top->vcl0 != NULL)
1200 480
                                VCL_Recache(wrk, &req->top->vcl0);
1201 127657
                }
1202 142295
                VCL_TaskLeave(ctx, req->privs);
1203 142295
                assert(!IS_NO_VXID(req->vsl->wid));
1204 142295
                VRB_Free(req);
1205 142295
                VRT_Assign_Backend(&req->director_hint, NULL);
1206 142295
                req->wrk = NULL;
1207 142295
        }
1208 144439
        assert(nxt == REQ_FSM_DISEMBARK || !WS_IsReserved(req->ws));
1209 144439
        return (nxt);
1210
}