vinyl-cache/bin/vinyld/cache/cache_vrt_var.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 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
 * Runtime support for compiled VCL programs
31
 */
32
#include "config.h"
33
34
#include <stdio.h>
35
36
#include "cache_int.h"
37
#include "cache_objhead.h"
38
#include "cache_transport.h"
39
#include "storage/storage.h"
40
#include "common/heritage.h"
41
42
#include "vcl.h"
43
#include "vtim.h"
44
#include "vtcp.h"
45
46
#include "vrt_obj.h"
47
48
#define VRT_TMO(tmo) (isinf(tmo) ? VRT_DECIMAL_MAX : tmo)
49
50
static char vrt_hostname[255] = "";
51
const char *retry_disabled = "disabled from VCL";
52
53
/*--------------------------------------------------------------------
54
 * VRT variables relating to first line of HTTP/1.1 req/resp
55
 */
56
57
static void
58 300
vrt_do_strands(VRT_CTX, struct http *hp, int fld,
59
    const char *err, const char *str, VCL_STRANDS s)
60
{
61
        const char *b;
62
63 300
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
64
65 300
        b = VRT_StrandsWS(hp->ws, str, s);
66 300
        if (b == NULL) {
67 0
                VRT_fail(ctx, "Workspace overflow (%s)", err);
68 0
                WS_MarkOverflow(hp->ws);
69 0
                return;
70
        }
71 300
        if (*b == '\0') {
72 12
                VRT_fail(ctx, "Setting %s to empty string", err);
73 12
                return;
74
        }
75 288
        http_SetH(hp, fld, b);
76 300
}
77
78
#define VRT_HDR_L(obj, hdr, fld)                                        \
79
VCL_VOID                                                                \
80
VRT_l_##obj##_##hdr(VRT_CTX, const char *str, VCL_STRANDS s)            \
81
{                                                                       \
82
                                                                        \
83
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
84
        vrt_do_strands(ctx, ctx->http_##obj, fld, #obj "." #hdr, str, s);       \
85
}
86
87
#define VRT_HDR_R(obj, hdr, fld)                                        \
88
VCL_STRING                                                              \
89
VRT_r_##obj##_##hdr(VRT_CTX)                                            \
90
{                                                                       \
91
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
92
        CHECK_OBJ_NOTNULL(ctx->http_##obj, HTTP_MAGIC);                 \
93
        return (ctx->http_##obj->hd[fld].b);                            \
94
}
95
96
#define VRT_HDR_LR(obj, hdr, fld)                                       \
97
        VRT_HDR_L(obj, hdr, fld)                                        \
98
        VRT_HDR_R(obj, hdr, fld)
99
100
#define VRT_STATUS_L(obj)                                               \
101
VCL_VOID                                                                \
102
VRT_l_##obj##_status(VRT_CTX, VCL_INT num)                              \
103
{                                                                       \
104
                                                                        \
105
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
106
        CHECK_OBJ_NOTNULL(ctx->http_##obj, HTTP_MAGIC);                 \
107
        if (num < 0)                                                    \
108
                VRT_fail(ctx, "%s.status (%jd) is negative",            \
109
                    #obj, (intmax_t)num);                               \
110
        else if (num > 65535)                                           \
111
                VRT_fail(ctx, "%s.status (%jd) > 65535",                \
112
                    #obj, (intmax_t)num);                               \
113
        else if ((num % 1000) < 100)                                    \
114
                VRT_fail(ctx, "illegal %s.status (%jd) (..0##)",        \
115
                    #obj, (intmax_t)num);                               \
116
        else                                                            \
117
                http_SetStatus(ctx->http_##obj, (uint16_t)num, NULL);   \
118
}
119
120
#define VRT_STATUS_R(obj)                                               \
121
VCL_INT                                                                 \
122
VRT_r_##obj##_status(VRT_CTX)                                           \
123
{                                                                       \
124
                                                                        \
125
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
126
        CHECK_OBJ_NOTNULL(ctx->http_##obj, HTTP_MAGIC);                 \
127
        return (ctx->http_##obj->status);                               \
128
}
129
130 34065
VRT_HDR_LR(req,    method,      HTTP_HDR_METHOD)
131 40484
VRT_HDR_LR(req,    url,         HTTP_HDR_URL)
132 495
VRT_HDR_LR(req,    proto,       HTTP_HDR_PROTO)
133
134 16
VRT_HDR_R(req_top,    method,   HTTP_HDR_METHOD)
135 16
VRT_HDR_R(req_top,    url,      HTTP_HDR_URL)
136 16
VRT_HDR_R(req_top,    proto,    HTTP_HDR_PROTO)
137
138 16
VRT_HDR_LR(resp,   proto,       HTTP_HDR_PROTO)
139 5708
VRT_HDR_LR(resp,   reason,      HTTP_HDR_REASON)
140 180
VRT_STATUS_L(resp)
141 3916
VRT_STATUS_R(resp)
142
143 9516
VRT_HDR_LR(bereq,  method,      HTTP_HDR_METHOD)
144 2356
VRT_HDR_LR(bereq,  url,         HTTP_HDR_URL)
145 12
VRT_HDR_LR(bereq,  proto,       HTTP_HDR_PROTO)
146 8
VRT_HDR_LR(beresp, proto,       HTTP_HDR_PROTO)
147 3744
VRT_HDR_LR(beresp, reason,      HTTP_HDR_REASON)
148 496
VRT_STATUS_L(beresp)
149 18552
VRT_STATUS_R(beresp)
150
151
/*--------------------------------------------------------------------
152
 * beresp bool-fields
153
 */
154
155
static inline int
156 1516
beresp_filter_fixed(VRT_CTX, const char *s)
157
{
158 1516
        if (ctx->bo->vfp_filter_list == NULL)
159 1512
                return (0);
160 8
        VRT_fail(ctx,
161 4
            "beresp.filters are already fixed, beresp.%s is undefined", s);
162 4
        return (1);
163 1516
}
164
165
#define VBERESPWF0(ctx, str) (void) 0
166
#define VBERESPWF1(ctx, str) do {               \
167
        if (beresp_filter_fixed((ctx), str))    \
168
                return;                 \
169
        } while(0)
170
171
#define VBERESPW0(field, str, fltchk)
172
#define VBERESPW1(field, str, fltchk)                                   \
173
void                                                                    \
174
VRT_l_beresp_##field(VRT_CTX, VCL_BOOL a)                               \
175
{                                                                       \
176
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
177
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);                      \
178
        VBERESPWF##fltchk(ctx, str);                                    \
179
        ctx->bo->field = a ? 1 : 0;                                     \
180
}
181
182
#define VBERESPRF0(ctx, str) (void) 0
183
#define VBERESPRF1(ctx, str) do {               \
184
        if (beresp_filter_fixed((ctx), str))    \
185
                return (0);                     \
186
        } while(0)
187
188
#define VBERESPR1(field, str, fltchk)                                   \
189
VCL_BOOL                                                                \
190
VRT_r_beresp_##field(VRT_CTX)                                           \
191
{                                                                       \
192
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
193
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);                      \
194
        VBERESPRF##fltchk(ctx, str);                                    \
195
        return (ctx->bo->field);                                        \
196
}
197
198
#define BERESP_FLAG(l, r, w, f, d)              \
199
        VBERESPR##r(l, #l, f)                   \
200
        VBERESPW##w(l, #l, f)
201
#include "tbl/beresp_flags.h"
202
203
#undef VBERESPWF0
204
#undef VBERESPWF1
205
#undef VBERESPW0
206
#undef VBERESPW1
207
208
#undef VBERESPRF0
209
#undef VBERESPRF1
210
#undef VBERESPR1
211
212
/*--------------------------------------------------------------------
213
 * bereq bool-fields
214
 *
215
 * for macro compatiblity with the client side, r is "req" for bereq
216
 */
217
218
#define VBEREQR0(field, str)
219
#define VBEREQRreq(field, str)                                          \
220
VCL_BOOL                                                                \
221
VRT_r_bereq_##field(VRT_CTX)                                            \
222
{                                                                       \
223
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
224
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);                      \
225
        return (ctx->bo->field);                                        \
226
}
227
228
#define BEREQ_FLAG(l, r, w, d)          \
229
        VBEREQR##r(l, #l)
230
#include "tbl/bereq_flags.h"
231
232
#undef VBEREQR0
233
#undef VBEREQRreq
234
/*--------------------------------------------------------------------*/
235
236
VCL_BOOL
237 8008
VRT_r_bereq_uncacheable(VRT_CTX)
238
{
239 8008
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
240 8008
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
241 8008
        return (ctx->bo->uncacheable);
242
}
243
244
VCL_VOID
245 380
VRT_l_beresp_uncacheable(VRT_CTX, VCL_BOOL a)
246
{
247
        struct objcore *oc;
248
249 380
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
250 380
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
251 380
        CHECK_OBJ_NOTNULL(ctx->bo->fetch_objcore, OBJCORE_MAGIC);
252
253 380
        if (ctx->bo->uncacheable && !a) {
254 0
                VSLb(ctx->vsl, SLT_VCL_Error,
255
                    "Ignoring attempt to reset beresp.uncacheable");
256 380
        } else if (a) {
257 376
                ctx->bo->uncacheable = 1;
258 376
        }
259 380
        oc = ctx->bo->fetch_objcore;
260
261 760
        VSLb(ctx->vsl, SLT_TTL, "VCL %.0f %.0f %.0f %.0f %s",   \
262 380
            oc->ttl, oc->grace, oc->keep, oc->t_origin,         \
263 760
            ctx->bo->uncacheable ? "uncacheable" : "cacheable");\
264
}
265
266
VCL_BOOL
267 4
VRT_r_beresp_uncacheable(VRT_CTX)
268
{
269 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
270 4
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
271 4
        return (ctx->bo->uncacheable);
272
}
273
274
VCL_VOID
275 4
VRT_l_req_trace(VRT_CTX, VCL_BOOL a)
276
{
277 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
278 4
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
279 4
        ctx->req->trace = a;
280 4
        VRT_trace(ctx, a);
281 4
}
282
VCL_VOID
283 0
VRT_l_bereq_trace(VRT_CTX, VCL_BOOL a)
284
{
285 0
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
286 0
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
287 0
        ctx->bo->trace = a;
288 0
        VRT_trace(ctx, a);
289 0
}
290
291
/*--------------------------------------------------------------------*/
292
293
VCL_BYTES
294 0
VRT_r_beresp_transit_buffer(VRT_CTX)
295
{
296
    struct objcore *oc;
297
298 0
    CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
299 0
    CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
300
301 0
    oc = ctx->bo->fetch_objcore;
302 0
    CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
303
304 0
    return oc->boc->transit_buffer;
305
}
306
307
VCL_VOID
308 8
VRT_l_beresp_transit_buffer(VRT_CTX, VCL_BYTES value)
309
{
310
    struct objcore *oc;
311
312 8
    CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
313 8
    CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
314
315 8
    oc = ctx->bo->fetch_objcore;
316 8
    CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
317
318 8
    oc->boc->transit_buffer = value;
319 8
}
320
321
/*--------------------------------------------------------------------*/
322
323
VCL_STRING
324 24
VRT_r_client_identity(VRT_CTX)
325
{
326
        const char *id;
327
328 24
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
329 24
        if (ctx->req != NULL) {
330 16
                CHECK_OBJ(ctx->req, REQ_MAGIC);
331 16
                id = ctx->req->client_identity;
332 16
        } else {
333 8
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
334 8
                id = ctx->bo->client_identity;
335
        }
336 24
        if (id != NULL)
337 16
                return (id);
338 8
        return (SES_Get_String_Attr(ctx->sp, SA_CLIENT_IP));
339 24
}
340
341
VCL_VOID
342 12
VRT_l_client_identity(VRT_CTX, const char *str, VCL_STRANDS s)
343
{
344
        const char *b;
345
346 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
347 12
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
348 12
        b = VRT_StrandsWS(ctx->req->http->ws, str, s);
349 12
        if (b == NULL) {
350 0
                VSLb(ctx->vsl, SLT_LostHeader, "client.identity");
351 0
                WS_MarkOverflow(ctx->req->http->ws);
352 0
                return;
353
        }
354 12
        ctx->req->client_identity = b;
355 12
}
356
357
/*--------------------------------------------------------------------*/
358
359
#define BEREQ_TIMEOUT(prefix, which)                            \
360
VCL_VOID                                                        \
361
VRT_l_bereq_##which(VRT_CTX, VCL_DURATION num)                  \
362
{                                                               \
363
                                                                \
364
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
365
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);              \
366
        ctx->bo->which = num;                                   \
367
}                                                               \
368
                                                                \
369
VCL_DURATION                                                    \
370
VRT_r_bereq_##which(VRT_CTX)                                    \
371
{                                                               \
372
        vtim_dur res;                                           \
373
                                                                \
374
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
375
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);              \
376
        res = BUSYOBJ_TMO(ctx->bo, prefix, which);              \
377
        return (VRT_TMO(res));                                  \
378
}                                                               \
379
                                                                \
380
VCL_VOID                                                        \
381
VRT_u_bereq_##which(VRT_CTX)                                    \
382
{                                                               \
383
                                                                \
384
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
385
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);              \
386
        ctx->bo->which = NAN;                                   \
387
}
388
389 28
BEREQ_TIMEOUT(, connect_timeout)
390 36
BEREQ_TIMEOUT(, first_byte_timeout)
391 56
BEREQ_TIMEOUT(, between_bytes_timeout)
392 36
BEREQ_TIMEOUT(pipe_, task_deadline)
393
394
395
/*--------------------------------------------------------------------*/
396
397
VCL_STRING
398 4
VRT_r_beresp_backend_name(VRT_CTX)
399
{
400
401 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
402 4
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
403 4
        if (ctx->bo->director_resp != NULL)
404 4
                return (ctx->bo->director_resp->vcl_name);
405 0
        return (NULL);
406 4
}
407
408
/*--------------------------------------------------------------------
409
 * Backends do not in general have a IP number (any more) and this
410
 * variable is really not about the backend, but the backend connection.
411
 * XXX: we may need a more general beresp.backend.{details|ident}
412
 */
413
414
VCL_IP
415 4
VRT_r_beresp_backend_ip(VRT_CTX)
416
{
417
418 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
419 4
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
420 4
        return (VDI_GetIP(ctx->bo));
421
}
422
423
/*--------------------------------------------------------------------*/
424
425
VCL_STEVEDORE
426 4
VRT_r_req_storage(VRT_CTX)
427
{
428 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
429 4
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
430 4
        return (ctx->req->storage);
431
}
432
433
VCL_VOID
434 28
VRT_l_req_storage(VRT_CTX, VCL_STEVEDORE stv)
435
{
436 28
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
437 28
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
438 28
        ctx->req->storage = stv;
439 28
}
440
441
/*--------------------------------------------------------------------*/
442
443
VCL_STEVEDORE
444 12
VRT_r_resp_storage(VRT_CTX)
445
{
446
        struct objcore *oc;
447
448 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
449 12
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
450 12
        oc = ctx->req->objcore;
451 12
        if (oc == NULL)
452 4
                VRT_l_resp_storage(ctx, NULL);
453 12
        oc = ctx->req->objcore;
454 12
        if (oc == NULL)
455 4
                return (NULL);
456 8
        CHECK_OBJ(oc, OBJCORE_MAGIC);
457 8
        return (oc->stobj->stevedore);
458 12
}
459
460
VCL_VOID
461 2020
VRT_l_resp_storage(VRT_CTX, VCL_STEVEDORE stv)
462
{
463
464 2020
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
465 2020
        if (stv == NULL)
466 2004
                stv = stv_synth;
467 2020
        if (! Resp_l_storage(ctx->req, stv))
468 4
                VRT_fail(ctx, "Storage %s failed", stv->vclname);
469 2020
}
470
471
/*--------------------------------------------------------------------*/
472
473
VCL_STEVEDORE
474 36
VRT_r_beresp_storage(VRT_CTX)
475
{
476 36
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
477 36
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
478 36
        return (ctx->bo->storage);
479
}
480
481
VCL_VOID
482 104
VRT_l_beresp_storage(VRT_CTX, VCL_STEVEDORE stv)
483
{
484 104
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
485 104
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
486 104
        ctx->bo->storage = stv;
487 104
}
488
489
/*--------------------------------------------------------------------*/
490
491
#define VRT_OC_VAR_R(obj, which, which_magic, field)            \
492
VCL_STEVEDORE                                                   \
493
VRT_r_##obj##_storage(VRT_CTX)                                  \
494
{                                                               \
495
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
496
        CHECK_OBJ_NOTNULL(ctx->which, which_magic);             \
497
        CHECK_OBJ_NOTNULL(ctx->which->field, OBJCORE_MAGIC);    \
498
        AN(ctx->which->field->stobj);                           \
499
        CHECK_OBJ_NOTNULL(ctx->which->field->stobj->stevedore,  \
500
            STEVEDORE_MAGIC);                                   \
501
        return (ctx->which->field->stobj->stevedore);           \
502
}                                                               \
503
                                                                \
504
VCL_BOOL                                                        \
505
VRT_r_##obj##_can_esi(VRT_CTX)                                  \
506
{                                                               \
507
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
508
        CHECK_OBJ_NOTNULL(ctx->which, which_magic);             \
509
        CHECK_OBJ_NOTNULL(ctx->which->field, OBJCORE_MAGIC);    \
510
        return (ObjHasAttr(ctx->which->wrk, ctx->which->field,  \
511
            OA_ESIDATA));                                       \
512
}                                                               \
513
                                                                \
514
VCL_BOOL                                                        \
515
VRT_r_##obj##_uncacheable(VRT_CTX)                              \
516
{                                                               \
517
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
518
        CHECK_OBJ_NOTNULL(ctx->which, which_magic);             \
519
        CHECK_OBJ_NOTNULL(ctx->which->field, OBJCORE_MAGIC);    \
520
                                                                \
521
        return (ctx->which->field->flags & OC_F_HFM ? 1 : 0);   \
522
}                                                               \
523
                                                                \
524
VCL_INT                                                         \
525
VRT_r_##obj##_status(VRT_CTX)                                   \
526
{                                                               \
527
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
528
        CHECK_OBJ_NOTNULL(ctx->which, which_magic);             \
529
        CHECK_OBJ_NOTNULL(ctx->which->field, OBJCORE_MAGIC);    \
530
                                                                \
531
        return (HTTP_GetStatusPack(ctx->which->wrk,             \
532
            ctx->which->field));                                \
533
}                                                               \
534
                                                                \
535
VCL_STRING                                                      \
536
VRT_r_##obj##_proto(VRT_CTX)                                    \
537
{                                                               \
538
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
539
        CHECK_OBJ_NOTNULL(ctx->which, which_magic);             \
540
        CHECK_OBJ_NOTNULL(ctx->which->field, OBJCORE_MAGIC);    \
541
                                                                \
542
        return (HTTP_GetHdrPack(ctx->which->wrk,                \
543
            ctx->which->field, H__Proto));                      \
544
}                                                               \
545
                                                                \
546
VCL_STRING                                                      \
547
VRT_r_##obj##_reason(VRT_CTX)                                   \
548
{                                                               \
549
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
550
        CHECK_OBJ_NOTNULL(ctx->which, which_magic);             \
551
        CHECK_OBJ_NOTNULL(ctx->which->field, OBJCORE_MAGIC);    \
552
                                                                \
553
        return (HTTP_GetHdrPack(ctx->which->wrk,                \
554
            ctx->which->field, H__Reason));                     \
555
}
556
557 88
VRT_OC_VAR_R(obj, req, REQ_MAGIC, objcore)
558 152
VRT_OC_VAR_R(obj_stale, bo, BUSYOBJ_MAGIC, stale_oc)
559
560
/*--------------------------------------------------------------------*/
561
562
#define REQ_VAR_L(nm, elem, type, extra)                                \
563
                                                                        \
564
VCL_VOID                                                                \
565
VRT_l_req_##nm(VRT_CTX, type arg)                                       \
566
{                                                                       \
567
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
568
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
569
        extra;                                                          \
570
        ctx->req->elem = arg;                                           \
571
}
572
573
#define REQ_VAR_R(nm, elem, type)                                       \
574
                                                                        \
575
type                                                                    \
576
VRT_r_req_##nm(VRT_CTX)                                                 \
577
{                                                                       \
578
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
579
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
580
        return (ctx->req->elem);                                        \
581
}
582
583
#define REQ_VAR_U(nm, elem, val)                                        \
584
                                                                        \
585
VCL_VOID                                                                \
586
VRT_u_req_##nm(VRT_CTX)                                                 \
587
{                                                                       \
588
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
589
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
590
        ctx->req->elem = val;                                           \
591
}
592
593 64
REQ_VAR_R(backend_hint, director_hint, VCL_BACKEND)
594
595 41
REQ_VAR_L(max_age, d_ttl, VCL_DURATION, if (!(arg>0.0)) arg = 0;)
596 24
REQ_VAR_R(max_age, d_ttl, VCL_DURATION)
597 0
REQ_VAR_U(max_age, d_ttl, -1)
598 12
REQ_VAR_L(grace, d_grace, VCL_DURATION, if (!(arg>0.0)) arg = 0;)
599 36
REQ_VAR_R(grace, d_grace, VCL_DURATION)
600 4
REQ_VAR_U(grace, d_grace, -1)
601
602
// deprecated, to be removed
603 0
VCL_VOID VRT_l_req_ttl(VRT_CTX, VCL_DURATION arg) { VRT_l_req_max_age(ctx, arg); }
604 0
VCL_DURATION VRT_r_req_ttl(VRT_CTX) { return (VRT_r_req_max_age(ctx)); }
605 0
VCL_VOID VRT_u_req_ttl(VRT_CTX) { VRT_u_req_max_age(ctx); }
606
607
VCL_VOID
608 596
VRT_l_req_backend_hint(VRT_CTX, VCL_BACKEND be)
609
{
610
611 596
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
612 596
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
613 596
        VRT_Assign_Backend(&ctx->req->director_hint, be);
614 596
}
615
616
/*--------------------------------------------------------------------*/
617
618
VCL_VOID
619 1080
VRT_l_bereq_backend(VRT_CTX, VCL_BACKEND be)
620
{
621
622 1080
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
623 1080
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
624 1080
        VRT_Assign_Backend(&ctx->bo->director_req, be);
625 1080
}
626
627
VCL_BACKEND
628 184
VRT_r_bereq_backend(VRT_CTX)
629
{
630
631 184
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
632 184
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
633 184
        return (ctx->bo->director_req);
634
}
635
636
VCL_BACKEND
637 156
VRT_r_beresp_backend(VRT_CTX)
638
{
639
640 156
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
641 156
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
642 156
        return (ctx->bo->director_resp);
643
}
644
645
/*--------------------------------------------------------------------*/
646
647
VCL_VOID
648 9004
VRT_u_bereq_body(VRT_CTX)
649
{
650 9004
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
651 9004
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
652
653 9004
        http_Unset(ctx->bo->bereq, H_Content_Length);
654
655 9004
        if (ctx->bo->bereq_body != NULL)
656 20
                (void)HSH_DerefObjCore(ctx->bo->wrk, &ctx->bo->bereq_body);
657
658 9004
        if (ctx->bo->req != NULL) {
659 32
                CHECK_OBJ(ctx->bo->req, REQ_MAGIC);
660 32
                VBO_SetState(ctx->bo->wrk, ctx->bo, BOS_REQ_DONE);
661 32
                AZ(ctx->bo->req);
662 32
        }
663 9004
}
664
665
/*--------------------------------------------------------------------*/
666
667
VCL_VOID
668 44
VRT_l_req_esi(VRT_CTX, VCL_BOOL process_esi)
669
{
670
671 44
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
672 44
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
673 44
        assert(ctx->syntax <= 40);
674
        /*
675
         * Only allow you to turn of esi in the main request
676
         * else everything gets confused
677
         * NOTE: this is not true, but we do not change behavior
678
         * for vcl 4.0. For 4.1, see VRT_l_resp_do_esi()
679
         */
680 44
        if (IS_TOPREQ(ctx->req))
681 28
                ctx->req->disable_esi = !process_esi;
682 44
}
683
684
VCL_BOOL
685 12
VRT_r_req_esi(VRT_CTX)
686
{
687
688 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
689 12
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
690 12
        assert(ctx->syntax <= 40);
691 12
        return (!ctx->req->disable_esi);
692
}
693
694
VCL_INT
695 922
VRT_r_req_esi_level(VRT_CTX)
696
{
697
698 922
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
699 922
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
700 922
        return (ctx->req->esi_level);
701
}
702
703
/*--------------------------------------------------------------------*/
704
705
VCL_BOOL
706 32
VRT_r_req_can_gzip(VRT_CTX)
707
{
708
709 32
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
710 32
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
711 32
        return (RFC2616_Req_Gzip(ctx->req->http));      // XXX ?
712
}
713
714
/*--------------------------------------------------------------------*/
715
716
VCL_INT
717 581
VRT_r_req_restarts(VRT_CTX)
718
{
719
720 581
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
721 581
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
722 581
        return (ctx->req->restarts);
723
}
724
725
VCL_INT
726 268
VRT_r_bereq_retries(VRT_CTX)
727
{
728
729 268
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
730 268
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
731 268
        return (ctx->bo->retries);
732
}
733
734
VCL_VOID
735 28
VRT_l_bereq_retry_connect(VRT_CTX, VCL_BOOL b)
736
{
737
738 28
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
739 28
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
740
741 28
        if (!b && ctx->bo->no_retry == NULL)
742 16
                ctx->bo->no_retry = retry_disabled;
743 12
        else if (b && ctx->bo->no_retry == retry_disabled)
744 0
                ctx->bo->no_retry = NULL;
745 28
}
746
747
VCL_BOOL
748 0
VRT_r_bereq_retry_connect(VRT_CTX)
749
{
750
751 0
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
752 0
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
753 0
        return (ctx->bo->no_retry == NULL);
754
}
755
756
/*--------------------------------------------------------------------*/
757
758
VCL_STRING
759 68
VRT_r_req_transport(VRT_CTX)
760
{
761 68
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
762
763 68
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
764 68
        CHECK_OBJ_NOTNULL(ctx->req->transport, TRANSPORT_MAGIC);
765 68
        return (ctx->req->transport->name);
766
}
767
768
/*--------------------------------------------------------------------
769
 * In exp.*:
770
 *      t_origin is absolute
771
 *      ttl is relative to t_origin
772
 *      grace&keep are relative to ttl
773
 * In VCL:
774
 *      ttl is relative to "ttl_now", which is t_req on the client
775
 *      side, except in vcl_deliver, where it is ctx->now. On the
776
 *      fetch side "ttl_now" is ctx->now (which is bo->t_prev).
777
 *      grace&keep are relative to ttl
778
 */
779
780
static double
781 6424
ttl_now(VRT_CTX)
782
{
783 6424
        if (ctx->bo) {
784 6312
                return (ctx->now);
785
        } else {
786 112
                CHECK_OBJ(ctx->req, REQ_MAGIC);
787 112
                return (ctx->method == VCL_MET_DELIVER
788 112
                    ? ctx->now : ctx->req->t_req);
789
        }
790 6424
}
791
792
#define VRT_DO_EXP_L(which, oc, fld, offset)                    \
793
                                                                \
794
VCL_VOID                                                        \
795
VRT_l_##which##_##fld(VRT_CTX, VCL_DURATION a)                  \
796
{                                                               \
797
                                                                \
798
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
799
        a += (offset);                                          \
800
        if (a < 0.0)                                            \
801
                a = 0.0;                                        \
802
        oc->fld = a;                                            \
803
        VSLb(ctx->vsl, SLT_TTL, "VCL %.0f %.0f %.0f %.0f %s",   \
804
            oc->ttl, oc->grace, oc->keep, oc->t_origin,         \
805
            ctx->bo->uncacheable ? "uncacheable" : "cacheable");\
806
}
807
808
#define VRT_DO_EXP_R(which, oc, fld, offset)                    \
809
                                                                \
810
VCL_DURATION                                                    \
811
VRT_r_##which##_##fld(VRT_CTX)                                  \
812
{                                                               \
813
        double d;                                               \
814
                                                                \
815
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
816
        d = oc->fld;                                            \
817
        if (d <= 0.0)                                           \
818
                d = 0.0;                                        \
819
        d -= (offset);                                          \
820
        return (d);                                             \
821
}
822
823
/*lint -save -e835 */   // Zero right hand arg to '-'
824
825 4
VRT_DO_EXP_R(obj_stale, ctx->bo->stale_oc, ttl,
826
    ttl_now(ctx) - ctx->bo->stale_oc->t_origin)
827 80
VRT_DO_EXP_R(obj, ctx->req->objcore, ttl,
828
    ttl_now(ctx) - ctx->req->objcore->t_origin)
829 4
VRT_DO_EXP_R(obj_stale, ctx->bo->stale_oc, grace, 0)
830 40
VRT_DO_EXP_R(obj, ctx->req->objcore, grace, 0)
831 4
VRT_DO_EXP_R(obj_stale, ctx->bo->stale_oc, keep, 0)
832 28
VRT_DO_EXP_R(obj, ctx->req->objcore, keep, 0)
833 1056
VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore, ttl,
834
    ttl_now(ctx) - ctx->bo->fetch_objcore->t_origin)
835 5244
VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore, ttl,
836
    ttl_now(ctx) - ctx->bo->fetch_objcore->t_origin)
