r4473 - in trunk/varnish-cache: bin/varnishd bin/varnishtest include lib/libvarnish

phk at projects.linpro.no phk at projects.linpro.no
Tue Jan 19 00:53:48 CET 2010


Author: phk
Date: 2010-01-19 00:53:48 +0100 (Tue, 19 Jan 2010)
New Revision: 4473

Modified:
   trunk/varnish-cache/bin/varnishd/cache_cli.c
   trunk/varnish-cache/bin/varnishd/heritage.h
   trunk/varnish-cache/bin/varnishd/mgt_cli.c
   trunk/varnish-cache/bin/varnishd/mgt_param.c
   trunk/varnish-cache/bin/varnishtest/vtc_varnish.c
   trunk/varnish-cache/include/cli_common.h
   trunk/varnish-cache/include/cli_serve.h
   trunk/varnish-cache/lib/libvarnish/cli_serve.c
Log:
CLI reworking in the manager process.

Use the new cli_serve stuff, as ammended.

Give cli's an "auth level" and only allow the commands with lower
auth levels than what the cli has collected.  Use this to implement
the -S handling.  In the future, we can also use it to do "R/O" vs. "R/W"
command separation.

Add a param (syslog_cli_traffic) to control if all CLI traffic is syslog'ed.

Everything should work the same, as far as I know.



Modified: trunk/varnish-cache/bin/varnishd/cache_cli.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_cli.c	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/bin/varnishd/cache_cli.c	2010-01-18 23:53:48 UTC (rev 4473)
@@ -94,11 +94,9 @@
 }
 
 static void
-cli_cb_before(void *priv)
+cli_cb_before(struct cli *cli)
 {
-	struct cli *cli;
 
-	cli = priv;
 	VSL(SLT_CLI, 0, "Rd %s", cli->cmd);
 	VCL_Poll();
 	VBE_Poll();
@@ -106,12 +104,9 @@
 }
 
 static void
-cli_cb_after(void *priv)
+cli_cb_after(struct cli *cli)
 {
-	struct cli *cli;
-
 	Lck_Unlock(&cli_mtx);
-	cli = priv;
 	VSL(SLT_CLI, 0, "Wr %03u %s", cli->result, vsb_data(cli->sb));
 }
 
@@ -123,11 +118,12 @@
 
 	add_check = 1;
 
-	cls = CLS_New(cli_cb_before, cli_cb_after, NULL, params->cli_buffer);
-	AZ(CLS_AddFd(cls, heritage.cli_in, heritage.cli_out, NULL, NULL));
-	AZ(CLS_AddFunc(cls, ccf_master_cli));
-	AZ(CLS_AddFunc(cls, ccf_public_cli));
-	AZ(CLS_AddFunc(cls, ccf_debug_cli));
+	cls = CLS_New(cli_cb_before, cli_cb_after, params->cli_buffer);
+	AN(cls);
+	AN(CLS_AddFd(cls, heritage.cli_in, heritage.cli_out, NULL, NULL));
+	AZ(CLS_AddFunc(cls, 0, ccf_master_cli));
+	AZ(CLS_AddFunc(cls, 0, ccf_public_cli));
+	AZ(CLS_AddFunc(cls, 0, ccf_debug_cli));
 
 	do {
 		i = CLS_Poll(cls, -1);

Modified: trunk/varnish-cache/bin/varnishd/heritage.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/heritage.h	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/bin/varnishd/heritage.h	2010-01-18 23:53:48 UTC (rev 4473)
@@ -193,14 +193,13 @@
 	/* Get rid of duplicate purges */
 	unsigned		purge_dups;
 
-	/* CLI banner */
-	unsigned		cli_banner;
-
 	/* How long time does the ban lurker sleep */
 	double			ban_lurker_sleep;
 
 	/* Max size of the saintmode list. 0 == no saint mode. */
 	unsigned		saintmode_threshold;
+
+	unsigned		syslog_cli_traffic;
 };
 
 extern volatile struct params *params;

