r533 - in trunk/varnish-cache: bin/varnishd include

phk at projects.linpro.no phk at projects.linpro.no
Fri Jul 21 11:32:10 CEST 2006


Author: phk
Date: 2006-07-21 11:32:09 +0200 (Fri, 21 Jul 2006)
New Revision: 533

Modified:
   trunk/varnish-cache/bin/varnishd/cache.h
   trunk/varnish-cache/bin/varnishd/cache_center.c
   trunk/varnish-cache/bin/varnishd/cache_hash.c
   trunk/varnish-cache/bin/varnishd/cache_http.c
   trunk/varnish-cache/bin/varnishd/cache_pass.c
   trunk/varnish-cache/bin/varnishd/cache_pool.c
   trunk/varnish-cache/bin/varnishd/cache_response.c
   trunk/varnish-cache/bin/varnishd/cache_vrt.c
   trunk/varnish-cache/include/http_headers.h
Log:
HTTP header munging part (N of M)

NB: Only pass mode (lightly) tested right now.

Give up on the three element array per header and use a two element struct
instead, it reduces obfuscation and removes risk of pointer fandango.

Introduce #defined filtercontrol in http_headers.h, use them in a new
field.  Only Pass is there for now.

Use the http-workspace for building headers instead of sbuf.

Move uiovec handling to cache_pool.c where it more naturally belongs
and so we can use it on both backends and sessions.

Add http header munging functiosn for copying, printf'ing, filtering and
writing headers.




Modified: trunk/varnish-cache/bin/varnishd/cache.h
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache.h	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache.h	2006-07-21 09:32:09 UTC (rev 533)
@@ -15,10 +15,10 @@
 #include "common.h"
 #include "miniobj.h"
 
-#define MAX_IOVS		10
-
 #define MAX_HTTP_HDRS		32
 
+#define MAX_IOVS		(MAX_HTTP_HDRS * 2)
+
 #define HTTP_HDR_REQ		0
 #define HTTP_HDR_URL		1
 #define HTTP_HDR_PROTO		2
@@ -26,10 +26,6 @@
 #define HTTP_HDR_RESPONSE	4
 #define HTTP_HDR_FIRST		5
 
-#define HTTP_START		0
-#define HTTP_DATA		1
-#define HTTP_END		2
-
 struct event_base;
 struct cli;
 struct sbuf;
@@ -52,6 +48,11 @@
 
 typedef void http_callback_f(void *, int bad);
 
+struct http_hdr {
+	char			*b;
+	char			*e;
+};
+
 struct http {
 	unsigned		magic;
 #define HTTP_MAGIC		0x6428b5c9
@@ -67,8 +68,9 @@
 
 	unsigned		conds;		/* If-* headers present */
 
-	char			*hd[MAX_HTTP_HDRS][HTTP_END + 1];
+	struct http_hdr		hd[MAX_HTTP_HDRS];
 	unsigned		nhd;
+	unsigned char		hdf[MAX_HTTP_HDRS];
 };
 
 /*--------------------------------------------------------------------*/
@@ -85,6 +87,8 @@
 	pthread_cond_t		cv;
 	TAILQ_ENTRY(worker)	list;
 
+	int			*wfd;
+	unsigned		werr;	/* valid after WRK_Flush() */
 	struct iovec		iov[MAX_IOVS];
 	unsigned		niov;
 	size_t			liov;
@@ -296,6 +300,13 @@
 
 /* cache_http.c */
 void HTTP_Init(void);
+void http_Write(struct worker *w, struct http *hp, int resp);
+void http_CopyReq(int fd, struct http *to, struct http *fm);
+void http_CopyResp(int fd, struct http *to, struct http *fm);
+void http_FilterHeader(int fd, struct http *to, struct http *fm, unsigned how);
+void http_CopyHeader(int fd, struct http *to, struct http *fm, unsigned n);
+void http_PrintfHeader(int fd, struct http *to, const char *fmt, ...);
+int http_IsHdr(struct http_hdr *hh, char *hdr);
 void http_Setup(struct http *ht, void *space, unsigned len);
 int http_GetHdr(struct http *hp, const char *hdr, char **ptr);
 int http_GetHdrField(struct http *hp, const char *hdr, const char *field, char **ptr);
@@ -318,7 +329,7 @@
 #undef HTTPH
 
 /* cache_pass.c */
-void PassSession(struct worker *w, struct sess *sp);
+void PassSession(struct sess *sp);
 void PassBody(struct worker *w, struct sess *sp);
 
 /* cache_pipe.c */
@@ -327,6 +338,10 @@
 /* cache_pool.c */
 void WRK_Init(void);
 void WRK_QueueSession(struct sess *sp);
+void WRK_Reset(struct worker *w, int *fd);
+int WRK_Flush(struct worker *w);
+void WRK_Write(struct worker *w, const void *ptr, size_t len);
+void WRK_WriteH(struct worker *w, struct http_hdr *hh, const char *suf);
 
 /* cache_session.c [SES] */
 void SES_Init(void);
@@ -352,8 +367,6 @@
 
 /* cache_response.c */
 void RES_Error(struct sess *sp, int error, const char *msg);
