aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-07-22 23:02:59 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2013-07-22 23:05:28 +0300
commit7cc646c790465f6975aafa52626b99d04ac2f62d (patch)
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.
-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)
337 if (cost <= bkt->tokens) { 337 if (cost <= bkt->tokens) {
338 res = 1; 338 res = 1;
339 bkt->tokens -= cost; 339 bkt->tokens -= cost;
340 debug(2, ("tbf_rate matched %s, tokens left %z", key, 340 debug(2, ("tbf_rate matched %s, tokens left %lu", key,
341 bkt->tokens)); 341 (unsigned long)bkt->tokens));
342 } else { 342 } else {
343 res = 0; 343 res = 0;
344 debug(1, ("tbf_rate overlimit on %s", key)); 344 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)
365 365
366 return res; 366 return res;
367} 367}
368
369#define ISWS(c) ((c)==' '||(c)=='\t')
370
371unsigned
372vmod_check(struct sess *sp, const char *key, const char *spec)
373{
374 double t, v, n;
375 char *p;
376#define SKIPWS(init) for (init; *spec && ISWS(*spec); spec++)
377 int burst;
378
379 errno = 0;
380 v = strtod(spec, &p);
381 if (errno || v < 0) {
382 syslog(LOG_DAEMON|LOG_ERR, "bad rate: %s", spec);
383 return false;
384 }
385 SKIPWS(spec = p);
386 if (strncmp(spec, "req", 3)) {
387 syslog(LOG_DAEMON|LOG_ERR,
388 "bad rate: expected \"req\", but found \"%s\"", spec);
389 return false;
390 }
391 SKIPWS(spec += 3);
392 if (*spec != '/') {
393 syslog(LOG_DAEMON|LOG_ERR,
394 "bad rate: expected \"/\", but found \"%c\"", *spec);
395 return false;
396 }
397 SKIPWS(++spec);
398 if (*spec >= '0' && *spec <= '9') {
399 errno = 0;
400 n = strtod(spec, &p);
401 if (errno || n < 0) {
402 syslog(LOG_DAEMON|LOG_ERR, "bad interval: %s", spec);
403 return false;
404 }
405 spec = p;
406 } else
407 n = 1;
408 SKIPWS();
409
410 switch (*spec) {
411 case 0:
412 case 's':
413 break;
414 case 'd':
415 n *= 24;
416 case 'h':
417 n *= 60;
418 case 'm':
419 n *= 60;
420 break;
421 default:
422 syslog(LOG_DAEMON|LOG_ERR, "invalid interval specifier: %s",
423 spec);
424 return false;
425 }
426
427 SKIPWS(++spec);
428
429 if (*spec)
430 syslog(LOG_DAEMON|LOG_WARNING, "garbage after rate spec: %s",
431 spec);
432
433 return vmod_rate(sp, key, 1, n/v, v/n+1);
434}
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)
4Function VOID close() 4Function VOID close()
5Function VOID sync() 5Function VOID sync()
6Function BOOL rate(STRING, INT, DURATION, INT) 6Function BOOL rate(STRING, INT, DURATION, INT)
7Function BOOL check(STRING, STRING)
7Function REAL getla(INT) 8Function REAL getla(INT)
8Function INT systime() 9Function INT systime()
9Function STRING strftime(STRING, INT) 10Function 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 @@
1VMOD_TESTS = \ 1VMOD_TESTS = \
2 test00.vtc\ 2 test00.vtc\
3 test01.vtc\ 3 test01.vtc\
4 test02.vtc\
5 test03.vtc\
4 time00.vtc 6 time00.vtc
5 7
6EXTRA_DIST=$(VMOD_TESTS) 8EXTRA_DIST=$(VMOD_TESTS)
diff --git a/tests/test02.vtc b/tests/test02.vtc
new file mode 100644
index 0000000..b957181
--- /dev/null
+++ b/tests/test02.vtc
@@ -0,0 +1,47 @@
1varnishtest "Test tbf overlimit"
2
3server s1 {
4 rxreq
5 txresp
6} -start
7
8varnish v1 -vcl+backend {
9 import tbf from "${vmod_topbuild}/src/.libs/libvmod_tbf.so";
10 sub vcl_init {
11 tbf.open("${vmod_topbuild}/tests/tbf.db", "truncate");
12 }
13 sub vcl_fini {
14 tbf.close();
15 }
16 sub vcl_recv {
17 if (!tbf.check("url:"+req.url, "4 req/s")) {
18 error 420 "Overlimit";
19 }
20 return (lookup);
21 }
22} -start
23
24client c1 {
25 txreq -url "/"
26 rxresp
27 expect resp.status == 200
28 txreq -url "/"
29 rxresp
30 expect resp.status == 200
31 txreq -url "/"
32 rxresp
33 expect resp.status == 200
34 txreq -url "/"
35 rxresp
36 expect resp.status == 200
37 txreq -url "/"
38 rxresp
39 expect resp.status == 200
40 txreq -url "/"
41 rxresp
42 expect resp.status == 420
43}
44
45client c1 -run
46
47
diff --git a/tests/test03.vtc b/tests/test03.vtc
new file mode 100644
index 0000000..5ffba9a
--- /dev/null
+++ b/tests/test03.vtc
@@ -0,0 +1,71 @@
1varnishtest "Test tbf flow"
2
3server s1 {
4 rxreq
5 txresp
6} -start
7
8varnish v1 -vcl+backend {
9 import tbf from "${vmod_topbuild}/src/.libs/libvmod_tbf.so";
10 sub vcl_init {
11 tbf.open("${vmod_topbuild}/tests/tbf.db", "trunc");
12 }
13 sub vcl_fini {
14 tbf.close();
15 }
16 sub vcl_deliver {
17 set resp.http.result = tbf.check("url:"+req.url, "4req/s");
18 }
19} -start
20
21client c1 {
22 txreq -url "/"
23 rxresp
24 expect resp.http.result == true
25
26 txreq -url "/"
27 rxresp
28 expect resp.http.result == true
29
30 txreq -url "/"
31 rxresp
32 expect resp.http.result == true
33
34 txreq -url "/"
35 rxresp
36 expect resp.http.result == true
37
38 txreq -url "/"
39 rxresp
40 expect resp.http.result == true
41
42 txreq -url "/"
43 rxresp
44 expect resp.http.result == false
45
46 delay 1.0
47
48 txreq -url "/"
49 rxresp
50 expect resp.http.result == true
51
52 txreq -url "/"
53 rxresp
54 expect resp.http.result == true
55
56 txreq -url "/"
57 rxresp
58 expect resp.http.result == true
59
60 txreq -url "/"
61 rxresp
62 expect resp.http.result == true
63
64 txreq -url "/"
65 rxresp
66 expect resp.http.result == false
67}
68
69client c1 -run
70
71
diff --git a/tests/time01.vtc b/tests/time01.vtc
new file mode 100644
index 0000000..2325f4c
--- /dev/null
+++ b/tests/time01.vtc
@@ -0,0 +1,23 @@