r5717 - trunk/varnish-cache/bin/varnishd

phk at varnish-cache.org phk at varnish-cache.org
Wed Jan 12 14:10:09 CET 2011


Author: phk
Date: 2011-01-12 14:10:08 +0100 (Wed, 12 Jan 2011)
New Revision: 5717

Added:
   trunk/varnish-cache/bin/varnishd/cache_esi.h
Modified:
   trunk/varnish-cache/bin/varnishd/Makefile.am
   trunk/varnish-cache/bin/varnishd/cache_esi_parse.c
Log:
Attempt to generate the correct VEC string for testcase e00001.vtc



Modified: trunk/varnish-cache/bin/varnishd/Makefile.am
===================================================================
--- trunk/varnish-cache/bin/varnishd/Makefile.am	2011-01-12 11:38:53 UTC (rev 5716)
+++ trunk/varnish-cache/bin/varnishd/Makefile.am	2011-01-12 13:10:08 UTC (rev 5717)
@@ -75,6 +75,7 @@
 	cache_ban.h \
 	cache_backend.h \
 	cache_backend_poll.h \
+	cache_esi.h \
 	cache_waiter.h \
 	common.h \
 	default_vcl.h \

Added: trunk/varnish-cache/bin/varnishd/cache_esi.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_esi.h	                        (rev 0)
+++ trunk/varnish-cache/bin/varnishd/cache_esi.h	2011-01-12 13:10:08 UTC (rev 5717)
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define	VEC_V1	'B'
+#define	VEC_V2	'W'
+#define	VEC_V4	'L'
+#define	VEC_S1	'b'
+#define	VEC_S2	'w'
+#define	VEC_S4	'l'

Modified: trunk/varnish-cache/bin/varnishd/cache_esi_parse.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_esi_parse.c	2011-01-12 11:38:53 UTC (rev 5716)
+++ trunk/varnish-cache/bin/varnishd/cache_esi_parse.c	2011-01-12 13:10:08 UTC (rev 5717)
@@ -27,23 +27,293 @@
  *
  */
 
-#ifndef OLD_ESI
 #include "config.h"
 
 #include "svnid.h"
 SVNID("$Id")
 
 #include "cache.h"
+#include "cache_esi.h"
+#include "vend.h"
+#include "vct.h"
 #include "stevedore.h"
 
+#ifndef OLD_ESI
+
+struct vep_match {
+	const char	*match;
+	const char	**state;
+};
+
 struct vep_state {
 	unsigned		magic;
 #define VEP_MAGIC		0x55cb9b82
 	vfp_bytes_f		*bytes;
 	struct vsb		*vsb;
+
+	/* parser state */
+	const char		*state;
+
+	const char		*ver_p;
+
+	const char		*until;
+	const char		*until_p;
+	const char		*until_s;
+
+	struct vep_match	*match;
+	int			match_l;
+
+	char			tag[10];
+	int			tag_i;
+	
 };
 