837
838 536
VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore, grace, 0)
839 24
VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore, grace, 0)
840 328
VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore, keep, 0)
841 4
VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore, keep, 0)
842
843
/*lint -restore */
844
845
// XXX more assertions?
846
#define VRT_DO_TIME_R(which, where, field)                              \
847
                                                                        \
848
VCL_TIME                                                                \
849
VRT_r_##which##_time(VRT_CTX)                                           \
850
{                                                                       \
851
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
852
        AN((ctx)->where);                                               \
853
                                                                        \
854
        return ((ctx)->where->field);                                   \
855
}
856
857 36
VRT_DO_TIME_R(req, req, t_req)
858 16
VRT_DO_TIME_R(req_top, req->top->topreq, t_req)
859 16
VRT_DO_TIME_R(resp, req, t_resp)
860 24
VRT_DO_TIME_R(bereq, bo, t_first)
861 8
VRT_DO_TIME_R(beresp, bo, t_resp)
862 8
VRT_DO_TIME_R(obj, req->objcore, t_origin)
863 4
VRT_DO_TIME_R(obj_stale, bo->stale_oc, t_origin)
864
865
/*--------------------------------------------------------------------
866
 */
867
868
#define VRT_DO_AGE_R(which, oc)                                 \
869
                                                                \
