| | varnish-cache/vmod/vmod_vtc.c |
| 0 |
|
/*- |
| 1 |
|
* Copyright (c) 2012-2017 Varnish Software AS |
| 2 |
|
* All rights reserved. |
| 3 |
|
* |
| 4 |
|
* Author: Poul-Henning Kamp <phk@FreeBSD.org> |
| 5 |
|
* Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com> |
| 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 |
|
#include "config.h" |
| 32 |
|
|
| 33 |
|
#include <stdlib.h> |
| 34 |
|
#include <stdio.h> |
| 35 |
|
#include <string.h> |
| 36 |
|
#include <unistd.h> |
| 37 |
|
|
| 38 |
|
#include "cache/cache.h" |
| 39 |
|
|
| 40 |
|
#include "vsb.h" |
| 41 |
|
#include "vtcp.h" |
| 42 |
|
#include "vtim.h" |
| 43 |
|
|
| 44 |
|
#include "vcc_vtc_if.h" |
| 45 |
|
|
| 46 |
|
VCL_VOID v_matchproto_(td_vtc_barrier_sync) |
| 47 |
2994 |
vmod_barrier_sync(VRT_CTX, VCL_STRING addr, VCL_DURATION tmo) |
| 48 |
|
{ |
| 49 |
|
const char *err; |
| 50 |
|
char buf[32]; |
| 51 |
|
int sock, i; |
| 52 |
|
ssize_t sz; |
| 53 |
|
|
| 54 |
2994 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 55 |
2994 |
AN(addr); |
| 56 |
2994 |
AN(*addr); |
| 57 |
2994 |
assert(tmo >= 0.0); |
| 58 |
|
|
| 59 |
2994 |
if (ctx->vsl != NULL) |
| 60 |
2994 |
VSLb(ctx->vsl, SLT_Debug, "barrier_sync(\"%s\")", addr); |
| 61 |
|
else |
| 62 |
0 |
VSL(SLT_Debug, NO_VXID, "barrier_sync(\"%s\")", addr); |
| 63 |
|
|
| 64 |
2994 |
sock = VTCP_open(addr, NULL, 0., &err); |
| 65 |
2994 |
if (sock < 0) { |
| 66 |
0 |
VRT_fail(ctx, "Barrier connection failed: %s", err); |
| 67 |
0 |
return; |
| 68 |
|
} |
| 69 |
|
|
| 70 |
2994 |
sz = VTCP_read(sock, buf, sizeof buf, tmo); |
| 71 |
2994 |
i = errno; |
| 72 |
2994 |
closefd(&sock); |
| 73 |
2994 |
if (sz < 0) |
| 74 |
0 |
VRT_fail(ctx, "Barrier read failed: %s (errno=%d)", |
| 75 |
0 |
strerror(i), i); |
| 76 |
2994 |
if (sz > 0) |
| 77 |
0 |
VRT_fail(ctx, "Barrier unexpected data (%zdB)", sz); |
| 78 |
2994 |
} |
| 79 |
|
|
| 80 |
|
/*--------------------------------------------------------------------*/ |
| 81 |
|
|
| 82 |
|
VCL_BACKEND v_matchproto_(td_vtc_no_backend) |
| 83 |
80 |
vmod_no_backend(VRT_CTX) |
| 84 |
|
{ |
| 85 |
|
|
| 86 |
80 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 87 |
80 |
return (NULL); |
| 88 |
|
} |
| 89 |
|
|
| 90 |
|
VCL_STEVEDORE v_matchproto_(td_vtc_no_stevedore) |
| 91 |
40 |
vmod_no_stevedore(VRT_CTX) |
| 92 |
|
{ |
| 93 |
|
|
| 94 |
40 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 95 |
40 |
return (NULL); |
| 96 |
|
} |
| 97 |
|
|
| 98 |
|
VCL_IP v_matchproto_(td_vtc_no_ip) |
| 99 |
40 |
vmod_no_ip(VRT_CTX) |
| 100 |
|
{ |
| 101 |
|
|
| 102 |
40 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 103 |
40 |
return (NULL); |
| 104 |
|
} |
| 105 |
|
|
| 106 |
|
/*--------------------------------------------------------------------*/ |
| 107 |
|
|
| 108 |
|
VCL_VOID v_noreturn_ v_matchproto_(td_vtc_panic) |
| 109 |
0 |
vmod_panic(VRT_CTX, VCL_STRANDS str) |
| 110 |
|
{ |
| 111 |
|
const char *b; |
| 112 |
|
|
| 113 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 114 |
|
|
| 115 |
0 |
b = VRT_StrandsWS(ctx->ws, "PANIC:", str); |
| 116 |
0 |
VAS_Fail("VCL", "", 0, b, VAS_VCL); |
| 117 |
|
} |
| 118 |
|
|
| 119 |
|
/*--------------------------------------------------------------------*/ |
| 120 |
|
|
| 121 |
|
VCL_VOID v_matchproto_(td_vtc_sleep) |
| 122 |
1000 |
vmod_sleep(VRT_CTX, VCL_DURATION t) |
| 123 |
|
{ |
| 124 |
|
|
| 125 |
1000 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 126 |
1000 |
VTIM_sleep(t); |
| 127 |
1000 |
} |
| 128 |
|
|
| 129 |
|
/*--------------------------------------------------------------------*/ |
| 130 |
|
|
| 131 |
|
// XXX this really should be PRIV_TASK state |
| 132 |
|
static uintptr_t vtc_ws_snapshot; |
| 133 |
|
|
| 134 |
|
static struct ws * |
| 135 |
21559 |
vtc_ws_find(VRT_CTX, VCL_ENUM which) |
| 136 |
|
{ |
| 137 |
|
|
| 138 |
21559 |
if (which == VENUM(client)) |
| 139 |
10320 |
return (ctx->ws); |
| 140 |
11239 |
if (which == VENUM(backend)) |
| 141 |
10080 |
return (ctx->bo->ws); |
| 142 |
1159 |
if (which == VENUM(session)) |
| 143 |
1079 |
return (ctx->req->sp->ws); |
| 144 |
80 |
if (which == VENUM(thread) && ctx->req != NULL) |
| 145 |
80 |
return (ctx->req->wrk->aws); |
| 146 |
0 |
if (which == VENUM(thread) && ctx->bo != NULL) |
| 147 |
0 |
return (ctx->bo->wrk->aws); |
| 148 |
0 |
WRONG("vtc_ws_find Illegal enum"); |
| 149 |
21559 |
} |
| 150 |
|
|
| 151 |
|
VCL_VOID v_matchproto_(td_vtc_workspace_alloc) |
| 152 |
19640 |
vmod_workspace_alloc(VRT_CTX, VCL_ENUM which, VCL_INT size) |
| 153 |
|
{ |
| 154 |
|
struct ws *ws; |
| 155 |
|
void *p; |
| 156 |
|
|
| 157 |
19640 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 158 |
|
|
| 159 |
19640 |
ws = vtc_ws_find(ctx, which); |
| 160 |
19640 |
if (ws == NULL) |
| 161 |
0 |
return; |
| 162 |
19640 |
WS_Assert(ws); |
| 163 |
|
|
| 164 |
19640 |
if (size < 0) { |
| 165 |
19000 |
size += WS_ReserveAll(ws); |
| 166 |
19000 |
WS_Release(ws, 0); |
| 167 |
19000 |
} |
| 168 |
19640 |
if (size <= 0) { |
| 169 |
80 |
VRT_fail(ctx, "Attempted negative WS allocation"); |
| 170 |
80 |
return; |
| 171 |
|
} |
| 172 |
19560 |
p = WS_Alloc(ws, size); |
| 173 |
19560 |
if (p == NULL) |
| 174 |
40 |
VRT_fail(ctx, "vtc.workspace_alloc"); |
| 175 |
|
else |
| 176 |
19520 |
memset(p, '\0', size); |
| 177 |
19640 |
} |
| 178 |
|
|
| 179 |
|
VCL_BYTES v_matchproto_(td_vtc_workspace_reserve) |
| 180 |
480 |
vmod_workspace_reserve(VRT_CTX, VCL_ENUM which, VCL_INT size) |
| 181 |
|
{ |
| 182 |
|
struct ws *ws; |
| 183 |
|
unsigned r; |
| 184 |
|
|
| 185 |
480 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 186 |
|
|
| 187 |
480 |
ws = vtc_ws_find(ctx, which); |
| 188 |
480 |
if (ws == NULL) |
| 189 |
0 |
return (0); |
| 190 |
480 |
WS_Assert(ws); |
| 191 |
|
|
| 192 |
480 |
if (size < 0) { |
| 193 |
280 |
size += WS_ReserveAll(ws); |
| 194 |
280 |
WS_Release(ws, 0); |
| 195 |
280 |
} |
| 196 |
480 |
if (size <= 0) { |
| 197 |
0 |
VRT_fail(ctx, "Attempted negative WS reservation"); |
| 198 |
0 |
return (0); |
| 199 |
|
} |
| 200 |
480 |
r = WS_ReserveSize(ws, size); |
| 201 |
480 |
if (r == 0) |
| 202 |
40 |
return (0); |
| 203 |
440 |
memset(WS_Reservation(ws), 0, r); |
| 204 |
440 |
WS_Release(ws, 0); |
| 205 |
440 |
return (r); |
| 206 |
480 |
} |
| 207 |
|
|
| 208 |
|
VCL_INT v_matchproto_(td_vtc_workspace_free) |
| 209 |
640 |
vmod_workspace_free(VRT_CTX, VCL_ENUM which) |
| 210 |
|
{ |
| 211 |
|
struct ws *ws; |
| 212 |
|
unsigned u; |
| 213 |
|
|
| 214 |
640 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 215 |
|
|
| 216 |
640 |
ws = vtc_ws_find(ctx, which); |
| 217 |
640 |
if (ws == NULL) |
| 218 |
0 |
return (-1); |
| 219 |
640 |
WS_Assert(ws); |
| 220 |
|
|
| 221 |
640 |
u = WS_ReserveAll(ws); |
| 222 |
640 |
WS_Release(ws, 0); |
| 223 |
640 |
return (u); |
| 224 |
640 |
} |
| 225 |
|
|
| 226 |
|
#define VTC_WS_OP(type, def, name, op) \ |
| 227 |
|
VCL_##type v_matchproto_(td_vtc_workspace_##name) \ |
| 228 |
|
vmod_workspace_##name(VRT_CTX, VCL_ENUM which) \ |
| 229 |
|
{ \ |
| 230 |
|
struct ws *ws; \ |
| 231 |
|
\ |
| 232 |
|
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \ |
| 233 |
|
\ |
| 234 |
|
ws = vtc_ws_find(ctx, which); \ |
| 235 |
|
if (ws == NULL) \ |
| 236 |
|
return def ; \ |
| 237 |
|
WS_Assert(ws); \ |
| 238 |
|
\ |
| 239 |
|
op; \ |
| 240 |
|
} |
| 241 |
40 |
VTC_WS_OP(VOID, , snapshot, (vtc_ws_snapshot = WS_Snapshot(ws))) |
| 242 |
40 |
VTC_WS_OP(VOID, , reset, WS_Reset(ws, vtc_ws_snapshot)) |
| 243 |
40 |
VTC_WS_OP(VOID, , overflow, WS_MarkOverflow(ws)) |
| 244 |
200 |
VTC_WS_OP(BOOL, (0), overflowed, return (WS_Overflowed(ws))) |
| 245 |
|
#undef VTC_WS_OP |
| 246 |
|
|
| 247 |
|
VCL_BLOB v_matchproto_(td_vtc_workspace_dump) |
| 248 |
477 |
vmod_workspace_dump(VRT_CTX, VCL_ENUM which, VCL_ENUM where, |
| 249 |
|
VCL_BYTES off, VCL_BYTES len) |
| 250 |
|
{ |
| 251 |
|
struct ws *ws; |
| 252 |
|
unsigned l; |
| 253 |
477 |
const unsigned maxlen = 1024; |
| 254 |
477 |
unsigned char buf[maxlen]; |
| 255 |
|
const char *p, *err; |
| 256 |
|
|
| 257 |
477 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 258 |
477 |
AN(where); |
| 259 |
|
|
| 260 |
477 |
ws = vtc_ws_find(ctx, which); |
| 261 |
477 |
if (ws == NULL) |
| 262 |
0 |
return (NULL); |
| 263 |
477 |
WS_Assert(ws); |
| 264 |
|
|
| 265 |
477 |
if (len > maxlen) { |
| 266 |
0 |
VRT_fail(ctx, "workspace_dump: max length is %jd", |
| 267 |
|
(intmax_t)maxlen); |
| 268 |
0 |
return (NULL); |
| 269 |
|
} |
| 270 |
|
|
| 271 |
477 |
l = WS_Dump(ws, *where, off, buf, len); |
| 272 |
477 |
assert(l <= maxlen); |
| 273 |
|
|
| 274 |
477 |
if (l == 0) { |
| 275 |
0 |
switch (errno) { |
| 276 |
0 |
case EINVAL: WRONG(where); break; |
| 277 |
0 |
case EAGAIN: err = "NULL"; break; |
| 278 |
0 |
case EFAULT: err = "off limit"; break; |
| 279 |
0 |
default: err = "unknown error"; break; |
| 280 |
|
} |
| 281 |
0 |
VRT_fail(ctx, "workspace_dump: %s", err); |
| 282 |
0 |
return (NULL); |
| 283 |
|
} |
| 284 |
|
|
| 285 |
477 |
p = WS_Copy(ctx->ws, buf, (int)l); |
| 286 |
477 |
if (p == NULL) { |
| 287 |
0 |
VRT_fail(ctx, "workspace_dump: copy failed"); |
| 288 |
0 |
return (NULL); |
| 289 |
|
} |
| 290 |
477 |
return (VRT_blob(ctx, "workspace_dump", p, l, 0xd000d000)); |
| 291 |
477 |
} |
| 292 |
|
|
| 293 |
|
/*--------------------------------------------------------------------*/ |
| 294 |
|
|
| 295 |
|
VCL_INT v_matchproto_(td_vtc_typesize) |
| 296 |
1000 |
vmod_typesize(VRT_CTX, VCL_STRING s) |
| 297 |
|
{ |
| 298 |
1000 |
size_t i = 0, l, a, p = 0; |
| 299 |
|
|
| 300 |
1000 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 301 |
1000 |
AN(s); |
| 302 |
1000 |
AN(*s); |
| 303 |
|
|
| 304 |
4480 |
for (; *s; s++) { |
| 305 |
3520 |
switch (*s) { |
| 306 |
|
#define VTC_TYPESIZE(c, t) case c: l = sizeof(t); break; |
| 307 |
440 |
VTC_TYPESIZE('c', char) |
| 308 |
120 |
VTC_TYPESIZE('d', double) |
| 309 |
40 |
VTC_TYPESIZE('f', float) |
| 310 |
120 |
VTC_TYPESIZE('i', int) |
| 311 |
40 |
VTC_TYPESIZE('j', intmax_t) |
| 312 |
40 |
VTC_TYPESIZE('l', long) |
| 313 |
40 |
VTC_TYPESIZE('o', off_t) |
| 314 |
640 |
VTC_TYPESIZE('p', void *) |
| 315 |
120 |
VTC_TYPESIZE('s', short) |
| 316 |
1160 |
VTC_TYPESIZE('u', unsigned) |
| 317 |
720 |
VTC_TYPESIZE('z', size_t) |
| 318 |
|
#undef VTC_TYPESIZE |
| 319 |
40 |
default: return (-1); |
| 320 |
|
} |
| 321 |
3480 |
if (l > p) |
| 322 |
1680 |
p = l; |
| 323 |
3480 |
a = i % l; |
| 324 |
3480 |
if (a != 0) |
| 325 |
200 |
i += (l - a); /* align */ |
| 326 |
3480 |
i += l; |
| 327 |
3480 |
} |
| 328 |
960 |
AN(p); |
| 329 |
960 |
a = i % p; |
| 330 |
960 |
if (a != 0) |
| 331 |
240 |
i += (p - a); /* pad */ |
| 332 |
960 |
return ((VCL_INT)i); |
| 333 |
1000 |
} |
| 334 |
|
|
| 335 |
|
/*--------------------------------------------------------------------*/ |
| 336 |
|
|
| 337 |
|
#define BLOB_VMOD_PROXY_HEADER_TYPE 0xc8f34f78 |
| 338 |
|
|
| 339 |
|
VCL_BLOB v_matchproto_(td_vtc_proxy_header) |
| 340 |
80 |
vmod_proxy_header(VRT_CTX, VCL_ENUM venum, VCL_IP client, VCL_IP server, |
| 341 |
|
VCL_STRING authority) |
| 342 |
|
{ |
| 343 |
|
struct vsb *vsb; |
| 344 |
|
const void *h; |
| 345 |
|
int version; |
| 346 |
|
size_t l; |
| 347 |
|
|
| 348 |
80 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 349 |
|
|
| 350 |
80 |
if (venum == VENUM(v1)) |
| 351 |
40 |
version = 1; |
| 352 |
40 |
else if (venum == VENUM(v2)) |
| 353 |
40 |
version = 2; |
| 354 |
|
else |
| 355 |
0 |
WRONG(venum); |
| 356 |
|
|
| 357 |
80 |
vsb = VSB_new_auto(); |
| 358 |
80 |
AN(vsb); |
| 359 |
80 |
VRT_Format_Proxy(vsb, version, client, server, authority); |
| 360 |
80 |
l = VSB_len(vsb); |
| 361 |
80 |
h = WS_Copy(ctx->ws, VSB_data(vsb), l); |
| 362 |
80 |
VSB_destroy(&vsb); |
| 363 |
|
|
| 364 |
80 |
if (h == NULL) { |
| 365 |
0 |
VRT_fail(ctx, "proxy_header: out of workspace"); |
| 366 |
0 |
return (NULL); |
| 367 |
|
} |
| 368 |
|
|
| 369 |
80 |
return (VRT_blob(ctx, "proxy_header", h, l, |
| 370 |
|
BLOB_VMOD_PROXY_HEADER_TYPE)); |
| 371 |
80 |
} |
| 372 |
|
|
| 373 |
|
// ref vsl.c |
| 374 |
|
struct vsl_tag2enum { |
| 375 |
|
const char *string; |
| 376 |
|
enum VSL_tag_e tag; |
| 377 |
|
}; |
| 378 |
|
|
| 379 |
|
static struct vsl_tag2enum vsl_tag2enum[SLT__MAX] = { |
| 380 |
|
#define SLTM(name,flags,sdesc,ldesc) [SLT_ ## name] = { \ |
| 381 |
|
.string = #name, \ |
| 382 |
|
.tag = SLT_ ## name \ |
| 383 |
|
}, |
| 384 |
|
#include "tbl/vsl_tags.h" |
| 385 |
|
}; |
| 386 |
|
|
| 387 |
|
static int |
| 388 |
2543960 |
vsl_tagcmp(const void *aa, const void *bb) |
| 389 |
|
{ |
| 390 |
2543960 |
const struct vsl_tag2enum *a = aa, *b = bb; |
| 391 |
|
|
| 392 |
|
// ref vsl2rst.c ptag_cmp |
| 393 |
2543960 |
if (a->string == NULL && b->string != NULL) |
| 394 |
5760 |
return (1); |
| 395 |
2538200 |
else if (a->string != NULL && b->string == NULL) |
| 396 |
277240 |
return (-1); |
| 397 |
2260960 |
else if (a->string == NULL && b->string == NULL) |
| 398 |
486720 |
return (0); |
| 399 |
1774240 |
return (strcmp(a->string, b->string)); |
| 400 |
2543960 |
} |
| 401 |
|
|
| 402 |
|
/*lint -esym(528, init_vsl_tag2enum) */ |
| 403 |
|
static void __attribute__((constructor)) |
| 404 |
2880 |
init_vsl_tag2enum(void) |
| 405 |
|
{ |
| 406 |
2880 |
qsort(vsl_tag2enum, SLT__MAX, sizeof *vsl_tag2enum, vsl_tagcmp); |
| 407 |
2880 |
} |
| 408 |
|
|
| 409 |
|
|
| 410 |
|
VCL_VOID |
| 411 |
2440 |
vmod_vsl(VRT_CTX, VCL_INT id, VCL_STRING tag_s, VCL_ENUM side, VCL_STRANDS s) |
| 412 |
|
{ |
| 413 |
|
struct vsl_tag2enum *te, key; |
| 414 |
|
vxid_t vxid; |
| 415 |
|
|
| 416 |
2440 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 417 |
|
|
| 418 |
2440 |
key.string = tag_s; |
| 419 |
2440 |
te = bsearch(&key, vsl_tag2enum, SLT__MAX, |
| 420 |
|
sizeof *vsl_tag2enum, vsl_tagcmp); |
| 421 |
|
|
| 422 |
2440 |
if (te == NULL) { |
| 423 |
0 |
VRT_fail(ctx, "No such tag: %s", tag_s); |
| 424 |
0 |
return; |
| 425 |
|
} |
| 426 |
|
|
| 427 |
2440 |
if (id < 0 || id > VRT_INTEGER_MAX) { |
| 428 |
0 |
VRT_fail(ctx, "id out of bounds"); |
| 429 |
0 |
return; |
| 430 |
|
} |
| 431 |
|
|
| 432 |
2440 |
vxid.vxid = id & VSL_IDENTMASK; |
| 433 |
2440 |
if (side == VENUM(c)) |
| 434 |
2360 |
vxid.vxid |= VSL_CLIENTMARKER; |
| 435 |
80 |
else if (side == VENUM(b)) |
| 436 |
80 |
vxid.vxid |= VSL_BACKENDMARKER; |
| 437 |
|
else |
| 438 |
0 |
WRONG("side"); |
| 439 |
|
|
| 440 |
2440 |
VSLs(te->tag, vxid, s); |
| 441 |
2440 |
} |
| 442 |
|
|
| 443 |
|
static void |
| 444 |
2360 |
vsl_line(VRT_CTX, char *str) |
| 445 |
|
{ |
| 446 |
|
VCL_INT id; |
| 447 |
|
VCL_ENUM side; |
| 448 |
|
VCL_STRANDS s; |
| 449 |
2360 |
const char *tag, *delim = " \t\r\n"; |
| 450 |
|
char *e, *save; |
| 451 |
|
|
| 452 |
2360 |
if (*str == '*') { |
| 453 |
|
// varnishtest |
| 454 |
2200 |
str = strstr(str, "vsl|"); |
| 455 |
2200 |
if (str == NULL) |
| 456 |
0 |
return; |
| 457 |
2200 |
str += 4; |
| 458 |
2200 |
} |
| 459 |
2360 |
if ((str = strtok_r(str, delim, &save)) == NULL) |
| 460 |
160 |
return; |
| 461 |
2200 |
id = strtoll(str, &e, 10); |
| 462 |
2200 |
if (e == str) |
| 463 |
0 |
return; |
| 464 |
|
|
| 465 |
2200 |
if ((str = strtok_r(NULL, delim, &save)) == NULL) |
| 466 |
0 |
return; |
| 467 |
2200 |
tag = str; |
| 468 |
|
|
| 469 |
2200 |
if ((str = strtok_r(NULL, delim, &save)) == NULL) |
| 470 |
0 |
return; |
| 471 |
2200 |
if (*str == 'c') |
| 472 |
2120 |
side = VENUM(c); |
| 473 |
80 |
else if (*str == 'b') |
| 474 |
80 |
side = VENUM(b); |
| 475 |
|
else |
| 476 |
0 |
return; |
| 477 |
|
|
| 478 |
2200 |
str = strtok_r(NULL, "\r\n", &save); |
| 479 |
|
// needs to be assigned here because of the compound literal lifetime |
| 480 |
2200 |
s = TOSTRAND(str); |
| 481 |
2200 |
if (str == NULL) |
| 482 |
320 |
s = vrt_null_strands; |
| 483 |
|
|
| 484 |
2200 |
vmod_vsl(ctx, id, tag, side, s); |
| 485 |
2360 |
} |
| 486 |
|
|
| 487 |
|
VCL_VOID |
| 488 |
80 |
vmod_vsl_replay(VRT_CTX, VCL_STRANDS s) |
| 489 |
|
{ |
| 490 |
|
struct vsb cp[1]; |
| 491 |
|
const char *p, *pp; |
| 492 |
|
size_t l; |
| 493 |
80 |
int i, err = 0; |
| 494 |
|
|
| 495 |
80 |
CHECK_OBJ_ORNULL(s, STRANDS_MAGIC); |
| 496 |
80 |
if (s == NULL || s->n == 0) |
| 497 |
0 |
return; |
| 498 |
|
|
| 499 |
80 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
| 500 |
80 |
CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC); |
| 501 |
80 |
WS_VSB_new(cp, ctx->ws); |
| 502 |
|
|
| 503 |
160 |
for (i = 0; i < s->n; i++) { |
| 504 |
80 |
p = s->p[i]; |
| 505 |
80 |
if (p == NULL || *p == '\0') |
| 506 |
0 |
continue; |
| 507 |
80 |
pp = strpbrk(p, "\r\n"); |
| 508 |
2360 |
while (pp != NULL) { |
| 509 |
2280 |
l = pp - p; |
| 510 |
2280 |
if (VSB_bcat(cp, p, l) || VSB_finish(cp)) { |
| 511 |
0 |
err = 1; |
| 512 |
0 |
break; |
| 513 |
|
} |
| 514 |
2280 |
vsl_line(ctx, VSB_data(cp)); |
| 515 |
2280 |
VSB_clear(cp); |
| 516 |
2280 |
p = pp + 1; |
| 517 |
2280 |
pp = strpbrk(p, "\r\n"); |
| 518 |
|
} |
| 519 |
80 |
if (err || VSB_cat(cp, p)) { |
| 520 |
0 |
err = 1; |
| 521 |
0 |
break; |
| 522 |
|
} |
| 523 |
80 |
} |
| 524 |
80 |
if (err || VSB_finish(cp)) { |
| 525 |
0 |
AZ(WS_VSB_finish(cp, ctx->ws, NULL)); |
| 526 |
0 |
VRT_fail(ctx, "out of workspace"); |
| 527 |
0 |
return; |
| 528 |
|
} |
| 529 |
80 |
vsl_line(ctx, VSB_data(cp)); |
| 530 |
80 |
VSB_clear(cp); |
| 531 |
80 |
AN(WS_VSB_finish(cp, ctx->ws, NULL)); |
| 532 |
80 |
} |