-void RES_Flush(struct sess *sp);
-void RES_Write(struct sess *sp, const void *ptr, size_t len);
 void RES_WriteObj(struct sess *sp);
 
 /* cache_vcl.c */

Modified: trunk/varnish-cache/bin/varnishd/cache_center.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_center.c	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache_center.c	2006-07-21 09:32:09 UTC (rev 533)
@@ -90,8 +90,7 @@
 	} else if (http_GetHdr(sp->http, H_Connection, &b) &&
 	    !strcmp(b, "close")) {
 		vca_close_session(sp, "Connection header");
-	} else if (strcmp(sp->http->hd[HTTP_HDR_PROTO][HTTP_START],
-	    "HTTP/1.1")) {
+	} else if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1")) {
 		vca_close_session(sp, "not HTTP/1.1");
 	}
 	VCL_Rel(sp->vcl);
@@ -263,7 +262,7 @@
 	if (sp->handling == VCL_RET_PASS) {
 		HSH_Deref(sp->obj);
 		sp->obj = NULL;
-		PassSession(sp->wrk, sp);
+		PassSession(sp);
 		sp->step = STP_PASSBODY;
 		return (0);
 	}
@@ -398,7 +397,7 @@
 		HSH_Unbusy(sp->obj);
 		HSH_Deref(sp->obj);
 		sp->obj = 0;
-		PassSession(sp->wrk, sp);
+		PassSession(sp);
 		sp->step = STP_PASSBODY;
 		return (0);
 	}
@@ -431,7 +430,7 @@
 cnt_pass(struct sess *sp)
 {
 
-	PassSession(sp->wrk, sp);
+	PassSession(sp);
 	sp->step = STP_PASSBODY;
 	return (0);
 }

Modified: trunk/varnish-cache/bin/varnishd/cache_hash.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_hash.c	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache_hash.c	2006-07-21 09:32:09 UTC (rev 533)
@@ -77,7 +77,7 @@
 	} else
 		CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
 
-	url = h->hd[HTTP_HDR_URL][HTTP_START];
+	url = h->hd[HTTP_HDR_URL].b;
 	if (!http_GetHdr(h, H_Host, &host))
 		host = url;
 	if (sp->obj != NULL) {

Modified: trunk/varnish-cache/bin/varnishd/cache_http.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_http.c	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache_http.c	2006-07-21 09:32:09 UTC (rev 533)
@@ -5,6 +5,7 @@
  */
 
 #include <stdio.h>
+#include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
@@ -19,8 +20,8 @@
 #include "http_headers.h"
 #undef HTTPH
 
-#define VSLH(a, b, c, d) \
-	VSLR((a), (b), (c)->hd[d][HTTP_START], (c)->hd[d][HTTP_END]);
+#define VSLH(ax, bx, cx, dx) \
+	VSLR((ax), (bx), (cx)->hd[(dx)].b, (cx)->hd[(dx)].e);
 
 /*--------------------------------------------------------------------*/
 
@@ -37,11 +38,30 @@
 	hp->v = sp;
 	hp->f = sp;
 	hp->e = sp + len;
+	hp->nhd = HTTP_HDR_FIRST;
 }
 
 /*--------------------------------------------------------------------*/
 
+
 int
