summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2013-07-22 20:02:59 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2013-07-22 20:05:28 (GMT)
commit7cc646c790465f6975aafa52626b99d04ac2f62d (patch) (side-by-side diff)
tree3ed4ed45093ce78750f228c737064f8327ac09c0
parent88126134cd43e8da9ade49d18c757c6a41b777bc (diff)
downloadvmod-tbf-7cc646c790465f6975aafa52626b99d04ac2f62d.tar.gz
vmod-tbf-7cc646c790465f6975aafa52626b99d04ac2f62d.tar.bz2
New function "check"
* src/vmod_tbf.c (vmod_rate): Use %lu instead of %z (vmod_check): New function. * src/vmod_tbf.vcc (check): New function. * tests/Makefile.am: Add new files. * tests/test02.vtc: New file. * tests/test03.vtc: New file. * tests/time01.vtc: New file.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/vmod_tbf.c71
-rw-r--r--src/vmod_tbf.vcc1
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/test02.vtc47
-rw-r--r--tests/test03.vtc71
-rw-r--r--tests/time01.vtc23
6 files changed, 213 insertions, 2 deletions
diff --git a/src/vmod_tbf.c b/src/vmod_tbf.c
index dab0987..02c26ec 100644
--- a/src/vmod_tbf.c
+++ b/src/vmod_tbf.c
@@ -337,8 +337,8 @@ vmod_rate(struct sess *sp, const char *key, int cost, double t, int burst_size)
if (cost <= bkt->tokens) {
res = 1;
bkt->tokens -= cost;
- debug(2, ("tbf_rate matched %s, tokens left %z", key,
- bkt->tokens));
+ debug(2, ("tbf_rate matched %s, tokens left %lu", key,
+ (unsigned long)bkt->tokens));
} else {
res = 0;
debug(1, ("tbf_rate overlimit on %s", key));
@@ -365,3 +365,70 @@ vmod_rate(struct sess *sp, const char *key, int cost, double t, int burst_size)
return res;
}
+
+#define ISWS(c) ((c)==' '||(c)=='\t')
+
+unsigned
+vmod_check(struct sess *sp, const char *key, const char *spec)
+{
+ double t, v, n;
+ char *p;
+#define SKIPWS(init) for (init; *spec && ISWS(*spec); spec++)
+ int burst;
+
+ errno = 0;
+ v = strtod(spec, &p);
+ if (errno || v < 0) {
+ syslog(LOG_DAEMON|LOG_ERR, "bad rate: %s", spec);
+ return false;
+ }
+ SKIPWS(spec = p);
+ if (strncmp(spec, "req", 3)) {
+ syslog(LOG_DAEMON|LOG_ERR,
+ "bad rate: expected \"req\", but found \"%s\"", spec);
+ return false;
+ }
+ SKIPWS(spec += 3);
+ if (*spec != '/') {
+ syslog(LOG_DAEMON|LOG_ERR,
+ "bad rate: expected \"/\", but found \"%c\"", *spec);
+ return false;
+ }
+ SKIPWS(++spec);
+ if (*spec >= '0' && *spec <= '9') {
+ errno = 0;
+ n = strtod(spec, &p);
+ if (errno || n < 0) {
+ syslog(LOG_DAEMON|LOG_ERR, "bad interval: %s", spec);
+ return false;
+ }
+ spec = p;
+ } else
+ n = 1;
+ SKIPWS();
+
+ switch (*spec) {
+ case 0:
+ case 's':
+ break;
+ case 'd':
+ n *= 24;
+ case 'h':
+ n *= 60;
+ case 'm':
+ n *= 60;
+ break;
+ default:
+ syslog(LOG_DAEMON|LOG_ERR, "invalid interval specifier: %s",
+ spec);
+ return false;
+ }
+
+ SKIPWS(++spec);
+
+ if (*spec)
+ syslog(LOG_DAEMON|LOG_WARNING, "garbage after rate spec: %s",
+ spec);
+
+ return vmod_rate(sp, key, 1, n/v, v/n+1);
+}
diff --git a/src/vmod_tbf.vcc b/src/vmod_tbf.vcc
index babca68..637c4f8 100644
--- a/src/vmod_tbf.vcc
+++ b/src/vmod_tbf.vcc
@@ -4,6 +4,7 @@ Function VOID open(STRING, STRING)
Function VOID close()
Function VOID sync()
Function BOOL rate(STRING, INT, DURATION, INT)
+Function BOOL check(STRING, STRING)
Function REAL getla(INT)
Function INT systime()
Function STRING strftime(STRING, INT)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5826201..383f18a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,8 @@
VMOD_TESTS = \
test00.vtc\
test01.vtc\
+ test02.vtc\
+ test03.vtc\
time00.vtc
EXTRA_DIST=$(VMOD_TESTS)
diff --git a/tests/test02.vtc b/tests/test02.vtc
new file mode 100644
index 0000000..b957181
--- a/dev/null
+++ b/tests/test02.vtc
@@ -0,0 +1,47 @@
+varnishtest "Test tbf overlimit"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -vcl+backend {
+ import tbf from "${vmod_topbuild}/src/.libs/libvmod_tbf.so";
+ sub vcl_init {
+ tbf.open("${vmod_topbuild}/tests/tbf.db", "truncate");
+ }
+ sub vcl_fini {
+ tbf.close();
+ }
+ sub vcl_recv {
+ if (!tbf.check("url:"+req.url, "4 req/s")) {
+ error 420 "Overlimit";
+ }
+ return (lookup);
+ }
+} -start
+
+client c1 {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+ txreq -url "/"
+ rxresp
+ expect resp.status == 420
+}
+
+client c1 -run
+
+
diff --git a/tests/test03.vtc b/tests/test03.vtc
new file mode 100644
index 0000000..5ffba9a
--- a/dev/null
+++ b/tests/test03.vtc
@@ -0,0 +1,71 @@
+varnishtest "Test tbf flow"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -vcl+backend {
+ import tbf from "${vmod_topbuild}/src/.libs/libvmod_tbf.so";
+ sub vcl_init {
+ tbf.open("${vmod_topbuild}/tests/tbf.db", "trunc");
+ }
+ sub vcl_fini {
+ tbf.close();
+ }
+ sub vcl_deliver {
+ set resp.http.result = tbf.check("url:"+req.url, "4req/s");
+ }
+} -start
+
+client c1 {
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == false
+
+ delay 1.0
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == true
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.result == false
+}
+
+client c1 -run
+
+
diff --git a/tests/time01.vtc b/tests/time01.vtc
new file mode 100644
index 0000000..2325f4c
--- a/dev/null
+++ b/tests/time01.vtc
@@ -0,0 +1,23 @@
+varnishtest "Test strftime"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -vcl+backend {
+ import tbf from "${vmod_topbuild}/src/.libs/libvmod_tbf.so";
+ sub vcl_deliver {
+ set resp.http.result = tbf.strftime("%Y-%m-%d", tbf.systime());
+ }
+} -start
+
+client c1 {
+ txreq
+ rxresp
+ expect resp.http.result == 2013
+}
+
+client c1 -run
+
+

Return to:

Send suggestions and report system problems to the System administrator.