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 150650
cnt_transport(struct worker *wrk, struct req *req)
86
{
87
        const char *p;
88
89 150650
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
90 150650
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
91 150650
        CHECK_OBJ_NOTNULL(req->http, HTTP_MAGIC);
92 150650
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
93 150650
        AN(req->req_body_status);
94
95 150650
        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 150570
        AZ(req->err_code);
109
110 150570
        req->doclose = http_DoConnection(req->http, SC_REQ_CLOSE);
111 150570
        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 150450
        if (req->req_body_status->avail == 1) {
118 5200
                AN(req->transport->req_body != NULL);
119 5200
                VFP_Setup(req->vfc, wrk);
120 5200
                req->vfc->resp = req->http;             // XXX
121 5200
                req->transport->req_body(req);
122 5200
        }
123
124 150450
        req->ws_req = WS_Snapshot(req->ws);
125 150450
        HTTP_Clone(req->http0, req->http);      // For ESI & restart
126 150450
        req->req_step = R_STP_RECV;
127 150450
        return (REQ_FSM_MORE);
128 150650
}
129
130
/*--------------------------------------------------------------------
131
 * Deliver an object to client
132
 */
133
134
int
135 132489
Resp_Setup_Deliver(struct req *req)
136
{
137
        struct http *h;
138
        struct objcore *oc;
139
        const void *hdrs;
140
141 132489
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
142 132489
        oc = req->objcore;
143 132489
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
144
145 132489
        h = req->resp;
146
147 132489
        HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
148
149 132489
        hdrs = ObjGetAttr(req->wrk, oc, OA_HEADERS, NULL);
150 132489
        if (hdrs == NULL || HTTP_Decode(h, hdrs))
151 101
                return (-1);
152
153 132406
        http_ForceField(h, HTTP_HDR_PROTO, "HTTP/1.1");
154
155 132406
        if (req->is_hit)
156 91090
                http_PrintfHeader(h, "X-Varnish: %ju %ju", VXID(req->vsl->wid),
157 45545
                    VXID(ObjGetXID(req->wrk, oc)));
158
        else
159 86861
                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 264812
        http_PrintfHeader(h, "Age: %.0f",
169 132406
            floor(fmax(0., req->t_prev - oc->t_origin)));
170
171 132406
        http_AppendHeader(h, H_Via, http_ViaHeader());
172
173 143406
        if (cache_param->http_gzip_support &&
174 132211
            ObjCheckFlag(req->wrk, oc, OF_GZIPED) &&
175 11000
            !RFC2616_Req_Gzip(req->http))
176 4000
                RFC2616_Weaken_Etag(h);
177 132406
        return (0);
178 132507
}
179
180
void
181 22635
Resp_Setup_Synth(struct req *req)
182
{
183
        struct http *h;
184
185 22635
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
186
187 22635
        h = req->resp;
188
189 22635
        HTTP_Setup(h, req->ws, req->vsl, SLT_RespMethod);
190
191 22635
        AZ(req->objcore);
192 22635
        http_PutResponse(h, "HTTP/1.1", req->err_code, req->err_reason);
193
194 22635
        http_TimeHeader(h, "Date: ", W_TIM_real(req->wrk));
195 22635
        http_SetHeader(h, "Server: Varnish");
196 22635
        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 22635
        if (req->want100cont)
204 120
                http_SetHeader(h, "Connection: close");
205 22635
}
206
207
static enum req_fsm_nxt v_matchproto_(req_state_f)
208 132081
cnt_deliver(struct worker *wrk, struct req *req)
209
{
210
        unsigned status;
211
212 132081
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
213 132081
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
214 132081
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
215 132081
        CHECK_OBJ_NOTNULL(req->objcore->objhead, OBJHEAD_MAGIC);
216 132081
        AZ(req->stale_oc);
217 132081
        AN(req->vcl);
218
219 132081
        assert(req->objcore->refcnt > 0);
220
221 132081
        ObjTouch(req->wrk, req->objcore, req->t_prev);
222
223 132081
        if (Resp_Setup_Deliver(req)) {
224 80
                (void)HSH_DerefObjCore(wrk, &req->objcore);
225 80
                req->err_code = 500;
226 80
                req->req_step = R_STP_SYNTH;
227 80
                return (REQ_FSM_MORE);
228
        }
229
230 132001
        status = http_GetStatus(req->resp);
231 132001
        if (cache_param->http_range_support && status == 200 &&
232 117214
            !(req->objcore->flags & OC_F_PRIVATE))
233 95106
                http_ForceHeader(req->resp, H_Accept_Ranges, "bytes");
234
235 132001
        req->t_resp = W_TIM_real(wrk);
236 132001
        VCL_deliver_method(req->vcl, wrk, req, NULL, NULL);
237
238 132001
        assert(req->restarts <= req->max_restarts);
239
240 132001
        if (wrk->vpi->handling != VCL_RET_DELIVER) {
241 5208
                HSH_Cancel(wrk, req->objcore, NULL);
242 5208
                (void)HSH_DerefObjCore(wrk, &req->objcore);
243 5208
                http_Teardown(req->resp);
244
245 5208
                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 3648
                        req->req_step = R_STP_VCLFAIL;
251 3648
                        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 5208
                return (REQ_FSM_MORE);
260
        }
261
262 126793
        VSLb_ts_req(req, "Process", W_TIM_real(wrk));
263
264 126793
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
265
266 126793
        if (IS_TOPREQ(req) && RFC2616_Do_Cond(req))
267 1200
                http_PutResponse(req->resp, "HTTP/1.1", 304, NULL);
268
269 126793
        req->req_step = R_STP_TRANSMIT;
270 126793
        return (REQ_FSM_MORE);
271 132081
}
272
273
/*--------------------------------------------------------------------
274
 * VCL failed, die horribly
275
 */
