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