+http_IsHdr(struct http_hdr *hh, char *hdr)
+{
+	unsigned l;
+
+	assert(hh->b != NULL);
+	assert(hh->e != NULL);
+	assert(hdr != NULL);
+	l = hdr[0];
+	assert(l == strlen(hdr + 1));
+	assert(hdr[l] == ':');
+	hdr++;
+	return (!strncasecmp(hdr, hh->b, l));
+}
+
+/*--------------------------------------------------------------------*/
+
+int
 http_GetHdr(struct http *hp, const char *hdr, char **ptr)
 {
 	unsigned u, l;
@@ -52,27 +72,26 @@
 	assert(hdr[l] == ':');
 	hdr++;
 	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-		assert(hp->hd[u][HTTP_START] != NULL);
-		assert(hp->hd[u][HTTP_END] != NULL);
-		if (hp->hd[u][HTTP_END] < hp->hd[u][HTTP_START] + l)
+		assert(hp->hd[u].b != NULL);
+		assert(hp->hd[u].e != NULL);
+		if (hp->hd[u].e < hp->hd[u].b + l)
 			continue;
-		if (hp->hd[u][HTTP_START][l-1] != ':')
+		if (hp->hd[u].b[l-1] != ':')
 			continue;
-		if (strncasecmp(hdr, hp->hd[u][HTTP_START], l))
+		if (strncasecmp(hdr, hp->hd[u].b, l))
 			continue;
-		if (hp->hd[u][HTTP_DATA] == NULL) {
-			p = hp->hd[u][HTTP_START] + l;
-			while (isspace(*p))
-				p++;
-			hp->hd[u][HTTP_DATA] = p;
-		}
-		*ptr = hp->hd[u][HTTP_DATA];
+		p = hp->hd[u].b + l;
+		while (isspace(*p))
+			p++;
+		*ptr = p;
 		return (1);
 	}
 	*ptr = NULL;
 	return (0);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_GetHdrField(struct http *hp, const char *hdr, const char *field, char **ptr)
 {
@@ -106,6 +125,8 @@
 	return (0);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_HdrIs(struct http *hp, const char *hdr, const char *val)
 {
@@ -119,6 +140,8 @@
 	return (0);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_GetTail(struct http *hp, unsigned len, char **b, char **e)
 {
@@ -140,6 +163,7 @@
 	return (1);
 }
 
+/*--------------------------------------------------------------------*/
 /* Read from fd, but soak up any tail first */
 
 int
@@ -168,12 +192,14 @@
 	return (u);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_GetStatus(struct http *hp)
 {
 
-	assert(hp->hd[HTTP_HDR_STATUS][HTTP_START] != NULL);
-	return (strtoul(hp->hd[HTTP_HDR_STATUS][HTTP_START],
+	assert(hp->hd[HTTP_HDR_STATUS].b != NULL);
+	return (strtoul(hp->hd[HTTP_HDR_STATUS].b,
 	    NULL /* XXX */, 10));
 }
 
@@ -211,8 +237,8 @@
 			hp->conds = 1;
 
 		if (hp->nhd < MAX_HTTP_HDRS) {
-			hp->hd[hp->nhd][HTTP_START] = p;
-			hp->hd[hp->nhd][HTTP_END] = q;
+			hp->hd[hp->nhd].b = p;
+			hp->hd[hp->nhd].e = q;
 			VSLH(SLT_RxHeader, fd, hp, hp->nhd);
 			hp->nhd++;
 		} else {
@@ -239,10 +265,10 @@
 		continue;
 
 	/* First, the request type (GET/HEAD etc) */
-	hp->hd[HTTP_HDR_REQ][HTTP_START] = p;
+	hp->hd[HTTP_HDR_REQ].b = p;
 	for (; isalpha(*p); p++)
 		;
-	hp->hd[HTTP_HDR_REQ][HTTP_END] = p;
+	hp->hd[HTTP_HDR_REQ].e = p;
 	VSLH(SLT_Request, fd, hp, HTTP_HDR_REQ);
 	*p++ = '\0';
 
@@ -253,10 +279,10 @@
 		VSLR(SLT_HttpGarbage, fd, hp->s, hp->v);
 		return (400);
 	}
-	hp->hd[HTTP_HDR_URL][HTTP_START] = p;
+	hp->hd[HTTP_HDR_URL].b = p;
 	while (!isspace(*p))
 		p++;
-	hp->hd[HTTP_HDR_URL][HTTP_END] = p;
+	hp->hd[HTTP_HDR_URL].e = p;
 	VSLH(SLT_URL, fd, hp, HTTP_HDR_URL);
 	if (*p == '\n') {
 		VSLR(SLT_HttpGarbage, fd, hp->s, hp->v);
@@ -271,10 +297,10 @@
 		VSLR(SLT_HttpGarbage, fd, hp->s, hp->v);
 		return (400);
 	}
-	hp->hd[HTTP_HDR_PROTO][HTTP_START] = p;
+	hp->hd[HTTP_HDR_PROTO].b = p;
 	while (!isspace(*p))
 		p++;
-	hp->hd[HTTP_HDR_PROTO][HTTP_END] = p;
+	hp->hd[HTTP_HDR_PROTO].e = p;
 	VSLH(SLT_Protocol, fd, hp, HTTP_HDR_PROTO);
 	if (*p != '\n')
 		*p++ = '\0';
@@ -303,34 +329,34 @@
 		continue;
 
 	/* First, protocol */
-	hp->hd[HTTP_HDR_PROTO][HTTP_START] = p;
+	hp->hd[HTTP_HDR_PROTO].b = p;
 	while (!isspace(*p))
 		p++;
-	hp->hd[HTTP_HDR_PROTO][HTTP_END] = p;
+	hp->hd[HTTP_HDR_PROTO].e = p;
 	VSLH(SLT_Protocol, fd, hp, HTTP_HDR_PROTO);
 	*p++ = '\0';
 
 	/* Next find the status */
 	while (isspace(*p))
 		p++;
-	hp->hd[HTTP_HDR_STATUS][HTTP_START] = p;
+	hp->hd[HTTP_HDR_STATUS].b = p;
 	while (!isspace(*p))
 		p++;
-	hp->hd[HTTP_HDR_STATUS][HTTP_END] = p;
+	hp->hd[HTTP_HDR_STATUS].e = p;
 	VSLH(SLT_Status, fd, hp, HTTP_HDR_STATUS);
 	*p++ = '\0';
 
 	/* Next find the response */
 	while (isspace(*p))
 		p++;
-	hp->hd[HTTP_HDR_RESPONSE][HTTP_START] = p;
+	hp->hd[HTTP_HDR_RESPONSE].b = p;
 	while (*p != '\n')
 		p++;
-	for (q = p; q > hp->hd[HTTP_HDR_RESPONSE][HTTP_START] &&
+	for (q = p; q > hp->hd[HTTP_HDR_RESPONSE].b &&
 	    isspace(q[-1]); q--)
 		continue;
 	*q = '\0';
-	hp->hd[HTTP_HDR_RESPONSE][HTTP_END] = q;
+	hp->hd[HTTP_HDR_RESPONSE].e = q;
 	VSLH(SLT_Response, fd, hp, HTTP_HDR_RESPONSE);
 	p++;
 
@@ -375,8 +401,6 @@
 
 /*--------------------------------------------------------------------*/
 
-#include <errno.h>
-
 static void
 http_read_f(int fd, short event, void *arg)
 {
@@ -484,7 +508,131 @@
 
 /*--------------------------------------------------------------------*/
 
+static void
+http_copyh(int fd, struct http *to, struct http *fm, unsigned n, enum shmlogtag tag)
+{
+
+	assert(n < MAX_HTTP_HDRS);
+	assert(fm->hd[n].b != NULL);
+	to->hd[n].b = fm->hd[n].b;
+	to->hd[n].e = fm->hd[n].e;
+	VSLH(tag, fd, to, n);
+}
+
 void
+http_CopyReq(int fd, struct http *to, struct http *fm)
+{
+
+	CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
+	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+	http_copyh(fd, to, fm, HTTP_HDR_REQ, SLT_Request);
+	http_copyh(fd, to, fm, HTTP_HDR_URL, SLT_URL);
+	http_copyh(fd, to, fm, HTTP_HDR_PROTO, SLT_Protocol);
+}
+
+
+void
+http_CopyResp(int fd, struct http *to, struct http *fm)
+{
+
+	CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
+	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+	http_copyh(fd, to, fm, HTTP_HDR_PROTO, SLT_Protocol);
+	http_copyh(fd, to, fm, HTTP_HDR_STATUS, SLT_Status);
+	http_copyh(fd, to, fm, HTTP_HDR_RESPONSE, SLT_Response);
+}
+
+void
+http_CopyHeader(int fd, struct http *to, struct http *fm, unsigned n)
+{
+
+	CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
+	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+	assert(n < MAX_HTTP_HDRS);
+	assert(fm->hd[n].b != NULL);
+	if (to->nhd < MAX_HTTP_HDRS) {
+		to->hd[to->nhd].b = fm->hd[n].b;
+		to->hd[to->nhd].e = fm->hd[n].e;
+		VSLH(SLT_TxHeader, fd, to, to->nhd);
+		to->nhd++;
+	} else  {
+		VSL_stats->losthdr++;
+		VSLH(SLT_LostHeader, fd, fm, n);
+	}
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+http_FilterHeader(int fd, struct http *to, struct http *fm, unsigned how)
+{
+	unsigned u;
+
+	to->nhd = HTTP_HDR_FIRST;
+	for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
+#define HTTPH(a, b, c, d, e, f, g) \
+		if (((e) & how) && http_IsHdr(&fm->hd[u], (b))) \
+			continue;
+#include "http_headers.h"
+#undef HTTPH
+		http_CopyHeader(fd, to, fm, u);
+	}
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+http_PrintfHeader(int fd, struct http *to, const char *fmt, ...)
+{
+	va_list ap;
+	unsigned l, n;
+
+	va_start(ap, fmt);
+	l = to->e - to->f;
+	n = vsnprintf(to->f, l, fmt, ap);
+	if (n + 1 > l || to->nhd >= MAX_HTTP_HDRS) {
+		VSL_stats->losthdr++;
+		VSL(SLT_LostHeader, fd, "%s", to->f);
+	} else {
+		assert(to->f < to->e);
+		to->hd[to->nhd].b = to->f;
+		to->hd[to->nhd].e = to->f + n;
+		to->f += n + 1;
+		VSLH(SLT_TxHeader, fd, to, to->nhd);
+		to->nhd++;
+	}
+	va_end(ap);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+http_Write(struct worker *w, struct http *hp, int resp)
+{
+	unsigned u;
+
+	if (resp) {
+		assert(hp->hd[HTTP_HDR_STATUS].b != NULL);
+		WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
+		WRK_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " ");
+		WRK_WriteH(w, &hp->hd[HTTP_HDR_RESPONSE], " ");
+	} else {
+		assert(hp->hd[HTTP_HDR_URL].b != NULL);
+		WRK_WriteH(w, &hp->hd[HTTP_HDR_REQ], " ");
+		WRK_WriteH(w, &hp->hd[HTTP_HDR_URL], " ");
+		WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
+	}
+	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
+		assert(hp->hd[u].b != NULL);
+		assert(hp->hd[u].e != NULL);
+		WRK_WriteH(w, &hp->hd[u], "\r\n");
+	}
+	WRK_Write(w, "\r\n", -1);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
 http_BuildSbuf(int fd, enum http_build mode, struct sbuf *sb, struct http *hp)
 {
 	unsigned u, sup, rr;
@@ -503,31 +651,29 @@
 		assert(__LINE__ == 0);
 	}
 	if (rr == 0) {
-		sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO][HTTP_START]);
+		sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO].b);
 		sbuf_cat(sb, " ");
-		sbuf_cat(sb, hp->hd[HTTP_HDR_STATUS][HTTP_START]);
+		sbuf_cat(sb, hp->hd[HTTP_HDR_STATUS].b);
 		sbuf_cat(sb, " ");
-		sbuf_cat(sb, hp->hd[HTTP_HDR_RESPONSE][HTTP_START]);
+		sbuf_cat(sb, hp->hd[HTTP_HDR_RESPONSE].b);
 	} else {
 		if (rr == 2) {
 			sbuf_cat(sb, "GET ");
 		} else {
-			sbuf_cat(sb, hp->hd[HTTP_HDR_REQ][HTTP_START]);
+			sbuf_cat(sb, hp->hd[HTTP_HDR_REQ].b);
 			sbuf_cat(sb, " ");
 		}
-		sbuf_cat(sb, hp->hd[HTTP_HDR_URL][HTTP_START]);
+		sbuf_cat(sb, hp->hd[HTTP_HDR_URL].b);
 		sbuf_cat(sb, " ");
-		sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO][HTTP_START]);
+		sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO].b);
 	}
 
 	sbuf_cat(sb, "\r\n");
 
 	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-		if (http_supress(hp->hd[u][HTTP_START], sup))
