Commit ba187152 authored by Geoff Simmons's avatar Geoff Simmons

Add the integer() function.

parent 55575021
Pipeline #218 skipped
......@@ -30,6 +30,7 @@ CONTENTS
* BOOL same(BLOB, BLOB)
* BOOL equal(BLOB, BLOB)
* INT length(BLOB)
* INT integer(BLOB, ENUM {LPAD,RPAD})
* STRING version()
.. _func_same:
......@@ -41,10 +42,8 @@ same
BOOL same(BLOB, BLOB)
Description
Returns true if and only if the two BLOB arguments are the
same object, i.e. they specify exactly the same region of
memory.
Returns true if and only if the two BLOB arguments are the same
object, i.e. they specify exactly the same region of memory.
.. _func_equal:
......@@ -55,9 +54,8 @@ equal
BOOL equal(BLOB, BLOB)
Description
Returns true if and only if the two BLOB arguments have equal
contents (possibly in different memory regions).
Returns true if and only if the two BLOB arguments have equal contents
(possibly in different memory regions).
.. _func_length:
......@@ -68,8 +66,36 @@ length
INT length(BLOB)
Description
Returns the length of the BLOB.
Returns the length of the BLOB.
.. _func_integer:
integer
-------
::
INT integer(BLOB, ENUM {LPAD,RPAD} padding="LPAD")
Returns the initial bytes of the BLOB as an integer.
If the BLOB has fewer bytes than the size of an INT, then the return
value is padded with zeroes to the left if ``padding`` is ``LPAD``, or
to the right if ``padding`` is ``RPAD``. That is, when ``padding`` is
``RPAD``, then the initial bytes of the BLOB are bit-shifted to the
left so that the size of an INT is filled. ``padding`` is ``LPAD`` by
default.
The value of the returned integer results from the bytes from the BLOB
in ascending order of addresses interpreted according to the
endianness of the system on which Varnish is running.
If the length of the BLOB is 0, then ``integer()`` returns 0 and emits
an error message to the Varnish log using the ``VCL_Error`` tag. If
this happens when ``integer()`` is called in ``vcl_init``, then the
VCL load fails with the error message. If it happens in any other VCL
subroutine, then VCL processing continues. Since 0 can be a legitimate
return value, you should monitor the Varnish log for the error.
.. _func_version:
......@@ -80,18 +106,18 @@ version
STRING version()
Description
Returns the version string for this VMOD.
Returns the version string for this VMOD.
Example::
Example
std.log("Using VMOD blob version " + blob.version());
std.log("Using VMOD blob version " + blob.version());
COPYRIGHT
=========
::
Copyright (c) 2016 UPLEX Nils Goroll Systemoptimierung
Copyright (c) 2016-2017 UPLEX Nils Goroll Systemoptimierung
All rights reserved
Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
......
......@@ -123,6 +123,9 @@ varnish v1 -vcl {
set resp.http.empty1len = blob.length(empty1.get());
set resp.http.empty2len = blob.length(empty2.get());
set resp.http.fooint = blob.integer(foo1.get());
set resp.http.hobbesint = blob.integer(hobbes1.get());
set resp.http.emptyint = blob.integer(empty1.get());
return(deliver);
}
} -start
......@@ -170,3 +173,118 @@ client c1 {
expect resp.http.empty1len == "0"
expect resp.http.empty2len == "0"
} -run
# integer()
varnish v1 -vcl {
import blob from "${vmod_topbuild}/src/.libs/libvmod_blob.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
# Byte values 7 to 0 in descending order
# $ printf "\x7\x6\x5\x4\x3\x2\x1\x0" | base64
new down07 = blobcode.blob(BASE64, "BwYFBAMCAQA=");
# Byte values 0 to 7 in ascending order
# $ printf "\x0\x1\x2\x3\x4\x5\x6\x7" | base64
new up07 = blobcode.blob(BASE64, "AAECAwQFBgc=");
# Byte values f down to 0
new down0f = blobcode.blob(BASE64, "Dw4NDAsKCQgHBgUEAwIBAA==");
# Byte values 0 up to f
new up0f = blobcode.blob(BASE64, "AAECAwQFBgcICQoLDA0ODw==");
# Byte values 3 down to 0
new down03 = blobcode.blob(BASE64, "AwIBAA==");
# Byte values 0 up to 3
new up03 = blobcode.blob(BASE64, "AAECAw==");
# 16 x 0xff
new minusone = blobcode.blob(BASE64, "//////////8=");
# Byte value 0x7f
new onebyte = blobcode.blob(BASE64, "fw==");
# Byte values 2 down to 0
new down02 = blobcode.blob(BASE64, "AgEA");
# Byte values 0 up to 2
new up02 = blobcode.blob(BASE64, "AAEC");
new empty = blobcode.blob(IDENTITY, "");
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.down07 = blob.integer(down07.get());
set resp.http.up07 = blob.integer(up07.get());
set resp.http.down0f = blob.integer(down0f.get());
set resp.http.up0f = blob.integer(up0f.get());
set resp.http.down03 = blob.integer(down03.get());
set resp.http.up03 = blob.integer(up03.get());
set resp.http.minusone = blob.integer(minusone.get());
set resp.http.onebyte = blob.integer(onebyte.get());
set resp.http.onebyterpad = blob.integer(onebyte.get(), RPAD);
set resp.http.down0frpad = blob.integer(down0f.get(), RPAD);
set resp.http.up0frpad = blob.integer(up0f.get(), RPAD);
set resp.http.down02 = blob.integer(down02.get());
set resp.http.down02lpad = blob.integer(down02.get(), LPAD);
set resp.http.down02rpad = blob.integer(down02.get(), RPAD);
set resp.http.up02 = blob.integer(up02.get());
set resp.http.up02lpad = blob.integer(up02.get(), LPAD);
set resp.http.up02rpad = blob.integer(up02.get(), RPAD);
set resp.http.empty = blob.integer(empty.get());
}
}
# Check possible values for 8-, 4- and 2-byte INTs.
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.down07 ~ "^(283686952306183|117835012|1798)$"
expect resp.http.up07 ~ "^(506097522914230528|66051|1)$"
expect resp.http.down07 != resp.http.up07
expect resp.http.down0f ~ "^(579005069656919567|252579084|3854)$"
expect resp.http.up0f ~ "^(506097522914230528|66051|1)$"
expect resp.http.up0f != resp.http.down0f
expect resp.http.down03 ~ "^(50462976|770)$"
expect resp.http.up03 ~ "^(66051|1)$"
expect resp.http.minusone == "-1"
expect resp.http.onebyte == "127"
expect resp.http.onebyterpad ~ "^(9151314442816847872|2130706432|32512)$"
expect resp.http.down0frpad == resp.http.down0f
expect resp.http.up0frpad == resp.http.up0f
expect resp.http.down02 ~ "^(131328|513)$"
expect resp.http.down02lpad == resp.http.down02
expect resp.http.down02rpad ~ "^(144396663052566528|33619968|513)$"
expect resp.http.up02 ~ "^(258|1)$"
expect resp.http.up02lpad == resp.http.up02
expect resp.http.up02rpad ~ "^(283673999966208|66048|1)$"
expect resp.http.empty == "0"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod blob error: blob length is 0 in blob.integer..$"
expect * = End
} -run
# VCL load fails if integer() is called for an empty blob in vcl_init
varnish v1 -errvcl {vmod blob error: blob length is 0 in blob.integer()} {
import blob from "${vmod_topbuild}/src/.libs/libvmod_blob.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new empty = blobcode.blob(IDENTITY, "");
if (blob.integer(empty.get()) == 0) {
new B = blobcode.blob(IDENTITY, "b");
}
}
}
......@@ -25,14 +25,46 @@
*
*/
#include "config.h"
#include <string.h>
#include "config.h"
#include "vcl.h"
#include "vas.h"
#include "vdef.h"
#include "vrt.h"
#include "cache/cache.h"
#include "vsb.h"
#include "vcc_if.h"
#define ERR(ctx, msg) \
errmsg((ctx), "vmod blob error: " msg)
#define VERR(ctx, fmt, ...) \
errmsg((ctx), "vmod blob error: " fmt, __VA_ARGS__)
static void
errmsg(VRT_CTX, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (ctx->vsl)
VSLbv(ctx->vsl, SLT_VCL_Error, fmt, args);
else
VSLv(SLT_VCL_Error, 0, fmt, args);
va_end(args);
if (ctx->method == VCL_MET_INIT) {
AN(ctx->msg);
va_start(args, fmt);
VSB_vprintf(ctx->msg, fmt, args);
va_end(args);
VRT_handling(ctx, VCL_RET_FAIL);
}
}
VCL_BOOL
vmod_same(VRT_CTX __attribute__((unused)), VCL_BLOB b1, VCL_BLOB b2)
{
......@@ -55,6 +87,24 @@ vmod_length(VRT_CTX __attribute__((unused)), VCL_BLOB b)
return b->len;
}
VCL_INT
vmod_integer(VRT_CTX, VCL_BLOB b, VCL_ENUM padding)
{
VCL_INT i = 0;
if (b->len >= sizeof(VCL_INT))
return *((VCL_INT *) b->priv);
if (b->len == 0) {
ERR(ctx, "blob length is 0 in blob.integer()");
return 0;
}
for (int j = 0; j < b->len; j++)
i |= ((unsigned char *)b->priv)[j] << ((b->len - j - 1) * 8);
if (padding[0] == 'R')
i <<= (sizeof(VCL_INT) - b->len) * 8;
return i;
}
VCL_STRING
vmod_version(VRT_CTX __attribute__((unused)))
{
......
#-
# Copyright (c) 2016 UPLEX Nils Goroll Systemoptimierung
# Copyright (c) 2016-2017 UPLEX Nils Goroll Systemoptimierung
# All rights reserved
#
# Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
......@@ -11,26 +11,44 @@ $Module blob 3 basic operations for the VCL blob type
$Function BOOL same(BLOB, BLOB)
Description
Returns true if and only if the two BLOB arguments are the
same object, i.e. they specify exactly the same region of
memory.
Returns true if and only if the two BLOB arguments are the same
object, i.e. they specify exactly the same region of memory.
$Function BOOL equal(BLOB, BLOB)
Description
Returns true if and only if the two BLOB arguments have equal
contents (possibly in different memory regions).
Returns true if and only if the two BLOB arguments have equal contents
(possibly in different memory regions).
$Function INT length(BLOB)
Description
Returns the length of the BLOB.
Returns the length of the BLOB.
$Function INT integer(BLOB, ENUM { LPAD, RPAD } padding="LPAD")
Returns the initial bytes of the BLOB as an integer.
If the BLOB has fewer bytes than the size of an INT, then the return
value is padded with zeroes to the left if ``padding`` is ``LPAD``, or
to the right if ``padding`` is ``RPAD``. That is, when ``padding`` is
``RPAD``, then the initial bytes of the BLOB are bit-shifted to the
left so that the size of an INT is filled. ``padding`` is ``LPAD`` by
default.
The value of the returned integer results from the bytes from the BLOB
in ascending order of addresses interpreted according to the
endianness of the system on which Varnish is running.
If the length of the BLOB is 0, then ``integer()`` returns 0 and emits
an error message to the Varnish log using the ``VCL_Error`` tag. If
this happens when ``integer()`` is called in ``vcl_init``, then the
VCL load fails with the error message. If it happens in any other VCL
subroutine, then VCL processing continues. Since 0 can be a legitimate
return value, you should monitor the Varnish log for the error.
$Function STRING version()
Description
Returns the version string for this VMOD.
Returns the version string for this VMOD.
Example::
Example
std.log("Using VMOD blob version " + blob.version());
std.log("Using VMOD blob version " + blob.version());
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