276
277
static enum req_fsm_nxt v_matchproto_(req_state_f)
278 6473
cnt_vclfail(struct worker *wrk, struct req *req)
279
{
280
        struct vrt_ctx ctx[1];
281
282 6473
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
283 6473
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
284
285 6473
        AZ(req->objcore);
286 6473
        AZ(req->stale_oc);
287
288 6473
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
289 6473
        VCL_Req2Ctx(ctx, req);
290
291 6473
        Req_Rollback(ctx);
292
293 6473
        if (req->req_reset) {
294 1073
                req->err_code = 408;
295 1073
                req->err_reason = "Client disconnected";
296 1073
        } else {
297 5400
                req->err_code = 503;
298 5400
                req->err_reason = "VCL failed";
299
        }
300 6473
        req->req_step = R_STP_SYNTH;
301 6473
        req->doclose = SC_VCL_FAILURE;
302 6473
        req->vdp_filter_list = NULL;
303 6473
        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 22560
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 22560
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
320 22560
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
321
322 22560
        AZ(req->objcore);
323 22560
        AZ(req->stale_oc);
324
325 22560
        wrk->stats->s_synth++;
326
327 22560
        if (req->err_code < 100)
328 0
                req->err_code = 501;
329
330 22560
        Resp_Setup_Synth(req);
331
332 22560
        req->vdp_filter_list = NULL;
333 22560
        synth_body = VSB_new_auto();
334 22560
        AN(synth_body);
335
336 22560
        req->t_resp = W_TIM_real(wrk);
337 22560
        VCL_synth_method(req->vcl, wrk, req, NULL, synth_body);
338
339 22560
        AZ(VSB_finish(synth_body));
340
341 22560
        VSLb_ts_req(req, "Process", W_TIM_real(wrk));
342
343 22560
        while (wrk->vpi->handling == VCL_RET_FAIL) {
344 1240
                if (req->esi_level > 0) {
345 40
                        wrk->vpi->handling = VCL_RET_DELIVER;
346 40
                        break;
347
                }
348 1200
                VSB_destroy(&synth_body);
349 1200
                (void)VRB_Ignore(req);
350 1200
                status = req->req_reset ? 408 : 500;
351 1200
                (void)req->transport->minimal_response(req, status);
352 1200
                req->doclose = SC_VCL_FAILURE; // XXX: Not necessary any more ?
353 1200
                VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
354 1200
                http_Teardown(req->resp);
355 1200
                return (REQ_FSM_DONE);
356
        }
357
358 21360
        if (wrk->vpi->handling == VCL_RET_RESTART && req->restarts > req->max_restarts)
359 40
                wrk->vpi->handling = VCL_RET_DELIVER;
360
361 21360
        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 20920
        assert(wrk->vpi->handling == VCL_RET_DELIVER);
372
373 20920
        http_Unset(req->resp, H_Content_Length);
374 41840
        http_PrintfHeader(req->resp, "Content-Length: %zd",
375 20920
            VSB_len(synth_body));
376
377 36160
        if (req->doclose == SC_NULL &&
378 15360
            (http_HdrIs(req->resp, H_Connection, "close") ||
379 15240
            http_HdrIs(req->http, H_Connection, "close")))
380 160
                req->doclose = SC_RESP_CLOSE;
381
382
        /* Discard any lingering request body before delivery */
383 20920
        (void)VRB_Ignore(req);
384
385 20920
        req->objcore = HSH_Private(wrk);
386 20920
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
387 20920
        szl = -1;
388 20920
        if (STV_NewObject(wrk, req->objcore, stv_transient, 0)) {
389 20840
                body = VSB_data(synth_body);
390 20840
                szl = VSB_len(synth_body);
391 20840
                assert(szl >= 0);
392 40440
                while (szl > 0) {
393 19600
                        sz = szl;
394 19600
                        if (! ObjGetSpace(wrk, req->objcore, &sz, &ptr)) {
395 0
                                szl = -1;
396 0
                                break;
397
                        }
398 19600
                        if (sz > szl)
399 0
                                sz = szl;
400 19600
                        szl -= sz;
401 19600
                        memcpy(ptr, body, sz);
402 19600
                        ObjExtend(wrk, req->objcore, sz, szl == 0 ? 1 : 0);
403 19600
                        body += sz;
404
                }
405 20840
        }
406
407 20920
        if (szl >= 0)
408 20839
                AZ(ObjSetU64(wrk, req->objcore, OA_LEN, VSB_len(synth_body)));
409 20920
        HSH_DerefBoc(wrk, req->objcore);
410 20920
        VSB_destroy(&synth_body);
411
412 20920
        if (szl < 0) {
413 80
                VSLb(req->vsl, SLT_Error, "Could not get storage");
414 80
                req->doclose = SC_OVERLOAD;
415 80
                VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
416 80
                (void)HSH_DerefObjCore(wrk, &req->objcore);
417 80
                http_Teardown(req->resp);
418 80
                return (REQ_FSM_DONE);
419
        }
420
421 20840
        req->req_step = R_STP_TRANSMIT;
422 20840
        return (REQ_FSM_MORE);
423 22560
}
424
425
/*--------------------------------------------------------------------
426
 * The mechanics of sending a response (from deliver or synth)
427
 */