+/*---------------------------------------------------------------------*/
+
+static const char *VEP_START =		"[Start]";
+static const char *VEP_NOTXML =	 	"[NotXml]";
+static const char *VEP_STARTTAG = 	"[StartTag]";
+static const char *VEP_MATCHBUF = 	"[MatchBuf]";
+static const char *VEP_NEXTTAG = 	"[NxtTag]";
+static const char *VEP_NOTMYTAG =	"[NotMyTag]";
+static const char *VEP_ESICMT =		"[EsiComment]";
+static const char *VEP_CMT =		"[Comment]";
+static const char *VEP_CDATA =		"[CDATA]";
+static const char *VEP_ESITAG =		"[ESITag]";
+static const char *VEP_ESIETAG =	"[ESIEndTag]";
+static const char *VEP_UNTIL =		"[Until]";
+static const char *VEP_ESIREMOVE =	"[ESI:Remove]";
+static const char *VEP_ESI_REMOVE =	"[ESI:/Remove]";
+static const char *VEP_ESIINCLUDE =	"[ESI:Include]";
+static const char *VEP_ESICOMMENT =	"[ESI:Comment]";
+static const char *VEP_MATCH =		"[Match]";
+static const char *VEP_XXX =		"[XXX]";
+
+/*---------------------------------------------------------------------*/
+
+static struct vep_match vep_match_tbl[] = {
+	{ "<!--esi",	&VEP_ESICMT },
+	{ "<!--",	&VEP_CMT },
+	{ "</esi:",	&VEP_ESIETAG },
+	{ "<esi:",	&VEP_ESITAG },
+	{ "<![CDATA[",	&VEP_CDATA },
+	{ NULL,		&VEP_NOTMYTAG }
+};
+
+static const int vep_match_tbl_len =
+    sizeof vep_match_tbl / sizeof vep_match_tbl[0];
+
+static struct vep_match vep_match_esi[] = {
+	{ "include",	&VEP_ESIINCLUDE },
+	{ "remove",	&VEP_ESIREMOVE },
+	{ "comment",	&VEP_ESICOMMENT },
+	{ NULL,		&VEP_XXX }
+};
+
+static const int vep_match_esi_len =
+    sizeof vep_match_esi / sizeof vep_match_esi[0];
+
 /*---------------------------------------------------------------------
+ * return match or NULL if more input needed.
+ */
+static struct vep_match *
+vep_match(struct vep_state *vep, const char *b, const char *e)
+{
+	struct vep_match *vm;
+	const char *q, *r;
+
+	for (vm = vep->match; vm->match; vm++) {
+		r = b;
+		for (q = vm->match; *q && r < e; q++, r++)
+			if (*q != *r)
+				break;
+		if (*q != '\0' && r == e) {
+			if (b != vep->tag) {
+				assert(e - b < sizeof vep->tag);
+				memcpy(vep->tag, b, e - b);
+				vep->tag_i = e - b;
+			}
+			return (NULL);
+		}
+		if (*q == '\0')
+			return (vm);
+	}
+	return (vm);
+}
+
+/*---------------------------------------------------------------------
+ *
+ */
+
+static void
+vep_end_verbatim(struct vep_state *vep, const char *p)
+{
+	ssize_t l;
+	uint8_t buf[5];
+
+	AN(vep->ver_p);
+	l = p - vep->ver_p;
+	if (l == 0)
+		return;
+	assert(l > 0);
+	if (l < 256) {
+		buf[0] = VEC_V1;
+		buf[1] = (uint8_t)l;
+		vsb_bcat(vep->vsb, buf, 2);
+	} else if (l < 65536) {
+		buf[0] = VEC_V2;
+		vbe16enc(buf + 1, (uint16_t)l);
+		vsb_bcat(vep->vsb, buf, 3);
+	} else {
+		/* XXX assert < 2^32 */
+		buf[0] = VEC_V4;
+		vbe32enc(buf + 1, (uint32_t)l);
+		vsb_bcat(vep->vsb, buf, 5);
+	}
+	vep->ver_p = p;
+} 
+
+static void
+vep_end_skip(struct vep_state *vep, const char *p)
+{
+	ssize_t l;
+	uint8_t buf[5];
+
+	AN(vep->ver_p);
+	l = p - vep->ver_p;
+	if (l == 0)
+		return;
+	assert(l > 0);
+	if (l < 256) {
+		buf[0] = VEC_S1;
+		buf[1] = (uint8_t)l;
+		vsb_bcat(vep->vsb, buf, 2);
+	} else if (l < 65536) {
+		buf[0] = VEC_S2;
+		vbe16enc(buf + 1, (uint16_t)l);
+		vsb_bcat(vep->vsb, buf, 3);
+	} else {
+		/* XXX assert < 2^32 */
+		buf[0] = VEC_S4;
+		vbe32enc(buf + 1, (uint32_t)l);
+		vsb_bcat(vep->vsb, buf, 5);
+	}
+	vep->ver_p = p;
+} 
+
+/*---------------------------------------------------------------------
+ * Parse object for ESI instructions
+ */
+
+#include <stdio.h>
+
+static void
+vep_parse(struct vep_state *vep, const char *b, size_t l)
+{
+	const char *e, *p;
+	struct vep_match *vm;
+
+	CHECK_OBJ_NOTNULL(vep, VEP_MAGIC);
+	assert(l > 0);
+
+	e = b + l;
+
+	vep->ver_p = b;
+	printf("EP Call %d [%.*s]\n", (int)l, (int)l, b);
+	p = b;
+	while (p < e) {
+		AN(vep->state);
+		printf("EP %s [%.*s]\n",
+		    vep->state,
+		    (int)(e - p), p);
+		if (vep->state == VEP_START) {
+			/*
+			 * Look for the first non-white char, and
+			 * abandon if it is not '<' under the assumption
+			 * that it is not an ESI file
+			 */
+			while (p < e && vct_islws(*p))
+				p++;
+			if (p < e) {
+				if (*p == '<')
+					vep->state = VEP_STARTTAG;
+				else
+					vep->state = VEP_NOTXML;
+			}
+		} else if (vep->state == VEP_NEXTTAG) {
+			/*
+			 * Hunt for start of next tag
+			 */
+			while (p < e && *p != '<') {
+#if 0
+				if (vep->incmt != NULL &&
+				    *p == *vep->incmt_p) {
+					if (*++vep->incmt_p == '\0') {
+						vep->incmt = NULL;
+						vep->incmt = NULL;
+					}
+				} else
+					vep->incmt_p = vep->incmt;
+#endif
+				p++;
+			}
+			if (p < e)
+				vep->state = VEP_STARTTAG;
+		} else if (vep->state == VEP_STARTTAG) {
+			/*
+			 * Start of tag, set up match table
+			 */
+			vep_end_verbatim(vep, p);
+			vep->match = vep_match_tbl;
+			vep->match_l = vep_match_tbl_len;
+			vep->state = VEP_MATCH;
+		} else if (vep->state == VEP_MATCH) {
+			/*
+			 * Match against a table
+			 */
+			vm = vep_match(vep, p, e);
+			if (vm != NULL) {
+				if (vm->match != NULL)
+					p += strlen(vm->match);
+				b = p;
+				vep->state = *vm->state;
+				vep->tag_i = 0;
+			} else {
+				vep->state = VEP_MATCHBUF;
+				return;
+			}
+		} else if (vep->state == VEP_UNTIL) {
+			/*
+			 * Skip until we see magic string
+			 */
+			while (p < e) {
+				if (*p++ != *vep->until_p++) {
+					vep->until_p = vep->until;
+				} else if (*vep->until_p == '\0') {
+					vep->state = vep->until_s;
+					break;
+				}
+			}
+		} else if (vep->state == VEP_ESITAG) {
+			vep->match = vep_match_esi;
+			vep->match_l = vep_match_esi_len;
+			vep->state = VEP_MATCH;
+		} else if (vep->state == VEP_ESIREMOVE) {
+			vep->until_p = vep->until = "</esi:remove>";
+			vep->until_s = VEP_ESI_REMOVE;
+			vep->state = VEP_UNTIL;;
+		} else if (vep->state == VEP_ESI_REMOVE) {
+			vep_end_skip(vep, p);
+			vep->state = VEP_NEXTTAG;
+		} else {
+			printf("*** Unknown state %s\n", vep->state);
+			break;
+		}
+	}
+	vep_end_verbatim(vep, p);
+}
+
+/*---------------------------------------------------------------------
  * We receive a ungzip'ed object, and want to store it ungzip'ed.
  */
 