870
VCL_DURATION                                                    \
871
VRT_r_##which##_##age(VRT_CTX)                                  \
872
{                                                               \
873
                                                                \
874
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
875
        return (ttl_now(ctx) - oc->t_origin);                   \
876
}
877
878 4
VRT_DO_AGE_R(obj_stale, ctx->bo->stale_oc)
879 32
VRT_DO_AGE_R(obj, ctx->req->objcore)
880 4
VRT_DO_AGE_R(beresp, ctx->bo->fetch_objcore)
881
882
/*--------------------------------------------------------------------
883
 * [[be]req|sess].xid
884
 */
885
886
VCL_INT
887 2704
VRT_r_req_xid(VRT_CTX)
888
{
889
890 2704
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
891 2704
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
892 2704
        CHECK_OBJ_NOTNULL(ctx->req->http, HTTP_MAGIC);
893 2704
        AN(ctx->req->vsl);
894 2704
        return (VXID(ctx->req->vsl->wid));
895
}
896
897
VCL_INT
898 2244
VRT_r_bereq_xid(VRT_CTX)
899
{
900
901 2244
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
902 2244
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
903 2244
        AN(ctx->bo->vsl);
904
905 2244
        return (VXID(ctx->bo->vsl->wid));
906
}
907
908
VCL_INT
909 28
VRT_r_sess_xid(VRT_CTX)
910
{
911
        struct sess *sp;
912
913 28
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
914
915 28
        if (ctx->req) {
916 16
                CHECK_OBJ(ctx->req, REQ_MAGIC);
917 16
                sp = ctx->req->sp;
918 16
        } else {
919 12
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
920 12
                sp = ctx->bo->sp;
921
        }
922
923 28
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
924 28
        return (VXID(sp->vxid));
925
}
926
927
/*--------------------------------------------------------------------
928
 * req/resp fields, both stored in struct req
929
 */
