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;
typedef const char * VCL_STRING;
typedef double VCL_TIME;
typedef void VCL_VOID;
typedef const struct vmod_priv * VCL_BLOB;
/***********************************************************************
* This is the composite argument we pass to compiled VCL and VRT
......@@ -238,6 +239,7 @@ struct vmod_priv;
typedef void vmod_priv_free_f(void *);
struct vmod_priv {
void *priv;
int len;
vmod_priv_free_f *free;
};
......
......@@ -392,7 +392,7 @@ vcc_arg_type(const char **p)
*/
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;
uint8_t constant = EXPR_VAR;
......@@ -423,6 +423,13 @@ vcc_expr_tostring(struct expr **e, enum var_type fmt)
case STRING:
case STRING_LIST:
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:
INCOMPL();
break;
......@@ -451,8 +458,10 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym)
vcc_expr0(tl, &e2, STRING);
if (e2 == NULL)
return;
if (e2->fmt != STRING)
vcc_expr_tostring(&e2, STRING);
if (e2->fmt != STRING) {
vcc_expr_tostring(tl, &e2, STRING);
ERRCHK(tl);
}
SkipToken(tl, ',');
ExpectErr(tl, CSTR);
......@@ -466,8 +475,10 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym)
vcc_expr0(tl, &e2, STRING);
if (e2 == NULL)
return;
if (e2->fmt != STRING)
vcc_expr_tostring(&e2, STRING);
if (e2->fmt != STRING) {
vcc_expr_tostring(tl, &e2, STRING);
ERRCHK(tl);
}
*e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2);
SkipToken(tl, ')');
}
......@@ -817,8 +828,10 @@ vcc_expr_string_add(struct vcc *tl, struct expr **e)
vcc_NextToken(tl);
vcc_expr_mul(tl, &e2, STRING);
ERRCHK(tl);
if (e2->fmt != STRING && e2->fmt != STRING_LIST)
vcc_expr_tostring(&e2, f2);
if (e2->fmt != STRING && e2->fmt != STRING_LIST) {
vcc_expr_tostring(tl, &e2, f2);
ERRCHK(tl);
}
ERRCHK(tl);
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)
/* Unless we specifically ask for a HEADER, fold them to string here */
if (fmt != HEADER && f2 == HEADER) {
vcc_expr_tostring(e, STRING);
vcc_expr_tostring(tl, e, STRING);
ERRCHK(tl);
f2 = (*e)->fmt;
assert(f2 == STRING);
}
......@@ -1184,8 +1198,11 @@ vcc_Expr(struct vcc *tl, enum var_type fmt)
t1 = tl->t;
vcc_expr0(tl, &e, fmt);
ERRCHK(tl);
if (fmt == STRING || fmt == STRING_LIST)
vcc_expr_tostring(&e, fmt);
e->t1 = t1;
if (fmt == STRING || fmt == STRING_LIST) {
vcc_expr_tostring(tl, &e, fmt);
ERRCHK(tl);
}
if (!tl->err && fmt != e->fmt) {
VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
vcc_Type(e->fmt), vcc_Type(fmt));
......
......@@ -60,6 +60,7 @@ ctypes = {
'STRING_LIST': "const char *, ...",
'TIME': "VCL_TIME",
'VOID': "VCL_VOID",
'BLOB': "VCL_BLOB",
}
#######################################################################
......@@ -381,7 +382,7 @@ class func(object):
fo.write(s + ")\n")
for i in self.doc_str:
fo.write(i + "\n")
#######################################################################
......
......@@ -53,6 +53,14 @@ $Function VOID test_priv_vcl(PRIV_VCL)
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)
Test object
......
......@@ -29,6 +29,7 @@
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include "cache/cache.h"
......@@ -94,3 +95,38 @@ vmod_test_priv_vcl(const struct vrt_ctx *ctx, struct vmod_priv *priv)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
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