Modified: trunk/varnish-cache/bin/varnishd/mgt_cli.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_cli.c	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/bin/varnishd/mgt_cli.c	2010-01-18 23:53:48 UTC (rev 4473)
@@ -38,7 +38,6 @@
 
 #include <stdarg.h>
 #include <stdio.h>
-#include <ctype.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <syslog.h>
@@ -54,6 +53,7 @@
 #include "cli.h"
 #include "vsb.h"
 #include "cli_common.h"
+#include "cli_serve.h"
 #include "vev.h"
 #include "vsha256.h"
 #include "shmlog.h"
@@ -66,32 +66,14 @@
 #include "mgt_cli.h"
 
 static int		cli_i = -1, cli_o = -1;
+static struct cls	*cls;
 static const char	*secret_file;
 
-struct telnet {
-	unsigned		magic;
-#define TELNET_MAGIC		0x53ec3ac0
-	int			fd;
-	struct vev		*ev;
-};
+#define	MCF_NOAUTH	0
+#define MCF_AUTH	16
 
-struct cli_port {
-	unsigned		magic;
-#define CLI_PORT_MAGIC		0x5791079f
-	VTAILQ_ENTRY(cli_port)	list;
-	struct vev		*ev;
-	int			fdi;
-	int			fdo;
-	int			verbose;
-	struct vlu		*vlu;
-	struct cli		cli[1];
-	char			*name;
-	char			challenge[34];
-	mgt_cli_close_f		*closefunc;
-	void			*priv;
-};
+static void mcf_help(struct cli *cli, const char * const *av, void *priv);
 
-static VTAILQ_HEAD(,cli_port)	clilist = VTAILQ_HEAD_INITIALIZER(clilist);
 
 /*--------------------------------------------------------------------*/
 
@@ -110,26 +92,7 @@
 #undef MAC_STAT
 }
 
-/*--------------------------------------------------------------------*/
 
-static void
-mcf_help(struct cli *cli, const char * const *av, void *priv)
-{
-	unsigned u;
-	char *p;
-
-	cli_func_help(cli, av, priv);
-	if (cli_o >= 0 && (av[2] == NULL || *av[2] == '-')) {
-		p = NULL;
-		if (!mgt_cli_askchild(&u, &p,
-		    "help %s\n", av[2] != NULL ? av[2] : "")) {
-			cli_out(cli, "%s", p);
-			cli_result(cli, u);
-		}
-		free(p);
-	}
-}
-
 /*--------------------------------------------------------------------*/
 
 static void
@@ -164,7 +127,6 @@
 
 /* XXX: what order should this list be in ? */
 static struct cli_proto cli_proto[] = {
-	{ CLI_HELP,		mcf_help, cli_proto },
 	{ CLI_BANNER,		mcf_banner, NULL },
 	{ CLI_PING,		cli_func_ping },
 	{ CLI_SERVER_STATUS,	mcf_server_status, NULL },
@@ -309,6 +271,24 @@
 }
 
 /*--------------------------------------------------------------------
+ * Generate a random challenge
+ */
+
+static void
+mgt_cli_challenge(struct cli *cli)
+{
+	int i;
+
+	for (i = 0; i + 2L < sizeof cli->challenge; i++)
+		cli->challenge[i] = (random() % 26) + 'a';
+	cli->challenge[i++] = '\n';
+	cli->challenge[i] = '\0';
+	cli_out(cli, "%s", cli->challenge);
+	cli_out(cli, "\nAuthentication required.\n");
+	cli_result(cli, CLIS_AUTH);
+}
+
+/*--------------------------------------------------------------------
  * Validate the authentication
  */
 
@@ -319,10 +299,8 @@
 	int i, fd;
 	struct SHA256Context sha256ctx;
 	unsigned char digest[SHA256_LEN];
-	struct cli_port *cp;
 
 	AN(av[2]);
-	CAST_OBJ_NOTNULL(cp, cli->priv, CLI_PORT_MAGIC);
 	(void)priv;
 	AN(secret_file);
 	fd = open(secret_file, O_RDONLY);