930
931
#define VREQW(where, field)                                             \
932
VCL_VOID                                                                \
933
VRT_l_##where##_##field(VRT_CTX, VCL_BOOL a)                            \
934
{                                                                       \
935
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
936
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
937
        ctx->req->field = a ? 1 : 0;                                    \
938
}
939
940
#define VREQR(where, field)                                             \
941
VCL_BOOL                                                                \
942
VRT_r_##where##_##field(VRT_CTX)                                        \
943
{                                                                       \
944
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
945
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
946
        return (ctx->req->field);                                       \
947
}
948
949
#define VREQW0(field)
950
#define VREQR0(field)
951
#define VREQWreq(field)         VREQW(req, field)
952
#define VREQRreq(field)         VREQR(req, field)
953
#define VREQWresp(field)        VREQW(resp, field)
954
#define VREQRresp(field)        VREQR(resp, field)
955
956
#define REQ_FLAG(l, r, w, d) \
957
        VREQR##r(l) \
958
        VREQW##w(l)
959
#include "tbl/req_flags.h"
960
961
#undef VREQW
962
#undef VREQR
963
#undef VREQW0
964
#undef VREQR0
965
#undef VREQWreq
966
#undef VREQRreq
967
#undef VREQWresp
968
#undef VREQRresp
969
970
971
/*--------------------------------------------------------------------*/
972
973
#define GIP(fld)                                                \
974
        VCL_IP                                                  \
