Commit 70789601 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Introduce VCL_BLOB type which VMOD functions can use to pass

random bits of memory to each other.

I have added a "len" field to the vmod_priv structure and used that
for BLOB's.

We may need some memory-mgt beauty/convenience functions for this.
parent 61ade8c8
varnishtest "Test VMOD BLOBS"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import ${vmod_debug};
sub vcl_deliver {
set resp.http.foo = debug.blob2hex(debug.str2blob("gunk"));
}
} -start
client c1 {
txreq
rxresp
expect resp.http.foo == 67756e6b
} -run
delay .1
varnish v1 -errvcl {BLOBs can only be used as arguments to VMOD functions.} {
backend b1 {.host = "127.0.0.1";}
import ${vmod_debug};
sub vcl_deliver {
set resp.http.foo = debug.str2blob("gunk");
}
}
varnish v1 -errvcl {Wrong argument type. Expected BLOB. Got STRING.} {
backend b1 {.host = "127.0.0.1";}
import ${vmod_debug};
sub vcl_deliver {
set resp.http.foo = debug.blob2hex("gunk");
}
}
...@@ -61,6 +61,7 @@ typedef double VCL_REAL; ...@@ -61,6 +61,7 @@ typedef double VCL_REAL;
typedef const char * VCL_STRING; typedef const char * VCL_STRING;
typedef double VCL_TIME; typedef double VCL_TIME;
typedef void VCL_VOID; typedef void VCL_VOID;
typedef const struct vmod_priv * VCL_BLOB;
/*********************************************************************** /***********************************************************************
* This is the composite argument we pass to compiled VCL and VRT * This is the composite argument we pass to compiled VCL and VRT
...@@ -238,6 +239,7 @@ struct vmod_priv; ...@@ -238,6 +239,7 @@ struct vmod_priv;
typedef void vmod_priv_free_f(void *); typedef void vmod_priv_free_f(void *);
struct vmod_priv { struct vmod_priv {
void *priv; void *priv;
int len;
vmod_priv_free_f *free; vmod_priv_free_f *free;
}; };
......
...@@ -392,7 +392,7 @@ vcc_arg_type(const char **p) ...@@ -392,7 +392,7 @@ vcc_arg_type(const char **p)
*/ */
static void static void
vcc_expr_tostring(struct expr **e, enum var_type fmt) vcc_expr_tostring(struct vcc *tl, struct expr **e, enum var_type fmt)
{ {
const char *p; const char *p;
uint8_t constant = EXPR_VAR; uint8_t constant = EXPR_VAR;
...@@ -423,6 +423,13 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt) ...@@ -423,6 +423,13 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt)
case STRING: case STRING:
case STRING_LIST: case STRING_LIST:
break; break;
case BLOB:
VSB_printf(tl->sb,
"Wrong use of BLOB value.\n"
"BLOBs can only be used as arguments to VMOD"
" functions.\n");
vcc_ErrWhere2(tl, (*e)->t1, tl->t);
return;
default: default:
INCOMPL(); INCOMPL();
break; break;
...@@ -451,8 +458,10 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -451,8 +458,10 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym)
vcc_expr0(tl, &e2, STRING); vcc_expr0(tl, &e2, STRING);
if (e2 == NULL) if (e2 == NULL)
return; return;
if (e2->fmt != STRING) if (e2->fmt != STRING) {
vcc_expr_tostring(&e2, STRING); vcc_expr_tostring(tl, &e2, STRING);
ERRCHK(tl);
}
SkipToken(tl, ','); SkipToken(tl, ',');
ExpectErr(tl, CSTR); ExpectErr(tl, CSTR);
...@@ -466,8 +475,10 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym) ...@@ -466,8 +475,10 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym)
vcc_expr0(tl, &e2, STRING); vcc_expr0(tl, &e2, STRING);
if (e2 == NULL) if (e2 == NULL)
return; return;
if (e2->fmt != STRING) if (e2->fmt != STRING) {
vcc_expr_tostring(&e2, STRING); vcc_expr_tostring(tl, &e2, STRING);
ERRCHK(tl);
}
*e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2); *e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2);
SkipToken(tl, ')'); SkipToken(tl, ')');
} }
...@@ -817,8 +828,10 @@ vcc_expr_string_add(struct vcc *tl, struct expr **e) ...@@ -817,8 +828,10 @@ vcc_expr_string_add(struct vcc *tl, struct expr **e)
vcc_NextToken(tl); vcc_NextToken(tl);
vcc_expr_mul(tl, &e2, STRING); vcc_expr_mul(tl, &e2, STRING);
ERRCHK(tl); ERRCHK(tl);
if (e2->fmt != STRING && e2->fmt != STRING_LIST) if (e2->fmt != STRING && e2->fmt != STRING_LIST) {
vcc_expr_tostring(&e2, f2); vcc_expr_tostring(tl, &e2, f2);
ERRCHK(tl);
}
ERRCHK(tl); ERRCHK(tl);
assert(e2->fmt == STRING || e2->fmt == STRING_LIST); assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
...@@ -857,7 +870,8 @@ vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -857,7 +870,8 @@ vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
/* Unless we specifically ask for a HEADER, fold them to string here */ /* Unless we specifically ask for a HEADER, fold them to string here */
if (fmt != HEADER && f2 == HEADER) { if (fmt != HEADER && f2 == HEADER) {
vcc_expr_tostring(e, STRING); vcc_expr_tostring(tl, e, STRING);
ERRCHK(tl);
f2 = (*e)->fmt; f2 = (*e)->fmt;
assert(f2 == STRING); assert(f2 == STRING);
} }
...@@ -1184,8 +1198,11 @@ vcc_Expr(struct vcc *tl, enum var_type fmt) ...@@ -1184,8 +1198,11 @@ vcc_Expr(struct vcc *tl, enum var_type fmt)
t1 = tl->t; t1 = tl->t;
vcc_expr0(tl, &e, fmt); vcc_expr0(tl, &e, fmt);
ERRCHK(tl); ERRCHK(tl);
if (fmt == STRING || fmt == STRING_LIST) e->t1 = t1;
vcc_expr_tostring(&e, fmt); if (fmt == STRING || fmt == STRING_LIST) {
vcc_expr_tostring(tl, &e, fmt);
ERRCHK(tl);
}
if (!tl->err && fmt != e->fmt) { if (!tl->err && fmt != e->fmt) {
VSB_printf(tl->sb, "Expression has type %s, expected %s\n", VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
vcc_Type(e->fmt), vcc_Type(fmt)); vcc_Type(e->fmt), vcc_Type(fmt));
......
...@@ -60,6 +60,7 @@ ctypes = { ...@@ -60,6 +60,7 @@ ctypes = {
'STRING_LIST': "const char *, ...", 'STRING_LIST': "const char *, ...",
'TIME': "VCL_TIME", 'TIME': "VCL_TIME",
'VOID': "VCL_VOID", 'VOID': "VCL_VOID",
'BLOB': "VCL_BLOB",
} }
####################################################################### #######################################################################
...@@ -381,7 +382,7 @@ class func(object): ...@@ -381,7 +382,7 @@ class func(object):
fo.write(s + ")\n") fo.write(s + ")\n")
for i in self.doc_str: for i in self.doc_str:
fo.write(i + "\n") fo.write(i + "\n")
####################################################################### #######################################################################
......
...@@ -53,6 +53,14 @@ $Function VOID test_priv_vcl(PRIV_VCL) ...@@ -53,6 +53,14 @@ $Function VOID test_priv_vcl(PRIV_VCL)
Test function for VCL private pointers Test function for VCL private pointers
$Function BLOB str2blob(STRING)
Turn a string into a blob
$Function STRING blob2hex(BLOB)
Hexdump a blob
$Object obj(STRING) $Object obj(STRING)
Test object Test object
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "config.h" #include "config.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "cache/cache.h" #include "cache/cache.h"
...@@ -94,3 +95,38 @@ vmod_test_priv_vcl(const struct vrt_ctx *ctx, struct vmod_priv *priv) ...@@ -94,3 +95,38 @@ vmod_test_priv_vcl(const struct vrt_ctx *ctx, struct vmod_priv *priv)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
assert(!strcmp(priv->priv, "FOO")); assert(!strcmp(priv->priv, "FOO"));
} }
VCL_BLOB
vmod_str2blob(const struct vrt_ctx *ctx, VCL_STRING s)
{
struct vmod_priv *p;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
p = (void*)WS_Alloc(ctx->ws, sizeof *p);
AN(p);
memset(p, 0, sizeof *p);
p->len = strlen(s);
p->priv = WS_Copy(ctx->ws, s, -1);
return (p);
}
VCL_STRING
vmod_blob2hex(const struct vrt_ctx *ctx, VCL_BLOB b)
{
char *s, *p;
uint8_t *q;
int i;
s = WS_Alloc(ctx->ws, b->len * 2 + 2);
AN(s);
p = s;
q = b->priv;
for (i = 0; i < b->len; i++) {
sprintf(p, "%02x", *q);
p += 2;
q += 1;
}
vmod_priv_fini(b);
return (s);
}
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