@@ -353,20 +331,20 @@
 	buf[i] = '\0';
 	AZ(close(fd));
 	SHA256_Init(&sha256ctx);
-	SHA256_Update(&sha256ctx, cp->challenge, strlen(cp->challenge));
+	SHA256_Update(&sha256ctx, cli->challenge, strlen(cli->challenge));
 	SHA256_Update(&sha256ctx, buf, i);
-	SHA256_Update(&sha256ctx, cp->challenge, strlen(cp->challenge));
+	SHA256_Update(&sha256ctx, cli->challenge, strlen(cli->challenge));
 	SHA256_Final(digest, &sha256ctx);
 	for (i = 0; i < SHA256_LEN; i++)
 		sprintf(buf + i + i, "%02x", digest[i]);
 	if (strcasecmp(buf, av[2])) {
-		cli_result(cli, CLIS_UNKNOWN);
+		mgt_cli_challenge(cli);
 		return;
 	}
-	cp->challenge[0] = '\0';
+	cli->auth = MCF_AUTH;
+	memset(cli->challenge, 0, sizeof cli->challenge);
 	cli_result(cli, CLIS_OK);
-	if (params->cli_banner)
-		mcf_banner(cli, av, priv);
+	mcf_banner(cli, av, priv);
 }
 
 static struct cli_proto cli_auth[] = {
@@ -376,101 +354,61 @@
 	{ NULL }
 };
 
-/*--------------------------------------------------------------------
- * Generate a random challenge
- */
+/*--------------------------------------------------------------------*/
 
 static void
-mgt_cli_challenge(struct cli_port *cp)
+mcf_help(struct cli *cli, const char * const *av, void *priv)
 {
-	int i;
+	unsigned u;
+	char *p;
 
-	for (i = 0; i + 2L < sizeof cp->challenge; i++)
-		cp->challenge[i] = (random() % 26) + 'a';
-	cp->challenge[i++] = '\n';
-	cp->challenge[i] = '\0';
-	cli_out(cp->cli, "%s", cp->challenge);
-	cli_out(cp->cli, "\nAuthentication required.\n");
-	cli_result(cp->cli, CLIS_AUTH);
+	(void)priv;
+	cli_func_help(cli, av, cli_auth);
+	if (cli->auth == MCF_NOAUTH)
+		return;
+	cli_func_help(cli, av, cli_proto);
+	if (cli_o >= 0 && (av[2] == NULL || *av[2] == '-')) {
+		p = NULL;
+		if (!mgt_cli_askchild(&u, &p,
+		    "help %s\n", av[2] != NULL ? av[2] : "")) {
+			cli_out(cli, "%s", p);
+			cli_result(cli, u);
+		}
+		free(p);
+	}
 }
 
-/*--------------------------------------------------------------------*/
 
-static int
-mgt_cli_vlu(void *priv, const char *p)
+/*--------------------------------------------------------------------*/
+static void
+mgt_cli_cb_before(struct cli *cli)
 {
-	struct cli_port *cp;
 
-	CAST_OBJ_NOTNULL(cp, priv, CLI_PORT_MAGIC);
-	vsb_clear(cp->cli->sb);
+	if (params->syslog_cli_traffic)
+		syslog(LOG_NOTICE, "CLI %s Rd %s", cli->ident, cli->cmd);
+}
 