975
        VRT_r_##fld##_ip(VRT_CTX)                               \
976
        {                                                       \
977
                struct suckaddr *sa;                            \
978
                                                                \
979
                CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
980
                CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC);         \
981
                AZ(SES_Get_##fld##_addr(ctx->sp, &sa));         \
982
                return (sa);                                    \
983
        }
984
985 200
GIP(local)
986 204
GIP(remote)
987 416
GIP(client)
988 865
GIP(server)
989
#undef GIP
990
991
/*--------------------------------------------------------------------
992
 * local.[endpoint|socket]
993
 */
994
995
#define LOC(var,fld)                                            \
996
VCL_STRING                                                      \
997
VRT_r_local_##var(VRT_CTX)                                      \
998
{                                                               \
999
        struct sess *sp;                                        \
1000
                                                                \
1001
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
1002
        if (ctx->req) {                                         \
1003
                CHECK_OBJ(ctx->req, REQ_MAGIC);                 \
1004
                sp = ctx->req->sp;                              \
1005
        } else {                                                \
1006
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);      \
1007
                sp = ctx->bo->sp;                               \
1008
        }                                                       \
1009
                                                                \
1010
        CHECK_OBJ_NOTNULL(sp->listen_sock, LISTEN_SOCK_MAGIC);  \