428
429
static enum req_fsm_nxt v_matchproto_(req_state_f)
430 147638
cnt_transmit(struct worker *wrk, struct req *req)
431
{
432 147638
        enum req_fsm_nxt nxt = REQ_FSM_MORE;
433
        enum vtr_deliver_e dnxt;
434
        uint16_t status;
435
        int sendbody, head;
436
        intmax_t clval;
437
438 147638
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
439 147638
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
440 147638
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
441 147638
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
442 147638
        AZ(req->stale_oc);
443 147638
        AZ(req->res_pipe | req->res_esi);
444 147638
        AZ(req->boc);
445 147638
        req->req_step = R_STP_FINISH;
446
447
        /* Grab a ref to the bo if there is one (=streaming) */
448 147638
        req->boc = HSH_RefBoc(req->objcore);
449 147638
        if (req->boc && req->boc->state < BOS_STREAM)
450 0
                ObjWaitState(req->objcore, BOS_STREAM);
451 147638
        clval = http_GetContentLength(req->resp);
452
        /* RFC 7230, 3.3.3 */
453 147638
        status = http_GetStatus(req->resp);
454 147638
        head = http_method_eq(req->http0->hd[HTTP_HDR_METHOD].b, HEAD);
455
456 147638
        if (req->boc != NULL || (req->objcore->flags & (OC_F_FAILED)))
457 34881
                req->resp_len = clval;
458
        else
459 112757
                req->resp_len = ObjGetLen(req->wrk, req->objcore);
460
461 147638
        if (head || status < 200 || status == 204 || status == 304) {
462
                // rfc7230,l,1748,1752
463 6776
                sendbody = 0;
464 6776
        } else {
465 140862
                sendbody = 1;
466
        }
467
468 147638
        VDP_Init(req->vdc, req->wrk, req->vsl, req, NULL, &req->resp_len);
469 147638
        if (req->vdp_filter_list == NULL)
470 136230
                req->vdp_filter_list = resp_Get_Filter_List(req);
471 147638
        if (req->vdp_filter_list == NULL ||
472 147637
            VCL_StackVDP(req->vdc, req->vcl, req->vdp_filter_list, req, NULL)) {
473 2524
                VSLb(req->vsl, SLT_Error, "Failure to push processors");
474 2524
                req->doclose = SC_OVERLOAD;
475 2524
                req->acct.resp_bodybytes +=
476 2524
                        VDP_Close(req->vdc, req->objcore, req->boc);
477 2524
        } else {
478 145132
                if (status < 200 || status == 204) {
479
                        // rfc7230,l,1691,1695
480 940
                        http_Unset(req->resp, H_Content_Length);
481 145132
                } else if (status == 304) {
482
                        // rfc7230,l,1675,1677
483 1360
                        http_Unset(req->resp, H_Content_Length);
484 144192
                } else if (clval >= 0 && clval == req->resp_len) {
485
                        /* Reuse C-L header */
486 142832
                } else if (head) {
487
                        /* rfc9110,l,3226,3227
488
                         * "MAY send Content-Length ... [for] HEAD"
489
                         * do not touch to support cached HEAD #4245
490
                         */
491 160
                        req->resp_len = 0;
492 160
                } else {
493 36672
                        http_Unset(req->resp, H_Content_Length);
494 36672
                        if (req->resp_len >= 0)
495 43520
                                http_PrintfHeader(req->resp,
496 21760
                                    "Content-Length: %jd", req->resp_len);
497
                }
498 145128
                if (req->resp_len == 0)
499 41416
                        sendbody = 0;
500 145128
                dnxt = req->transport->deliver(req, sendbody);
501 145128
                if (dnxt == VTR_D_DISEMBARK)
502 2880
                        nxt = REQ_FSM_DISEMBARK;
503
                else
504 142248
                        assert(dnxt == VTR_D_DONE);
505
        }
506 147652
        return (nxt);
507
}
508
509
static enum req_fsm_nxt v_matchproto_(req_state_f)
510 147604
cnt_finish(struct worker *wrk, struct req *req)
511
{
512
513 147604
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
514 147604
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
515
516 147604
        VSLb_ts_req(req, "Resp", W_TIM_real(wrk));
517
518 147604
        if (req->doclose == SC_NULL && (req->objcore->flags & OC_F_FAILED)) {
519
                /* The object we delivered failed due to a streaming error.
520
                 * Fail the request. */
521 637
                req->doclose = SC_TX_ERROR;
522 637
        }
523
524 147604
        if (req->boc != NULL) {
525 34811
                HSH_DerefBoc(wrk, req->objcore);
526 34811
                req->boc = NULL;
527 34811
        }
528
529 147604
        (void)HSH_DerefObjCore(wrk, &req->objcore);
530 147604
        http_Teardown(req->resp);
531
532 147604
        req->vdp_filter_list = NULL;
533 147604
        req->res_pipe = 0;
534 147604
        req->res_esi = 0;
535 147604
        return (REQ_FSM_DONE);
536
}
537
538
/*--------------------------------------------------------------------
539
 * Initiated a fetch (pass/miss) which we intend to deliver
540
 */
541
542
static enum req_fsm_nxt v_matchproto_(req_state_f)
543 87704
cnt_fetch(struct worker *wrk, struct req *req)
544
{
545
546 87704
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
547 87704
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
548 87704
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
549 87704
        AZ(req->stale_oc);
550
551 87704
        wrk->stats->s_fetch++;
552 87704
        (void)VRB_Ignore(req);
553
554 87704
        if (req->objcore->flags & OC_F_FAILED) {
555 1080
                req->err_code = 503;
556 1080
                req->req_step = R_STP_SYNTH;
557 1080
                (void)HSH_DerefObjCore(wrk, &req->objcore);
558 1080
                AZ(req->objcore);
559 1080
                return (REQ_FSM_MORE);
560
        }
561
562 86624
        req->req_step = R_STP_DELIVER;
563 86624
        return (REQ_FSM_MORE);
564 87704
}
565
566
/*--------------------------------------------------------------------
567
 * Attempt to lookup objhdr from hash.  We disembark and reenter
568
 * this state if we get suspended on a busy objhdr.
569
 */