-	/* Skip whitespace */
-	for (; isspace(*p); p++)
-		continue;
+static void
+mgt_cli_cb_after(struct cli *cli)
+{
 
-	/* Ignore empty lines */
-	if (*p == '\0')
-		return (0);
-
-	cp->cli->cmd = p;
-	if (secret_file != NULL && cp->challenge[0] != '\0') {
-		/* Authentication not yet passed */
-		cli_dispatch(cp->cli, cli_auth, p);
-		if (cp->cli->result == CLIS_UNKNOWN)
-			mgt_cli_challenge(cp);
-	} else {
-		cli_dispatch(cp->cli, cli_proto, p);
-		if (cp->cli->result == CLIS_UNKNOWN) {
-			vsb_clear(cp->cli->sb);
-			cli_dispatch(cp->cli, cli_debug, p);
-		}
-		if (cp->cli->result == CLIS_UNKNOWN) {
-			vsb_clear(cp->cli->sb);
-			cli_dispatch(cp->cli, cli_askchild, p);
-		}
-	}
-	vsb_finish(cp->cli->sb);
-	AZ(vsb_overflowed(cp->cli->sb));
-
-	cp->cli->cmd = NULL;
-
-	/* send the result back */
-	syslog(LOG_INFO, "CLI %d result %d \"%s\"",
-	    cp->fdi, cp->cli->result, p);
-	if (cli_writeres(cp->fdo, cp->cli) || cp->cli->result == CLIS_CLOSE)
-		return (1);
-	return (0);
+	if (params->syslog_cli_traffic)
+		syslog(LOG_NOTICE, "CLI %s Wr %03u %s",
+		    cli->ident, cli->result, vsb_data(cli->sb));
 }
 
-/*--------------------------------------------------------------------
- * Get rid of a CLI session.
- *
- * Always and only called from mgt_cli_callback().
- *
- * We must get rid of everything but the event, which gets GC'ed by
- * ev_schdule_one() when mgt_cli_callback, through our return value
- * returns non-zero.
- */
+/*--------------------------------------------------------------------*/
 
-static int
-mgt_cli_close(struct cli_port *cp)
+static void
+mgt_cli_init_cls(void)
 {
 
-	CHECK_OBJ_NOTNULL(cp, CLI_PORT_MAGIC);
-	syslog(LOG_NOTICE, "CLI %d closed", cp->fdi);
-	/*
-	 * Remove from list, so that if closefunc calls mgt_cli_close_all
-	 * it will not try to remove this one too.
-	 */
-	VTAILQ_REMOVE(&clilist, cp, list);
-
-	free(cp->name);
-	vsb_delete(cp->cli->sb);
-	VLU_Destroy(cp->vlu);
-
-	cp->closefunc(cp->priv);
-	FREE_OBJ(cp);
-	return (1);
+	cls = CLS_New(mgt_cli_cb_before, mgt_cli_cb_after, params->cli_buffer);
+	AN(cls);
+	AZ(CLS_AddFunc(cls, MCF_NOAUTH, cli_auth));
+	AZ(CLS_AddFunc(cls, MCF_AUTH, cli_proto));
+	AZ(CLS_AddFunc(cls, MCF_AUTH, cli_debug));
+	AZ(CLS_AddFunc(cls, MCF_AUTH, cli_askchild));
 }
 
 /*--------------------------------------------------------------------
@@ -480,13 +418,8 @@
 void
 mgt_cli_close_all(void)
 {
-	struct cli_port *cp;
 
-	while (!VTAILQ_EMPTY(&clilist)) {
-		cp = VTAILQ_FIRST(&clilist);
-		vev_del(mgt_evb, cp->ev);
-		(void)mgt_cli_close(cp);
-	}
+	CLS_Destroy(&cls);
 }
 
 /*--------------------------------------------------------------------
@@ -494,18 +427,14 @@
  */
 
 static int
-mgt_cli_callback(const struct vev *e, int what)
+mgt_cli_callback2(const struct vev *e, int what)
 {
-	struct cli_port *cp;
+	int i;
 
-	CAST_OBJ_NOTNULL(cp, e->priv, CLI_PORT_MAGIC);
-
-	if (what & (EV_ERR | EV_HUP | EV_GONE))
-		return (mgt_cli_close(cp));
-
-	if (VLU_Fd(cp->fdi, cp->vlu))
-		return (mgt_cli_close(cp));
-	return (0);
+	(void)e;
+	(void)what;
+	i = CLS_PollFd(cls, e->fd, 0);
+	return (i);
 }
 
 /*--------------------------------------------------------------------*/