@@ -74,6 +344,7 @@
 		w = HTC_Read(htc, st->ptr + st->len, l);
 		if (w <= 0)
 			return (w);
+		vep_parse(vep, (const char *)st->ptr + st->len, w);
 		st->len += w;
 		sp->obj->len += w;
 		if (st->len == st->space) {
@@ -99,10 +370,12 @@
 	vep = (void*)WS_Alloc(sp->wrk->ws, sizeof *vep);
 	AN(vep);
 
+
 	memset(vep, 0, sizeof *vep);
 	vep->magic = VEP_MAGIC;
 	vep->bytes = vfp_esi_bytes_uu;
 	vep->vsb = vsb_newauto();
+	vep->state = VEP_START;
 	AN(vep->vsb);
 
 	sp->wrk->vep = vep;
@@ -124,9 +397,34 @@
 static int __match_proto__()
 vfp_esi_end(struct sess *sp)
 {
+	struct storage *st;
+	struct vep_state *vep;
 
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
-	return (-1);
+	vep = sp->wrk->vep;
+	CHECK_OBJ_NOTNULL(vep, VEP_MAGIC);
+
+	vsb_finish(vep->vsb);
+	printf("ESI <%s>\n", vsb_data(vep->vsb));
+
+	/* XXX: This is a huge waste of storage... */
+	sp->obj->esidata = STV_alloc(sp, vsb_len(vep->vsb));
+	AN(sp->obj->esidata);
+	memcpy(sp->obj->esidata->ptr, vsb_data(vep->vsb), vsb_len(vep->vsb));
+
+	st = sp->wrk->storage;
+	sp->wrk->storage = NULL;
+	if (st == NULL)
+		return (0);
+
+	if (st->len == 0) {
+		STV_free(st);
+		return (0);
+	}
+	if (st->len < st->space)
+		STV_trim(st, st->len);
+	VTAILQ_INSERT_TAIL(&sp->obj->store, st, list);
+	return (0);
 }
 
 struct vfp vfp_esi = {




More information about the varnish-commit mailing list