1011
        AN(sp->listen_sock->fld);                               \
1012
        return (sp->listen_sock->fld);                          \
1013
}
1014
1015 28
LOC(endpoint, endpoint)
1016 28
LOC(socket, name)
1017
#undef LOC
1018
1019
/*--------------------------------------------------------------------*/
1020
1021
VCL_STRING
1022 40
VRT_r_server_identity(VRT_CTX)
1023
{
1024
1025 40
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1026 40
        if (heritage.identity != NULL)
1027 40
                return (heritage.identity);
1028
        else
1029 0
                return ("vinyld");
1030 40
}
1031
1032
VCL_STRING
1033 12
VRT_r_server_hostname(VRT_CTX)
1034
{
1035
1036 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1037 12
        if (vrt_hostname[0] == '\0')
1038 8
                AZ(gethostname(vrt_hostname, sizeof(vrt_hostname)));
1039 12
        return (vrt_hostname);
1040
}
1041
1042
/*--------------------------------------------------------------------*/
1043
1044
VCL_INT
1045 352
VRT_r_obj_hits(VRT_CTX)
1046
{
1047 352
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1048 352
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
1049 352
        CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
1050 352
        if (ctx->method == VCL_MET_HIT)
1051 8
                return (ctx->req->objcore->hits);
1052 344
        return (ctx->req->is_hit ? ctx->req->objcore->hits : 0);
1053 352
}
1054
1055
/*--------------------------------------------------------------------*/
1056
1057
VCL_INT
1058 4
VRT_r_obj_stale_hits(VRT_CTX)
1059
{
1060 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1061 4
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
1062 4
        CHECK_OBJ_NOTNULL(ctx->bo->stale_oc, OBJCORE_MAGIC);
1063
1064 4
        return (ctx->bo->stale_oc->hits);
1065
}
1066
1067
VCL_BOOL
1068 156
VRT_r_obj_stale_is_valid(VRT_CTX)
1069
{
1070 156
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1071 156
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
1072 156
        CHECK_OBJ_NOTNULL(ctx->bo->stale_oc, OBJCORE_MAGIC);
1073
1074 156
        return (!(ctx->bo->stale_oc->flags & OC_F_DYING));
1075
}
1076
1077
/*--------------------------------------------------------------------*/
1078
1079
VCL_BOOL
1080 20
VRT_r_resp_is_streaming(VRT_CTX)
1081
{
1082 20
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1083 20
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
1084 20
        if (ctx->req->objcore == NULL)
1085 4
                return (0);     /* When called from vcl_synth */
1086 16
        CHECK_OBJ(ctx->req->objcore, OBJCORE_MAGIC);
1087 16
        return (ctx->req->objcore->boc == NULL ? 0 : 1);
1088 20
}
1089
1090
/*--------------------------------------------------------------------*/
1091
1092
static inline int
1093 56
resp_filter_fixed(VRT_CTX, const char *s)
1094
{
1095 56
        if (ctx->req->vdp_filter_list == NULL)
1096 52
                return (0);
1097 4
        VRT_fail(ctx, "resp.filters are already fixed, %s is undefined", s);
1098 4
        return (1);
1099 56
}
1100
1101
VCL_VOID
1102 20
VRT_l_resp_do_esi(VRT_CTX, VCL_BOOL process_esi)
1103
{
1104
1105 20
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1106 20
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
1107 20
        assert(ctx->syntax >= 41);
1108 20
        if (resp_filter_fixed(ctx, "resp.do_esi"))
1109 4
                return;
1110 16
        ctx->req->disable_esi = !process_esi;
1111 20
}
1112
1113
VCL_BOOL
1114 36
VRT_r_resp_do_esi(VRT_CTX)
1115
{
1116
1117 36
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1118 36
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
1119 36
        assert(ctx->syntax >= 41);
1120 36
        if (resp_filter_fixed(ctx, "resp.do_esi"))
1121 0
                return (0);
1122 36
        return (!ctx->req->disable_esi);
1123 36
}
1124
1125
/*--------------------------------------------------------------------*/
1126
1127
#define VRT_BODY_L(which)                                       \
1128
VCL_VOID                                                        \
1129
VRT_l_##which##_body(VRT_CTX, enum lbody_e type,                \
1130
    const char *str, VCL_BODY body)                             \