570
571
static enum req_fsm_nxt v_matchproto_(req_state_f)
572 106476
cnt_lookup(struct worker *wrk, struct req *req)
573
{
574
        struct objcore *oc, *busy;
575
        enum lookup_e lr;
576
        int waitinglist_gen;
577
578 106476
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
579 106476
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
580 106476
        AZ(req->stale_oc);
581
582 106476
        AN(req->vcl);
583
584 106476
        VRY_Prep(req);
585 106476
        waitinglist_gen = req->waitinglist_gen;
586
587 106476
        if (req->waitinglist_gen) {
588 2213
                CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
589 2213
                req->waitinglist_gen = 0;
590 2213
        } else
591 104263
                AZ(req->objcore);
592
593 106476
        wrk->strangelove = 0;
594 106476
        lr = HSH_Lookup(req, &oc, &busy);
595 106476
        if (lr == HSH_BUSY) {
596
                /*
597
                 * We lost the session to a busy object, disembark the
598
                 * worker thread.   We return to STP_LOOKUP when the busy
599
                 * object has been unbusied, and still have the objhead
600
                 * around to restart the lookup with.
601
                 */
602 2201
                return (REQ_FSM_DISEMBARK);
603
        }
604 104275
        assert(wrk->strangelove >= 0);
605 104275
        if ((unsigned)wrk->strangelove >= cache_param->vary_notice)
606 4960
                VSLb(req->vsl, SLT_Notice, "vsl: High number of variants (%d)",
607 2480
                    wrk->strangelove);
608 104275
        if (waitinglist_gen)
609 2204
                VSLb_ts_req(req, "Waitinglist", W_TIM_real(wrk));
610
611 104275
        if (req->vcf != NULL) {
612 240
                (void)req->vcf->func(req, NULL, NULL, 2);
613 240
                req->vcf = NULL;
614 240
        }
615
616 104275
        if (busy == NULL) {
617 43410
                VRY_Finish(req, DISCARD);
618 43410
        } else {
619 60865
                AN(busy->flags & OC_F_BUSY);
620 60865
                VRY_Finish(req, KEEP);
621
        }
622
623 104275
        AZ(req->objcore);
624 104275
        if (lr == HSH_MISS || lr == HSH_HITMISS) {
625 57107
                AN(busy);
626 57107
                AN(busy->flags & OC_F_BUSY);
627 57107
                req->objcore = busy;
628 57107
                req->stale_oc = oc;
629 57107
                req->req_step = R_STP_MISS;
630 57107
                if (lr == HSH_HITMISS)
631 1440
                        req->is_hitmiss = 1;
632 57107
                return (REQ_FSM_MORE);
633
        }
634 47168
        if (lr == HSH_HITPASS) {
635 440
                AZ(busy);
636 440
                AZ(oc);
637 440
                req->req_step = R_STP_PASS;
638 440
                req->is_hitpass = 1;
639 440
                return (REQ_FSM_MORE);
640
        }
641
642 46728
        assert(lr == HSH_HIT || lr == HSH_GRACE);
643
644 46728
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
645 46728
        AZ(oc->flags & OC_F_BUSY);
646 46728
        req->objcore = oc;
647 46728
        AZ(oc->flags & OC_F_HFM);
648
649 46728
        VCL_hit_method(req->vcl, wrk, req, NULL, NULL);
650
651 46728
        switch (wrk->vpi->handling) {
652
        case VCL_RET_DELIVER:
653 45506
                if (busy != NULL) {
654 3480
                        AZ(oc->flags & OC_F_HFM);
655 3480
                        CHECK_OBJ_NOTNULL(busy->boc, BOC_MAGIC);
656
                        // XXX: shouldn't we go to miss?
657 3480
                        VBF_Fetch(wrk, req, busy, oc, VBF_BACKGROUND);
658 3480
                        wrk->stats->s_fetch++;
659 3480
                        wrk->stats->s_bgfetch++;
660 3480
                } else {
661 42026
                        (void)VRB_Ignore(req);// XXX: handle err
662
                }
663 45506
                wrk->stats->cache_hit++;
664 45506
                req->is_hit = 1;
665 45506
                if (lr == HSH_GRACE)
666 3600
                        wrk->stats->cache_hit_grace++;
667 45506
                req->req_step = R_STP_DELIVER;
668 45506
                return (REQ_FSM_MORE);
669
        case VCL_RET_RESTART:
670 581
                req->req_step = R_STP_RESTART;
671 581
                break;
672
        case VCL_RET_FAIL:
673 201
                req->req_step = R_STP_VCLFAIL;
674 201
                break;
675
        case VCL_RET_SYNTH:
676 360
                req->req_step = R_STP_SYNTH;
677 360
                break;
678
        case VCL_RET_PASS:
679 80
                wrk->stats->cache_hit++;
680 80
                req->is_hit = 1;
681 80
                req->req_step = R_STP_PASS;
682 80
                break;
683
        default:
684 0
                WRONG("Illegal return from vcl_hit{}");
685 0
        }
686
687
        /* Drop our object, we won't need it */
688 1222
        (void)HSH_DerefObjCore(wrk, &req->objcore);
689
690 1222
        if (busy != NULL) {
691 280
                HSH_Withdraw(wrk, &busy);
692 280
                VRY_Clear(req);
693 280
        }
694
695 1222
        return (REQ_FSM_MORE);
696 106476
}
697
698
/*--------------------------------------------------------------------
699
 * Cache miss.
700
 */