@@ -513,50 +442,41 @@
 void
 mgt_cli_setup(int fdi, int fdo, int verbose, const char *ident, mgt_cli_close_f *closefunc, void *priv)
 {
-	struct cli_port *cp;
+	struct cli *cli;
+	struct vev *ev;
 
-	cp = calloc(sizeof *cp, 1);
-	XXXAN(cp);
-	cp->vlu = VLU_New(cp, mgt_cli_vlu, params->cli_buffer);
+	(void)ident;
+	(void)verbose;
+	if (cls == NULL) 
+		mgt_cli_init_cls();
 
-	cp->name = strdup(ident);
-	XXXAN(cp->name);
-	syslog(LOG_NOTICE, "CLI %d open %s", fdi, cp->name);
-	cp->magic = CLI_PORT_MAGIC;
+	cli = CLS_AddFd(cls, fdi, fdo, closefunc, priv);
 
-	cp->fdi = fdi;
-	cp->fdo = fdo;
-	cp->verbose = verbose;
+	cli->ident = strdup(ident);
 
-	cp->closefunc = closefunc;
-	cp->priv = priv;
-
-	cp->cli->sb = vsb_newauto();
-	XXXAN(cp->cli->sb);
-	cp->cli->priv = cp;
-
 	/* Deal with TELNET options */
-	if (cp->fdi != 0)
-		VLU_SetTelnet(cp->vlu, cp->fdo);
+	if (fdi != 0)
+		VLU_SetTelnet(cli->vlu, fdo);
 
-	/*
-	 * If we have a secret file authenticate all CLI connections
-	 * except the stdin/stdout debug port.
-	 */
-	if (cp->fdi != 0 && secret_file != NULL) {
-		mgt_cli_challenge(cp);
-		(void)VLU_Data("auth -\n", -1, cp->vlu);
-	} else if (params->cli_banner)
-		(void)VLU_Data("banner\n", -1, cp->vlu);
+	if (fdi != 0 && secret_file != NULL) {
+		cli->auth = MCF_NOAUTH;
+		mgt_cli_challenge(cli);
+	} else {
+		cli->auth = MCF_AUTH;
+		mcf_banner(cli, NULL, NULL);
+	}
+	vsb_finish(cli->sb);
+	(void)cli_writeres(fdo, cli);
 
-	cp->ev = vev_new();
-	cp->ev->name = cp->name;
-	cp->ev->fd = fdi;
-	cp->ev->fd_flags = EV_RD;
-	cp->ev->callback = mgt_cli_callback;
-	cp->ev->priv = cp;
-	VTAILQ_INSERT_TAIL(&clilist, cp, list);
-	AZ(vev_add(mgt_evb, cp->ev));
+
+	ev = vev_new();
+	AN(ev);
+	ev->name = cli->ident;
+	ev->fd = fdi;
+	ev->fd_flags = EV_RD;
+	ev->callback = mgt_cli_callback2;
+	ev->priv = cli;
+	AZ(vev_add(mgt_evb, ev));
 }
 
 /*--------------------------------------------------------------------*/
@@ -581,6 +501,13 @@
 
 /*--------------------------------------------------------------------*/
 
+struct telnet {
+	unsigned		magic;
+#define TELNET_MAGIC		0x53ec3ac0
+	int			fd;
+	struct vev		*ev;
+};
+
 static void
 telnet_close(void *priv)
 {

Modified: trunk/varnish-cache/bin/varnishd/mgt_param.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/mgt_param.c	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/bin/varnishd/mgt_param.c	2010-01-18 23:53:48 UTC (rev 4473)
@@ -756,9 +756,8 @@
 		"Detect and eliminate duplicate purges.\n",
 		0,
 		"on", "bool" },
