| | 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 |
771195 |
VPI_wrk_init(struct worker *wrk, void *p, size_t spc) |
| 53 |
|
{ |
| 54 |
771195 |
struct wrk_vpi *vpi = p; |
| 55 |
|
|
| 56 |
771195 |
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); |
| 57 |
771195 |
AN(vpi); |
| 58 |
771195 |
assert(spc >= sizeof *vpi); |
| 59 |
771195 |
INIT_OBJ(vpi, WRK_VPI_MAGIC); |
| 60 |
771195 |
wrk->vpi = vpi; |
| 61 |
771195 |
} |
| 62 |
|
|
| 63 |
|
void |
| 64 |
10920 |
VPI_trace(VRT_CTX, unsigned u) |
| 65 |
|
{ |
| 66 |
|
|
| 67 |
10920 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 68 |
10920 |
CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC); |
| 69 |
10920 |
CHECK_OBJ_NOTNULL(ctx->vcl->conf, VCL_CONF_MAGIC); |
| 70 |
10920 |
assert(u < ctx->vcl->conf->nref); |
| 71 |
10920 |
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 |
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 |
10920 |
} |
| 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 |
839 |
VPI_Call_Check(VRT_CTX, const struct VCL_conf *conf, |
| 262 |
|
unsigned methods, unsigned n) |
| 263 |
|
{ |
| 264 |
|
struct vbitmap *vbm; |
| 265 |
|
|
| 266 |
839 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 267 |
839 |
CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC); |
| 268 |
|
|
| 269 |
839 |
assert(conf == ctx->vcl->conf); |
| 270 |
|
|
| 271 |
799 |
vbm = ctx->called; |
| 272 |
799 |
AN(vbm); |
| 273 |
|
|
| 274 |
799 |
if ((methods & ctx->method) == 0) |
| 275 |
119 |
return (VSUB_E_METHOD); |
| 276 |
|
|
| 277 |
680 |
if (vbit_test(vbm, n)) |
| 278 |
80 |
return (VSUB_E_RECURSE); |
| 279 |
|
|
| 280 |
600 |
return (VSUB_E_OK); |
| 281 |
799 |
} |
| 282 |
|
|
| 283 |
|
void |
| 284 |
600 |
VPI_Call_Begin(VRT_CTX, unsigned n) |
| 285 |
|
{ |
| 286 |
|
struct vbitmap *vbm; |
| 287 |
|
|
| 288 |
600 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 289 |
600 |
vbm = ctx->called; |
| 290 |
600 |
AN(vbm); |
| 291 |
600 |
vbit_set(vbm, n); |
| 292 |
600 |
} |
| 293 |
|
|
| 294 |
|
void |
| 295 |
600 |
VPI_Call_End(VRT_CTX, unsigned n) |
| 296 |
|
{ |
| 297 |
|
struct vbitmap *vbm; |
| 298 |
|
|
| 299 |
600 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 300 |
600 |
vbm = ctx->called; |
| 301 |
600 |
AN(vbm); |
| 302 |
600 |
vbit_clr(vbm, n); |
| 303 |
600 |
} |