Commit e1e90c38 authored by Geoff Simmons's avatar Geoff Simmons

intial commit, passes the first tests

parents
((nil . ((indent-tabs-mode . t)))
(c-mode . ((c-file-style . "BSD"))))
Makefile
Makefile.in
.deps/
.libs/
*.o
*.lo
*.la
*~
*.[1-9]
/aclocal.m4
/autom4te.cache/
/compile
/config.guess
/config.h
/config.h.in
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/missing
/stamp-h1
/m4/
/src/vcc_if.c
/src/vcc_if.h
/src/vmod_*rst
See LICENSE for details.
Copyright (c) 2015 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.
ACLOCAL_AMFLAGS = -I m4 -I ${LIBVARNISHAPI_DATAROOTDIR}/aclocal
SUBDIRS = src
DISTCHECK_CONFIGURE_FLAGS = \
VMOD_DIR='$${libdir}/varnish/vmods'
EXTRA_DIST = LICENSE
doc_DATA = LICENSE vmod_backend_dyn.3 src/vmod_backend_dyn.man.rst
dist_man_MANS = vmod_backend_dyn.3
MAINTAINERCLEANFILES = $(dist_man_MANS)
vmod_backend_dyn.3: src/vmod_backend_dyn.man.rst
%.1 %.2 %.3 %.4 %.5 %.6 %.7 %.8 %.9:
if HAVE_RST2MAN
${RST2MAN} $< $@
else
@echo "========================================"
@echo "You need rst2man installed to make dist"
@echo "========================================"
@false
endif
#!/bin/sh
warn() {
echo "WARNING: $@" 1>&2
}
case `uname -s` in
Darwin)
LIBTOOLIZE=glibtoolize
;;
FreeBSD)
LIBTOOLIZE=libtoolize
;;
Linux)
LIBTOOLIZE=libtoolize
;;
SunOS)
LIBTOOLIZE=libtoolize
;;
*)
warn "unrecognized platform:" `uname -s`
LIBTOOLIZE=libtoolize
esac
automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'`
if [ -z "$automake_version" ] ; then
warn "unable to determine automake version"
else
case $automake_version in
0.*|1.[0-8]|1.[0-8][.-]*)
warn "automake ($automake_version) detected; 1.9 or newer recommended"
;;
*)
;;
esac
fi
# check for varnishapi.m4 in custom paths
dataroot=$(pkg-config --variable=datarootdir varnishapi 2>/dev/null)
if [ -z "$dataroot" ] ; then
cat >&2 <<'EOF'
Package varnishapi was not found in the pkg-config search path.
Perhaps you should add the directory containing `varnishapi.pc'
to the PKG_CONFIG_PATH environment variable
EOF
exit 1
fi
set -ex
aclocal -I m4 -I ${dataroot}/aclocal
$LIBTOOLIZE --copy --force
autoheader
automake --add-missing --copy --foreign
autoconf
AC_PREREQ(2.59)
AC_COPYRIGHT([Copyright (c) 2011-2015 Varnish Software AS])
AC_INIT([libvmod-backend_dyn], [trunk])
AC_CONFIG_MACRO_DIR([m4])
m4_ifndef([VARNISH_VMOD_INCLUDES], AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
AC_CONFIG_SRCDIR(src/vmod.vcc)
AM_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_LANG(C)
AM_INIT_AUTOMAKE([foreign])
AC_GNU_SOURCE
AC_PROG_CC
AC_PROG_CC_STDC
if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([Could not find a C99 compatible compiler])
fi
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_MAKE_SET
# Check for rst utilities
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], "no")
if test "x$RST2MAN" = "xno"; then
AC_MSG_WARN([rst2man not found - not building man pages])
fi
AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([sys/stdlib.h])
# backwards compat with older pkg-config
# - pull in AC_DEFUN from pkg.m4
m4_ifndef([PKG_CHECK_VAR], [
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------
# Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
])
PKG_CHECK_MODULES([libvarnishapi], [varnishapi])
PKG_CHECK_VAR([LIBVARNISHAPI_PREFIX], [varnishapi], [prefix])
PKG_CHECK_VAR([LIBVARNISHAPI_DATAROOTDIR], [varnishapi], [datarootdir])
PKG_CHECK_VAR([LIBVARNISHAPI_BINDIR], [varnishapi], [bindir])
PKG_CHECK_VAR([LIBVARNISHAPI_SBINDIR], [varnishapi], [sbindir])
AC_SUBST([LIBVARNISHAPI_DATAROOTDIR])
# Varnish include files tree
VARNISH_VMOD_INCLUDES
VARNISH_VMOD_DIR
VARNISH_VMODTOOL
# inherit the prefix from Varnish.
# acessing ac_ variable because AC_PREFIX_DEFAULT acts too early
ac_default_prefix=$LIBVARNISHAPI_PREFIX
AC_PATH_PROG([VARNISHTEST], [varnishtest], [],
[$LIBVARNISHAPI_BINDIR:$LIBVARNISHAPI_SBINDIR:$PATH])
AC_PATH_PROG([VARNISHD], [varnishd], [],
[$LIBVARNISHAPI_SBINDIR:$LIBVARNISHAPI_BINDIR:$PATH])
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT
AM_CPPFLAGS = @VMOD_INCLUDES@ -Wall -Werror
vmoddir = @VMOD_DIR@
vmod_LTLIBRARIES = libvmod_backend_dyn.la
libvmod_backend_dyn_la_LDFLAGS = -module -export-dynamic -avoid-version -shared
libvmod_backend_dyn_la_SOURCES = \
vmod.c
nodist_libvmod_backend_dyn_la_SOURCES = \
vcc_if.c \
vcc_if.h
vmod.lo: vcc_if.c vcc_if.h
vcc_if.c: vcc_if.h
vcc_if.h: @VMODTOOL@ $(top_srcdir)/src/vmod.vcc
@VMODTOOL@ $(top_srcdir)/src/vmod.vcc
VMOD_TESTS = $(top_srcdir)/src/tests/*.vtc
.PHONY: $(VMOD_TESTS)
$(top_srcdir)/src/tests/*.vtc: libvmod_backend_dyn.la
@VARNISHTEST@ -Dvarnishd=@VARNISHD@ -Dvmod_topbuild=$(abs_top_builddir) $@
check: $(VMOD_TESTS)
EXTRA_DIST = \
vmod.vcc \
$(VMOD_TESTS)
CLEANFILES = \
$(builddir)/vcc_if.c \
$(builddir)/vcc_if.h \
$(builddir)/vmod_backend_dyn.rst \
$(builddir)/vmod_backend_dyn.man.rst
varnishtest "Does anything get through at all ?"
server s1 {
rxreq
txresp -body "012345\n"
} -start
varnish v1 -vcl {
import backend_dyn from "${vmod_topbuild}/src/.libs/libvmod_backend_dyn.so";
backend dummy { .host="${bad_ip}"; }
sub vcl_init {
if (!backend_dyn.create(name="be", host="${s1_addr}",
port="${s1_port}")) {
return(fail);
}
}
sub vcl_backend_fetch {
set bereq.backend = backend_dyn.by_name("be");
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.body == "012345\n"
}
client c1 -run
varnish v1 -cliok "backend.list -p"
varnish v1 -expect VBE.vcl1.be.bereq_hdrbytes > 0
varnish v1 -expect VBE.vcl1.be.bereq_bodybytes == 0
varnish v1 -expect VBE.vcl1.be.beresp_hdrbytes == 38
varnish v1 -expect VBE.vcl1.be.beresp_bodybytes == 7
varnish v1 -expect s_resp_bodybytes == 7
varnish v1 -expect s_resp_hdrbytes == 167
varnishtest "Check that a pipe transaction works"
server s1 -repeat 1 {
rxreq
txresp -body "012345\n"
} -start
varnish v1 -vcl {
import backend_dyn from "${vmod_topbuild}/src/.libs/libvmod_backend_dyn.so";
backend dummy { .host="${bad_ip}"; }
sub vcl_init {
if (!backend_dyn.create(name="be", host="${s1_addr}",
port="${s1_port}")) {
return(fail);
}
}
sub vcl_recv {
set req.backend_hint = backend_dyn.by_name("be");
return(pipe);
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.status == 200
} -run
varnish v1 -cliok "backend.list -p"
varnish v1 -expect s_pipe == 1
varnishtest "Check chunked encoding from backend works"
server s1 {
rxreq
expect req.url == "/bar"
send "HTTP/1.1 200 OK\r\n"
send "Transfer-encoding: chunked\r\n"
send "\r\n"
send "00000004\r\n1234\r\n"
send "00000000\r\n"
send "\r\n"
rxreq
expect req.url == "/foo"
send "HTTP/1.1 200 OK\r\n"
send "Transfer-encoding: chunked\r\n"
send "\r\n"
send "00000004\r\n1234\r\n"
chunked "1234"
chunked ""
} -start
varnish v1 -vcl {
import backend_dyn from "${vmod_topbuild}/src/.libs/libvmod_backend_dyn.so";
backend dummy { .host="${bad_ip}"; }
sub vcl_init {
if (!backend_dyn.create(name="be", host="${s1_addr}",
port="${s1_port}")) {
return(fail);
}
}
sub vcl_recv {
set req.backend_hint = backend_dyn.by_name("be");
}
} -start
client c1 {
txreq -url "/bar"
rxresp
expect resp.status == 200
expect resp.bodylen == "4"
txreq -url "/foo"
rxresp
expect resp.status == 200
expect resp.bodylen == "8"
} -run
varnishtest "Check pipelining"
server s1 {
rxreq
expect req.url == "/foo"
txresp -body "foo"
rxreq
expect req.url == "/bar"
txresp -body "foobar"
} -start
varnish v1 -vcl {
import backend_dyn from "${vmod_topbuild}/src/.libs/libvmod_backend_dyn.so";
backend dummy { .host="${bad_ip}"; }
sub vcl_init {
if (!backend_dyn.create(name="be", host="${s1_addr}",
port="${s1_port}")) {
return(fail);
}
}
sub vcl_recv {
set req.backend_hint = backend_dyn.by_name("be");
}
} -start
client c1 {
send "GET /foo HTTP/1.1\n\nGET /bar HTTP/1.1\n\nGET /bar HTTP/1.1\n\n"
rxresp
expect resp.status == 200
expect resp.bodylen == 3
expect resp.http.x-varnish == "1001"
rxresp
expect resp.status == 200
expect resp.bodylen == 6
expect resp.http.x-varnish == "1003"
rxresp
expect resp.status == 200
expect resp.bodylen == 6
expect resp.http.x-varnish == "1005 1004"
} -run
varnish v1 -expect sess_readahead == 2
varnishtest "Check read-head / partial pipelining"
server s1 {
rxreq
expect req.url == "/foo"
txresp -body "foo"
rxreq
expect req.url == "/bar"
txresp -body "foobar"
} -start
varnish v1 -vcl {
import backend_dyn from "${vmod_topbuild}/src/.libs/libvmod_backend_dyn.so";
backend dummy { .host="${bad_ip}"; }
sub vcl_init {
if (!backend_dyn.create(name="be", host="${s1_addr}",
port="${s1_port}")) {
return(fail);
}
}
sub vcl_recv {
set req.backend_hint = backend_dyn.by_name("be");
}
}
# NB: The accept_filter param may not exist.
varnish v1 -cli "param.set accept_filter false"
varnish v1 -start
client c1 {
send "GET /foo HTTP/1.1\r\n\r\nGET "
rxresp
expect resp.status == 200
expect resp.bodylen == 3
expect resp.http.x-varnish == "1001"
send "/bar HTTP/1.1\n\nGET /bar "
rxresp
expect resp.status == 200
expect resp.bodylen == 6
expect resp.http.x-varnish == "1003"
send "HTTP/1.1\n\n"
rxresp
expect resp.status == 200
expect resp.bodylen == 6
expect resp.http.x-varnish == "1005 1004"
} -run
varnish v1 -expect sess_readahead == 2
/*-
* Copyright (c) 2015 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@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 <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include "vcl.h"
#include "vrt.h"
#include "vas.h"
#include "vsa.h"
#include "vtcp.h"
#include "vdef.h"
#include "vsb.h"
#include "cache/cache.h"
#include "cache/cache_director.h"
#include "cache/cache_backend.h"
#include "vapi/vsl.h"
#include "vcc_if.h"
struct bentry {
unsigned magic;
#define BENTRY_MAGIC 0x51ced5b5
struct director *be;
VTAILQ_ENTRY(bentry) bentry;
};
struct belist {
unsigned magic;
#define BELIST_MAGIC 0x66d0afdb
VTAILQ_HEAD(behead, bentry) *behead;
};
static void
free_belist(void *priv)
{
struct belist *belist;
struct bentry *bentry;
CAST_OBJ_NOTNULL(belist, priv, BELIST_MAGIC);
AN(belist->behead);
VTAILQ_FOREACH(bentry, belist->behead, bentry)
FREE_OBJ(bentry);
FREE_OBJ(belist);
}
static void
errmsg(VRT_CTX, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (ctx->method == VCL_MET_INIT) {
AN(ctx->msg);
VSB_vprintf(ctx->msg, fmt, args);
VRT_handling(ctx, VCL_RET_FAIL);
}
else {
AN(ctx->vsl);
VSLbv(ctx->vsl, SLT_VCL_Error, fmt, args);
}
va_end(args);
}
static struct suckaddr *
get_suckaddr(VCL_STRING host, VCL_STRING port, int family)
{
struct addrinfo hints, *res = NULL;
struct suckaddr *sa = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = family;
if (getaddrinfo(host, port, &hints, &res) != 0)
return NULL;
if (res->ai_next != NULL)
return NULL;
sa = VSA_Malloc(res->ai_addr, res->ai_addrlen);
AN(sa);
assert(VSA_Sane(sa));
assert(VSA_Get_Proto(sa) == family);
freeaddrinfo(res);
return sa;
}
static char *
get_addrname(struct suckaddr *sa)
{
char a[VTCP_ADDRBUFSIZE], p[VTCP_PORTBUFSIZE], *addr;
struct vsb *sb = VSB_new_auto();
VTCP_name(sa, a, sizeof(a), p, sizeof(p));
AZ(VSB_printf(sb, "%s:%s", a, p));
AZ(VSB_finish(sb));
addr = strdup(VSB_data(sb));
AN(addr);
VSB_delete(sb);
return(addr);
}
VCL_BOOL
vmod_create(VRT_CTX, struct vmod_priv *priv, VCL_STRING vcl_name,
VCL_STRING host, VCL_STRING port, VCL_STRING host_header,
VCL_DURATION connect_timeout, VCL_DURATION first_byte_timeout,
VCL_DURATION between_bytes_timeout, VCL_INT max_connections)
{
struct belist *belist;
struct bentry *bentry;
struct director *dir;
struct vrt_backend be = { .magic = VRT_BACKEND_MAGIC };
struct suckaddr *sa4 = NULL, *sa6 = NULL;
char *ipv4_addr = NULL, *ipv6_addr = NULL;
const char *hosthdr = host_header;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(priv);
AN(vcl_name);
AN(host);
AN(port);
AN(hosthdr);
if (vcl_name[0] == '\0') {
errmsg(ctx, "vmod backend_dyn error: name must be non-empty");
return 0;
}
if (host[0] == '\0') {
errmsg(ctx, "vmod backend_dyn error: host must be non-empty");
return 0;
}
if (hosthdr[0] == '\0')
hosthdr = host;
/* XXX: check that name does not already exist in ctx->vcl */
if (priv->priv == NULL) {
ALLOC_OBJ(belist, BELIST_MAGIC);
AN(belist);
belist->behead = malloc(sizeof(belist->behead));
VTAILQ_INIT(belist->behead);
priv->priv = belist;
priv->free = free_belist;
}
else
CAST_OBJ(belist, priv->priv, BELIST_MAGIC);
sa4 = get_suckaddr(host, port, AF_INET);
sa6 = get_suckaddr(host, port, AF_INET6);
if (sa4 == NULL && sa6 == NULL) {
errmsg(ctx, "vmod backend_dyn error: "
"Cannot resolve %s:%s as a unique IPv4 or IPv6 address",
host, port);
return 0;
}
if (sa4 != NULL)
ipv4_addr = get_addrname(sa4);
if (sa6 != NULL)
ipv6_addr = get_addrname(sa6);
be.ipv4_suckaddr = sa4;
be.ipv6_suckaddr = sa6;
#define DA(x) if (x != NULL && x[0] != '\0') be.x = strdup(x);
#define DN(x) be.x = x;
VRT_BACKEND_HANDLE();
#undef DA
#undef DN
if (ipv4_addr != NULL)
free(ipv4_addr);
if (ipv6_addr != NULL)
free(ipv6_addr);
dir = VRT_new_backend(ctx, &be);
CHECK_OBJ_NOTNULL(dir, DIRECTOR_MAGIC);
ALLOC_OBJ(bentry, BENTRY_MAGIC);
AN(bentry);
bentry->be = dir;
VTAILQ_INSERT_HEAD(belist->behead, bentry, bentry);
return 1;
}
VCL_BACKEND
vmod_by_name(VRT_CTX, struct vmod_priv *priv, VCL_STRING name)
{
struct belist *belist;
struct bentry *bentry;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(priv);
AN(name);
if (priv->priv == NULL)
return NULL;
CAST_OBJ_NOTNULL(belist, priv->priv, BELIST_MAGIC);
AN(belist->behead);
VTAILQ_FOREACH(bentry, belist->behead, bentry) {
CHECK_OBJ_NOTNULL(bentry, BENTRY_MAGIC);
CHECK_OBJ_NOTNULL(bentry->be, DIRECTOR_MAGIC);
if (strcmp(name, bentry->be->vcl_name) == 0)
return bentry->be;
}
return NULL;
}
static inline struct backend *
check_and_get_backend(VRT_CTX, VCL_BACKEND be)
{
struct backend *backend;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
if (be->priv == NULL) {
errmsg(ctx, "vmod backend_dyn error: %s is not a leaf backend",
be->vcl_name);
return NULL;
}
backend = (struct backend *) be->priv;
if (backend->magic != BACKEND_MAGIC) {
errmsg(ctx, "vmod backend_dyn error: "
"%s is not a standard backend", be->vcl_name);
return NULL;
}
return backend;
}
VCL_BOOL
vmod_delete(VRT_CTX, struct vmod_priv *priv, VCL_BACKEND be)
{
struct backend *backend;
AN(priv);
backend = check_and_get_backend(ctx, be);
if (backend == NULL)
return 0;
if (priv->priv != NULL) {
struct belist *belist;
struct bentry *bentry;
CAST_OBJ(belist, priv->priv, BELIST_MAGIC);
AN(belist->behead);
VTAILQ_FOREACH(bentry, belist->behead, bentry) {
CHECK_OBJ_NOTNULL(bentry, BENTRY_MAGIC);
CHECK_OBJ_NOTNULL(bentry->be, DIRECTOR_MAGIC);
if (bentry->be == be) {
VTAILQ_REMOVE(belist->behead, bentry, bentry);
break;
}
}
}
VCL_DelBackend(backend);
return 1;
}
VCL_BOOL
vmod_add_probe(VRT_CTX, VCL_BACKEND be, VCL_PROBE probe)
{
struct backend *backend;
CHECK_OBJ_NOTNULL(probe, VRT_BACKEND_PROBE_MAGIC);
backend = check_and_get_backend(ctx, be);
if (backend == NULL)
return 0;
if (backend->probe != NULL)
VBP_Remove(backend);
VBP_Insert(backend, probe, backend->tcp_pool);
AN(backend->probe);
return 1;
}
VCL_BOOL
vmod_remove_probe(VRT_CTX, VCL_BACKEND be)
{
struct backend *backend;
backend = check_and_get_backend(ctx, be);
if (backend == NULL)
return 0;
if (backend->probe != NULL)
VBP_Remove(backend);
return 1;
}
static VCL_BOOL
control_probe(VRT_CTX, VCL_BACKEND be, int stop)
{
struct backend *backend;
backend = check_and_get_backend(ctx, be);
if (backend == NULL)
return 0;
VBP_Control(backend, stop);
return 1;
}
VCL_BOOL
vmod_stop_probe(VRT_CTX, VCL_BACKEND be)
{
return(control_probe(ctx, be, 1));
}
VCL_BOOL
vmod_start_probe(VRT_CTX, VCL_BACKEND be)
{
return(control_probe(ctx, be, 0));
}
VCL_STRING
vmod_version(VRT_CTX __attribute__((unused)))
{
return VERSION;
}
#-
# Copyright (c) 2015 UPLEX Nils Goroll Systemoptimierung
# All rights reserved
#
# Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#
# See LICENCE
#
$Module backend_dyn 3 Varnish Module to dynamically create and remove backends and probes
DESCRIPTION
===========
This is the embedded documentation for the example VMOD. It should
mention what the vmod is intended to do.
$Function BOOL create(PRIV_VCL, STRING name, STRING host, STRING port="",
STRING host_header="", DURATION connect_timeout=0,
DURATION first_byte_timeout=0,
DURATION between_bytes_timeout=0,
INT max_connections=0)
$Function BACKEND by_name(PRIV_VCL, STRING name)
$Function BOOL delete(PRIV_VCL, BACKEND be)
$Function BOOL add_probe(BACKEND be, PROBE probe)
$Function BOOL remove_probe(BACKEND be)
$Function BOOL stop_probe(BACKEND be)
$Function BOOL start_probe(BACKEND be)
$Function STRING version()
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