701
702
static enum req_fsm_nxt v_matchproto_(req_state_f)
703 57065
cnt_miss(struct worker *wrk, struct req *req)
704
{
705
706 57065
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
707 57065
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
708 57065
        AN(req->vcl);
709 57065
        CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
710 57065
        CHECK_OBJ_ORNULL(req->stale_oc, OBJCORE_MAGIC);
711
712 57065
        VCL_miss_method(req->vcl, wrk, req, NULL, NULL);
713 57065
        switch (wrk->vpi->handling) {
714
        case VCL_RET_FETCH:
715 56319
                wrk->stats->cache_miss++;
716 56319
                VBF_Fetch(wrk, req, req->objcore, req->stale_oc, VBF_NORMAL);
717 56319
                if (req->stale_oc != NULL)
718 2840
                        (void)HSH_DerefObjCore(wrk, &req->stale_oc);
719 56319
                req->req_step = R_STP_FETCH;
720 56319
                return (REQ_FSM_MORE);
721
        case VCL_RET_FAIL:
722 146
                req->req_step = R_STP_VCLFAIL;
723 146
                break;
724
        case VCL_RET_SYNTH:
725 320
                req->req_step = R_STP_SYNTH;
726 320
                break;
727
        case VCL_RET_RESTART:
728 160
                req->req_step = R_STP_RESTART;
729 160
                break;
730
        case VCL_RET_PASS:
731 120
                req->req_step = R_STP_PASS;
732 120
                break;
733
        default:
734 0
                WRONG("Illegal return from vcl_miss{}");
735 0
        }
736 746
        VRY_Clear(req);
737 746
        if (req->stale_oc != NULL)
738 40
                (void)HSH_DerefObjCore(wrk, &req->stale_oc);
739 746
        HSH_Withdraw(wrk, &req->objcore);
740 746
        return (REQ_FSM_MORE);
741 57065
}
742
743
/*--------------------------------------------------------------------
744
 * Pass processing
745
 */
746
747
static enum req_fsm_nxt v_matchproto_(req_state_f)
748 31480
cnt_pass(struct worker *wrk, struct req *req)
749
{
750
751 31480
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
752 31480
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
753 31480
        AN(req->vcl);
754 31480
        AZ(req->objcore);
755 31480
        AZ(req->stale_oc);
756
757 31480
        VCL_pass_method(req->vcl, wrk, req, NULL, NULL);
758 31480
        switch (wrk->vpi->handling) {
759
        case VCL_RET_FAIL:
760 40
                req->req_step = R_STP_VCLFAIL;
761 40
                break;
762
        case VCL_RET_SYNTH:
763 40
                req->req_step = R_STP_SYNTH;
764 40
                break;
765
        case VCL_RET_RESTART:
766 0
                req->req_step = R_STP_RESTART;
767 0
                break;
768
        case VCL_RET_FETCH:
769 31400
                wrk->stats->s_pass++;
770 31400
                req->objcore = HSH_Private(wrk);
771 31400
                CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
772 31400
                VBF_Fetch(wrk, req, req->objcore, NULL, VBF_PASS);
773 31400
                req->req_step = R_STP_FETCH;
774 31400
                break;
775
        default:
776 0
                WRONG("Illegal return from cnt_pass{}");
777 0
        }
778 31480
        return (REQ_FSM_MORE);
779
}
780
781
/*--------------------------------------------------------------------
782
 * Pipe mode
783
 */
784
785
static enum req_fsm_nxt v_matchproto_(req_state_f)
786 1200
cnt_pipe(struct worker *wrk, struct req *req)
787
{
788
        struct busyobj *bo;
789
        enum req_fsm_nxt nxt;
790
791 1200
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
792 1200
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
793 1200
        AZ(req->objcore);
794 1200
        AZ(req->stale_oc);
795 1200
        AN(req->vcl);
796
797 1200
        wrk->stats->s_pipe++;
798 1200
        bo = VBO_GetBusyObj(wrk, req);
799 1200
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
800 1200
        VSLb(bo->vsl, SLT_Begin, "bereq %ju pipe", VXID(req->vsl->wid));
801 1200
        VSLb(req->vsl, SLT_Link, "bereq %ju pipe", VXID(bo->vsl->wid));
802 1200
        VSLb_ts_busyobj(bo, "Start", W_TIM_real(wrk));
803 1200
        THR_SetBusyobj(bo);
804 1200
        bo->sp = req->sp;
805 1200
        SES_Ref(bo->sp);
806
807 1200
        HTTP_Setup(bo->bereq, req->ws, bo->vsl, SLT_BereqMethod);
808 1200
        http_FilterReq(bo->bereq, req->http, 0);        // XXX: 0 ?
809 1200
        http_PrintfHeader(bo->bereq, "X-Varnish: %ju", VXID(req->vsl->wid));
810 1200
        http_ForceHeader(bo->bereq, H_Connection, "close");
811
812 1200
        if (req->want100cont) {
813 0
                http_SetHeader(bo->bereq, "Expect: 100-continue");
814 0
                req->want100cont = 0;
815 0
        }
816
817 1200
        bo->wrk = wrk;
818 1200
        bo->task_deadline = NAN; /* XXX: copy req->task_deadline */
819 1200
        if (WS_Overflowed(req->ws))
820 40
                wrk->vpi->handling = VCL_RET_FAIL;
821
        else
822 1160
                VCL_pipe_method(req->vcl, wrk, req, bo, NULL);
823
824 1200
        switch (wrk->vpi->handling) {
825
        case VCL_RET_SYNTH:
826 120
                req->req_step = R_STP_SYNTH;
827 120
                nxt = REQ_FSM_MORE;
828 120
                break;
829
        case VCL_RET_PIPE:
830 1000
                VSLb_ts_req(req, "Process", W_TIM_real(wrk));
831 1000
                VSLb_ts_busyobj(bo, "Process", wrk->lastused);
832 1000
                if (V1P_Enter() == 0) {
833 960
                        AZ(bo->req);
834 960
                        bo->req = req;
835 960
                        bo->wrk = wrk;
836
                        /* Unless cached, reqbody is not our job */
837 960
                        if (req->req_body_status != BS_CACHED)
838 920
                                req->req_body_status = BS_NONE;
839 960
                        SES_Close(req->sp, VDI_Http1Pipe(req, bo));
840 960
                        nxt = REQ_FSM_DONE;
841 960
                        V1P_Leave();
842 960
                        break;
843
                }
844 40
                wrk->stats->pipe_limited++;
845
                /* fall through */
846
        case VCL_RET_FAIL:
847 120
                req->req_step = R_STP_VCLFAIL;
848 120
                nxt = REQ_FSM_MORE;
849 120
                break;
850
        default:
851 0
                WRONG("Illegal return from vcl_pipe{}");
852 0
        }
853 1200
        http_Teardown(bo->bereq);
854 1200
        SES_Rel(bo->sp);
855 1200
        VBO_ReleaseBusyObj(wrk, &bo);
856 1200
        THR_SetBusyobj(NULL);
857 1200
        return (nxt);
858
}
859
860
/*--------------------------------------------------------------------
861
 * Handle restart events
862
 */
