From bba17b7b236fffaa6fa902e83eb35e103c724aa4 Mon Sep 17 00:00:00 2001
From: Arianna Aondio <arianna.aondio@varnish-software.com>
Date: Fri, 23 Oct 2015 14:53:04 +0200
Subject: [PATCH] Priv pointers are now available in a vmod object method

---
 bin/varnishtest/tests/v00041.vtc   | 10 ++++++++++
 bin/varnishtest/tests/v00042.vtc   |  8 ++++++++
 lib/libvcc/vcc_action.c            |  4 +++-
 lib/libvcc/vcc_compile.h           |  3 ++-
 lib/libvcc/vcc_expr.c              | 38 +++++++++++++++-----------------------
 lib/libvcc/vcc_vmod.c              |  4 ++++
 lib/libvmod_debug/vmod.vcc         |  4 ++++
 lib/libvmod_debug/vmod_debug_obj.c | 13 +++++++++++++
 8 files changed, 59 insertions(+), 25 deletions(-)

diff --git a/bin/varnishtest/tests/v00041.vtc b/bin/varnishtest/tests/v00041.vtc
index 9604eb2..e903a68 100644
--- a/bin/varnishtest/tests/v00041.vtc
+++ b/bin/varnishtest/tests/v00041.vtc
@@ -11,6 +11,10 @@ varnish v1 -vcl+backend {
 	import ${vmod_debug};
 	import ${vmod_std};
 
+	sub vcl_init {
+	        new obj = debug.obj("obj");
+	}
+
 	sub vcl_recv {
 		set req.http.x0 = debug.test_priv_task(req.url);
 	}
@@ -18,6 +22,7 @@ varnish v1 -vcl+backend {
 	sub vcl_deliver {
 		set resp.http.x0 = req.http.x0;
 		set resp.http.x1 = debug.test_priv_task("");
+		set resp.http.x2 = obj.priv_task_obj(resp.http.x1);
 	}
 
 	sub vcl_backend_fetch {
@@ -29,6 +34,7 @@ varnish v1 -vcl+backend {
 	sub vcl_backend_response {
 		set beresp.http.bx0 = bereq.http.bx0;
 		set beresp.http.bx1 = debug.test_priv_task("");
+		set beresp.http.bx2 = obj.priv_task_obj(beresp.http.bx0);
 	}
 } -start
 
@@ -38,13 +44,17 @@ client c1 {
 	rxresp
 	expect resp.http.x0 == /foobar
 	expect resp.http.x1 == /foobar
+	expect resp.http.x2 == /foobar
 	expect resp.http.bx0 == /foobar
 	expect resp.http.bx1 == /foobar
+	expect resp.http.bx2 == /foobar
 
 	txreq -url /snafu
 	rxresp
 	expect resp.http.x0 == /snafu
 	expect resp.http.x1 == /snafu
+	expect resp.http.x2 == /snafu
 	expect resp.http.bx0 == /snafu
 	expect resp.http.bx1 == /snafu
+	expect resp.http.bx2 == /snafu
 } -run
diff --git a/bin/varnishtest/tests/v00042.vtc b/bin/varnishtest/tests/v00042.vtc
index 1640f56..1e1121d 100644
--- a/bin/varnishtest/tests/v00042.vtc
+++ b/bin/varnishtest/tests/v00042.vtc
@@ -36,8 +36,13 @@ server s1 {
 varnish v1 -vcl+backend {
 	import ${vmod_debug};
 
+	sub vcl_init {
+		new obj = debug.obj("obj");
+	}
+
 	sub vcl_recv {
 		set req.http.x0 = debug.test_priv_task(req.url + req.esi_level);
+		set req.http.y0 = obj.priv_task_obj(req.url + req.esi_level);
 	}
 
 	sub vcl_miss {
@@ -51,6 +56,7 @@ varnish v1 -vcl+backend {
 
 	sub vcl_deliver {
 		set resp.http.x1 = debug.test_priv_task("");
+		set resp.http.y1 = req.http.y0;
 	}
 } -start
 
@@ -59,10 +65,12 @@ client c1 {
 	txreq -url /a
 	rxresp
 	expect resp.http.x1 == "/a0"
+	expect resp.http.y1 == resp.http.x1
 
 	txreq -url /b
 	rxresp
 	expect resp.http.x1 == "/b0"
+	expect resp.http.y1 == resp.http.x1
 } -run
 
 varnish v1 -expect s_req == 2
diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c
index 41eac6b..86f5c6c 100644
--- a/lib/libvcc/vcc_action.c
+++ b/lib/libvcc/vcc_action.c
@@ -218,7 +218,8 @@ parse_new(struct vcc *tl)
 	vcc_NextToken(tl);
 
 	bprintf(buf1, ", &vo_%s, \"%s\"", sy1->name, sy1->name);
-	vcc_Eval_Func(tl, s_init, buf1, sy2->name, s_init + strlen(s_init) + 1);
+	AN(sy2->vmod);
+	vcc_Eval_Func(tl, s_init, buf1, sy2->vmod, s_init + strlen(s_init) + 1);
 	ifp = New_IniFin(tl);
 	VSB_printf(ifp->fin, "\t\t%s(&vo_%s);", s_fini, sy1->name);
 	ExpectErr(tl, ';');
@@ -234,6 +235,7 @@ parse_new(struct vcc *tl)
 		p += strlen(p) + 1;
 		sy3->cfunc = p;
 		p += strlen(p) + 1;
+		sy3->vmod = sy2->vmod;
 
 		/* Functions which return VOID are procedures */
 		if (!memcmp(p, "VOID\0", 5))
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 4c155a1..a53e431 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -135,6 +135,7 @@ struct symbol {
 	const char			*cfunc;
 	const char			*extra;
 	const char			*args;
+	const char			*vmod;
 
 	/* SYM_VAR */
 	const struct var		*var;
@@ -278,7 +279,7 @@ void vcc_Expr_Init(struct vcc *tl);
 sym_expr_t vcc_Eval_Var;
 sym_expr_t vcc_Eval_SymFunc;
 void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra,
-    const char *name, const char *args);
+    const char *vmod, const char *args);
 sym_expr_t vcc_Eval_Backend;
 sym_expr_t vcc_Eval_Probe;
 
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 294d12a..f069a13 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -551,18 +551,16 @@ vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym)
  */
 
 static struct expr *
-vcc_priv_arg(struct vcc *tl, const char *p, const char *name)
+vcc_priv_arg(struct vcc *tl, const char *p, const char *vmod)
 {
-	const char *r;
 	struct expr *e2;
 	char buf[32];
 	struct inifin *ifp;
 
+	AN(vmod);
+
 	if (!strcmp(p, "PRIV_VCL")) {
-		r = strchr(name, '.');
-		AN(r);
-		e2 = vcc_mk_expr(VOID, "&vmod_priv_%.*s",
-		    (int) (r - name), name);
+		e2 = vcc_mk_expr(VOID, "&vmod_priv_%s", vmod);
 	} else if (!strcmp(p, "PRIV_CALL")) {
 		bprintf(buf, "vmod_priv_%u", tl->unique++);
 		ifp = New_IniFin(tl);
@@ -570,17 +568,11 @@ vcc_priv_arg(struct vcc *tl, const char *p, const char *name)
 		VSB_printf(ifp->fin, "\tVRT_priv_fini(&%s);", buf);
 		e2 = vcc_mk_expr(VOID, "&%s", buf);
 	} else if (!strcmp(p, "PRIV_TASK")) {
-		r = strchr(name, '.');
-		AN(r);
-		e2 = vcc_mk_expr(VOID,
-		    "VRT_priv_task(ctx, &VGC_vmod_%.*s)",
-		    (int) (r - name), name);
+		e2 = vcc_mk_expr(VOID,"VRT_priv_task(ctx, &VGC_vmod_%s)",
+		    vmod);
 	} else if (!strcmp(p, "PRIV_TOP")) {
-		r = strchr(name, '.');
-		AN(r);
-		e2 = vcc_mk_expr(VOID,
-		    "VRT_priv_top(ctx, &VGC_vmod_%.*s)",
-		    (int) (r - name), name);
+		e2 = vcc_mk_expr(VOID, "VRT_priv_top(ctx, &VGC_vmod_%s)",
+		    vmod);
 	} else {
 		WRONG("Wrong PRIV_ type");
 	}
@@ -647,7 +639,7 @@ vcc_do_arg(struct vcc *tl, struct func_arg *fa)
 
 static void
 vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
-    const char *extra, const char *name, const char *args)
+    const char *extra, const char *vmod, const char *args)
 {
 	const char *p;
 	struct expr *e1;
@@ -658,7 +650,7 @@ vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
 
 	AN(cfunc);
 	AN(args);
-	AN(name);
+	AN(vmod);
 	SkipToken(tl, '(');
 	p = args;
 	if (extra == NULL)
@@ -671,7 +663,7 @@ vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
 		VTAILQ_INSERT_TAIL(&head, fa, list);
 		fa->type = vcc_arg_type(&p);
 		if (fa->type == VOID && !memcmp(p, "PRIV_", 5)) {
-			fa->result = vcc_priv_arg(tl, p, name);
+			fa->result = vcc_priv_arg(tl, p, vmod);
 			fa->name = "";
 			p += strlen(p) + 1;
 			continue;
@@ -762,13 +754,13 @@ vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
 
 void
 vcc_Eval_Func(struct vcc *tl, const char *cfunc,
-    const char *extra, const char *name, const char *args)
+    const char *extra, const char *vmod, const char *args)
 {
 	struct expr *e = NULL;
 	struct token *t1;
 
 	t1 = tl->t;
-	vcc_func(tl, &e, cfunc, extra, name, args);
+	vcc_func(tl, &e, cfunc, extra, vmod, args);
 	if (!tl->err) {
 		vcc_expr_fmt(tl->fb, tl->indent, e);
 		VSB_cat(tl->fb, ";\n");
@@ -787,10 +779,10 @@ vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym)
 
 	assert(sym->kind == SYM_FUNC || sym->kind == SYM_PROC);
 	AN(sym->cfunc);
-	AN(sym->name);
+	AN(sym->vmod);
 	AN(sym->args);
 	SkipToken(tl, ID);
-	vcc_func(tl, e, sym->cfunc, sym->extra, sym->name, sym->args);
+	vcc_func(tl, e, sym->cfunc, sym->extra, sym->vmod, sym->args);
 }
 
 /*--------------------------------------------------------------------
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index e8bab4f..d9b1f24 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -194,6 +194,8 @@ vcc_ParseImport(struct vcc *tl)
 			sym = VCC_AddSymbolStr(tl, p, SYM_OBJECT);
 			XXXAN(sym);
 			sym->args = p;
+			AN(vmd->name);
+			sym->vmod = vmd->name;
 		} else if (!strcmp(p, "$EVENT")) {
 			p += strlen(p) + 1;
 			if (ifp == NULL)
@@ -217,6 +219,8 @@ vcc_ParseImport(struct vcc *tl)
 			sym->cfunc = p;
 			p += strlen(p) + 1;
 			sym->args = p;
+			AN(vmd->name);
+			sym->vmod = vmd->name;
 
 			/* Functions which return VOID are procedures */
 			if (!memcmp(p, "VOID\0", 5))
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index dad36ec..6d322e1 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -89,6 +89,10 @@ $Method TIME .date()
 
 You never know when you need a date.
 
+$Method STRING .priv_task_obj(PRIV_TASK, STRING)
+
+Test function for task private pointers in a method
+
 $Function VOID rot52(HTTP hdr)
 
 Encrypt the HTTP header with quad-ROT13 encryption,
diff --git a/lib/libvmod_debug/vmod_debug_obj.c b/lib/libvmod_debug/vmod_debug_obj.c
index 0b9c248..cfce81e 100644
--- a/lib/libvmod_debug/vmod_debug_obj.c
+++ b/lib/libvmod_debug/vmod_debug_obj.c
@@ -98,3 +98,16 @@ vmod_obj_date(VRT_CTX, struct vmod_debug_obj *o)
 	assert(o->foobar == 42);
 	return (21.4);
 }
+
+VCL_STRING __match_proto__()
+vmod_obj_priv_task_obj(VRT_CTX, struct vmod_debug_obj *o,
+    struct vmod_priv *priv, VCL_STRING s)
+{
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
+	if (priv->priv == NULL) {
+		priv->priv = strdup(s);
+		priv->free = free;
+	}
+	return (priv->priv);
+}
-- 
1.9.1

