varnish-cache/bin/varnishd/cache/cache_vpi.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2019 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
 */
31
32
#include "config.h"
33
34
#include <stdio.h>
35
36
#include "cache_varnishd.h"
37
38
#include "vcl.h"
39
#include "vbm.h"
40
41
#include "vcc_interface.h"
42
43
#include "cache_vcl.h"
44
45
/*--------------------------------------------------------------------
46
 * Private & exclusive interfaces between VCC and varnishd
47
 */
48
49
const size_t vpi_wrk_len = sizeof(struct wrk_vpi);
50
51
void
52 777333
VPI_wrk_init(struct worker *wrk, void *p, size_t spc)
53
{
54 777333
        struct wrk_vpi *vpi = p;
55
56 777333
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
57 777333
        AN(vpi);
58 777333
        assert(spc >= sizeof *vpi);
59 777333
        INIT_OBJ(vpi, WRK_VPI_MAGIC);
60 777333
        wrk->vpi = vpi;
61 777333
}
62
63
void
64 10960
VPI_trace(VRT_CTX, unsigned u)
65
{
66
67 10960
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
68 10960
        CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC);
69 10960
        CHECK_OBJ_NOTNULL(ctx->vcl->conf, VCL_CONF_MAGIC);
70 10960
        assert(u < ctx->vcl->conf->nref);
71 10960
        if (ctx->vsl != NULL)
72 21360
                VSLb(ctx->vsl, SLT_VCL_trace, "%s %u %u.%u.%u",
73 10680
                    ctx->vcl->loaded_name, u, ctx->vcl->conf->ref[u].source,
74 10680
                    ctx->vcl->conf->ref[u].line, ctx->vcl->conf->ref[u].pos);
75
        else
76 560
                VSL(SLT_VCL_trace, NO_VXID, "%s %u %u.%u.%u",
77 280
                    ctx->vcl->loaded_name, u, ctx->vcl->conf->ref[u].source,
78 280
                    ctx->vcl->conf->ref[u].line, ctx->vcl->conf->ref[u].pos);
79 10960
}
80
81
static void
82 280
vpi_ref_panic(struct vsb *vsb, unsigned n, const struct vcl *vcl)
83
{
84 280
        const struct VCL_conf *conf = NULL;
85
        const struct vpi_ref *ref;
86 280
        const char *src = NULL;
87 280
        int w = 0;
88
89 280
        AN(vsb);
90
91 280
        if (vcl != NULL)
92 280
                conf = vcl->conf;
93 280
        if (conf != NULL && conf->magic != VCL_CONF_MAGIC)
94 0
                conf = NULL;
95
96 280
        if (conf == NULL) {
97 0
                VSB_printf(vsb, "ref = %u, nref = ?,\n", n);
98 0
                return;
99
        }
100 280
        if (n >= conf->nref) {
101 0
                VSB_printf(vsb, "ref = %u *invalid*, nref = %u\n",
102 0
                    n, conf->nref);
103 0
                return;
104
        }
105
106 280
        VSB_printf(vsb, "ref = %u,\n", n);
107
108 280
        ref = &conf->ref[n];
109 280
        if (PAN_dump_struct(vsb, ref, VPI_REF_MAGIC, "vpi_ref"))
110 0
                return;
111
112 280
        if (ref->source < conf->nsrc) {
113 560
                VSB_printf(vsb, "source = %u (\"%s\"),\n", ref->source,
114 280
                    conf->srcname[ref->source]);
115 280
                src = conf->srcbody[ref->source];
116 280
        } else {
117 0
                VSB_printf(vsb, "source = %u *invalid*,\n", ref->source);
118
        }
119
120 280
        if (src != NULL) {
121 280
                w = strlen(src);
122 280
                assert(w > 0);
123 280
                if (ref->offset >= (unsigned)w) {
124 0
                        src = NULL;
125 0
                } else {
126 280
                        src += ref->offset;
127
                }
128 280
        }
129
130 280
        VSB_printf(vsb, "offset = %u,\n", ref->offset);
131 280
        VSB_printf(vsb, "line = %u,\n", ref->line);
132 280
        VSB_printf(vsb, "pos = %u,\n", ref->pos);
133 280
        if (src != NULL) {
134 280
                VSB_cat(vsb, "src = ");
135 280
                VSB_quote(vsb, src, 40, VSB_QUOTE_CSTR | VSB_QUOTE_ABBREVIATE);
136 280
                VSB_putc(vsb, '\n');
137 280
        } else {
138 0
                VSB_printf(vsb, "token = \"%s\"\n", ref->token);
139
        }
140 280
        VSB_indent(vsb, -2);
141 280
        VSB_cat(vsb, "},\n");
142
143 280
}
144
void
145 280
VPI_Panic(struct vsb *vsb, const struct wrk_vpi *vpi, const struct vcl *vcl)
146
{
147
        const char *hand;
148
149 280
        AN(vsb);
150 280
        if (PAN_dump_struct(vsb, vpi, WRK_VPI_MAGIC, "vpi"))
151 0
                return;
152
153 280
        hand = VCL_Return_Name(vpi->handling);
154 280
        if (vpi->handling == 0)
155 280
                hand = "none";
156 0
        else if (hand == NULL)
157 0
                hand = "*invalid*";
158
159 560
        VSB_printf(vsb, "handling (VCL::return) = 0x%x (%s),\n",
160 280
            vpi->handling, hand);
161
162 280
        vpi_ref_panic(vsb, vpi->ref, vcl);
163
164 280
        VSB_indent(vsb, -2);
165 280
        VSB_cat(vsb, "},\n");
166 280
}
167
168
/*
169
 * After vcl_fini {} == VGC_function_vcl_fini() is called from VGC_Discard(),
170
 * handling must either be OK from VCL "return (ok)" or FAIL from VRT_fail().
171
 *
172
 * replace OK with 0 for _fini callbacks because that handling has meaning only
173
 * when returning from VCL subs
174
 */