863
864
static enum req_fsm_nxt v_matchproto_(req_state_f)
865 2901
cnt_restart(struct worker *wrk, struct req *req)
866
{
867
868 2901
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
869 2901
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
870 2901
        AZ(req->objcore);
871 2901
        AZ(req->stale_oc);
872
873 2901
        if (++req->restarts > req->max_restarts) {
874 400
                VSLb(req->vsl, SLT_VCL_Error, "Too many restarts");
875 400
                req->err_code = 503;
876 400
                req->req_step = R_STP_SYNTH;
877 400
        } else {
878
                // XXX: ReqEnd + ReqAcct ?
879 2501
                VSLb_ts_req(req, "Restart", W_TIM_real(wrk));
880 5002
                VSL_ChgId(req->vsl, "req", "restart",
881 2501
                    VXID_Get(wrk, VSL_CLIENTMARKER));
882 2501
                VSLb_ts_req(req, "Start", req->t_prev);
883 2501
                req->err_code = 0;
884 2501
                req->req_step = R_STP_RECV;
885
        }
886 2901
        return (REQ_FSM_MORE);
887
}
888
889
/*
890
 * prepare the request for vcl_recv, either initially or after a reset
891
 * e.g. due to vcl switching
892
 *
893
 * TODO
894
 * - make restarts == 0 bit re-usable for rollback
895
 * - remove duplication with Req_Cleanup()
896
 */
897
898
static void v_matchproto_(req_state_f)
899 153346
cnt_recv_prep(struct req *req, const char *ci)
900
{
901
902 153346
        if (req->restarts == 0) {
903
                /*
904
                 * This really should be done earlier, but we want to capture
905
                 * it in the VSL log.
906
                 */
907 150845
                http_AppendHeader(req->http, H_X_Forwarded_For, ci);
908 150845
                http_AppendHeader(req->http, H_Via, http_ViaHeader());
909 150845
                http_CollectHdr(req->http, H_Cache_Control);
910
911
                /* By default we use the first backend */
912 301690
                VRT_Assign_Backend(&req->director_hint,
913 150845
                    VCL_DefaultDirector(req->vcl));
914
915 150845
                req->d_ttl = -1;
916 150845
                req->d_grace = -1;
917 150845
                req->disable_esi = 0;
918 150845
                req->hash_always_miss = 0;
919 150845
                req->hash_ignore_busy = 0;
920 150845
                req->hash_ignore_vary = 0;
921 150845
                req->client_identity = NULL;
922 150845
                req->storage = NULL;
923 150845
                req->trace = FEATURE(FEATURE_TRACE);
924 150845
        }
925
926 153346
        req->is_hit = 0;
927 153346
        req->is_hitmiss = 0;
928 153346
        req->is_hitpass = 0;
929 153346
        req->err_code = 0;
930 153346
        req->err_reason = NULL;
931
932 153346
        req->vfp_filter_list = NULL;
933 153346
}
934
935
/*--------------------------------------------------------------------
936
 * We have a complete request, set everything up and start it.
937
 * We can come here both with a request from the client and with
938
 * a interior request during ESI delivery.
939
 */