-	{ "cli_banner", tweak_bool, &master.cli_banner, 0, 0,
-		"Emit CLI banner on connect.\n"
-		"Set to off for compatibility with pre 2.1 versions.\n",
+	{ "syslog_cli_traffic", tweak_bool, &master.syslog_cli_traffic, 0, 0,
+		"Log all CLI traffic to syslog(LOG_INFO).\n",
 		0,
 		"on", "bool" },
 	{ "ban_lurker_sleep", tweak_timeout_double,

Modified: trunk/varnish-cache/bin/varnishtest/vtc_varnish.c
===================================================================
--- trunk/varnish-cache/bin/varnishtest/vtc_varnish.c	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/bin/varnishtest/vtc_varnish.c	2010-01-18 23:53:48 UTC (rev 4473)
@@ -247,6 +247,8 @@
 	struct vss_addr **ap;
 	char abuf[128],pbuf[128];
 	struct pollfd fd;
+	unsigned retval;
+	char *r;
 
 	/* Create listener socket */
 	nap = VSS_resolve("127.0.0.1", "0", &ap);
@@ -261,8 +263,8 @@
 	AN(vsb);
 	vsb_printf(vsb, "cd ../varnishd &&");
 	vsb_printf(vsb, " ./varnishd -d -d -n %s", v->workdir);
-	vsb_printf(vsb, " -p cli_banner=off");
 	vsb_printf(vsb, " -p auto_restart=off");
+	vsb_printf(vsb, " -p syslog_cli_traffic=off");
 	vsb_printf(vsb, " -a '%s'", "127.0.0.1:0");
 	vsb_printf(vsb, " -M %s:%s", abuf, pbuf);
 	vsb_printf(vsb, " -P %s/varnishd.pid", v->workdir);
@@ -317,6 +319,13 @@
 	
 	vtc_log(v->vl, 3, "CLI connection fd = %d", v->cli_fd);
 	assert(v->cli_fd >= 0);
+
+	i = cli_readres(v->cli_fd, &retval, &r, 20.0);
+	if (i != 0 || retval != CLIS_OK)
+		vtc_log(v->vl, 0, "CLI banner fail", v->cli_fd);
+	vtc_log(v->vl, 4, "CLI banner %03u", retval);
+	free(r);
+
 	if (v->stats != NULL)
 		VSL_Close();
 	v->stats = VSL_OpenStats(v->workdir);

Modified: trunk/varnish-cache/include/cli_common.h
===================================================================
--- trunk/varnish-cache/include/cli_common.h	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/include/cli_common.h	2010-01-18 23:53:48 UTC (rev 4473)
@@ -29,12 +29,17 @@
  * $Id$
  */
 
+struct vlu;
+
 struct cli {
 	/* XXX: should be MINI_OBJ */
 	struct vsb		*sb;
 	enum cli_status_e	result;
-	void			*priv;
 	const char		*cmd;
+	unsigned		auth;
+	char			challenge[34];
+	char			*ident;
+	struct vlu		*vlu;
 };
 
 int cli_writeres(int fd, const struct cli *cli);

Modified: trunk/varnish-cache/include/cli_serve.h
===================================================================
--- trunk/varnish-cache/include/cli_serve.h	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/include/cli_serve.h	2010-01-18 23:53:48 UTC (rev 4473)
@@ -31,8 +31,12 @@
 
 struct cls;
 typedef void cls_cb_f(void *priv);
-struct cls *CLS_New(cls_cb_f *before, cls_cb_f *after, void *priv, unsigned maxlen);
-int CLS_AddFd(struct cls *cs, int fdi, int fdo, cls_cb_f *closefunc,
+typedef void cls_cbc_f(struct cli*);
+struct cls *CLS_New(cls_cbc_f *before, cls_cbc_f *after, unsigned maxlen);
+struct cli *CLS_AddFd(struct cls *cs, int fdi, int fdo, cls_cb_f *closefunc,
     void *priv);
-int CLS_AddFunc(struct cls *cs, struct cli_proto *clp);
+int CLS_AddFunc(struct cls *cs, unsigned auth, struct cli_proto *clp);
 int CLS_Poll(struct cls *cs, int timeout);
+int CLS_PollFd(struct cls *cs, int fd, int timeout);
+void CLS_Destroy(struct cls **);
+

Modified: trunk/varnish-cache/lib/libvarnish/cli_serve.c
===================================================================
--- trunk/varnish-cache/lib/libvarnish/cli_serve.c	2010-01-18 21:53:58 UTC (rev 4472)
+++ trunk/varnish-cache/lib/libvarnish/cli_serve.c	2010-01-18 23:53:48 UTC (rev 4473)
@@ -55,6 +55,7 @@
 	unsigned			magic;
 #define CLS_FUNC_MAGIC			0x7d280c9b
 	VTAILQ_ENTRY(cls_func)		list;
+	unsigned			auth;
 	struct cli_proto		*clp;
 };
 
@@ -63,7 +64,6 @@
 #define CLS_FD_MAGIC			0x010dbd1e
 	VTAILQ_ENTRY(cls_fd)		list;
 	int				fdi, fdo;
-	struct vlu			*vlu;
 	struct cls			*cls;
 	struct cli			*cli, clis;
 	cls_cb_f			*closefunc;
@@ -76,8 +76,7 @@
 	VTAILQ_HEAD(,cls_fd)		fds;
 	unsigned			nfd;
 	VTAILQ_HEAD(,cls_func)		funcs;
-	cls_cb_f			*before, *after;
-	void				*priv;
+	cls_cbc_f			*before, *after;
 	unsigned			maxlen;
 };
 
@@ -92,10 +91,22 @@
 	cs = cfd->cls;
 	CHECK_OBJ_NOTNULL(cs, CLS_MAGIC);
 
+	/* Skip whitespace */
+	for (; isspace(*p); p++)
+		continue;
+
+	/* Ignore empty lines */
+	if (*p == '\0')
+		return (0);
+
 	cfd->cli->cmd = p;
 	if (cs->before != NULL)
-		cs->before(cs->priv != NULL ? cs->priv : cfd->cli);
+		cs->before(cfd->cli);
+	vsb_clear(cfd->cli->sb);
+	cfd->cli->result = CLIS_UNKNOWN; 
 	VTAILQ_FOREACH(cfn, &cs->funcs, list) {
+		if (cfn->auth > cfd->cli->auth)
+			continue;
 		vsb_clear(cfd->cli->sb);
 		cfd->cli->result = CLIS_OK;
 		cli_dispatch(cfd->cli, cfn->clp, p);
@@ -105,7 +116,7 @@
 	vsb_finish(cfd->cli->sb);
 	AZ(vsb_overflowed(cfd->cli->sb));
 	if (cs->after != NULL)
-		cs->after(cs->priv != NULL ? cs->priv : cfd->cli);
+		cs->after(cfd->cli);
 	if (cli_writeres(cfd->fdo, cfd->cli) || cfd->cli->result == CLIS_CLOSE)
 		return (1);
 	cfd->cli->cmd = NULL;
@@ -113,7 +124,7 @@
 }
 
 struct cls *
-CLS_New(cls_cb_f *before, cls_cb_f *after, void *priv, unsigned maxlen)
+CLS_New(cls_cbc_f *before, cls_cbc_f *after, unsigned maxlen)
 {
 	struct cls *cs;
 
@@ -123,12 +134,11 @@
 	VTAILQ_INIT(&cs->funcs);
 	cs->before = before;
 	cs->after = after;
-	cs->priv = priv;
 	cs->maxlen = maxlen;
 	return (cs);
 }
 
-int
+struct cli *
 CLS_AddFd(struct cls *cs, int fdi, int fdo, cls_cb_f *closefunc, void *priv)
 {
 	struct cls_fd *cfd;
@@ -141,15 +151,15 @@
 	cfd->cls = cs;
 	cfd->fdi = fdi;
 	cfd->fdo = fdo;
-	cfd->vlu = VLU_New(cfd, cls_vlu, cs->maxlen);
 	cfd->cli = &cfd->clis;
+	cfd->cli->vlu = VLU_New(cfd, cls_vlu, cs->maxlen);
 	cfd->cli->sb = vsb_newauto();
 	cfd->closefunc = closefunc;
 	cfd->priv = priv;
 	AN(cfd->cli->sb);
 	VTAILQ_INSERT_TAIL(&cs->fds, cfd, list);
 	cs->nfd++;
-	return (0);
+	return (cfd->cli);
 }
 
 static void
@@ -161,7 +171,7 @@
 
 	VTAILQ_REMOVE(&cs->fds, cfd, list);
 	cs->nfd--;
-	VLU_Destroy(cfd->vlu);
+	VLU_Destroy(cfd->cli->vlu);
 	vsb_delete(cfd->cli->sb);
 	if (cfd->closefunc == NULL) {
 		(void)close(cfd->fdi);
@@ -170,12 +180,14 @@
 	} else {
 		cfd->closefunc(cfd->priv);
 	}
+	if (cfd->cli->ident != NULL)
+		free(cfd->cli->ident);
 	FREE_OBJ(cfd);
 }
 
 
 int