+		if (http_supress(hp->hd[u].b, sup))
 			continue;
-		if (1)
-			VSL(SLT_TxHeader, fd, "%s", hp->hd[u][HTTP_START]);
-		sbuf_cat(sb, hp->hd[u][HTTP_START]);
+		sbuf_cat(sb, hp->hd[u].b);
 		sbuf_cat(sb, "\r\n");
 	}
 	if (mode != Build_Reply) {

Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_pass.c	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache_pass.c	2006-07-21 09:32:09 UTC (rev 533)
@@ -46,8 +46,9 @@
 		if (i == 0 && bi == NULL)
 			return (1);
 		assert(i > 0);
-		RES_Write(sp, buf, i);
-		RES_Flush(sp);
+		WRK_Write(sp->wrk, buf, i);
+		if (WRK_Flush(sp->wrk))
+			vca_close_session(sp, "remote closed");
 		cl -= i;
 	}
 	return (0);
@@ -92,7 +93,7 @@
 		if (u == 0)
 			break;
 
-		RES_Write(sp, p, q - p);
+		WRK_Write(sp->wrk, p, q - p);
 
 		p = q;
 
@@ -104,28 +105,30 @@
 			}
 			if (bp - p < j)
 				j = bp - p;
-			RES_Write(sp, p, j);
+			WRK_Write(sp->wrk, p, j);
 			p += j;
 			u -= j;
 		}
 		while (u > 0) {
 			if (http_GetTail(hp, u, &b, &e)) {
 				j = e - b;
-				RES_Write(sp, q, j);
+				WRK_Write(sp->wrk, q, j);
 				u -= j;
 			} else
 				break;
 		}
