diff --git a/bin/varnishd/acceptor/mgt_acceptor.c b/bin/varnishd/acceptor/mgt_acceptor.c index 6984dd7d6b..002d16e901 100644 --- a/bin/varnishd/acceptor/mgt_acceptor.c +++ b/bin/varnishd/acceptor/mgt_acceptor.c @@ -106,13 +106,15 @@ VCA_reopen_sockets(void) return (fail); } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * [name=][%kind,][listen_address[,PROTO|,option=value,...]] + */ void VCA_Arg(const char *spec) { - struct acceptor *vca; - char **av; + struct acceptor *vca = NULL; + char **av, **ap; struct listen_arg *la; const char *err; int error; @@ -122,12 +124,21 @@ VCA_Arg(const char *spec) av = MGT_NamedArg(spec, &name, "-a"); AN(av); + ap = av + 1; ALLOC_OBJ(la, LISTEN_ARG_MAGIC); AN(la); VTAILQ_INIT(&la->socks); VTAILQ_INSERT_TAIL(&listen_args, la, list); - la->endpoint = av[1]; + + if (ap[0] != NULL && ap[0][0] == '%') { + vca = VCA_Find(ap[0] + 1); + if (vca == NULL) + ARGV_ERR("Acceptor %s not found\n", ap[0] + 1); + ap++; + } + + la->endpoint = *(ap++); if (name == NULL) { bprintf(name_buf, "a%u", seq++); @@ -137,13 +148,13 @@ VCA_Arg(const char *spec) la->name = name; - if (VUS_is(la->endpoint)) + if (vca == NULL && VUS_is(la->endpoint)) vca = VCA_Find("uds"); - else + else if (vca == NULL) vca = VCA_Find("tcp"); AN(vca); - error = vca->open(av + 2, la, &err); + error = vca->open(ap, la, &err); if (error) { ARGV_ERR("Got no socket(s) for %s=%s (%s)\n", diff --git a/bin/varnishd/acceptor/mgt_acceptor_tcp.c b/bin/varnishd/acceptor/mgt_acceptor_tcp.c index 1ebb4f8e5c..5661bbf698 100644 --- a/bin/varnishd/acceptor/mgt_acceptor_tcp.c +++ b/bin/varnishd/acceptor/mgt_acceptor_tcp.c @@ -167,6 +167,7 @@ vca_tcp_open(char **av, struct listen_arg *la, const char **err) CHECK_OBJ_NOTNULL(la, LISTEN_ARG_MAGIC); AN(av); AN(err); + AN(la->endpoint); AZ(la->perms); if (strchr(la->endpoint, '/') != NULL) diff --git a/bin/varnishd/acceptor/mgt_acceptor_uds.c b/bin/varnishd/acceptor/mgt_acceptor_uds.c index c10fa7af66..d9500241ad 100644 --- a/bin/varnishd/acceptor/mgt_acceptor_uds.c +++ b/bin/varnishd/acceptor/mgt_acceptor_uds.c @@ -171,7 +171,12 @@ vca_uds_open(char **av, struct listen_arg *la, const char **err) CHECK_OBJ_NOTNULL(la, LISTEN_ARG_MAGIC); AN(av); AN(err); + AN(la->endpoint); + if (! VUS_is(la->endpoint)) { + ARGV_ERR("Not a unix domain socket addresses" + " in -a (%s)\n", la->endpoint); + } if (*la->endpoint != '/' && strchr(la->endpoint, '/') != NULL) ARGV_ERR("Unix domain socket addresses must be" " absolute paths in -a (%s)\n", la->endpoint); diff --git a/bin/varnishd/http1/cache_http1_fsm.c b/bin/varnishd/http1/cache_http1_fsm.c index cc34203628..1d9efb1aa1 100644 --- a/bin/varnishd/http1/cache_http1_fsm.c +++ b/bin/varnishd/http1/cache_http1_fsm.c @@ -82,7 +82,6 @@ http1_req(struct worker *wrk, void *arg) CAST_OBJ_NOTNULL(req, arg, REQ_MAGIC); THR_SetRequest(req); - req->transport = &HTTP1_transport; assert(!WS_IsReserved(wrk->aws)); HTTP1_Session(wrk, req); AZ(wrk->v1l); @@ -114,7 +113,10 @@ http1_new_session(struct worker *wrk, void *arg) CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); HTC_RxInit(req->htc, req->ws); - if (!SES_Reserve_proto_priv(sp, &u, &sz)) { + + sz = sizeof u; + if (SES_Get_proto_priv(sp, &u) && + !SES_Reserve_proto_priv(sp, &u, &sz)) { /* Out of session workspace. Free the req, close the sess, * and do not set a new task func, which will exit the * worker thread. */ @@ -306,8 +308,7 @@ HTTP1_Session(struct worker *wrk, struct req *req) */ if (http1_getstate(sp) == H1NEWREQ) VTCP_blocking(sp->fd); - - req->transport = &HTTP1_transport; + req->transport = XPORT_ByNumber(sp->sattr[SA_TRANSPORT]); while (1) { st = http1_getstate(sp); diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c index a31ef05061..48a9933c1d 100644 --- a/bin/varnishd/mgt/mgt_main.c +++ b/bin/varnishd/mgt/mgt_main.c @@ -109,12 +109,13 @@ usage(void) printf("\nBasic options:\n"); - printf(FMT, "[-a [name=][listen_address", + printf(FMT, "[-a [name=][%kind,][listen_address", "HTTP listen address, protocol, options."); printf(FMT, " [,PROTO|,option=value,...]]", "Can be specified multiple times."); printf(FMT, "", " default: \":80,HTTP\""); + printf(FMT, " %kind", "Selects an acceptor implementation"); printf(FMT, " options:", "Proto can be \"PROXY\" or \"HTTP\" (default)"); printf(FMT, " [,user=][,group=]", @@ -628,7 +629,6 @@ main(int argc, char * const *argv) const char *h_arg = "critbit"; const char *n_arg = getenv("VARNISH_DEFAULT_N"); const char *S_arg = NULL; - const char *s_arg = "default,100m"; const char *W_arg = NULL; const char *c; char *p; @@ -796,9 +796,6 @@ main(int argc, char * const *argv) /* Process delayed arguments */ VTAILQ_FOREACH(alp, &arglist, list) { switch(alp->arg[0]) { - case 'a': - VCA_Arg(alp->val); - break; case 'f': if (*alp->val != '\0') alp->priv = mgt_f_read(alp->val); @@ -829,9 +826,6 @@ main(int argc, char * const *argv) case 'r': MCF_ParamProtect(cli, alp->val); break; - case 's': - STV_Config(alp->val); - break; default: break; } @@ -921,17 +915,32 @@ main(int argc, char * const *argv) if (C_flag) AZ(atexit(mgt_Cflag_atexit)); - /* If no -s argument specified, process default -s argument */ + vext_copyin(vident); + vext_load(); + + /* defaults if arguments not present */ if (!arg_list_count("s")) - STV_Config(s_arg); + (void) arg_list_add('s', "default,100m"); + + VTAILQ_FOREACH(alp, &arglist, list) { + switch(alp->arg[0]) { + case 'a': + VCA_Arg(alp->val); + break; + case 's': + STV_Config(alp->val); + break; + default: + break; + } + cli_check(cli); + } /* Configure CLI and Transient storage, if user did not */ STV_Config_Final(); mgt_vcl_init(); - vext_copyin(vident); - u = 0; VTAILQ_FOREACH(alp, &arglist, list) { if (!strcmp(alp->arg, "f") && alp->priv != NULL) diff --git a/bin/varnishtest/tests/c00003.vtc b/bin/varnishtest/tests/c00003.vtc index 1ad2569222..08cbe9e629 100644 --- a/bin/varnishtest/tests/c00003.vtc +++ b/bin/varnishtest/tests/c00003.vtc @@ -1,5 +1,7 @@ varnishtest "Check that we fail to start with erroneous -a/-b arguments" +setenv VARNISH_DEFAULT_N ${tmpdir} + # Duplicate -a arguments # XXX: this cannot be tested reliably, we tolerate port collision shell -err -match "have same address|already in use|Address in use" { diff --git a/bin/varnishtest/tests/x00001.vtc b/bin/varnishtest/tests/x00001.vtc new file mode 100644 index 0000000000..9b30ee9506 --- /dev/null +++ b/bin/varnishtest/tests/x00001.vtc @@ -0,0 +1,27 @@ +varnishtest "Minimal acceptor VEXT test" + +shell -err -expect {Error: Acceptor foo not found} { + varnishd -b None -a %foo,socket -n ${tmpdir} +} + +shell -err -expect {Error: Acceptor bar not found} { + varnishd -b None -a name=%bar,socket -n ${tmpdir} +} + +varnish v1 \ + -arg "-E ${topbuild}/vmod/.libs/libvmod_vext_debug.so" \ + -arg "-a dbg=%dbg,${listen_addr}" \ + -vcl { + + backend none none; + + sub vcl_recv { + return (synth(200)); + } +} -start + +#client c1 -repeat 10 { +client c1 { + txreq + rxresp +} -run diff --git a/doc/sphinx/reference/varnishd.rst b/doc/sphinx/reference/varnishd.rst index a3c445d142..8fcb9c7532 100644 --- a/doc/sphinx/reference/varnishd.rst +++ b/doc/sphinx/reference/varnishd.rst @@ -21,7 +21,7 @@ SYNOPSIS ======== varnishd - [-a [name=][listen_address[,PROTO|,option=value,...]] + [-a [name=][%kind,][listen_address[,PROTO|,option=value,...]] [-b [host[:port]|path]] [-C] [-d] @@ -63,7 +63,7 @@ OPTIONS Basic options ------------- --a <[name=][listen_address[,PROTO|,option=value,...]]> +-a <[name=][%kind,][listen_address[,PROTO|,option=value,...]]> Generic syntax to accept client requests on a listen_address. See below for details. @@ -71,6 +71,8 @@ Basic options Name is referenced in logs and available to vcl as ``local.socket``. If name is not specified, ``a`` with a numerical sequence ("a0", "a1", etc.) is used. + ``%kind`` selects the acceptor implementation *kind*. + Any arguments after the listen_address separated by comma are taken as either an acceptor ``option=value`` pair if containing a ``=``, or as a PROTO(col) selection otherwise. @@ -85,7 +87,7 @@ Basic options If no -a argument is given, the default `-a :80` will listen on all IPv4 and IPv6 interfaces. --a <[name=][ip_address][:port][,PROTO]> +-a <[name=][%kind,][ip_address][:port][,PROTO]> The ip_address can be a host name ("localhost"), an IPv4 dotted-quad ("127.0.0.1") or an IPv6 address enclosed in square brackets @@ -97,7 +99,7 @@ Basic options At least one of ip_address or port is required. --a <[name=][path][,PROTO][,user=name][,group=name][,mode=octal]> +-a <[name=][%kind,][path][,PROTO][,user=name][,group=name][,mode=octal]> (VCL4.1 and higher) diff --git a/doc/sphinx/users-guide/command-line.rst b/doc/sphinx/users-guide/command-line.rst index 7519d347e0..2e964eba8c 100644 --- a/doc/sphinx/users-guide/command-line.rst +++ b/doc/sphinx/users-guide/command-line.rst @@ -21,8 +21,8 @@ you will find the startup options here: * FreeBSD: `/etc/rc.conf` (See also: /usr/local/etc/rc.d/varnishd) -'-a' *<[name=][listen_address[,PROTO|,option=value,...]]>* -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +'-a' *<[name=][%kind,][listen_address[,PROTO|,option=value,...]]>* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Each '-a' argument defines one endpoint which Varnish should service HTTP requests on. diff --git a/vmod/Makefile.am b/vmod/Makefile.am index 1d2df6317e..8b1ba83e6a 100644 --- a/vmod/Makefile.am +++ b/vmod/Makefile.am @@ -31,6 +31,7 @@ include $(srcdir)/automake_boilerplate_blob.am include $(srcdir)/automake_boilerplate_h2.am include $(srcdir)/automake_boilerplate_cookie.am include $(srcdir)/automake_boilerplate_debug.am +include $(srcdir)/automake_boilerplate_vext_debug.am include $(srcdir)/automake_boilerplate_directors.am include $(srcdir)/automake_boilerplate_proxy.am include $(srcdir)/automake_boilerplate_purge.am @@ -55,6 +56,8 @@ vmod_debug_symbols_regex = 'Vmod_.*_Data' # not --strict vmodtoolargs_debug = --boilerplate -o vcc_debug_if -dist_noinst_DATA = $(srcdir)/vmod_debug.vcc +dist_noinst_DATA = \ + $(srcdir)/vmod_debug.vcc \ + $(srcdir)/vmod_vext_debug.vcc dist_vcc_DATA = $(vmod_vcc_files) diff --git a/vmod/automake_boilerplate_vext_debug.am b/vmod/automake_boilerplate_vext_debug.am new file mode 100644 index 0000000000..a8543c3240 --- /dev/null +++ b/vmod/automake_boilerplate_vext_debug.am @@ -0,0 +1,43 @@ +## Generated by vmodtool.py --boilerplate. + +vmod_vext_debug_vcc ?= $(srcdir)/vmod_vext_debug.vcc + +vmod_vcc_files += $(vmod_vext_debug_vcc) + +vmod_LTLIBRARIES += libvmod_vext_debug.la + +libvmod_vext_debug_la_SOURCES = \ + vmod_vext_debug.c \ + vmod_vext_debug_acceptor.c + +libvmod_vext_debug_la_CFLAGS = + +vmodtoolargs_vext_debug ?= --strict --boilerplate -o vcc_vext_debug_if +vmod_vext_debug_symbols_regex ?= Vmod_vext_debug_Data + +libvmod_vext_debug_la_LDFLAGS = \ + -export-symbols-regex $(vmod_vext_debug_symbols_regex) \ + $(AM_LDFLAGS) \ + $(VMOD_LDFLAGS) + +nodist_libvmod_vext_debug_la_SOURCES = vcc_vext_debug_if.c vcc_vext_debug_if.h + +EXTRA_libvmod_vext_debug_la_DEPENDENCIES = $(nodist_libvmod_vext_debug_la_SOURCES) + +EXTRA_DIST += automake_boilerplate_vext_debug.am + +$(libvmod_vext_debug_la_OBJECTS): vcc_vext_debug_if.h + +vcc_vext_debug_if.h vmod_vext_debug.rst vmod_vext_debug.man.rst: vcc_vext_debug_if.c + +# A doc-change will not update mtime on the .h and .c files, so a +# touch(1) is necessary to signal that vmodtool was in fact run. +vcc_vext_debug_if.c: $(VMODTOOL) $(srcdir)/vmod_vext_debug.vcc + @PYTHON@ $(VMODTOOL) $(vmodtoolargs_vext_debug) $(srcdir)/vmod_vext_debug.vcc + touch vcc_vext_debug_if.c + +clean-local: clean-vmod-vext_debug + +clean-vmod-vext_debug: + rm -f $(nodist_libvmod_vext_debug_la_SOURCES) + rm -f vmod_vext_debug.rst vmod_vext_debug.man.rst diff --git a/vmod/vmod_vext_debug.c b/vmod/vmod_vext_debug.c new file mode 100644 index 0000000000..d3fa106a79 --- /dev/null +++ b/vmod/vmod_vext_debug.c @@ -0,0 +1,10 @@ +#include "config.h" +#include "vdef.h" +#include "vrt.h" +#include "vcc_vext_debug_if.h" + +VCL_VOID +dbgvext_dummy(VRT_CTX) +{ + (void) ctx; +} diff --git a/vmod/vmod_vext_debug.vcc b/vmod/vmod_vext_debug.vcc new file mode 100644 index 0000000000..3cb3fa23f6 --- /dev/null +++ b/vmod/vmod_vext_debug.vcc @@ -0,0 +1,40 @@ +# Copyright 2024 UPLEX - Nils Goroll Systemoptimierung +# All rights reserved. +# +# Author: Nils Goroll +# +# SPDX-License-Identifier: BSD-2-Clause +# +# 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. + +$ABI strict +$Prefix dbgvext +$Module vext_debug 3 "Varnish Extension development, test and debug" +$Synopsis auto +DESCRIPTION +=========== + +At this point, this vmod does not expose any interface to VCL. + +It implements the "dbg" acceptor, which simply wraps the "tcp" acceptor. + +$Function VOID dummy() diff --git a/vmod/vmod_vext_debug_acceptor.c b/vmod/vmod_vext_debug_acceptor.c new file mode 100644 index 0000000000..58227aaf8d --- /dev/null +++ b/vmod/vmod_vext_debug_acceptor.c @@ -0,0 +1,86 @@ +/*- + * Copyright 2024 UPLEX - Nils Goroll Systemoptimierung + * All rights reserved. + * + * Author: Nils Goroll + * + * SPDX-License-Identifier: BSD-2-Clause + * + * 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 + +#include "cache/cache_varnishd.h" +#include "acceptor/cache_acceptor.h" +#include "acceptor/mgt_acceptor.h" + +struct acceptor DBG_acceptor; + +// these callbacks are all noops, because we initialize our dbg acceptor as a +// tcp acceptor, which keeps a list of its instances, so the respective +// functions get already called through the tcp acceptor + +static int +acc_dbg_reopen(void) +{ + return (0); +} + +static void +acc_dbg_start(struct cli *cli) +{ + (void) cli; +} + +static void +acc_dbg_accept(struct pool * pp) +{ + (void) pp; +} + +static void +acc_dbg_update(pthread_mutex_t * shut_mtx) +{ + (void) shut_mtx; +} + +static void +acc_dbg_shutdown(void) +{ +} + +static void __attribute__((constructor)) +init_register_acceptor(void) { + fprintf(stderr, "HELLO from dbg acceptor VEXT\n"); + DBG_acceptor = TCP_acceptor; + DBG_acceptor.name = "dbg"; + DBG_acceptor.reopen = acc_dbg_reopen; + DBG_acceptor.start = acc_dbg_start; + DBG_acceptor.accept = acc_dbg_accept; + DBG_acceptor.update = acc_dbg_update; + DBG_acceptor.shutdown = acc_dbg_shutdown; + + VCA_Add(&DBG_acceptor); +}