940
941
static enum req_fsm_nxt v_matchproto_(req_state_f)
942 152780
cnt_recv(struct worker *wrk, struct req *req)
943
{
944
        unsigned recv_handling;
945
        struct VSHA256Context sha256ctx;
946
        const char *ci;
947
948 152780
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
949 152780
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
950 152780
        AN(req->vcl);
951 152780
        AZ(req->objcore);
952 152780
        AZ(req->stale_oc);
953 152780
        AZ(req->err_code);
954
955 152780
        AZ(isnan(req->t_first));
956 152780
        AZ(isnan(req->t_prev));
957 152780
        AZ(isnan(req->t_req));
958
959 152780
        ci = Req_LogStart(wrk, req);
960 152780
        http_VSL_log(req->http);
961
962 152780
        if (http_CountHdr(req->http0, H_Host) > 1) {
963 80
                VSLb(req->vsl, SLT_BogoHeader, "Multiple Host: headers");
964 80
                wrk->stats->client_req_400++;
965 80
                req->doclose = SC_RX_BAD;
966 80
                (void)req->transport->minimal_response(req, 400);
967 80
                return (REQ_FSM_DONE);
968
        }
969
970 152700
        if (http_CountHdr(req->http0, H_Content_Length) > 1) {
971 40
                VSLb(req->vsl, SLT_BogoHeader, "Multiple Content-Length: headers");
972 40
                wrk->stats->client_req_400++;
973 40
                req->doclose = SC_RX_BAD;
974 40
                (void)req->transport->minimal_response(req, 400);
975 40
                return (REQ_FSM_DONE);
976
        }
977
978 152660
        cnt_recv_prep(req, ci);
979
980 152660
        if (req->req_body_status == BS_ERROR) {
981 0
                req->doclose = SC_OVERLOAD;
982 0
                return (REQ_FSM_DONE);
983
        }
984
985 152660
        VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
986
987 152660
        if (wrk->vpi->handling == VCL_RET_FAIL) {
988 1880
                req->req_step = R_STP_VCLFAIL;
989 1880
                return (REQ_FSM_MORE);
990
        }
991
992 150780
        if (wrk->vpi->handling == VCL_RET_VCL && req->restarts == 0) {
993
                // Req_Rollback has happened in VPI_vcl_select
994 520
                assert(WS_Snapshot(req->ws) == req->ws_req);
995 520
                cnt_recv_prep(req, ci);
996 520
                VCL_recv_method(req->vcl, wrk, req, NULL, NULL);
997 520
        }
998
999 150780
        if (req->want100cont && !req->late100cont) {
1000 160
                req->want100cont = 0;
1001 160
                if (req->transport->minimal_response(req, 100)) {
1002 0
                        req->doclose = SC_REM_CLOSE;
1003 0
                        return (REQ_FSM_DONE);
1004
                }
1005 160
        }
1006
1007
        /* Attempts to cache req.body may fail */
1008 150780
        if (req->req_body_status == BS_ERROR) {
1009 200
                req->doclose = SC_RX_BODY;
1010 200
                (void)req->transport->minimal_response(req, 400);
1011 200
                return (REQ_FSM_DONE);
1012
        }
1013
1014 150580
        recv_handling = wrk->vpi->handling;
1015
1016
        /* We wash the A-E header here for the sake of VRY */
1017 299685
        if (cache_param->http_gzip_support &&
1018 150385
             (recv_handling != VCL_RET_PIPE) &&
1019 149105
             (recv_handling != VCL_RET_PASS)) {
1020 118335
                if (RFC2616_Req_Gzip(req->http)) {
1021 8800
                        http_ForceHeader(req->http, H_Accept_Encoding, "gzip");
1022 8800
                } else {
1023 109535
                        http_Unset(req->http, H_Accept_Encoding);
1024
                }
1025 118335
        }
1026
1027 150580
        VSHA256_Init(&sha256ctx);
1028 150580
        VCL_hash_method(req->vcl, wrk, req, NULL, &sha256ctx);
1029 150580
        if (wrk->vpi->handling == VCL_RET_FAIL)
1030 402
                recv_handling = wrk->vpi->handling;
1031
        else
1032 150178
                assert(wrk->vpi->handling == VCL_RET_LOOKUP);
1033 150580
        VSHA256_Final(req->digest, &sha256ctx);
1034
1035 150580
        switch (recv_handling) {
1036
        case VCL_RET_VCL:
1037 320
                VSLb(req->vsl, SLT_VCL_Error,
1038
                    "Illegal return(vcl): %s",
1039 160
                    req->restarts ? "Not after restarts" :
1040
                    "Only from active VCL");
1041 160
                req->err_code = 503;
1042 160
                req->req_step = R_STP_SYNTH;
1043 160
                break;
1044
        case VCL_RET_PURGE:
1045 400
                req->req_step = R_STP_PURGE;
1046 400
                break;
1047
        case VCL_RET_HASH:
1048 104265
                req->req_step = R_STP_LOOKUP;
1049 104265
                break;
1050
        case VCL_RET_PIPE:
1051 1280
                if (!IS_TOPREQ(req)) {
1052 0
                        VSLb(req->vsl, SLT_VCL_Error,
1053
                            "vcl_recv{} returns pipe for ESI included object."
1054
                            "  Doing pass.");
1055 0
                        req->req_step = R_STP_PASS;
1056 1280
                } else if (req->http0->protover > 11) {
1057 80
                        VSLb(req->vsl, SLT_VCL_Error,
1058
                            "vcl_recv{} returns pipe for HTTP/2 request."
1059
                            "  Doing pass.");
1060 80
                        req->req_step = R_STP_PASS;
1061 80
                } else {
1062 1200
                        req->req_step = R_STP_PIPE;
1063
                }
1064 1280
                break;
1065
        case VCL_RET_PASS:
1066 30758
                req->req_step = R_STP_PASS;
1067 30758
                break;
1068
        case VCL_RET_SYNTH:
1069 12959
                req->req_step = R_STP_SYNTH;
1070 12959
                break;
1071
        case VCL_RET_RESTART:
1072 360
                req->req_step = R_STP_RESTART;
1073 360
                break;
1074
        case VCL_RET_FAIL:
1075 398
                req->req_step = R_STP_VCLFAIL;
1076 398
                break;
1077
        default:
1078 0
                WRONG("Illegal return from vcl_recv{}");
1079 0
        }
1080 150580
        return (REQ_FSM_MORE);
1081 152780
}
1082
1083
/*--------------------------------------------------------------------
1084
 * Find the objhead, purge it.
1085
 *
1086
 * In VCL, a restart is necessary to get a new object
1087
 */