1131
{                                                               \
1132
        int n;                                                  \
1133
        struct vsb *vsb;                                        \
1134
        VCL_STRANDS s;                                          \
1135
        VCL_BLOB b;                                             \
1136
                                                                \
1137
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
1138
        AN(body);                                               \
1139
        CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);        \
1140
        if (type == LBODY_SET_STRING || type == LBODY_SET_BLOB) \
1141
                VSB_clear(vsb);                                 \
1142
        if (type == LBODY_SET_BLOB || type == LBODY_ADD_BLOB) { \
1143
                AZ(str);                                        \
1144
                b = body;                                       \
1145
                CHECK_OBJ_NOTNULL(b, VRT_BLOB_MAGIC);           \
1146
                VSB_bcat(vsb, b->blob, b->len);                 \
1147
                return;                                         \
1148
        }                                                       \
1149
        if (str != NULL)                                        \
1150
                VSB_cat(vsb, str);                              \
1151
        assert(type == LBODY_SET_STRING ||                      \
1152
            type == LBODY_ADD_STRING);                          \
1153
        s = body;                                               \
1154
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);                    \
1155
        for (n = 0; s != NULL && n < s->n; n++)                 \
1156
                if (s->p[n] != NULL)                            \
1157
                        VSB_cat(vsb, s->p[n]);                  \
1158
}
1159
1160 17412
VRT_BODY_L(beresp)
1161 16
static VRT_BODY_L(resp_vsb)
1162
1163
VCL_VOID
1164 2024
VRT_l_resp_body(VRT_CTX, enum lbody_e type,
1165
    const char *str, VCL_BODY body)
1166
{
1167
        struct vscarab *scarab;
1168
        struct viov *viov;
1169
        struct req *req;
1170 2024
        ssize_t sz = 0;
1171
        VCL_STRANDS s;
1172
        VCL_BLOB b;
1173
        int n;
1174
1175
1176 2024
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1177 2024
        AN(body);
1178 2024
        req = ctx->req;
1179 2024
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
1180
1181 2024
        if (req->objcore == NULL)
1182 2000
                VRT_l_resp_storage(ctx, NULL);
1183 24
        else if (type == LBODY_SET_STRING || type == LBODY_SET_BLOB)
1184 12
                VRT_l_resp_storage(ctx, req->objcore->stobj->stevedore);
1185 2024
        if (req->objcore == NULL)
1186 0
                return;
1187
1188 2024
        AN(req->objcore->stobj->stevedore);
1189 2024
        if (req->objcore->stobj->stevedore->allocobj != ssy_stevedore.allocobj) {
1190 4
                VRT_l_resp_vsb_body(ctx, type, str, body);
1191 4
                return;
1192
        }
1193
1194 2020
        if (! ObjGetSpace(req->wrk, req->objcore, &sz, (uint8_t **)(void*)&scarab)) {
1195 0
                VRT_fail(ctx, "Synth storage failed");
1196 0
                return;
1197
        }
1198
1199 2020
        VSCARAB_CHECK_NOTNULL(scarab);
1200
1201 2020
        if (type == LBODY_SET_BLOB || type == LBODY_ADD_BLOB) {
1202 24
                AZ(str);
1203 24
                b = body;
1204 24
                viov = VSCARAB_GET(scarab);
1205 24
                AN(viov);       // ObjGetSpace ensures
1206 24
                viov->iov.iov_base = TRUST_ME(b->blob);
1207 24
                viov->iov.iov_len = b->len;
1208 24
                return;
1209
        }
1210 1996
        if (str != NULL) {
1211 0
                viov = VSCARAB_GET(scarab);
1212 0
                AN(viov);       // ObjGetSpace ensures
1213 0
                viov->iov.iov_base = TRUST_ME(str);
1214 0
                viov->iov.iov_len = vstrlen(str);
1215 0
        }
1216
1217 1996
        s = body;
1218 26524
        for (n = 0; s != NULL && n < s->n; n++) {
1219 24528
                if (s->p[n] == NULL || *s->p[n] == '\0')
1220 20
                        continue;
1221
1222 24508
                viov = VSCARAB_GET(scarab);
1223 24508
                if (viov == NULL) {
1224 1876
                        if (! ObjGetSpace(req->wrk, req->objcore, &sz,
1225
                            (uint8_t **)(void*)&scarab)) {
1226 0
                                VRT_fail(ctx, "Synth storage failed");
1227 0
                                return;
1228
                        }
1229 1876
                        viov = VSCARAB_GET(scarab);
1230 1876
                }
1231 24508
                AN(viov);
1232 24508
                viov->iov.iov_base = TRUST_ME(s->p[n]);
1233 24508
                viov->iov.iov_len = vstrlen(s->p[n]);
1234 24508
        }
1235 2024
}
1236
1237
1238
/*--------------------------------------------------------------------*/
1239
1240
                        /* digest */