-CLS_AddFunc(struct cls *cs, struct cli_proto *clp)
+CLS_AddFunc(struct cls *cs, unsigned auth, struct cli_proto *clp)
 {
 	struct cls_func *cfn;
 
@@ -183,11 +195,51 @@
 	ALLOC_OBJ(cfn, CLS_FUNC_MAGIC);
 	AN(cfn);
 	cfn->clp = clp;
+	cfn->auth = auth;
 	VTAILQ_INSERT_TAIL(&cs->funcs, cfn, list);
 	return (0);
 }
 
 int
+CLS_PollFd(struct cls *cs, int fd, int timeout)
+{
+	struct cls_fd *cfd;
+	struct pollfd pfd[1];
+	int i, j, k;
+
+	CHECK_OBJ_NOTNULL(cs, CLS_MAGIC);
+	if (cs->nfd == 0) {
+		errno = 0;
+		return (-1);
+	}
+	assert(cs->nfd > 0);
+
+	i = 0;
+	VTAILQ_FOREACH(cfd, &cs->fds, list) {
+		if (cfd->fdi != fd)
+			continue;
+		pfd[i].fd = cfd->fdi;
+		pfd[i].events = POLLIN;
+		pfd[i].revents = 0;
+		i++;
+		break;
+	}
+	assert(i == 1);
+	CHECK_OBJ_NOTNULL(cfd, CLS_FD_MAGIC);
+
+	j = poll(pfd, 1, timeout);
+	if (j <= 0)
+		return (j);
+	if (pfd[0].revents & POLLHUP)
+		k = 1;
+	else
+		k = VLU_Fd(cfd->fdi, cfd->cli->vlu);
+	if (k)
+		cls_close_fd(cs, cfd);
+	return (k);
+}
+
+int
 CLS_Poll(struct cls *cs, int timeout)
 {
 	struct cls_fd *cfd, *cfd2;
@@ -220,7 +272,7 @@
 			if (pfd[i].revents & POLLHUP)
 				k = 1;
 			else
-				k = VLU_Fd(cfd->fdi, cfd->vlu);
+				k = VLU_Fd(cfd->fdi, cfd->cli->vlu);
 			if (k)
 				cls_close_fd(cs, cfd);
 			i++;
@@ -229,3 +281,25 @@
 	}
 	return (j);
 }
+
+void
+CLS_Destroy(struct cls **csp)
+{
+	struct cls *cs;
+	struct cls_fd *cfd, *cfd2;
+	struct cls_func *cfn;
+
+	cs = *csp;
+	*csp = NULL;
+	CHECK_OBJ_NOTNULL(cs, CLS_MAGIC);
+	VTAILQ_FOREACH_SAFE(cfd, &cs->fds, list, cfd2) 
+		cls_close_fd(cs, cfd);
+
+	while (!VTAILQ_EMPTY(&cs->funcs)) {
+		cfn = VTAILQ_FIRST(&cs->funcs);
+		VTAILQ_REMOVE(&cs->funcs, cfn, list);
+		FREE_OBJ(cfn);
+	}
+	FREE_OBJ(cs);
+}
+



More information about the varnish-commit mailing list