1088
1089
static enum req_fsm_nxt v_matchproto_(req_state_f)
1090 400
cnt_purge(struct worker *wrk, struct req *req)
1091
{
1092
        struct objcore *oc, *boc;
1093
        enum lookup_e lr;
1094
1095 400
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1096 400
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1097 400
        AZ(req->objcore);
1098 400
        AZ(req->stale_oc);
1099
1100 400
        AN(req->vcl);
1101
1102 400
        VRY_Prep(req);
1103
1104 400
        AZ(req->objcore);
1105 400
        req->hash_always_miss = 1;
1106 400
        lr = HSH_Lookup(req, &oc, &boc);
1107 400
        assert (lr == HSH_MISS);
1108 400
        AZ(oc);
1109 400
        CHECK_OBJ_NOTNULL(boc, OBJCORE_MAGIC);
1110 400
        VRY_Finish(req, DISCARD);
1111
1112 400
        (void)HSH_Purge(wrk, boc->objhead, req->t_req, 0, 0, 0);
1113
1114 400
        HSH_Withdraw(wrk, &boc);
1115
1116 400
        VCL_purge_method(req->vcl, wrk, req, NULL, NULL);
1117 400
        switch (wrk->vpi->handling) {
1118
        case VCL_RET_RESTART:
1119 120
                req->req_step = R_STP_RESTART;
1120 120
                break;
1121
        case VCL_RET_FAIL:
1122 40
                req->req_step = R_STP_VCLFAIL;
1123 40
                break;
1124
        case VCL_RET_SYNTH:
1125 240
                req->req_step = R_STP_SYNTH;
1126 240
                break;
1127
        default:
1128 0
                WRONG("Illegal return from vcl_purge{}");
1129 0
        }
1130 400
        return (REQ_FSM_MORE);
1131
}
1132
1133
/*--------------------------------------------------------------------
1134
 * Central state engine dispatcher.
1135
 *
1136
 * Kick the session around until it has had enough.
1137
 *
1138
 */
1139
1140
static void v_matchproto_(req_state_f)
1141 17869
cnt_diag(struct req *req, const char *state)
1142
{
1143
1144 17869
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1145
1146 35738
        VSLb(req->vsl,  SLT_Debug, "vxid %ju STP_%s sp %p vcl %p",
1147 17869
            VXID(req->vsl->wid), state, req->sp, req->vcl);
1148 17869
        VSL_Flush(req->vsl, 0);
1149 17869
}
1150
1151
void
1152 158616
CNT_Embark(struct worker *wrk, struct req *req)
1153
{
1154
1155 158616
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1156 158616
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1157
1158
        /* wrk can have changed for restarts */
1159 158616
        req->vfc->wrk = req->wrk = wrk;
1160 158616
        wrk->vsl = req->vsl;
1161 158616
        if (req->req_step == R_STP_TRANSPORT && req->vcl == NULL) {
1162 135964
                VCL_Refresh(&wrk->wpriv->vcl);
1163 135964
                req->vcl = wrk->wpriv->vcl;
1164 135964
                wrk->wpriv->vcl = NULL;
1165 135964
                VSLbs(req->vsl, SLT_VCL_use, TOSTRAND(VCL_Name(req->vcl)));
1166 135964
        }
1167
1168 158616
        AN(req->vcl);
1169 158616
}
1170
1171
enum req_fsm_nxt
1172 155738
CNT_Request(struct req *req)
1173
{
1174
        struct vrt_ctx ctx[1];
1175
        struct worker *wrk;
1176
        enum req_fsm_nxt nxt;
1177
1178 155738
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1179
1180 155738
        wrk = req->wrk;
1181 155738
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1182
1183 155738
        CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
1184 155738
        AN(req->transport->deliver);
1185 155738
        AN(req->transport->minimal_response);
1186
1187
        /*
1188
         * Possible entrance states
1189
         */
1190 155738
        assert(
1191
            req->req_step == R_STP_LOOKUP ||
1192
            req->req_step == R_STP_FINISH ||
1193
            req->req_step == R_STP_TRANSPORT);
1194
1195 155738
        AN(VXID_TAG(req->vsl->wid) & VSL_CLIENTMARKER);
1196 155738
        AN(req->vcl);
1197
1198 1202667
        for (nxt = REQ_FSM_MORE; nxt == REQ_FSM_MORE; ) {
1199
                /*
1200
                 * This is a good place to be paranoid about the various
1201
                 * pointers still pointing to the things we expect.
1202
                 */
1203 1046929
                CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1204 1046929
                CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
1205 1046929
                CHECK_OBJ_ORNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
1206 1046929
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1207 1046929
                CHECK_OBJ_NOTNULL(req->doclose, STREAM_CLOSE_MAGIC);
1208
1209 1046929
                AN(req->req_step);
1210 1046929
                AN(req->req_step->name);
1211 1046929
                AN(req->req_step->func);
1212 1046929
                if (DO_DEBUG(DBG_REQ_STATE))
1213 17869
                        cnt_diag(req, req->req_step->name);
1214 1046929
                nxt = req->req_step->func(wrk, req);
1215 1046929
                CHECK_OBJ_ORNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
1216
        }
1217 155738
        wrk->vsl = NULL;
1218 155738
        if (nxt == REQ_FSM_DONE) {
1219 150369
                INIT_OBJ(ctx, VRT_CTX_MAGIC);
1220 150369
                VCL_Req2Ctx(ctx, req);
1221 150369
                if (IS_TOPREQ(req)) {
1222 135727
                        VCL_TaskLeave(ctx, req->top->privs);
1223 135727
                        if (req->top->vcl0 != NULL)
1224 480
                                VCL_Recache(wrk, &req->top->vcl0);
1225 135727
                }
1226 150369
                VCL_TaskLeave(ctx, req->privs);
1227 150369
                assert(!IS_NO_VXID(req->vsl->wid));
1228 150369
                VRB_Free(req);
1229 150369
                VRT_Assign_Backend(&req->director_hint, NULL);
1230 150369
                req->wrk = NULL;
1231 150369
        }
1232 155738
        assert(nxt == REQ_FSM_DISEMBARK || !WS_IsReserved(req->ws));
1233 155738
        return (nxt);
1234
}