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