1241
#define BLOB_HASH_TYPE 0x00d16357
1242
1243
VCL_BLOB
1244 16
VRT_r_req_hash(VRT_CTX)
1245
{
1246 16
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1247 16
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
1248 16
        return (VRT_blob(ctx, "req.hash", ctx->req->digest, DIGEST_LEN,
1249
            BLOB_HASH_TYPE));
1250
}
1251
1252
VCL_BLOB
1253 48
VRT_r_bereq_hash(VRT_CTX)
1254
{
1255 48
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1256 48
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
1257 48
        return (VRT_blob(ctx, "bereq.hash", ctx->bo->digest, DIGEST_LEN,
1258
            BLOB_HASH_TYPE));
1259
}
1260
1261
/*--------------------------------------------------------------------*/
1262
1263
#define HTTP_VAR(x)                                             \
1264
VCL_HTTP                                                        \
1265
VRT_r_##x(VRT_CTX)                                              \
1266
{                                                               \
1267
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
1268
        CHECK_OBJ_NOTNULL(ctx->http_##x, HTTP_MAGIC);           \
1269
        return (ctx->http_##x);                                 \
1270
}
1271
1272 60
HTTP_VAR(req)
1273 4
HTTP_VAR(resp)
1274 36
HTTP_VAR(bereq)
1275 0
HTTP_VAR(beresp)
1276
1277
/*--------------------------------------------------------------------*/
1278
1279
static inline void
1280 12
set_idle_send_timeout(const struct sess *sp, VCL_DURATION d)
1281
{
1282 12
        struct timeval tv = VTIM_timeval_sock(d);
1283 12
        VTCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_SNDTIMEO,
1284
            &tv, sizeof tv));
1285 12
}
1286
1287
#define SESS_VAR_DUR(x, setter)                         \
1288
VCL_VOID                                                \
1289
VRT_l_sess_##x(VRT_CTX, VCL_DURATION d)                 \
1290
{                                                       \
1291
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
1292
        CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC);         \
1293
        d = vmax(d, 0.0);                               \
1294
        setter;                                         \
1295
        ctx->sp->x = d;                                 \
1296
}                                                       \
1297
                                                        \
1298
VCL_DURATION                                            \
1299
VRT_r_sess_##x(VRT_CTX)                                 \
1300
{                                                       \
1301
        vtim_dur res;                                   \
1302
                                                        \
1303
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
1304
        CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC);         \
1305
        res = SESS_TMO(ctx->sp, x);                     \
1306
        return (VRT_TMO(res));                          \
1307
}                                                       \
1308
                                                        \
1309
VCL_VOID                                                \
1310
VRT_u_sess_##x(VRT_CTX)                                 \
1311
{                                                       \
1312
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
1313
        CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC);         \
1314
        ctx->sp->x = NAN;                               \
1315
}
1316
1317 40
SESS_VAR_DUR(timeout_idle, )
1318 44
SESS_VAR_DUR(timeout_linger, )
1319 28
SESS_VAR_DUR(send_timeout, )
1320 32
SESS_VAR_DUR(idle_send_timeout, set_idle_send_timeout(ctx->sp, d))
1321
1322
/*--------------------------------------------------------------------*/
1323
1324
#define PARAM_VAR(x, type)                              \
1325
VCL_##type                                              \
1326
VRT_r_param_##x(VRT_CTX)                                \
1327
{                                                       \
1328
                                                        \
1329
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
1330
        return (cache_param->x);                        \
1331
}                                                       \
1332
1333 0
PARAM_VAR(backend_idle_timeout, DURATION)
1334 0
PARAM_VAR(backend_wait_limit, INT)
1335 0
PARAM_VAR(backend_wait_timeout, DURATION)
1336 0
PARAM_VAR(between_bytes_timeout, DURATION)
1337 0
PARAM_VAR(connect_timeout, DURATION)
1338 0
PARAM_VAR(default_grace, DURATION)
1339 0
PARAM_VAR(default_keep, DURATION)
1340 0
PARAM_VAR(default_ttl, DURATION)
1341 0
PARAM_VAR(first_byte_timeout, DURATION)
1342 0
PARAM_VAR(idle_send_timeout, DURATION)
1343 0
PARAM_VAR(max_esi_depth, INT)
1344 0
PARAM_VAR(max_restarts, INT)
1345 0
PARAM_VAR(max_retries, INT)
1346 0
PARAM_VAR(pipe_task_deadline, DURATION)
1347 0
PARAM_VAR(pipe_timeout, DURATION)
1348 0
PARAM_VAR(send_timeout, DURATION)
1349 0
PARAM_VAR(shortlived, DURATION)
1350 8
PARAM_VAR(timeout_idle, DURATION)
1351 0
PARAM_VAR(transit_buffer, BYTES)
1352 168
PARAM_VAR(uncacheable_ttl, DURATION)