-		RES_Flush(sp);
+		if (WRK_Flush(sp->wrk))
+			vca_close_session(sp, "remote closed");
 		while (u > 0) {
 			j = u;
 			if (j > sizeof buf)
 				j = sizeof buf;
 			i = read(fd, buf, j);
 			assert(i > 0);
-			RES_Write(sp, buf, i);
+			WRK_Write(sp->wrk, buf, i);
 			u -= i;
-			RES_Flush(sp);
+			if (WRK_Flush(sp->wrk))
+				vca_close_session(sp, "remote closed");
 		}
 	}
 	return (0);
@@ -138,32 +141,34 @@
 PassBody(struct worker *w, struct sess *sp)
 {
 	struct vbe_conn *vc;
-	struct http *hp;
 	char *b;
 	int cls;
 
-	hp = sp->bkd_http;
-	assert(hp != NULL);
 	vc = sp->vbc;
 	assert(vc != NULL);
 
-	http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp);
-	sbuf_cat(w->sb, "\r\n");
-	sbuf_finish(w->sb);
-	RES_Write(sp, sbuf_data(w->sb), sbuf_len(w->sb));
+	sp->http->f = sp->http->v;
+	sp->http->nhd = HTTP_HDR_FIRST;
+	http_CopyResp(sp->fd, sp->http, vc->http);
+	http_FilterHeader(sp->fd, sp->http, vc->http, HTTPH_A_PASS);
+	http_PrintfHeader(sp->fd, sp->http, "X-Varnish: %u", sp->xid);
+	WRK_Reset(w, &sp->fd);
+	http_Write(w, sp->http, 1);
 
-	if (http_GetHdr(hp, H_Content_Length, &b))
-		cls = pass_straight(sp, vc->fd, hp, b);
-	else if (http_HdrIs(hp, H_Connection, "close"))
-		cls = pass_straight(sp, vc->fd, hp, NULL);
-	else if (http_HdrIs(hp, H_Transfer_Encoding, "chunked"))
-		cls = pass_chunked(sp, vc->fd, hp);
+	if (http_GetHdr(vc->http, H_Content_Length, &b))
+		cls = pass_straight(sp, vc->fd, vc->http, b);
+	else if (http_HdrIs(vc->http, H_Connection, "close"))
+		cls = pass_straight(sp, vc->fd, vc->http, NULL);
+	else if (http_HdrIs(vc->http, H_Transfer_Encoding, "chunked"))
+		cls = pass_chunked(sp, vc->fd, vc->http);
 	else {
-		cls = pass_straight(sp, vc->fd, hp, NULL);
+		cls = pass_straight(sp, vc->fd, vc->http, NULL);
 	}
-	RES_Flush(sp);
 
