Commit 39a430d3 authored by Nils Goroll's avatar Nils Goroll

Initial release

parent c2259e0a
......@@ -10,6 +10,7 @@ m4/
*.lo
*.o
*.tar.gz
*.vcc
Makefile
Makefile.in
......@@ -26,6 +27,7 @@ stamp-h1
*.log
*.trs
*.vtc
# vmodtool
......
INSTALLATION
============
Building from source
~~~~~~~~~~~~~~~~~~~~
The VMOD is built on a system where an instance of Varnish is
installed, and the auto-tools will attempt to locate the Varnish
instance, and then pull in libraries and other support files from
there.
Quick start
-----------
This sequence should be enough in typical setups:
1. ``./bootstrap`` (for git-installation)
3. ``make``
4. ``make check`` (regression tests)
5. ``make install`` (may require root: sudo make install)
Alternative configs
-------------------
If you have installed Varnish to a non-standard directory, call
``autogen.sh`` and ``configure`` with ``PKG_CONFIG_PATH`` pointing to
the appropriate path. For example, when varnishd configure was called
with ``--prefix=$PREFIX``, use::
PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig
ACLOCAL_PATH=${PREFIX}/share/aclocal
export PKG_CONFIG_PATH ACLOCAL_PATH
Copyright 2018 UPLEX Nils Goroll Systemoptimierung
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
==============
varnish-objvar
==============
This bundle contains four varnish modules (vmods) implementing a next
level variable interface using the VCL object model:
* vmod_taskvar:
`task` scoped variables as objects: Each client or backend request
(`task`) has their own view of taskvar variables.
* vmod_topvar:
`top` scoped variables as objects: Each client request including all
esi include levels (`top`) has its own view of topvar variables.
* vmod_globalvar:
globally (per vcl) scoped variables as objects: All vcl subroutines
have the same view on variables, any change comes in effect
immediately.
* vmod_constant:
gobally (per vcl) scoped constants as objects: All vcl subroutines
have the same view on constants.
Full type support
-----------------
The vmods in this bundle aim to support all native VCL types, which
currently are:
* ``ACL``
* ``BACKEND``
* ``BLOB``
* ``BODY``
* ``BOOL``
* ``BYTES``
* ``DURATION``
* ``HEADER``
* ``INT``
* ``IP``
* ``PROBE``
* ``REAL``
* ``STEVEDORE``
* ``STRANDS`` implicit via ``STRING``\ -folding
* ``STRING_LIST`` implicit via ``STRING``\ -folding
* ``STRING``
* ``TIME``
SYNOPSIS
========
Variable object construction is identical for all vmods from this
bundle, shown here by example of the ``int`` type, but the other types
mentioned above are supported likewise:
::
import constant [from "path"] ;
import globalvar [from "path"] ;
import taskvar [from "path"] ;
import topvar [from "path"] ;
vcl_init {
new xconst_int = constant.int(5);
new xglob_int = globalvar.int(5);
new xtask_int = taskvar.int(5);
new xtop_int = topvar.int(5);
}
All vmods support methods to ``.get()`` the value and check if the
variable is ``.defined()``.
All vmods except ``vmod_constant`` support ``.set()`` and
``.undefine()`` to assign a value to a variable or unset it.
``vmod_taskvar`` and ``vmod_topvar`` also support ``.protect()`` to
make a variable read-only for the rest of its lifetime and
``.protected()`` to check for protection status.
For details see the documentation of the individual vmods.
REQUIREMENTS
============
The VMOD requires the Varnish since version 6.0.0 or the master
branch. See the project repository for versions that are compatible
with other versions of Varnish.
INSTALLATION
============
See `INSTALL.rst <INSTALL.rst>`_ in the project source repository.
COPYRIGHT
=========
::
Copyright 2018 UPLEX Nils Goroll Systemoptimierung
All rights reserved
This document is licensed under the same conditions as the varnish-objvar
project. See LICENSE for details.
Author: Nils Goroll <nils.goroll@uplex.de>
......@@ -37,6 +37,47 @@ nodist_libvmod_topvar_la_SOURCES = \
@BUILD_VMOD_TASKVAR@
@BUILD_VMOD_TOPVAR@
VCCS = \
vmod_constant.vcc \
vmod_globalvar.vcc \
vmod_taskvar.vcc \
vmod_topvar.vcc
CS = \
vmod_constant.c \
vmod_globalvar.c \
vmod_taskvar.c \
vmod_topvar.c
TESTS = \
vtc/vmod_constant.vtc \
vtc/vmod_globalvar.vtc \
vtc/vmod_taskvar.vtc \
vtc/vmod_topvar.vtc
$(CS): type_magics.h type_cp.h tbl_types.h
vmod_taskvar.c: tasktop.h
vmod_topvar.c: tasktop.h
$(VCCS): $(top_srcdir)/LICENSE tbl_types.h
$(TESTS): tbl_vtc.h
.vcctpl.vcc:
@rm -f $<.h
@ln -s $< $<.h
$(AM_V_GEN) ( echo '#-' && \
sed < $(top_srcdir)/LICENSE 's:^:# :' && \
$(CPP) $<.h | sed '/^#/ d; s:\\n *:\n:g') >$@
@rm -f $<.h
.vtctpl.vtc:
@rm -f $<.h
@ln $< $<.h
$(AM_V_GEN) ($(CPP) $<.h | sed '/^#/ d; s:\\n *:\n:g; s: *%% *::g;') >$@
@rm -f $<.h
# Test suite
AM_TESTS_ENVIRONMENT = \
......@@ -48,19 +89,10 @@ AM_VTC_LOG_FLAGS = \
-p vcl_path="$(abs_top_srcdir)/vcl" \
-p vmod_path="$(abs_builddir)/.libs:$(vmoddir)"
TESTS = \
vtc/vmod_constant.vtc \
vtc/vmod_globalvar.vtc \
vtc/vmod_taskvar.vtc \
vtc/vmod_topvar.vtc
# Documentation
dist_doc_DATA = \
vmod_constant.vcc \
vmod_globalvar.vcc \
vmod_taskvar.vcc \
vmod_topvar.vcc \
$(VCCS) \
$(TESTS)
dist_man_MANS = \
......
/*-
* Copyright 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define var_code(VMODPFX_, vmodpfx_, TYPE, type) \
struct vmodpfx_ ## type { \
uint16_t magic; \
int defined:1; \
int protected:1; \
VCL_ ## TYPE var; \
}; \
\
VCL_VOID \
vmod_ ## type ## __init(VRT_CTX, \
struct vmodpfx_ ## type **vp, \
const char *vcl_name, \
struct vmod_ ## type ##__init_arg *args) \
{ \
struct vmodpfx_ ## type *v; \
\
AN(vp); \
AZ(*vp); \
\
ALLOC_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
if (v == NULL) { \
VRT_fail(ctx, "%s: alloc failed", vcl_name); \
return; \
} \
\
if (args->valid_init) { \
CP_ ## TYPE (v->var, args->init); \
v->defined = 1; \
} \
*vp = v; \
} \
\
VCL_VOID \
vmod_ ## type ## __fini(struct vmodpfx_ ## type **vp) \
{ \
struct vmodpfx_ ## type *v = *vp; \
\
*vp = NULL; \
if (v == NULL) \
return; \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
FREE_ ## TYPE (v->var); \
FREE_OBJ(v); \
} \
\
VCL_ ## TYPE \
vmod_ ## type ## _get(VRT_CTX, struct vmodpfx_ ## type *va, \
VCL_ ## TYPE fallback) \
{ \
const struct vmodpfx_ ## type *v = state_r(ctx, va); \
\
if (v == NULL) \
return (fallback); \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
if (v->defined) \
return (v->var); \
\
return (fallback); \
} \
\
VCL_VOID \
vmod_ ## type ## _set(VRT_CTX, struct vmodpfx_ ## type *va, \
VCL_ ## TYPE val) \
{ \
struct vmodpfx_ ## type *v = \
state_l(ctx, va, sizeof *v); \
\
if (v == NULL) \
return; \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
if (v->protected) { \
VRT_fail(ctx, \
"attempt to set protected variable"); \
return; \
} \
\
if (v == va) \
CP_ ## TYPE (va->var, val); \
else \
v->var = val; \
\
v->defined = 1; \
} \
\
VCL_VOID \
vmod_ ## type ## _undefine(VRT_CTX, struct vmodpfx_ ## type *v) \
{ \
v = state_l(ctx, v, sizeof *v); \
\
if (v == NULL) \
return; \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
v->defined = 0; \
} \
\
VCL_BOOL \
vmod_ ## type ## _defined(VRT_CTX, struct vmodpfx_ ## type *va) \
{ \
const struct vmodpfx_ ## type *v = state_r(ctx, va); \
\
if (v == NULL) \
return (0); \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
return (!!v->defined); \
} \
VCL_VOID \
vmod_ ## type ## _protect(VRT_CTX, struct vmodpfx_ ## type *v) \
{ \
v = state_l(ctx, v, sizeof *v); \
\
if (v == NULL) \
return; \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
v->protected = 1; \
} \
\
VCL_BOOL \
vmod_ ## type ## _protected(VRT_CTX, \
struct vmodpfx_ ## type *va) \
{ \
const struct vmodpfx_ ## type *v = state_r(ctx, va); \
\
if (v == NULL) \
return (0); \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
return (!!v->protected); \
}
/* subset of tbl/vcc_types.h which we support */
/* standard text for defaults doc */
#define DEFDOC The default fallback is
#define DEF_ACL
#define DEFDOC_ACL
VCC_TYPE(ACL, acl)
#define DEF_BACKEND =0
#define DEFDOC_BACKEND DEFDOC no backend.
#define DEF_BACKEND =0
VCC_TYPE(BACKEND, backend)
#define DEF_BLOB
#define DEFDOC_BLOB
VCC_TYPE(BLOB, blob)
#define DEF_BODY
#define DEFDOC_BODY
VCC_TYPE(BODY, body)
#define DEF_BOOL
#define DEFDOC_BOOL
VCC_TYPE(BOOL, bool)
#define DEF_BYTES
#define DEFDOC_BYTES
VCC_TYPE(BYTES, bytes)
#define DEF_DURATION =0
#define DEFDOC_DURATION DEFDOC 0s.
VCC_TYPE(DURATION, duration)
// VCC_TYPE(ENUM, enum)
#define DEF_HEADER
#define DEFDOC_HEADER
VCC_TYPE(HEADER, header)
// VCC_TYPE(HTTP, http)
// VCC_TYPE(INSTANCE, instance)
#define DEF_INT =0
#define DEFDOC_INT DEFDOC 0.
VCC_TYPE(INT, int)
#define DEF_IP
#define DEFDOC_IP
VCC_TYPE(IP, ip)
#define DEF_PROBE
#define DEFDOC_PROBE
VCC_TYPE(PROBE, probe)
#define DEF_REAL =0.0
#define DEFDOC_REAL DEFDOC 0.0.
VCC_TYPE(REAL, real)
#define DEF_STEVEDORE
#define DEFDOC_STEVEDORE
VCC_TYPE(STEVEDORE, stevedore)
// VCC_TYPE(STRANDS)
#define DEF_STRING =0
#define DEFDOC_STRING DEFDOC the empty string.
VCC_TYPE(STRING, string)
// VCC_TYPE(STRINGS)
// VCC_TYPE(STRING_LIST)
// VCC_TYPE(SUB)
#define DEF_TIME =0
#define DEFDOC_TIME DEFDOC the epoch (1970/1/1 0:00:00 GMT).
VCC_TYPE(TIME, time)
// VCC_TYPE(VCL)
// VCC_TYPE(VOID)
#undef VCC_TYPE
/* subset of tbl/vcc_types.h which we can test */
#define VTC1_ACL acl1
#define VTC2_ACL acl2
#define CMP_ACL(a, b) a == b
VCC_TYPE(ACL, acl)
#define VTC1_BACKEND b1
#define VTC2_BACKEND b2
#define CMP_BACKEND(a, b) a == b
VCC_TYPE(BACKEND, backend)
#define VTC1_BLOB blob1.get()
#define VTC2_BLOB blob2.get()
#define CMP_BLOB(a, b) blob.equal(a, b)
VCC_TYPE(BLOB, blob)
// body support is very rudimentary
//#define VTC1_BODY
//#define VTC2_BODY
//VCC_TYPE(BODY, body)
// #2809 VCC bug for xx = bool1 == bool2
//#define VTC1_BOOL true
//#define VTC2_BOOL false
//#define CMP_BOOL(a, b) a == b
//VCC_TYPE(BOOL, bool)
#define VTC1_BYTES 1MB
#define VTC2_BYTES 2GB
#define CMP_BYTES(a, b) a == b
VCC_TYPE(BYTES, bytes)
#define VTC1_DURATION 1s
#define VTC2_DURATION 2h
#define CMP_DURATION(a, b) a == b
VCC_TYPE(DURATION, duration)
// VCC_TYPE(ENUM, enum)
// no way to get a header in vcl_init{}
//#define VTC1_HEADER
//#define VTC2_HEADER
//#define CMP_HEADER(a, b) a == b
//VCC_TYPE(HEADER, header)
// VCC_TYPE(HTTP, http)
// VCC_TYPE(INSTANCE, instance)
#define VTC1_INT 1
#define VTC2_INT 2
#define CMP_INT(a, b) a == b
VCC_TYPE(INT, int)
#define VTC1_IP "127.0.0.1"
#define VTC2_IP "127.0.0.2"
#define CMP_IP(a, b) a == b
VCC_TYPE(IP, ip)
#define VTC1_PROBE p1
#define VTC2_PROBE p2
#define CMP_PROBE(a, b) a == b
VCC_TYPE(PROBE, probe)
#define VTC1_REAL 1.1
#define VTC2_REAL 2.2
#define CMP_REAL(a, b) a == b
VCC_TYPE(REAL, real)
#define VTC1_STEVEDORE storage.stv1
#define VTC2_STEVEDORE storage.stv2
#define CMP_STEVEDORE(a, b) a == b
VCC_TYPE(STEVEDORE, stevedore)
// VCC_TYPE(STRANDS)
#define VTC1_STRING "1"
#define VTC2_STRING "2"
#define CMP_STRING(a, b) a == b
VCC_TYPE(STRING, string)
// VCC_TYPE(STRINGS)
// VCC_TYPE(STRING_LIST)
// VCC_TYPE(SUB)
#define VTC1_TIME now + 1h
#define VTC2_TIME now + 2h
#define CMP_TIME(a, b) (b - a < 10m)
VCC_TYPE(TIME, time)
// VCC_TYPE(VCL)
// VCC_TYPE(VOID)
#undef VCC_TYPE
/*-
* Copyright 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
const struct vmod_priv null_blob[1] = {{ 0 }};
/* based upon REPLACE() from miniobj.h */
#define cp_string(dst, src) \
do { \
char *d; \
if ((dst) != NULL) \
free(TRUST_ME(dst)); \
if ((src) != NULL) { \
d = strdup(src); \
AN(d); \
(dst) = d; \
} else { \
(dst) = NULL; \
} \
} while(0)
#define free_string(x) \
if (x) { \
free(TRUST_ME(x)); \
(x) = NULL; \
} \
(void)0
#define KIND_ACL immediate
#define CP_ACL(dst, src) (dst) = (src)
#define FREE_ACL(ptr) (void)0
#define KIND_BACKEND immediate
#define CP_BACKEND(dst, src) (dst) = (src)
#define FREE_BACKEND(ptr) (void)0
#define KIND_BLOB pointer
#define CP_BLOB(dst, src) \
do { \
struct vmod_priv *d; \
\
FREE_BLOB(dst); \
if ((src) == NULL || (src)->len == 0 || \
(src)->priv == NULL) { \
(dst) = null_blob; \
} else { \
d = malloc(sizeof *d); \
AN(d); \
d->priv = malloc((src)->len); \
AN(d->priv); \
memcpy(d->priv, (src)->priv, (src)->len); \
d->len = (src)->len; \
d->free = free; \
(dst) = d; \
} \
} while(0)
#define FREE_BLOB(ptr) \
if ((ptr) != NULL && (ptr) != null_blob) { \
VRT_priv_fini(ptr); \
free(TRUST_ME(ptr)); \
(ptr) = NULL; \
} \
(void)0
#define KIND_BODY pointer
#define CP_BODY(dst, src) cp_string(dst, src)
#define FREE_BODY(ptr) free_string(ptr)
#define KIND_BOOL immediate
#define CP_BOOL(dst, src) (dst) = (src)
#define FREE_BOOL(ptr) (void)0
#define KIND_BYTES immediate
#define CP_BYTES(dst, src) (dst) = (src)
#define FREE_BYTES(ptr) (void)0
#define KIND_DURATION immediate
#define CP_DURATION(dst, src) (dst) = (src)
#define FREE_DURATION(ptr) (void)0
#define KIND_HEADER pointer
#define CP_HEADER(dst, src) \
do { \
const struct gethdr_s *o = dst; \
struct gethdr_s *h; \
FREE_HEADER(o); \
AN(src); \
AN((src)->what); \
h = malloc(sizeof *h); \
AN(h); \
h->where = (src)->where; \
h->what = strdup((src)->what); \
AN(h->what); \
(dst) = h; \
} while(0)
#define FREE_HEADER(ptr) \
if ((ptr) != NULL) { \
if ((ptr)->what) \
free(TRUST_ME((ptr)->what)); \
free(TRUST_ME(ptr)); \
(ptr) = NULL; \
} \
(void)0
#define KIND_INT immediate
#define CP_INT(dst, src) (dst) = (src)
#define FREE_INT(ptr) (void)0
#define KIND_IP pointer
#define CP_IP(dst, src) \
do { \
struct suckaddr *d; \
FREE_IP(dst); \
d = malloc(vsa_suckaddr_len); \
AN(d); \
memcpy(d, (src), vsa_suckaddr_len); \
(dst) = d; \
} while(0)
#define FREE_IP(ptr) \
if ((ptr) != NULL) { \
free(TRUST_ME(ptr)); \
(ptr) = NULL; \
} \
(void)0
#define KIND_PROBE immediate
#define CP_PROBE(dst, src) (dst) = (src)
#define FREE_PROBE(ptr) (void)0
#define KIND_REAL immediate
#define CP_REAL(dst, src) (dst) = (src)
#define FREE_REAL(ptr) (void)0
#define KIND_STEVEDORE immediate
#define CP_STEVEDORE(dst, src) (dst) = (src)
#define FREE_STEVEDORE(ptr) (void)0
#define KIND_STRING pointer
#define CP_STRING(dst, src) cp_string(dst, src)
#define FREE_STRING(ptr) free_string(ptr)
#define KIND_TIME immediate
#define CP_TIME(dst, src) (dst) = (src)
#define FREE_TIME(ptr) (void)0
// max 3 nibbles
#define OBJVAR_ACL_MAGIC 0xac1
#define OBJVAR_BACKEND_MAGIC 0xbec
#define OBJVAR_BLOB_MAGIC 0xb10
#define OBJVAR_BODY_MAGIC 0xb0d
#define OBJVAR_BOOL_MAGIC 0xb00
#define OBJVAR_BYTES_MAGIC 0xb47
#define OBJVAR_DURATION_MAGIC 0xd08
#define OBJVAR_HEADER_MAGIC 0x6ea
#define OBJVAR_INT_MAGIC 0x1e7
#define OBJVAR_IP_MAGIC 0x017
#define OBJVAR_PROBE_MAGIC 0x680
#define OBJVAR_REAL_MAGIC 0x8ea
#define OBJVAR_STEVEDORE_MAGIC 0x57e
#define OBJVAR_STRING_MAGIC 0x578
#define OBJVAR_TIME_MAGIC 0x71e
/*-
* Copyright (c) 2010 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Memory barriers
*
* XXX: It is utterly braindamaged, that no standard facility for this
* XXX: is available. The "just use pthreads locking" excuse does not
* XXX: make sense, and does not apply to two unthreaded programs sharing
* XXX: a memory segment.
*/
#ifndef VMB_H_INCLUDED
#define VMB_H_INCLUDED
#if defined(__FreeBSD__)
#include <sys/param.h>
#endif
#if defined(__FreeBSD__) && __FreeBSD_version >= 800058
#include <sys/types.h>
#include <machine/atomic.h>
#define VMB() mb()
#define VWMB() wmb()
#define VRMB() rmb()
#elif defined(__amd64__) && defined(__GNUC__)
#define VMB() __asm __volatile("mfence;" : : : "memory")
#define VWMB() __asm __volatile("sfence;" : : : "memory")
#define VRMB() __asm __volatile("lfence;" : : : "memory")
#elif defined(__arm__)
#define VMB()
#define VWMB()
#define VRMB()
#elif defined(__i386__) && defined(__GNUC__)
#define VMB() __asm __volatile("lock; addl $0,(%%esp)" : : : "memory")
#define VWMB() __asm __volatile("lock; addl $0,(%%esp)" : : : "memory")
#define VRMB() __asm __volatile("lock; addl $0,(%%esp)" : : : "memory")
#elif defined(__sparc64__) && defined(__GNUC__)
#define VMB() __asm__ __volatile__ ("membar #MemIssue": : :"memory")
#define VWMB() VMB()
#define VRMB() VMB()
#else
#define VMB_NEEDS_PTHREAD_WORKAROUND_THIS_IS_BAD_FOR_PERFORMANCE 1
void vmb_pthread(void);
#define VMB() vmb_pthread()
#define VWMB() vmb_pthread()
#define VRMB() vmb_pthread()
#endif
#endif /* VMB_H_INCLUDED */
/*-
* Copyright 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <cache/cache.h>
#include <vdef.h>
#include <vrt.h>
#include <vcl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <vsa.h>
#include "vcc_constant_if.h"
#include "type_magics.h"
#include "type_cp.h"
#define tv_magic 0x4000
#define VMOD_CONSTANT_ACL_MAGIC (tv_magic | OBJVAR_ACL_MAGIC)
#define VMOD_CONSTANT_BACKEND_MAGIC (tv_magic | OBJVAR_BACKEND_MAGIC)
#define VMOD_CONSTANT_BLOB_MAGIC (tv_magic | OBJVAR_BLOB_MAGIC)
#define VMOD_CONSTANT_BODY_MAGIC (tv_magic | OBJVAR_BODY_MAGIC)
#define VMOD_CONSTANT_BOOL_MAGIC (tv_magic | OBJVAR_BOOL_MAGIC)
#define VMOD_CONSTANT_BYTES_MAGIC (tv_magic | OBJVAR_BYTES_MAGIC)
#define VMOD_CONSTANT_DURATION_MAGIC (tv_magic | OBJVAR_DURATION_MAGIC)
#define VMOD_CONSTANT_HEADER_MAGIC (tv_magic | OBJVAR_HEADER_MAGIC)
#define VMOD_CONSTANT_INT_MAGIC (tv_magic | OBJVAR_INT_MAGIC)
#define VMOD_CONSTANT_IP_MAGIC (tv_magic | OBJVAR_IP_MAGIC)
#define VMOD_CONSTANT_PROBE_MAGIC (tv_magic | OBJVAR_PROBE_MAGIC)
#define VMOD_CONSTANT_REAL_MAGIC (tv_magic | OBJVAR_REAL_MAGIC)
#define VMOD_CONSTANT_STEVEDORE_MAGIC (tv_magic | OBJVAR_STEVEDORE_MAGIC)
#define VMOD_CONSTANT_STRING_MAGIC (tv_magic | OBJVAR_STRING_MAGIC)
#define VMOD_CONSTANT_TIME_MAGIC (tv_magic | OBJVAR_TIME_MAGIC)
VCL_STRING __match_proto__(td_constant_hello)
vmod_hello(VRT_CTX)
{
#define var_code(VMODPFX_, vmodpfx_, TYPE, type) \
struct vmodpfx_ ## type { \
uint16_t magic; \
int defined:1; \
VCL_ ## TYPE var; \
}; \
\
VCL_VOID \
vmod_ ## type ## __init(VRT_CTX, \
struct vmodpfx_ ## type **vp, \
const char *vcl_name, \
struct vmod_ ## type ##__init_arg *args) \
{ \
struct vmodpfx_ ## type *v; \
\
AN(vp); \
AZ(*vp); \
\
ALLOC_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
if (v == NULL) { \
VRT_fail(ctx, "%s: alloc failed", vcl_name); \
return; \
} \
\
if (args->valid_init) { \
CP_ ## TYPE (v->var, args->init); \
v->defined = 1; \
} \
*vp = v; \
} \
\
VCL_VOID \
vmod_ ## type ## __fini(struct vmodpfx_ ## type **vp) \
{ \
struct vmodpfx_ ## type *v = *vp; \
\
*vp = NULL; \
if (v == NULL) \
return; \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
FREE_ ## TYPE (v->var); \
FREE_OBJ(v); \
} \
\
VCL_ ## TYPE \
vmod_ ## type ## _get(VRT_CTX, struct vmodpfx_ ## type *v, \
VCL_ ## TYPE fallback) \
{ \
CHECK_OBJ_NOTNULL(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
if (v->defined) \
return (v->var); \
\
return (fallback); \
} \
\
VCL_BOOL \
vmod_ ## type ## _defined(VRT_CTX, struct vmodpfx_ ## type *v) \
{ \
CHECK_OBJ_NOTNULL(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
return (!!v->defined); \
}
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
return ("vmod-constant");
}
#define VCC_TYPE(TYPE, type) var_code(VMOD_CONSTANT_, vmod_constant_, TYPE, type)
#include "tbl_types.h"
$Module constant 3 Varnish constant Module
DESCRIPTION
===========
This VCC file was generated by VCDK, it is used to for both the VMOD
interface and its manual using reStructuredText.
XXX: document vmod-constant
Example
::
import constant;
sub vcl_deliver {
set resp.http.Hello = constant.hello();
}
XXX: define vmod-constant interface
$Function STRING hello()
Description
Hello world for vmod-constant
SEE ALSO
========vcl\(7),varnishd\(1)
$Module constant 3 Varnish constant Module
DESCRIPTION
===========
This module implements globally (per vcl) scoped constants as objects:
All vcl subroutines have the same view on constants.
The value of a constant is the value assigned to it at construction
time, if any.
constants can be undefined. Attempts to ``.get`` an undefined value
will return a the ``.get`` method`s `fallback` argument, which in turn
may have a default for some cases.
Example::
import constant;
sub vcl_init {
new xint = constant.int(42);
new xundef = constant.int();
}
sub vcl_recv {
set req.http.def = xundef.defined(); # false
set req.http.fallback = xundef.get(5); # 5
}
sub vcl_deliver {
set resp.http.the-answer = xint.get(); # 42
}
The implementation of the various classes of this vmod is
auto-generated, and so is the documentation. Thus, the documentation
following this generic description is identical for all types except
for the respective type names and the ``.get()`` fallback.
.. just a newline
#define VCC_TYPE(TYPE, type) \
$Object type([TYPE init])\n \
Construct a(n) TYPE constant with the value `init`,\n \
if provided. If no `init` value is provided, the constant\n \
will be undefined.\n \
$Method TYPE .get(TYPE fallback DEF_ ## TYPE)\n \
Return the value of the constant or the `fallback` argument\n \
if it is undefined. DEFDOC_ ## TYPE\n \
$Method BOOL .defined()\n \
Return whether the constant is defined.
#include "tbl_types.h"
SEE ALSO
========
vcl\(7),varnishd\(1)
/*-
* Copyright 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <cache/cache.h>
#include <vdef.h>
#include <vrt.h>
#include <vcl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <vsa.h>
#include "vmb.h"
#include "vcc_globalvar_if.h"
#include "type_magics.h"
#include "type_cp.h"
typedef void var_free_f(const void *);
VCL_STRING __match_proto__(td_globalvar_hello)
vmod_hello(VRT_CTX)
struct vmod_globalvar_var {
unsigned magic; // same magic as vmod obj | below
#define VMOD_GLOBALVAR_VAR_MAGIC_BITS 0x07a80000
unsigned refcnt;
pthread_mutex_t mtx;
var_free_f *free_f;
const void *val;
};
/* reference per value where the value is not immediate:
*
* the vmod obj keeps a reference as long as the value is live
*
* for read access, we grab a reference once per task: when the priv_task is new
* (priv is NULL) we refcnt, then set the priv to the value struct
*
* return void pointer to value
*/
static void
unref_var(struct vmod_globalvar_var *v)
{
unsigned r;
pthread_mutex_lock(&v->mtx);
r = --v->refcnt;
pthread_mutex_unlock(&v->mtx);
if (r)
return;
AZ(v->refcnt);
AN(v->free_f);
v->free_f(v->val);
AZ(pthread_mutex_destroy(&v->mtx));
free(v);
}
static void
ref_var(struct vmod_globalvar_var *v)
{
AN(v->refcnt); // must be alive
pthread_mutex_lock(&v->mtx);
v->refcnt++;
pthread_mutex_unlock(&v->mtx);
}
static void
task_unref_var(void *ptr) {
unref_var((struct vmod_globalvar_var *) ptr);
}
static const void *
task_ref_var(VRT_CTX, struct vmod_globalvar_var *v, unsigned magic) {
struct vmod_priv *t;
CHECK_OBJ_NOTNULL(v, magic);
if (ctx->method & VCL_MET_TASK_H)
return (v);
t = VRT_priv_task(ctx, v);
if (t == NULL) {
VRT_fail(ctx, "no priv_task");
return (NULL);
}
if (t->priv == NULL) {
ref_var(v);
t->priv = v;
t->free = task_unref_var;
}
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
return ("vmod-globalvar");
assert(t->priv == v);
AN(v->refcnt);
return (v->val);
}
#define tv_magic 0x3000
#define VMOD_GLOBALVAR_ACL_MAGIC (tv_magic | OBJVAR_ACL_MAGIC)
#define VMOD_GLOBALVAR_BACKEND_MAGIC (tv_magic | OBJVAR_BACKEND_MAGIC)
#define VMOD_GLOBALVAR_BLOB_MAGIC (tv_magic | OBJVAR_BLOB_MAGIC)
#define VMOD_GLOBALVAR_BODY_MAGIC (tv_magic | OBJVAR_BODY_MAGIC)
#define VMOD_GLOBALVAR_BOOL_MAGIC (tv_magic | OBJVAR_BOOL_MAGIC)
#define VMOD_GLOBALVAR_BYTES_MAGIC (tv_magic | OBJVAR_BYTES_MAGIC)
#define VMOD_GLOBALVAR_DURATION_MAGIC (tv_magic | OBJVAR_DURATION_MAGIC)
#define VMOD_GLOBALVAR_HEADER_MAGIC (tv_magic | OBJVAR_HEADER_MAGIC)
#define VMOD_GLOBALVAR_INT_MAGIC (tv_magic | OBJVAR_INT_MAGIC)
#define VMOD_GLOBALVAR_IP_MAGIC (tv_magic | OBJVAR_IP_MAGIC)
#define VMOD_GLOBALVAR_PROBE_MAGIC (tv_magic | OBJVAR_PROBE_MAGIC)
#define VMOD_GLOBALVAR_REAL_MAGIC (tv_magic | OBJVAR_REAL_MAGIC)
#define VMOD_GLOBALVAR_STEVEDORE_MAGIC (tv_magic | OBJVAR_STEVEDORE_MAGIC)
#define VMOD_GLOBALVAR_STRING_MAGIC (tv_magic | OBJVAR_STRING_MAGIC)
#define VMOD_GLOBALVAR_TIME_MAGIC (tv_magic | OBJVAR_TIME_MAGIC)
#define immediate(VMODPFX_, vmodpfx_, TYPE, type) \
struct vmodpfx_ ## type { \
uint16_t magic; \
int defined:1; \
VCL_ ## TYPE var; \
}; \
\
static inline void \
init_var_ ## type(struct vmodpfx_ ## type *v) \
{ \
(void)0; \
} \
\
static inline void \
fini_var_ ## type(struct vmodpfx_ ## type *v) \
{ \
FREE_ ## TYPE (v->var); \
} \
\
static inline void \
set_var_ ## type(struct vmodpfx_ ## type *v, VCL_ ## TYPE val) \
{ \
CP_ ## TYPE (v->var, val); \
VWMB(); \
v->defined = 1; \
} \
\
static inline void \
undef_var_ ## type(struct vmodpfx_ ## type *v) \
{ \
v->defined = 0; \
} \
\
VCL_ ## TYPE \
vmod_ ## type ## _get(VRT_CTX, struct vmodpfx_ ## type *v, \
VCL_ ## TYPE fallback) \
{ \
if (! v->defined) \
return (fallback); \
VRMB(); \
return (v->var); \
}
#define pointer(VMODPFX_, vmodpfx_, TYPE, type) \
struct vmodpfx_ ## type { \
uint16_t magic; \
int defined:1; \
pthread_mutex_t mtx; \
struct vmod_globalvar_var *var; \
}; \
\
static inline void \
init_var_ ## type(struct vmodpfx_ ## type *v) \
{ \
AZ(pthread_mutex_init(&v->mtx, NULL)); \
} \
\
static inline void \
fini_var_ ## type(struct vmodpfx_ ## type *v) \
{ \
unref_var(v->var); \
AZ(pthread_mutex_destroy(&v->mtx)); \
} \
\
static void \
free_var_ ## type(const void *v) \
{ \
VCL_ ## TYPE vv = v; \
FREE_ ## TYPE(vv); \
} \
\
static inline void \
set_var_ ## type(struct vmodpfx_ ## type *v, VCL_ ## TYPE val) \
{ \
struct vmod_globalvar_var *o, *n; \
const unsigned magic = VMOD_GLOBALVAR_VAR_MAGIC_BITS | \
VMODPFX_ ## TYPE ## _MAGIC; \
\
ALLOC_OBJ(n, magic); \
AN(n); \
n->refcnt = 1; \
AZ(pthread_mutex_init(&n->mtx, NULL)); \
n->free_f = free_var_ ## type; \
CP_ ## TYPE (n->val, val); \
\
pthread_mutex_lock(&v->mtx); \
o = v->var; \
v->var = n; \
v->defined = 1; \
pthread_mutex_unlock(&v->mtx); \
if (o) \
unref_var(o); \
} \
\
static inline void \
undef_var_ ## type(struct vmodpfx_ ## type *v) \
{ \
struct vmod_globalvar_var *o; \
\
pthread_mutex_lock(&v->mtx); \
o = v->var; \
v->var = NULL; \
v->defined = 0; \
pthread_mutex_unlock(&v->mtx); \
if (o) \
unref_var(o); \
} \
\
VCL_ ## TYPE \
vmod_ ## type ## _get(VRT_CTX, struct vmodpfx_ ## type *v, \
VCL_ ## TYPE fallback) \
{ \
VCL_ ## TYPE r; \
const unsigned magic = VMOD_GLOBALVAR_VAR_MAGIC_BITS | \
VMODPFX_ ## TYPE ## _MAGIC; \
\
CHECK_OBJ_NOTNULL(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
if (! v->defined) \
return (fallback); \
\
pthread_mutex_lock(&v->mtx); \
if (! v->defined) \
r = fallback; \
else \
r = task_ref_var(ctx, v->var, magic); \
pthread_mutex_unlock(&v->mtx); \
return (r); \
}
#define var_code(VMODPFX_, vmodpfx_, TYPE, type) \
KIND_ ## TYPE (VMODPFX_, vmodpfx_, TYPE, type) \
\
VCL_VOID \
vmod_ ## type ## __init(VRT_CTX, \
struct vmodpfx_ ## type **vp, \
const char *vcl_name, \
struct vmod_ ## type ##__init_arg *args) \
{ \
struct vmodpfx_ ## type *v; \
\
AN(vp); \
AZ(*vp); \
\
ALLOC_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
if (v == NULL) { \
VRT_fail(ctx, "%s: alloc failed", vcl_name); \
return; \
} \
\
init_var_ ## type(v); \
\
if (args->valid_init) \
set_var_ ## type(v, args->init); \
\
*vp = v; \
} \
\
VCL_VOID \
vmod_ ## type ## __fini(struct vmodpfx_ ## type **vp) \
{ \
struct vmodpfx_ ## type *v = *vp; \
\
*vp = NULL; \
if (v == NULL) \
return; \
\
CHECK_OBJ(v, VMODPFX_ ## TYPE ## _MAGIC); \
fini_var_ ## type(v); \
FREE_OBJ(v); \
} \
\
VCL_VOID \
vmod_ ## type ## _set(VRT_CTX, struct vmodpfx_ ## type *v, \
VCL_ ## TYPE val) \
{ \
CHECK_OBJ_NOTNULL(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
set_var_ ## type(v, val); \
} \
\
VCL_VOID \
vmod_ ## type ## _undefine(VRT_CTX, struct vmodpfx_ ## type *v) \
{ \
struct vmod_globalvar_var *o; \
\
CHECK_OBJ_NOTNULL(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
if (! v->defined) \
return; \
\
undef_var_ ## type(v); \
} \
\
VCL_BOOL \
vmod_ ## type ## _defined(VRT_CTX, struct vmodpfx_ ## type *v) \
{ \
CHECK_OBJ_NOTNULL(v, VMODPFX_ ## TYPE ## _MAGIC); \
\
return (!!v->defined); \
}
#define VCC_TYPE(TYPE, type) var_code(VMOD_GLOBALVAR_, vmod_globalvar_, TYPE, type)
#include "tbl_types.h"
$Module globalvar 3 Varnish globalvar Module
DESCRIPTION
===========
This VCC file was generated by VCDK, it is used to for both the VMOD
interface and its manual using reStructuredText.
XXX: document vmod-globalvar
Example
::
import globalvar;
sub vcl_deliver {
set resp.http.Hello = globalvar.hello();
}
XXX: define vmod-globalvar interface
$Function STRING hello()
Description
Hello world for vmod-globalvar
SEE ALSO
========vcl\(7),varnishd\(1)
$Module globalvar 3 Varnish globalvar Module
DESCRIPTION
===========
This module implements globally (per vcl) scoped variables as objects:
All vcl subroutines have the same view on variables, any change comes
in effect immediately.
The value of a globalvar is the value assigned to it by any vcl
subroutine within each vcl or a default provided at construction time,
if any.
globalvars can be undefined. Attempts to ``.get`` an undefined value
will return a the ``.get`` method`s `fallback` argument, which in turn
may have a default for some cases.
Where necessary, read access to globalvar variables is reference
counted using priv_task state, such that changed variables` storage is
not freed before the last access ceased.
Example with an initially undefined variable::
import globalvar;
sub vcl_init {
new xint = globalvar.int();
}
sub vcl_recv {
set req.http.def = xint.defined(); # false
set req.http.fallback = xint.get(5); # 5
xint.set(42);
}
\# in some other request, later
sub vcl_deliver {
set resp.http.the-answer = xint.get(); # 42
}
The implementation of the various classes of this vmod is
auto-generated, and so is the documentation. Thus, the documentation
following this generic description is identical for all types except
for the respective type names and the ``.get()`` fallback.
.. just a newline
#define VCC_TYPE(TYPE, type) \
$Object type([TYPE init])\n \
Construct a(n) TYPE globalvar with the default value `init`,\n \
if provided. If no `init` value is provided, the variable\n \
will be initially undefined.\n \
$Method TYPE .get(TYPE fallback DEF_ ## TYPE)\n \
Return the value of the globalvar or the `fallback` argument\n \
if it is undefined. DEFDOC_ ## TYPE\n \
$Method VOID .set(TYPE)\n \
Set the value of the globalvar.\n\n \
$Method VOID .undefine()\n \
Undefine the globalvar.\n \
$Method BOOL .defined()\n \
Return whether the globalvar is defined.\n
#include "tbl_types.h"
SEE ALSO
========
vcl\(7),varnishd\(1)
/*-
* Copyright 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <cache/cache.h>
#include <vdef.h>
#include <vrt.h>
#include <vcl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <vsa.h>
#include "vcc_taskvar_if.h"
#include "type_magics.h"
#include "type_cp.h"
#include "tasktop.h"
#define task_common(ctx, t, v) \
do { \
if (ctx->method & VCL_MET_TASK_H) \
return (v); \
\
t = VRT_priv_task(ctx, v); \
\
if (t == NULL) { \
VRT_fail(ctx, "no priv_task"); \
return (NULL); \
} \
\
if (t->priv) \
return (t->priv); \
} while(0)
static const void *
state_r(VRT_CTX, void *v)
{
struct vmod_priv *t;
task_common(ctx, t, v);
VCL_STRING __match_proto__(td_taskvar_hello)
vmod_hello(VRT_CTX)
return (v);
}
static void *
state_l(VRT_CTX, void *v, size_t sz)
{
struct vmod_priv *t;
task_common(ctx, t, v);
t->priv = WS_Alloc(ctx->ws, sz);
if (t->priv == NULL) {
VRT_fail(ctx, "out of workspace");
return (NULL);
}
memcpy(t->priv, v, sz);
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
return ("vmod-taskvar");
return (t->priv);
}
#define tv_magic 0x1000
#define VMOD_TASKVAR_ACL_MAGIC (tv_magic | OBJVAR_ACL_MAGIC)
#define VMOD_TASKVAR_BACKEND_MAGIC (tv_magic | OBJVAR_BACKEND_MAGIC)
#define VMOD_TASKVAR_BLOB_MAGIC (tv_magic | OBJVAR_BLOB_MAGIC)
#define VMOD_TASKVAR_BODY_MAGIC (tv_magic | OBJVAR_BODY_MAGIC)
#define VMOD_TASKVAR_BOOL_MAGIC (tv_magic | OBJVAR_BOOL_MAGIC)
#define VMOD_TASKVAR_BYTES_MAGIC (tv_magic | OBJVAR_BYTES_MAGIC)
#define VMOD_TASKVAR_DURATION_MAGIC (tv_magic | OBJVAR_DURATION_MAGIC)
#define VMOD_TASKVAR_HEADER_MAGIC (tv_magic | OBJVAR_HEADER_MAGIC)
#define VMOD_TASKVAR_INT_MAGIC (tv_magic | OBJVAR_INT_MAGIC)
#define VMOD_TASKVAR_IP_MAGIC (tv_magic | OBJVAR_IP_MAGIC)
#define VMOD_TASKVAR_PROBE_MAGIC (tv_magic | OBJVAR_PROBE_MAGIC)
#define VMOD_TASKVAR_REAL_MAGIC (tv_magic | OBJVAR_REAL_MAGIC)
#define VMOD_TASKVAR_STEVEDORE_MAGIC (tv_magic | OBJVAR_STEVEDORE_MAGIC)
#define VMOD_TASKVAR_STRING_MAGIC (tv_magic | OBJVAR_STRING_MAGIC)
#define VMOD_TASKVAR_TIME_MAGIC (tv_magic | OBJVAR_TIME_MAGIC)
#define VCC_TYPE(TYPE, type) var_code(VMOD_TASKVAR_, vmod_taskvar_, TYPE, type)
#include "tbl_types.h"
......@@ -26,3 +26,27 @@ Description
SEE ALSO
========vcl\(7),varnishd\(1)
$Object acl([ACL init])
$Method ACL .get(ACL fallback=0)
$Method VOID .set(ACL)
$Method VOID .undefine()
$Method BOOL .defined()
$Method VOID .protect()
$Method BOOL .protected()
$Object int([INT init])
$Method INT .get(INT fallback=0)
$Method VOID .set(INT)
$Method VOID .undefine()
$Method BOOL .defined()
$Method VOID .protect()
$Method BOOL .protected()
$Object string([STRING init])
$Method STRING .get(STRING fallback=0)
$Method VOID .set(STRING)
$Method VOID .undefine()
$Method BOOL .defined()
$Method VOID .protect()
$Method BOOL .protected()
$Module taskvar 3 Varnish taskvar Module
DESCRIPTION
===========
This module implements `task` scoped variables as objects: Each client
or backend request (`task`) has their own view of taskvar variables.
The value of a taskvar is the value assigned to it within a `task` or
a default provided at construction time, if any.
taskvars can be undefined. Attempts to ``.get`` an undefined value
will return a the ``.get`` method`s `fallback` argument, which in turn
may have a default for some cases.
taskvar variables can be protected against write access, in which case
any attempt to set them triggers a VCL failure at runtime.
Example with an initially undefined variable::
import taskvar;
sub vcl_init {
new xint = taskvar.int();
}
sub vcl_recv {
set req.http.def = xint.defined(); # false
set req.http.fallback = xint.get(5); # 5
xint.set(42);
}
sub vcl_deliver {
set resp.http.the-answer = xint.get(); # 42
}
Example with an initially defined variable::
import taskvar;
sub vcl_init {
new xint = taskvar.int(17);
}
sub vcl_recv {
set req.http.def = xint.defined(); # true
set req.http.fallback = xint.get(5); # 17
xint.set(42);
xint.protect();
if (false) {
xint.set(3); # would fail
}
}
sub vcl_deliver {
set resp.http.the-answer = xint.get(); # 42
}
The implementation of the various classes of this vmod is
auto-generated, and so is the documentation. Thus, the documentation
following this generic description is identical for all types except
for the respective type names and the ``.get()`` fallback.
.. just a newline
#define VCC_TYPE(TYPE, type) \
$Object type([TYPE init])\n \
Construct a(n) TYPE taskvar with the default value `init`,\n \
if provided. If no `init` value is provided, the variable\n \
will be initially undefined.\n \
$Method TYPE .get(TYPE fallback DEF_ ## TYPE)\n \
Return the value of the taskvar or the `fallback` argument\n \
if it is undefined. DEFDOC_ ## TYPE\n \
$Method VOID .set(TYPE)\n \
Set the value of the taskvar.\n\n \
Triggers a vcl failure for protected variables.\n \
$Method VOID .undefine()\n \
Undefine the taskvar.\n \
$Method BOOL .defined()\n \
Return whether the taskvar is defined.\n \
$Method VOID .protect()\n \
Protect the taskvar, so any future .set() calls on it\n \
trigger a vcl failure.\n \
$Method BOOL .protected()\n \
Return whether the taskvar is protected.\n
#include "tbl_types.h"
SEE ALSO
========
vcl\(7),varnishd\(1)
/*-
* Copyright 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <cache/cache.h>
#include <vdef.h>
#include <vrt.h>
#include <vcl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <vsa.h>
#include "vcc_topvar_if.h"
#include "type_magics.h"
#include "type_cp.h"
#include "tasktop.h"
#define top_common(ctx, t, v) \
do { \
if (ctx->method & VCL_MET_TASK_H) \
return (v); \
\
if (ctx->req == NULL) { \
VRT_fail(ctx, "only available" \
" in client context"); \
return (NULL); \
} \
t = VRT_priv_top(ctx, v); \
\
if (t == NULL) { \
VRT_fail(ctx, "no priv_top"); \
return (NULL); \
} \
\
if (t->priv) \
return (t->priv); \
} while(0)
static const void *
state_r(VRT_CTX, void *v)
{
struct vmod_priv *t;
top_common(ctx, t, v);
VCL_STRING __match_proto__(td_topvar_hello)
vmod_hello(VRT_CTX)
return (v);
}
static void *
state_l(VRT_CTX, void *v, size_t sz)
{
struct vmod_priv *t;
top_common(ctx, t, v);
t->priv = WS_Alloc(ctx->req->top->ws, sz);
if (t->priv == NULL) {
VRT_fail(ctx, "out of workspace");
return (NULL);
}
memcpy(t->priv, v, sz);
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
return ("vmod-topvar");
return (t->priv);
}
#define tv_magic 0x2000
#define VMOD_TOPVAR_ACL_MAGIC (tv_magic | OBJVAR_ACL_MAGIC)
#define VMOD_TOPVAR_BACKEND_MAGIC (tv_magic | OBJVAR_BACKEND_MAGIC)
#define VMOD_TOPVAR_BLOB_MAGIC (tv_magic | OBJVAR_BLOB_MAGIC)
#define VMOD_TOPVAR_BODY_MAGIC (tv_magic | OBJVAR_BODY_MAGIC)
#define VMOD_TOPVAR_BOOL_MAGIC (tv_magic | OBJVAR_BOOL_MAGIC)
#define VMOD_TOPVAR_BYTES_MAGIC (tv_magic | OBJVAR_BYTES_MAGIC)
#define VMOD_TOPVAR_DURATION_MAGIC (tv_magic | OBJVAR_DURATION_MAGIC)
#define VMOD_TOPVAR_HEADER_MAGIC (tv_magic | OBJVAR_HEADER_MAGIC)
#define VMOD_TOPVAR_INT_MAGIC (tv_magic | OBJVAR_INT_MAGIC)
#define VMOD_TOPVAR_IP_MAGIC (tv_magic | OBJVAR_IP_MAGIC)
#define VMOD_TOPVAR_PROBE_MAGIC (tv_magic | OBJVAR_PROBE_MAGIC)
#define VMOD_TOPVAR_REAL_MAGIC (tv_magic | OBJVAR_REAL_MAGIC)
#define VMOD_TOPVAR_STEVEDORE_MAGIC (tv_magic | OBJVAR_STEVEDORE_MAGIC)
#define VMOD_TOPVAR_STRING_MAGIC (tv_magic | OBJVAR_STRING_MAGIC)
#define VMOD_TOPVAR_TIME_MAGIC (tv_magic | OBJVAR_TIME_MAGIC)
#define VCC_TYPE(TYPE, type) var_code(VMOD_TOPVAR_, vmod_topvar_, TYPE, type)
#include "tbl_types.h"
$Module topvar 3 Varnish topvar Module
DESCRIPTION
===========
This VCC file was generated by VCDK, it is used to for both the VMOD
interface and its manual using reStructuredText.
XXX: document vmod-topvar
Example
::
import topvar;
sub vcl_deliver {
set resp.http.Hello = topvar.hello();
}
XXX: define vmod-topvar interface
$Function STRING hello()
Description
Hello world for vmod-topvar
SEE ALSO
========vcl\(7),varnishd\(1)
$Module topvar 3 Varnish topvar Module
DESCRIPTION
===========
This module implements `top` scoped variables as objects: Each client
request including all esi include levels (`top`) has its own view of
topvar variables.
The value of a topvar is the value assigned to it within any esi
subrequest or a default provided at construction time, if any.
topvars can be undefined. Attempts to ``.get`` an undefined value will
return a the ``.get`` method`s `fallback` argument, which in turn may
have a default for some cases.
topvar variables can be protected against write access, in which case
any attempt to set them triggers a VCL failure at runtime.
Example::
import topvar;
sub vcl_init {
new xint = topvar.int();
}
sub vcl_recv {
if (req.esi_level == 0) {
set req.http.def = xint.defined(); # false
set req.http.fallback = xint.get(5); # 5
xint.set(42);
} else {
set req.http.fallback = xint.get(5); #42
}
}
sub vcl_deliver {
set resp.http.the-answer = xint.get(); # 42
}
The implementation of the various classes of this vmod is
auto-generated, and so is the documentation. Thus, the documentation
following this generic description is identical for all types except
for the respective type names and the ``.get()`` fallback.
.. just a newline
#define VCC_TYPE(TYPE, type) \
$Object type([TYPE init])\n \
Construct a(n) TYPE topvar with the default value `init`,\n \
if provided. If no `init` value is provided, the variable\n \
will be initially undefined.\n \
$Method TYPE .get(TYPE fallback DEF_ ## TYPE)\n \
Return the value of the topvar or the `fallback` argument\n \
if it is undefined. DEFDOC_ ## TYPE\n \
$Method VOID .set(TYPE)\n \
Set the value of the topvar.\n\n \
Triggers a vcl failure for protected variables.\n \
$Method VOID .undefine()\n \
Undefine the topvar.\n \
$Method BOOL .defined()\n \
Return whether the topvar is defined.\n \
$Method VOID .protect()\n \
Protect the topvar, so any future .set() calls on it\n \
trigger a vcl failure.\n \
$Method BOOL .protected()\n \
Return whether the topvar is protected.\n
#include "tbl_types.h"
SEE ALSO
========
vcl\(7),varnishd\(1)
varnishtest "test vmod-constant"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import constant;
sub vcl_deliver {
set resp.http.Hello = constant.hello();
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Hello == "vmod-constant"
} -run
varnishtest "test vmod-globalvar"
server s1 {
#define VCC_TYPE(TYPE, type) \
rxreq\n \
txresp
#include "../tbl_vtc.h"
} -start
varnish v1 \\
-arg "-sstv1=default,1m" \\
-arg "-sstv2=default,1m" \\
-vcl+backend {
import globalvar;
import blob;
acl acl1 { "127.0.0.1"/32; }
acl acl2 { "127.0.0.2"/32; }
probe p1 { .url = "/1"; }
probe p2 { .url = "/2"; }
backend b1 { .host = "127.0.0.1"; }
backend b2 { .host = "127.0.0.2"; }
sub vcl_init {
new blob1 = blob.blob(encoded="1");
new blob2 = blob.blob(encoded="2");
#define VCC_TYPE(TYPE, type) \
new x ## type = globalvar. %% type (); \
new xd ## type = globalvar. %% type ( VTC1_ ## TYPE );
#include "../tbl_vtc.h"
}
sub vcl_recv {
#define VCC_TYPE(TYPE, type) \
if (req.http.what == #type) { \
set req.http.def1-x = x ## type %% .defined(); \
set req.http.def1-xd = xd ## type %% .defined(); \
set req.http.get1-x = CMP_ ## TYPE ( \
x ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
set req.http.get1-xd = CMP_ ## TYPE ( \
xd ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
return (pass);
}
sub vcl_deliver {
set resp.http.def1-x = req.http.def1-x;
set resp.http.def1-xd = req.http.def1-xd;
set resp.http.get1-x = req.http.get1-x;
set resp.http.get1-xd = req.http.get1-xd;
}
} -start
#define VCC_TYPE(TYPE, type) \
client c ## type {\n \
txreq -hdr {what: type}\n \
rxresp\n \
expect resp.status == 200\n \
expect resp.http.def1-x == "false"\n \
expect resp.http.def1-xd == "true"\n \
expect resp.http.get1-x == "true"\n \
expect resp.http.get1-xd == "false"\n \
} -run
#include "../tbl_vtc.h"
varnishtest "test vmod-globalvar"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import globalvar;
sub vcl_deliver {
set resp.http.Hello = globalvar.hello();
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Hello == "vmod-globalvar"
} -run
varnishtest "test vmod-globalvar"
server s1 {
#define VCC_TYPE(TYPE, type) \
rxreq\n \
txresp
#include "../tbl_vtc.h"
} -start
varnish v1 \\
-arg "-sstv1=default,1m" \\
-arg "-sstv2=default,1m" \\
-vcl+backend {
import globalvar;
import blob;
acl acl1 { "127.0.0.1"/32; }
acl acl2 { "127.0.0.2"/32; }
probe p1 { .url = "/1"; }
probe p2 { .url = "/2"; }
backend b1 { .host = "127.0.0.1"; }
backend b2 { .host = "127.0.0.2"; }
sub vcl_init {
new blob1 = blob.blob(encoded="1");
new blob2 = blob.blob(encoded="2");
#define VCC_TYPE(TYPE, type) \
new x ## type = globalvar. %% type (); \
new xd ## type = globalvar. %% type ( VTC1_ ## TYPE );
#include "../tbl_vtc.h"
}
sub vcl_recv {
#define VCC_TYPE(TYPE, type) \
if (req.http.what == #type) { \
set req.http.def1-x = x ## type %% .defined(); \
set req.http.def1-xd = xd ## type %% .defined(); \
set req.http.get1-x = CMP_ ## TYPE ( \
x ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
set req.http.get1-xd = CMP_ ## TYPE ( \
xd ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
x ## type %% .set( VTC2_ ## TYPE ); \
xd ## type %% .set( VTC2_ ## TYPE ); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
return (pass);
}
sub vcl_deliver {
set resp.http.def1-x = req.http.def1-x;
set resp.http.def1-xd = req.http.def1-xd;
set resp.http.get1-x = req.http.get1-x;
set resp.http.get1-xd = req.http.get1-xd;
#define VCC_TYPE(TYPE, type) \
if (req.http.what == #type) { \
set resp.http.def2-x = x ## type %% .defined(); \
set resp.http.def2-xd = xd ## type %% .defined(); \
set resp.http.cmp2 = CMP_ ## TYPE ( \
x ## type %% .get( VTC1_ ## TYPE ), \
xd ## type %% .get( VTC1_ ## TYPE )); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
}
sub vcl_backend_fetch {
#define VCC_TYPE(TYPE, type) \
if (bereq.http.what == #type) { \
set bereq.http.bedef1-x = x ## type %% .defined(); \
set bereq.http.bedef1-xd = xd ## type %% .defined();\
set bereq.http.beget1-x = CMP_ ## TYPE ( \
x ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
set bereq.http.beget1-xd = CMP_ ## TYPE ( \
xd ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
x ## type %% .set( VTC2_ ## TYPE ); \
xd ## type %% .set( VTC2_ ## TYPE ); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
}
sub vcl_backend_response {
set beresp.http.bedef1-x = bereq.http.bedef1-x;
set beresp.http.bedef1-xd = bereq.http.bedef1-xd;
set beresp.http.beget1-x = bereq.http.beget1-x;
set beresp.http.beget1-xd = bereq.http.beget1-xd;
#define VCC_TYPE(TYPE, type) \
if (bereq.http.what == #type) { \
set beresp.http.bedef2-x = x ## type %% .defined();\
set beresp.http.bedef2-xd = xd ## type %% .defined();\
set beresp.http.becmp2 = CMP_ ## TYPE ( \
x ## type %% .get( VTC1_ ## TYPE ), \
xd ## type %% .get( VTC1_ ## TYPE )); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
}
} -start
#define VCC_TYPE(TYPE, type) \
client c ## type {\n \
txreq -hdr {what: type}\n \
rxresp\n \
expect resp.status == 200\n \
expect resp.http.def1-x == "false"\n \
expect resp.http.def1-xd == "true"\n \
expect resp.http.get1-x == "true"\n \
expect resp.http.get1-xd == "false"\n \
expect resp.http.def2-x == "true"\n \
expect resp.http.def2-xd == "true"\n \
expect resp.http.cmp2 == "true"\n \
expect resp.http.bedef1-x == "true"\n \
expect resp.http.bedef1-xd == "true"\n \
expect resp.http.beget1-x == "true"\n \
expect resp.http.beget1-xd == "true"\n \
expect resp.http.bedef2-x == "true"\n \
expect resp.http.bedef2-xd == "true"\n \
expect resp.http.becmp2 == "true"\n \
} -run
#include "../tbl_vtc.h"
varnishtest "test vmod-taskvar"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import taskvar;
sub vcl_deliver {
set resp.http.Hello = taskvar.hello();
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Hello == "vmod-taskvar"
} -run
varnishtest "test vmod-taskvar"
server s1 {
#define VCC_TYPE(TYPE, type) \
rxreq\n \
txresp
#include "../tbl_vtc.h"
} -start
varnish v1 \\
-arg "-sstv1=default,1m" \\
-arg "-sstv2=default,1m" \\
-vcl+backend {
import taskvar;
import blob;
acl acl1 { "127.0.0.1"/32; }
acl acl2 { "127.0.0.2"/32; }
probe p1 { .url = "/1"; }
probe p2 { .url = "/2"; }
backend b1 { .host = "127.0.0.1"; }
backend b2 { .host = "127.0.0.2"; }
sub vcl_init {
new blob1 = blob.blob(encoded="1");
new blob2 = blob.blob(encoded="2");
#define VCC_TYPE(TYPE, type) \
new x ## type = taskvar. %% type (); \
new xd ## type = taskvar. %% type ( VTC1_ ## TYPE );
#include "../tbl_vtc.h"
}
sub vcl_recv {
#define VCC_TYPE(TYPE, type) \
if (req.http.what == #type) { \
set req.http.def1-x = x ## type %% .defined(); \
set req.http.def1-xd = xd ## type %% .defined(); \
set req.http.get1-x = CMP_ ## TYPE ( \
x ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
set req.http.get1-xd = CMP_ ## TYPE ( \
xd ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
x ## type %% .set( VTC2_ ## TYPE ); \
xd ## type %% .set( VTC2_ ## TYPE ); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
return (pass);
}
sub vcl_deliver {
set resp.http.def1-x = req.http.def1-x;
set resp.http.def1-xd = req.http.def1-xd;
set resp.http.get1-x = req.http.get1-x;
set resp.http.get1-xd = req.http.get1-xd;
#define VCC_TYPE(TYPE, type) \
if (req.http.what == #type) { \
set resp.http.def2-x = x ## type %% .defined(); \
set resp.http.def2-xd = xd ## type %% .defined(); \
set resp.http.cmp2 = CMP_ ## TYPE ( \
x ## type %% .get( VTC1_ ## TYPE ), \
xd ## type %% .get( VTC1_ ## TYPE )); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
}
sub vcl_backend_fetch {
#define VCC_TYPE(TYPE, type) \
if (bereq.http.what == #type) { \
set bereq.http.bedef1-x = x ## type %% .defined(); \
set bereq.http.bedef1-xd = xd ## type %% .defined();\
set bereq.http.beget1-x = CMP_ ## TYPE ( \
x ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
set bereq.http.beget1-xd = CMP_ ## TYPE ( \
xd ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
x ## type %% .set( VTC2_ ## TYPE ); \
xd ## type %% .set( VTC2_ ## TYPE ); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
}
sub vcl_backend_response {
set beresp.http.bedef1-x = bereq.http.bedef1-x;
set beresp.http.bedef1-xd = bereq.http.bedef1-xd;
set beresp.http.beget1-x = bereq.http.beget1-x;
set beresp.http.beget1-xd = bereq.http.beget1-xd;
#define VCC_TYPE(TYPE, type) \
if (bereq.http.what == #type) { \
set beresp.http.bedef2-x = x ## type %% .defined();\
set beresp.http.bedef2-xd = xd ## type %% .defined();\
set beresp.http.becmp2 = CMP_ ## TYPE ( \
x ## type %% .get( VTC1_ ## TYPE ), \
xd ## type %% .get( VTC1_ ## TYPE )); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
}
} -start
#define VCC_TYPE(TYPE, type) \
client c ## type {\n \
txreq -hdr {what: type}\n \
rxresp\n \
expect resp.status == 200\n \
expect resp.http.def1-x == "false"\n \
expect resp.http.def1-xd == "true"\n \
expect resp.http.get1-x == "true"\n \
expect resp.http.get1-xd == "false"\n \
expect resp.http.def2-x == "true"\n \
expect resp.http.def2-xd == "true"\n \
expect resp.http.cmp2 == "true"\n \
expect resp.http.bedef1-x == "false"\n \
expect resp.http.bedef1-xd == "true"\n \
expect resp.http.beget1-x == "true"\n \
expect resp.http.beget1-xd == "false"\n \
expect resp.http.bedef2-x == "true"\n \
expect resp.http.bedef2-xd == "true"\n \
expect resp.http.becmp2 == "true"\n \
} -run
#include "../tbl_vtc.h"
varnishtest "test vmod-topvar"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import topvar;
sub vcl_deliver {
set resp.http.Hello = topvar.hello();
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Hello == "vmod-topvar"
} -run
varnishtest "test vmod-topvar"
#if 0
XXX IMPLEMENT ACTUAL ESI TEST
#endif
server s1 {
rxreq
txresp
} -start
varnish v1 \\
-arg "-sstv1=default,1m" \\
-arg "-sstv2=default,1m" \\
-vcl+backend {
import topvar;
import blob;
acl acl1 { "127.0.0.1"/32; }
acl acl2 { "127.0.0.2"/32; }
probe p1 { .url = "/1"; }
probe p2 { .url = "/2"; }
backend b1 { .host = "127.0.0.1"; }
backend b2 { .host = "127.0.0.2"; }
sub vcl_init {
new blob1 = blob.blob(encoded="1");
new blob2 = blob.blob(encoded="2");
#define VCC_TYPE(TYPE, type) \
new x ## type = topvar. %% type (); \
new xd ## type = topvar. %% type ( VTC1_ ## TYPE );
#include "../tbl_vtc.h"
}
sub vcl_recv {
if (req.url ~ "^/backend/") {
return (pass);
}
#define VCC_TYPE(TYPE, type) \
if (req.http.what == #type) { \
set req.http.def1-x = x ## type %% .defined(); \
set req.http.def1-xd = xd ## type %% .defined(); \
set req.http.get1-x = CMP_ ## TYPE ( \
x ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
set req.http.get1-xd = CMP_ ## TYPE ( \
xd ## type %% .get( VTC2_ ## TYPE ), \
VTC2_ ## TYPE ); \
x ## type %% .set( VTC2_ ## TYPE ); \
xd ## type %% .set( VTC2_ ## TYPE ); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
return (hash);
}
sub vcl_backend_fetch {
if (bereq.url !~ "^/backend/") {
return (fetch);
} else
if (bereq.url ~ "/get$") {
set bereq.http.foo = xint.get();
} else
if (bereq.url ~ "/set$") {
xint.set(5);
} else
if (bereq.url ~ "/undefine$") {
xint.undefine();
} else
if (bereq.url ~ "/defined$") {
set bereq.http.foo = xint.defined();
} else
if (bereq.url ~ "/protect$") {
xint.protect();
} else
if (bereq.url ~ "/protected$") {
set bereq.http.foo = xint.protected();
}
}
sub vcl_deliver {
set resp.http.def1-x = req.http.def1-x;
set resp.http.def1-xd = req.http.def1-xd;
set resp.http.get1-x = req.http.get1-x;
set resp.http.get1-xd = req.http.get1-xd;
#define VCC_TYPE(TYPE, type) \
if (req.http.what == #type) { \
set resp.http.def2-x = x ## type %% .defined(); \
set resp.http.def2-xd = xd ## type %% .defined(); \
set resp.http.cmp2 = CMP_ ## TYPE ( \
x ## type %% .get( VTC1_ ## TYPE ), \
xd ## type %% .get( VTC1_ ## TYPE )); \
} else
#include "../tbl_vtc.h"
{ return (fail); }
}
} -start
#define VCC_TYPE(TYPE, type) \
client c ## type {\n \
txreq -hdr {what: type}\n \
rxresp\n \
expect resp.status == 200\n \
expect resp.http.def1-x == "false"\n \
expect resp.http.def1-xd == "true"\n \
expect resp.http.get1-x == "true"\n \
expect resp.http.get1-xd == "false"\n \
expect resp.http.def2-x == "true"\n \
expect resp.http.def2-xd == "true"\n \
expect resp.http.cmp2 == "true"\n \
} -run
#include "../tbl_vtc.h"
client cget {
txreq -url "/backend/get"
rxresp
expect resp.status == 503
} -run
client cset {
txreq -url "/backend/set"
rxresp
expect resp.status == 503
} -run
client cundefine {
txreq -url "/backend/undefine"
rxresp
expect resp.status == 503
} -run
client cdefined {
txreq -url "/backend/defined"
rxresp
expect resp.status == 503
} -run
client cprotect {
txreq -url "/backend/protect"
rxresp
expect resp.status == 503
} -run
client cprotected {
txreq -url "/backend/protected"
rxresp
expect resp.status == 503
} -run
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment