Mailing List Archive

r87 - trunk/varnish-cache/lib/libvcl
Author: phk
Date: 2006-03-30 12:56:57 +0200 (Thu, 30 Mar 2006)
New Revision: 87

Modified:
trunk/varnish-cache/lib/libvcl/vcl_compile.c
Log:
Rework the compilation of backend specifications in order to be able
to check the provided hostname/portname at compile time.



Modified: trunk/varnish-cache/lib/libvcl/vcl_compile.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-03-30 09:26:34 UTC (rev 86)
+++ trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-03-30 10:56:57 UTC (rev 87)
@@ -44,6 +44,11 @@
#include <sys/sbuf.h>
#include <sys/stat.h>
#include <sys/queue.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
#include "vcl_priv.h"

#include "libvcl.h"
@@ -82,7 +87,9 @@
RATE,
TIME,
STRING,
- IP
+ IP,
+ HOSTNAME,
+ PORTNAME
};

struct var {
@@ -90,7 +97,6 @@
enum var_type fmt;
int len;
const char *cname;
-
};

enum ref_type {
@@ -108,9 +114,13 @@
};


+static struct var be_vars[] = {
+ { "backend.host", HOSTNAME, 0, "backend->hostname" },
+ { "backend.port", PORTNAME, 0, "backend->portname" },
+};
+
+
static struct var vars[] = {
- { "backend.host", STRING, 0, "backend->hostname" },
- { "backend.port", STRING, 0, "backend->portname" },
#if 0
{ "req.ttlfactor", FLOAT, 0, "req->ttlfactor" },
{ "req.url.host", STRING, 0, "req->url.host" },
@@ -279,6 +289,58 @@
return (1);
}

+/*--------------------------------------------------------------------*/
+
+char *
+EncString(struct token *t)
+{
+ char *p, *q;
+ const char *r;
+ unsigned u;
+
+ assert(t->tok == CSTR);
+ p = malloc(t->e - t->b);
+ assert(p != NULL);
+ q = p;
+ for (r = t->b + 1; r < t->e - 1; ) {
+ if (*r != '\\') {
+ *q++ = *r++;
+ continue;
+ }
+ switch (r[1]) {
+ case 'n': *q++ = '\n'; r += 2; break;
+ case 'r': *q++ = '\r'; r += 2; break;
+ case 'v': *q++ = '\v'; r += 2; break;
+ case 'f': *q++ = '\f'; r += 2; break;
+ case 't': *q++ = '\t'; r += 2; break;
+ case 'b': *q++ = '\b'; r += 2; break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ u = digittoint(r[1]);
+ r += 2;
+ if (isdigit(r[0]) && digittoint(r[0]) < 8) {
+ u <<= 3;
+ u |= digittoint(r[0]);
+ r++;
+ if (isdigit(r[0]) && digittoint(r[0]) < 8) {
+ u <<= 3;
+ u |= digittoint(r[0]);
+ r++;
+ }
+ }
+ *q++ = u;
+ break;
+ default:
+ *q++ = r[1];
+ r += 2;
+ break;
+ }
+ }
+ *q = '\0';
+ return (p);
+}
+
+
/*--------------------------------------------------------------------
* Keep track of definitions and references
*/
@@ -487,11 +549,11 @@
/*--------------------------------------------------------------------*/

static struct var *
-FindVar(struct tokenlist *tl, struct token *t)
+FindVar(struct tokenlist *tl, struct token *t, struct var *vl)
{
struct var *v;

- for (v = vars; v->name != NULL; v++) {
+ for (v = vl; v->name != NULL; v++) {
if (t->e - t->b != v->len)
continue;
if (!memcmp(t->b, v->name, v->len))
@@ -683,7 +745,7 @@
ExpectErr(tl, ')');
NextToken(tl);
} else if (tl->t->tok == VAR) {
- vp = FindVar(tl, tl->t);
+ vp = FindVar(tl, tl->t, vars);
ERRCHK(tl);
assert(vp != NULL);
NextToken(tl);
@@ -876,7 +938,7 @@
return;
case T_SET:
ExpectErr(tl, VAR);
- vp = FindVar(tl, tl->t);
+ vp = FindVar(tl, tl->t, vars);
ERRCHK(tl);
assert(vp != NULL);
I(tl);
@@ -1046,12 +1108,36 @@

/*--------------------------------------------------------------------*/

+static const char *
+CheckHostPort(const char *host, const char *port)
+{
+ struct addrinfo *res, hint;
+ int error;
+
+ memset(&hint, 0, sizeof hint);
+ hint.ai_family = PF_UNSPEC;
+ hint.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, port, &hint, &res);
+ if (error)
+ return (gai_strerror(error));
+ freeaddrinfo(res);
+ return (NULL);
+}
+
static void
Backend(struct tokenlist *tl)
{
+ struct var *vp;
+ struct token *t_be = NULL;
+ struct token *t_host = NULL;
+ struct token *t_port = NULL;
+ char *host = NULL;
+ char *port = NULL;
+ const char *ep;

NextToken(tl);
ExpectErr(tl, ID);
+ t_be = tl->t;
AddDef(tl, tl->t, R_BACKEND);
I(tl);
sbuf_printf(tl->fh, "static struct backend VCL_backend_%*.*s;\n",
@@ -1066,8 +1152,86 @@
"VCL_init_backend_%*.*s (struct backend *backend)\n",
tl->t->e - tl->t->b,
tl->t->e - tl->t->b, tl->t->b);
+ I(tl);
+ sbuf_printf(tl->fc, "{\n");
NextToken(tl);
- L(tl, Compound(tl));
+ ExpectErr(tl, '{');
+ NextToken(tl);
+ while (1) {
+ if (tl->t->tok == '}')
+ break;
+ ExpectErr(tl, T_SET);
+ NextToken(tl);
+ ExpectErr(tl, VAR);
+ vp = FindVar(tl, tl->t, be_vars);
+ ERRCHK(tl);
+ assert(vp != NULL);
+ NextToken(tl);
+ ExpectErr(tl, '=');
+ NextToken(tl);
+ switch (vp->fmt) {
+ case HOSTNAME:
+ ExpectErr(tl, CSTR);
+ t_host = tl->t;
+ host = EncString(tl->t);
+ I(tl);
+ sbuf_printf(tl->fc, "\t%s = %*.*s;\n",
+ vp->cname,
+ tl->t->e - tl->t->b,
+ tl->t->e - tl->t->b, tl->t->b);
+ NextToken(tl);
+ break;
+ case PORTNAME:
+ ExpectErr(tl, CSTR);
+ t_port = tl->t;
+ port = EncString(tl->t);
+ sbuf_printf(tl->fc, "\t%s = %*.*s;\n",
+ vp->cname,
+ tl->t->e - tl->t->b,
+ tl->t->e - tl->t->b, tl->t->b);
+ NextToken(tl);
+ break;
+ default:
+ sbuf_printf(tl->sb,
+ "Assignments not possible for '%s'\n", vp->name);
+ ErrWhere(tl, tl->t);
+ return;
+ }
+ ExpectErr(tl, ';');
+ NextToken(tl);
+ }
+ ExpectErr(tl, '}');
+ if (host == NULL) {
+ sbuf_printf(tl->sb, "Backend '%*.*s' has no hostname\n",
+ t_be->e - t_be->b,
+ t_be->e - t_be->b, t_be->b);
+ ErrWhere(tl, tl->t);
+ return;
+ }
+ ep = CheckHostPort(host, "80");
+ if (ep != NULL) {
+ sbuf_printf(tl->sb,
+ "Backend '%*.*s': %s\n",
+ t_be->e - t_be->b,
+ t_be->e - t_be->b, t_be->b, ep);
+ ErrWhere(tl, t_host);
+ return;
+ }
+ if (port != NULL) {
+ ep = CheckHostPort(host, port);
+ if (ep != NULL) {
+ sbuf_printf(tl->sb,
+ "Backend '%*.*s': %s\n",
+ t_be->e - t_be->b,
+ t_be->e - t_be->b, t_be->b, ep);
+ ErrWhere(tl, t_port);
+ return;
+ }
+ }
+
+ NextToken(tl);
+ I(tl);
+ sbuf_printf(tl->fc, "}\n");
sbuf_printf(tl->fc, "\n");
}

@@ -1504,4 +1668,6 @@
vcl_init_tnames();
for (v = vars; v->name != NULL; v++)
v->len = strlen(v->name);
+ for (v = be_vars; v->name != NULL; v++)
+ v->len = strlen(v->name);
}