-	if (http_GetHdr(hp, H_Connection, &b) && !strcasecmp(b, "close"))
+	if (WRK_Flush(w))
+		vca_close_session(sp, "remote closed");
+
+	if (http_GetHdr(vc->http, H_Connection, &b) && !strcasecmp(b, "close"))
 		cls = 1;
 
 	if (cls)
@@ -172,21 +177,31 @@
 		VBE_RecycleFd(vc);
 }
 
+
 /*--------------------------------------------------------------------*/
+
 void
-PassSession(struct worker *w, struct sess *sp)
+PassSession(struct sess *sp)
 {
 	int i;
 	struct vbe_conn *vc;
 	struct http *hp;
+	struct worker *w;
 
+	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+	CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
+	w = sp->wrk;
 	vc = VBE_GetFd(sp->backend, sp->xid);
 	assert(vc != NULL);
 	VSL(SLT_Backend, sp->fd, "%d %s", vc->fd, sp->backend->vcl_name);
 
-	http_BuildSbuf(vc->fd, Build_Pass, w->sb, sp->http);
-	i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
-	assert(i == sbuf_len(w->sb));
+	http_CopyReq(vc->fd, vc->http, sp->http);
+	http_FilterHeader(vc->fd, vc->http, sp->http, HTTPH_R_PASS);
+	http_PrintfHeader(vc->fd, vc->http, "X-Varnish: %u", sp->xid);
+	WRK_Reset(w, &vc->fd);
+	http_Write(w, vc->http, 0);
+	i = WRK_Flush(w);
+	assert(i == 0);
 
 	/* XXX: copy any contents */
 

Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_pool.c	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache_pool.c	2006-07-21 09:32:09 UTC (rev 533)
@@ -24,6 +24,73 @@
 static TAILQ_HEAD(, worker) wrk_head = TAILQ_HEAD_INITIALIZER(wrk_head);
 static TAILQ_HEAD(, workreq) wrk_reqhead = TAILQ_HEAD_INITIALIZER(wrk_reqhead);
 
+/*--------------------------------------------------------------------
+ * Write data to fd
+ * We try to use writev() if possible in order to minimize number of
+ * syscalls made and packets sent.  It also just might allow the worker
+ * thread to complete the request without holding stuff locked.
+ */
+
+void
+WRK_Reset(struct worker *w, int *fd)
+{
+
+	CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+	w->werr = 0;
+	w->liov = 0;
+	w->niov = 0;
+	w->wfd = fd;
+}
+
+int
+WRK_Flush(struct worker *w)
+{
+	int i;
+
+	CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+	if (*w->wfd < 0 || w->niov == 0 || w->werr)
+		return (w->werr);
+VSL(SLT_Debug, 0, "%s %d", __func__, *w->wfd);
+	i = writev(*w->wfd, w->iov, w->niov);
+	if (i != w->liov)
+		w->werr++;
+	else {
+		w->liov = 0;
+		w->niov = 0;
+	}
+	return (w->werr);
+}
+
+void
+WRK_WriteH(struct worker *w, struct http_hdr *hh, const char *suf)
+{
+	
+	CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+	assert(w != NULL);
+	assert(hh != NULL);
+	assert(hh->b != NULL);
+	assert(hh->e != NULL);
+	WRK_Write(w, hh->b, hh->e - hh->b);
+	if (suf != NULL)
+		WRK_Write(w, suf, -1);
+}
+
+void
+WRK_Write(struct worker *w, const void *ptr, size_t len)
+{
+
+	CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+	if (len == 0 || *w->wfd < 0)
+		return;
+	if (len == -1)
+		len = strlen(ptr);
+	if (w->niov == MAX_IOVS)
+		WRK_Flush(w);
+	w->iov[w->niov].iov_base = (void*)(uintptr_t)ptr;
+	w->iov[w->niov++].iov_len = len;
+	w->liov += len;
+}
+
 /*--------------------------------------------------------------------*/
 
 static void

Modified: trunk/varnish-cache/bin/varnishd/cache_response.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_response.c	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache_response.c	2006-07-21 09:32:09 UTC (rev 533)
@@ -65,50 +65,12 @@
 		"  </BODY>\r\n"
 		"</HTML>\r\n");
 	sbuf_finish(sb);
-	RES_Write(sp, sbuf_data(sb), sbuf_len(sb));
-	RES_Flush(sp);
+	WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
+	WRK_Flush(sp->wrk);
 	vca_close_session(sp, msg);
 }
 
 
-/*--------------------------------------------------------------------
- * Write data to client
- * We try to use writev() if possible in order to minimize number of
- * syscalls made and packets sent.  It also just might allow the worker
- * thread to complete the request without holding stuff locked.
- */
-
-void
-RES_Flush(struct sess *sp)
-{
-	int i;
-
-	if (sp->fd < 0 || sp->wrk->niov == 0)
-		return;
-	i = writev(sp->fd, sp->wrk->iov, sp->wrk->niov);
-	if (i != sp->wrk->liov)
-		vca_close_session(sp, "remote closed");
-	sp->wrk->liov = 0;
-	sp->wrk->niov = 0;
-}
-
-void
-RES_Write(struct sess *sp, const void *ptr, size_t len)
-{
-
-	if (sp->fd < 0 || len == 0)
-		return;
-	if (len == -1)
-		len = strlen(ptr);
-	if (sp->wrk->niov == MAX_IOVS)
-		RES_Flush(sp);
-	if (sp->fd < 0)
-		return;
-	sp->wrk->iov[sp->wrk->niov].iov_base = (void*)(uintptr_t)ptr;
-	sp->wrk->iov[sp->wrk->niov++].iov_len = len;
-	sp->wrk->liov += len;
-}
-
 /*--------------------------------------------------------------------*/
 
 static void