175
176
void
177 3069
VPI_vcl_fini(VRT_CTX)
178
{
179 3069
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
180 3069
        AN(ctx->vpi);
181
182 3069
        if (ctx->vpi->handling == VCL_RET_FAIL)
183 40
                return;
184 3029
        assert(ctx->vpi->handling == VCL_RET_OK);
185 3029
        ctx->vpi->handling = 0;
186 3069
}
187
188
VCL_VCL
189 840
VPI_vcl_get(VRT_CTX, const char *name)
190
{
191
        VCL_VCL vcl;
192
193 840
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
194 840
        vcl = vcl_find(name);
195 840
        AN(vcl);
196 840
        Lck_Lock(&vcl_mtx);
197 840
        vcl->nrefs++;
198 840
        Lck_Unlock(&vcl_mtx);
199 840
        return (vcl);
200
}
201
202
void
203 240
VPI_vcl_rel(VRT_CTX, VCL_VCL vcl)
204
{
205 240
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
206 240
        AN(vcl);
207 240
        Lck_Lock(&vcl_mtx);
208 240
        vcl->nrefs--;
209 240
        Lck_Unlock(&vcl_mtx);
210 240
}
211
212
void
213 1640
VPI_vcl_select(VRT_CTX, VCL_VCL vcl)
214
{
215 1640
        struct req *req = ctx->req;
216
217 1640
        CHECK_OBJ_NOTNULL(vcl, VCL_MAGIC);
218 1640
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
219 1640
        CHECK_OBJ_NOTNULL(req->top, REQTOP_MAGIC);
220
221 1640
        if ((IS_TOPREQ(req) && req->top->vcl0 != NULL) || req->restarts > 0)
222 1120
                return;         // Illegal, req-FSM will fail this later.
223
224 520
        if (! IS_TOPREQ(req))
225 40
                assert(req->vcl == req->top->vcl0);
226
227 520
        Req_Rollback(ctx);
228
229 520
        if (IS_TOPREQ(req)) {
230 480
                AN(req->top);
231 480
                AZ(req->top->vcl0);
232 480
                req->top->vcl0 = req->vcl;
233 480
                req->vcl = NULL;
234 480
        }
235 520
        VCL_Update(&req->vcl, vcl);
236 1040
        VSLb(ctx->req->vsl, SLT_VCL_use, "%s via %s",
237 520
            req->vcl->loaded_name, vcl->loaded_name);
238 680
}
239
240
void v_noreturn_
241 0
VPI_Fail(const char *func, const char *file, int line,
242
    const char *cond)
243
{
244 0
        VAS_Fail(func, file, line, cond, VAS_ASSERT);
245
}
246
247
enum vcl_func_fail_e
248 840
VPI_Call_Check(VRT_CTX, const struct VCL_conf *conf,
249
    unsigned methods, unsigned n)
250
{
251
        struct vbitmap *vbm;
252
253 840
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
254 840
        CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC);
255
256 840
        assert(conf == ctx->vcl->conf);
257
258 800
        vbm = ctx->called;
259 800
        AN(vbm);
260
261 800
        if ((methods & ctx->method) == 0)
262 120
                return (VSUB_E_METHOD);
263
264 680
        if (vbit_test(vbm, n))
265 80
                return (VSUB_E_RECURSE);
266
267 600
        return (VSUB_E_OK);
268 800
}
269
270
void
271 599
VPI_Call_Begin(VRT_CTX, unsigned n)
272
{
273
        struct vbitmap *vbm;
274
275 599
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
276 599
        vbm = ctx->called;
277 599
        AN(vbm);
278 599
        vbit_set(vbm, n);
279 599
}
280
281
void
282 600
VPI_Call_End(VRT_CTX, unsigned n)
283
{
284
        struct vbitmap *vbm;
285
286 600
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
287 600
        vbm = ctx->called;
288 600
        AN(vbm);
289 600
        vbit_clr(vbm, n);
290 600
}
291
292
VCL_BOOL
293 240
VPI_PtrCmp(const void *p1, const void *p2)
294
{
295
296 240
        return (p1 != p2);
297
}