@@ -121,18 +83,18 @@
 
 	VSL(SLT_Status, sp->fd, "%u", 304);
 	VSL(SLT_Length, sp->fd, "%u", 0);
-	RES_Write(sp, "HTTP/1.1 304 Not Modified\r\n", -1);
-	RES_Write(sp, "Via: 1.1 varnish\r\n", -1);
-	RES_Write(sp, "Last-Modified: ", -1);
-	RES_Write(sp, p, -1);
-	RES_Write(sp, "\r\n", -1);
-	if (strcmp(sp->http->hd[HTTP_HDR_PROTO][HTTP_START], "HTTP/1.1")) 
-		RES_Write(sp, "Connection: close\r\n", -1);
+	WRK_Write(sp->wrk, "HTTP/1.1 304 Not Modified\r\n", -1);
+	WRK_Write(sp->wrk, "Via: 1.1 varnish\r\n", -1);
+	WRK_Write(sp->wrk, "Last-Modified: ", -1);
+	WRK_Write(sp->wrk, p, -1);
+	WRK_Write(sp->wrk, "\r\n", -1);
+	if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1")) 
+		WRK_Write(sp->wrk, "Connection: close\r\n", -1);
 	sbuf_printf(sb, "X-Varnish: xid %u\r\n", sp->obj->xid);
 	sbuf_printf(sb, "\r\n");
 	sbuf_finish(sb);
-	RES_Write(sp, sbuf_data(sb), sbuf_len(sb));
-	RES_Flush(sp);
+	WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
+	WRK_Flush(sp->wrk);
 }
 
 /*--------------------------------------------------------------------*/
@@ -180,26 +142,26 @@
 	VSL(SLT_Status, sp->fd, "%u", sp->obj->response);
 	VSL(SLT_Length, sp->fd, "%u", sp->obj->len);
 
-	RES_Write(sp, sp->obj->header, strlen(sp->obj->header));
+	WRK_Write(sp->wrk, sp->obj->header, strlen(sp->obj->header));
 
 	sbuf_clear(sb);
 	sbuf_printf(sb, "Age: %u\r\n",
 		sp->obj->age + sp->t_req - sp->obj->entered);
 	sbuf_printf(sb, "Via: 1.1 varnish\r\n");
 	sbuf_printf(sb, "X-Varnish: xid %u\r\n", sp->obj->xid);
-	if (strcmp(sp->http->hd[HTTP_HDR_PROTO][HTTP_START], "HTTP/1.1")) 
+	if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1")) 
 		sbuf_printf(sb, "Connection: close\r\n");
 	sbuf_printf(sb, "\r\n");
 	sbuf_finish(sb);
-	RES_Write(sp, sbuf_data(sb), sbuf_len(sb));
+	WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
 	bytes += sbuf_len(sb);
 	/* XXX: conditional request handling */
-	if (!strcmp(sp->http->hd[HTTP_HDR_REQ][HTTP_START], "GET")) {
+	if (!strcmp(sp->http->hd[HTTP_HDR_REQ].b, "GET")) {
 		TAILQ_FOREACH(st, &sp->obj->store, list) {
 			assert(st->stevedore != NULL);
 			u += st->len;
 			if (st->stevedore->send == NULL) {
-				RES_Write(sp, st->ptr, st->len);
+				WRK_Write(sp->wrk, st->ptr, st->len);
 				continue;
 			}
 			st->stevedore->send(st, sp,
@@ -210,5 +172,5 @@
 		assert(u == sp->obj->len);
 	}
 	SES_ChargeBytes(sp, bytes + u);
-	RES_Flush(sp);
+	WRK_Flush(sp->wrk);
 }

Modified: trunk/varnish-cache/bin/varnishd/cache_vrt.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_vrt.c	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/bin/varnishd/cache_vrt.c	2006-07-21 09:32:09 UTC (rev 533)
@@ -60,7 +60,7 @@
 	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
 	assert(sp != NULL);
 	assert(sp->http != NULL);
-	return (sp->http->hd[HTTP_HDR_REQ][HTTP_START]);
+	return (sp->http->hd[HTTP_HDR_REQ].b);
 }
 
 /*--------------------------------------------------------------------*/

Modified: trunk/varnish-cache/include/http_headers.h
===================================================================
--- trunk/varnish-cache/include/http_headers.h	2006-07-21 07:18:40 UTC (rev 532)
+++ trunk/varnish-cache/include/http_headers.h	2006-07-21 09:32:09 UTC (rev 533)
@@ -5,7 +5,7 @@
  * b	session field name
  * c	Request(1)/Response(2) bitfield
  * d	Supress header to backend (1) / Supress header to client (2)
- * e	unused
+ * e	Supress header in pass from client to backend
  * f	unused
  * g	unused
  *
@@ -15,24 +15,29 @@
  *--------------------------------------------------------------------
  */
 
-HTTPH("Keep-Alive",		H_Keep_Alive,		3, 3, 0, 0, 0)	/* RFC2068 */
+#ifndef HTTPH_R_PASS
+#define HTTPH_R_PASS	(1 << 0)
+#define HTTPH_A_PASS	(1 << 1)
+#endif
 
+HTTPH("Keep-Alive",		H_Keep_Alive,		3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2068 */
+
 HTTPH("Accept",			H_Accept,		1, 0, 0, 0, 0)	/* RFC2616 14.1 */
 HTTPH("Accept-Charset",		H_Accept_Charset,	1, 0, 0, 0, 0)	/* RFC2616 14.2 */
 HTTPH("Accept-Encoding",	H_Accept_Encoding,	1, 0, 0, 0, 0)	/* RFC2616 14.3 */
 HTTPH("Accept-Language",	H_Accept_Language,	1, 0, 0, 0, 0)	/* RFC2616 14.4 */
-HTTPH("Accept-Ranges",		H_Accept_Ranges,	2, 3, 0, 0, 0)	/* RFC2616 14.5 */
+HTTPH("Accept-Ranges",		H_Accept_Ranges,	2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2616 14.5 */
 HTTPH("Age",			H_Age,			2, 0, 0, 0, 0)	/* RFC2616 14.6 */
 HTTPH("Allow",			H_Allow,		2, 0, 0, 0, 0)	/* RFC2616 14.7 */
 HTTPH("Authorization",		H_Authorization,	1, 0, 0, 0, 0)	/* RFC2616 14.8 */
-HTTPH("Cache-Control",		H_Cache_Control,	3, 3, 0, 0, 0)	/* RFC2616 14.9 */
-HTTPH("Connection",		H_Connection,		3, 3, 0, 0, 0)	/* RFC2616 14.10 */
+HTTPH("Cache-Control",		H_Cache_Control,	3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2616 14.9 */
+HTTPH("Connection",		H_Connection,		3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2616 14.10 */
 HTTPH("Content-Encoding",	H_Content_Encoding,	2, 0, 0, 0, 0)	/* RFC2616 14.11 */
 HTTPH("Content-Langugae",	H_Content_Language,	2, 0, 0, 0, 0)	/* RFC2616 14.12 */
 HTTPH("Content-Length",		H_Content_Length,	2, 2, 0, 0, 0)	/* RFC2616 14.13 */
 HTTPH("Content-Location",	H_Content_Location,	2, 0, 0, 0, 0)  /* RFC2616 14.14 */
 HTTPH("Content-MD5",		H_Content_MD5,		2, 0, 0, 0, 0)  /* RFC2616 14.15 */
-HTTPH("Content-Range",		H_Content_Range,	2, 3, 0, 0, 0)  /* RFC2616 14.16 */
+HTTPH("Content-Range",		H_Content_Range,	2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.16 */
 HTTPH("Content-Type",		H_Content_Type,		2, 0, 0, 0, 0)  /* RFC2616 14.17 */
 HTTPH("Date",			H_Date,			2, 0, 0, 0, 0)  /* RFC2616 14.18 */
 HTTPH("ETag", 			H_ETag,			2, 0, 0, 0, 0)	/* RFC2616 14.19 */
@@ -55,10 +60,10 @@
 HTTPH("Referer",		H_Referer,		1, 0, 0, 0, 0)	/* RFC2616 14.36 */
 HTTPH("Retry-After",		H_Retry_After,		2, 0, 0, 0, 0)	/* RFC2616 14.37 */
 HTTPH("Server",			H_Server,		2, 0, 0, 0, 0)	/* RFC2616 14.38 */
-HTTPH("TE",			H_TE,			1, 3, 0, 0, 0)	/* RFC2616 14.39 */
-HTTPH("Trailer",		H_Trailer,		1, 3, 0, 0, 0)	/* RFC2616 14.40 */
-HTTPH("Transfer-Encoding", 	H_Transfer_Encoding,	2, 3, 0, 0, 0)	/* RFC2616 14.41 */
-HTTPH("Upgrade", 		H_Upgrade,		2, 3, 0, 0, 0)	/* RFC2616 14.42 */
+HTTPH("TE",			H_TE,			1, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2616 14.39 */
+HTTPH("Trailer",		H_Trailer,		1, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2616 14.40 */
+HTTPH("Transfer-Encoding", 	H_Transfer_Encoding,	2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2616 14.41 */
+HTTPH("Upgrade", 		H_Upgrade,		2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)	/* RFC2616 14.42 */
 HTTPH("User-Agent",		H_User_Agent,		1, 0, 0, 0, 0)	/* RFC2616 14.43 */
 HTTPH("Vary",			H_Vary,			2, 0, 0, 0, 0)	/* RFC2616 14.44 */
 HTTPH("Via",			H_Via,			2, 0, 0, 0, 0)	/* RFC2616 14.45 */




More information about the varnish-commit mailing list