[master] 4cff3b9 Rename cache_response.c to cache_http1_deliver.c and make it responsible for all deliveries, streaming or non-streaming

Poul-Henning Kamp phk at varnish-cache.org
Fri Sep 6 09:00:38 CEST 2013


commit 4cff3b9978e367c4a7425db32376b74c75164e0f
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Sep 5 12:45:15 2013 +0000

    Rename cache_response.c to cache_http1_deliver.c and make it responsible
    for all deliveries, streaming or non-streaming

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index 4759414..da3480f 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -39,7 +39,7 @@ varnishd_SOURCES = \
 	cache/cache_pipe.c \
 	cache/cache_pool.c \
 	cache/cache_req_fsm.c \
-	cache/cache_response.c \
+	cache/cache_http1_deliver.c \
 	cache/cache_rfc2616.c \
 	cache/cache_session.c \
 	cache/cache_shmlog.c \
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 5be6aab..f178691 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -815,6 +815,9 @@ int HTTP1_DiscardReqBody(struct req *req);
 int HTTP1_CacheReqBody(struct req *req, ssize_t maxsize);
 int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv);
 
+/* cache_http1_deliver.c */
+void V1D_Deliver(struct req *);
+
 /* cache_req_fsm.c [CNT] */
 enum req_fsm_nxt CNT_Request(struct worker *, struct req *);
 
@@ -1052,10 +1055,6 @@ void VSL_Flush(struct vsl_log *, int overflow);
 
 #endif
 
-/* cache_response.c */
-void RES_BuildHttp(struct req *);
-void RES_WriteObj(struct req *);
-
 /* cache_vary.c */
 int VRY_Create(struct busyobj *bo, struct vsb **psb);
 int VRY_Match(struct req *, const uint8_t *vary);
diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c
new file mode 100644
index 0000000..4d784d2
--- /dev/null
+++ b/bin/varnishd/cache/cache_http1_deliver.c
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-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.
+ */
+
+#include "config.h"
+
+#include "cache.h"
+
+#include "vct.h"
+
+/*--------------------------------------------------------------------*/
+
+static void
+res_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh)
+{
+	ssize_t low, high, has_low;
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	assert(req->obj->response == 200);
+	if (strncmp(r, "bytes=", 6))
+		return;
+	r += 6;
+
+	/* The low end of range */
+	has_low = low = 0;
+	if (!vct_isdigit(*r) && *r != '-')
+		return;
+	while (vct_isdigit(*r)) {
+		has_low = 1;
+		low *= 10;
+		low += *r - '0';
+		r++;
+	}
+
+	if (low >= req->obj->len)
+		return;
+
+	if (*r != '-')
+		return;
+	r++;
+
+	/* The high end of range */
+	if (vct_isdigit(*r)) {
+		high = 0;
+		while (vct_isdigit(*r)) {
+			high *= 10;
+			high += *r - '0';
+			r++;
+		}
+		if (!has_low) {
+			low = req->obj->len - high;
+			high = req->obj->len - 1;
+		}
+	} else
+		high = req->obj->len - 1;
+	if (*r != '\0')
+		return;
+
+	if (high >= req->obj->len)
+		high = req->obj->len - 1;
+
+	if (low > high)
+		return;
+
+	http_PrintfHeader(req->resp, "Content-Range: bytes %jd-%jd/%jd",
+	    (intmax_t)low, (intmax_t)high, (intmax_t)req->obj->len);
+	http_Unset(req->resp, H_Content_Length);
+	assert(req->res_mode & RES_LEN);
+	http_PrintfHeader(req->resp, "Content-Length: %jd",
+	    (intmax_t)(1 + high - low));
+	http_SetResp(req->resp, "HTTP/1.1", 206, "Partial Content");
+
+	*plow = low;
+	*phigh = high;
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+RES_BuildHttp(struct req *req)
+{
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC);
+
+	req->res_mode = 0;
+
+	if (!req->disable_esi && req->obj->esidata != NULL) {
+		/* In ESI mode, we can't know the aggregate length */
+		req->res_mode &= ~RES_LEN;
+		req->res_mode |= RES_ESI;
+	} else if (req->obj->objcore->busyobj == NULL) {
+		/* XXX: Not happy with this convoluted test */
+		req->res_mode |= RES_LEN;
+		if (!(req->obj->objcore->flags & OC_F_PASS) ||
+		    req->obj->len != 0) {
+			http_Unset(req->resp, H_Content_Length);
+			http_PrintfHeader(req->resp,
+			    "Content-Length: %zd", req->obj->len);
+		}
+		if (cache_param->http_range_support)
+			http_SetHeader(req->resp, "Accept-Ranges: bytes");
+	}
+
+	if (req->esi_level > 0) {
+		/* Included ESI object, always CHUNKED or EOF */
+		req->res_mode &= ~RES_LEN;
+		req->res_mode |= RES_ESI_CHILD;
+	}
+
+	if (cache_param->http_gzip_support && req->obj->gziped &&
+	    !RFC2616_Req_Gzip(req->http)) {
+		/*
+		 * We don't know what it uncompresses to
+		 * XXX: we could cache that
+		 */
+		req->res_mode &= ~RES_LEN;
+		req->res_mode |= RES_GUNZIP;
+	}
+
+	if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) {
+		/* We havn't chosen yet, do so */
+		if (!req->wantbody) {
+			/* Nothing */
+		} else if (req->http->protover >= 11) {
+			req->res_mode |= RES_CHUNKED;
+		} else {
+			req->res_mode |= RES_EOF;
+			req->doclose = SC_TX_EOF;
+		}
+	}
+	VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode);
+
+	if (!(req->res_mode & RES_LEN))
+		http_Unset(req->resp, H_Content_Length);
+
+	if (req->res_mode & RES_GUNZIP)
+		http_Unset(req->resp, H_Content_Encoding);
+
+	if (req->obj->objcore != NULL
+	    && !(req->obj->objcore->flags & OC_F_PASS)
+	    && req->obj->response == 200
+	    && req->http->conds && RFC2616_Do_Cond(req)) {
+		req->wantbody = 0;
+		http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified");
+		http_Unset(req->resp, H_Content_Length);
+	} else if (req->res_mode & RES_CHUNKED)
+		http_SetHeader(req->resp, "Transfer-Encoding: chunked");
+
+	http_PrintfHeader(req->resp, "Connection: %s",
+	    req->doclose ? "close" : "keep-alive");
+}
+
+/*--------------------------------------------------------------------
+ * We have a gzip'ed object and need to ungzip it for a client which
+ * does not understand gzip.
+ * XXX: handle invalid gzip data better (how ?)
+ */
+
+static void
+res_WriteGunzipObj(struct req *req)
+{
+	unsigned u = 0;
+	struct vgz *vg;
+	struct objiter *oi;
+	void *ptr;
+	ssize_t len;
+	int i;
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+
+	vg = VGZ_NewUngzip(req->vsl, "U D -");
+	AZ(VGZ_WrwInit(vg));
+
+	oi = ObjIterBegin(req->obj);
+	XXXAN(oi);
+
+	while (ObjIter(oi, &ptr, &len)) {
+		CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+		u += len;
+
+		i = VGZ_WrwGunzip(req, vg, ptr, len);
+		/* XXX: error check */
+		(void)i;
+	}
+	VGZ_WrwFlush(req, vg);
+	(void)VGZ_Destroy(&vg);
+	assert(u == req->obj->len);
+	ObjIterEnd(&oi);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+res_WriteDirObj(struct req *req, ssize_t low, ssize_t high)
+{
+	ssize_t u = 0;
+	ssize_t idx, skip, len;
+	struct objiter *oi;
+	void *ptr;
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+
+	oi = ObjIterBegin(req->obj);
+	XXXAN(oi);
+
+	idx = 0;
+	while (ObjIter(oi, &ptr, &len)) {
+		u += len;
+		skip = 0;
+		if (idx + len <= low) {
+			/* This segment is too early */
+			idx += len;
+			continue;
+		}
+		if (idx < low) {
+			/* Chop front of segment off */
+			skip += (low - idx);
+			len -= (low - idx);
+			idx += (low - idx);
+		}
+		if (idx + len > high)
+			/* Chop tail of segment off */
+			len = 1 + high - idx;
+
+		idx += len;
+
+		req->acct_req.bodybytes += len;
+		(void)WRW_Write(req->wrk, (char*)ptr + skip, len);
+	}
+	assert(u == req->obj->len);
+	ObjIterEnd(&oi);
+}
+
+/*--------------------------------------------------------------------
+ * Deliver an object.
+ * Attempt optimizations like 304 and 206 here.
+ */
+
+static void
+RES_WriteObj(struct req *req)
+{
+	char *r;
+	ssize_t low, high;
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+
+	/*
+	 * If nothing special planned, we can attempt Range support
+	 */
+	low = 0;
+	high = req->obj->len - 1;
+	if (
+	    req->wantbody &&
+	    (req->res_mode & RES_LEN) &&
+	    !(req->res_mode & (RES_ESI|RES_ESI_CHILD|RES_GUNZIP)) &&
+	    cache_param->http_range_support &&
+	    req->obj->response == 200 &&
+	    http_GetHdr(req->http, H_Range, &r))
+		res_dorange(req, r, &low, &high);
+
+	WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp);
+
+	/*
+	 * Send HTTP protocol header, unless interior ESI object
+	 */
+	if (!(req->res_mode & RES_ESI_CHILD))
+		req->acct_req.hdrbytes +=
+		    HTTP1_Write(req->wrk, req->resp, 1);
+
+	if (!req->wantbody)
+		req->res_mode &= ~RES_CHUNKED;
+
+	if (req->res_mode & RES_CHUNKED)
+		WRW_Chunked(req->wrk);
+
+	if (!req->wantbody) {
+		/* This was a HEAD or conditional request */
+	} else if (req->obj->len == 0) {
+		/* Nothing to do here */
+	} else if (req->res_mode & RES_ESI) {
+		ESI_Deliver(req);
+	} else if (req->res_mode & RES_ESI_CHILD && req->gzip_resp) {
+		ESI_DeliverChild(req);
+	} else if (req->res_mode & RES_ESI_CHILD &&
+	    !req->gzip_resp && req->obj->gziped) {
+		res_WriteGunzipObj(req);
+	} else if (req->res_mode & RES_GUNZIP) {
+		res_WriteGunzipObj(req);
+	} else {
+		res_WriteDirObj(req, low, high);
+	}
+
+	if (req->res_mode & RES_CHUNKED &&
+	    !(req->res_mode & RES_ESI_CHILD))
+		WRW_EndChunk(req->wrk);
+
+	if (WRW_FlushRelease(req->wrk) && req->sp->fd >= 0)
+		SES_Close(req->sp, SC_REM_CLOSE);
+}
+
+void
+V1D_Deliver(struct req *req)
+{
+	while (req->obj->objcore->busyobj)
+		(void)usleep(10000);
+	
+	RES_BuildHttp(req);
+	RES_WriteObj(req);
+}
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index 4a10c14..a50b65c 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -76,72 +76,6 @@ DOT acceptor -> recv [style=bold,color=green]
 #endif
 
 /*--------------------------------------------------------------------
- * We have a refcounted object on the session, and possibly the busyobj
- * which is fetching it, prepare a response.
- *
-DOT	stream [
-DOT		shape=record
-DOT		label="{cnt_stream:}"
-DOT	]
-DOT	stream:deliver:s -> DONE [style=bold,color=red]
-DOT	stream:deliver:s -> DONE [style=bold,color=blue]
- *
- */
-
-static enum req_fsm_nxt
-cnt_stream(struct worker *wrk, struct req *req)
-{
-	struct busyobj *bo;
-
-	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-	bo = req->obj->objcore->busyobj;
-	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
-	AN(bo->do_stream);
-
-	CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC);
-	CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC);
-
-	AZ(bo->do_esi);
-
-	if (wrk->handling == VCL_RET_RESTART) {
-		assert(req->obj == bo->fetch_obj);
-		req->obj = NULL;
-		VBO_DerefBusyObj(wrk, &bo);
-		AZ(req->obj);
-		http_Teardown(req->resp);
-		req->req_step = R_STP_RESTART;
-		return (REQ_FSM_MORE);
-	}
-	assert(wrk->handling == VCL_RET_DELIVER);
-
-	VBO_waitstate(bo, BOS_FINISHED);
-	assert(bo->state >= BOS_FINISHED);
-
-	if (bo->state == BOS_FAILED) {
-		(void)HSH_DerefObj(&wrk->stats, &req->obj);
-		VBO_DerefBusyObj(wrk, &bo);
-		req->err_code = 503;
-		req->req_step = R_STP_ERROR;
-		return (REQ_FSM_MORE);
-	}
-	VBO_DerefBusyObj(wrk, &bo);
-
-	AZ(bo);
-
-	RES_WriteObj(req);
-
-	/* No point in saving the body if it is hit-for-pass */
-	if (req->obj->objcore->flags & OC_F_PASS)
-		STV_Freestore(req->obj);
-
-	assert(WRW_IsReleased(wrk));
-	(void)HSH_DerefObj(&wrk->stats, &req->obj);
-	http_Teardown(req->resp);
-	return (REQ_FSM_DONE);
-}
-
-/*--------------------------------------------------------------------
  * Deliver an already stored object
  *
 DOT	deliver [
@@ -202,13 +136,6 @@ cnt_deliver(struct worker *wrk, struct req *req)
 
 	VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws);
 
-	while (req->obj->objcore->busyobj) {
-		VSLb(req->vsl, SLT_Debug, "HERE %s %d", __func__, __LINE__);
-		(void)usleep(10000);
-	}
-
-	RES_BuildHttp(req);
-
 	/* Stop the insanity before it turns "Hotel California" on us */
 	if (req->restarts >= cache_param->max_restarts)
 		wrk->handling = VCL_RET_DELIVER;
@@ -220,9 +147,10 @@ cnt_deliver(struct worker *wrk, struct req *req)
 		req->req_step = R_STP_RESTART;
 		return (REQ_FSM_MORE);
 	}
+
 	assert(wrk->handling == VCL_RET_DELIVER);
 
-	RES_WriteObj(req);
+	V1D_Deliver(req);
 
 	/* No point in saving the body if it is hit-for-pass */
 	if (req->obj->objcore->flags & OC_F_PASS)
diff --git a/bin/varnishd/cache/cache_response.c b/bin/varnishd/cache/cache_response.c
deleted file mode 100644
index c56932e..0000000
--- a/bin/varnishd/cache/cache_response.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-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.
- */
-
-#include "config.h"
-
-#include "cache.h"
-
-#include "vct.h"
-
-/*--------------------------------------------------------------------*/
-
-static void
-res_dorange(const struct req *req, const char *r, ssize_t *plow, ssize_t *phigh)
-{
-	ssize_t low, high, has_low;
-
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-	assert(req->obj->response == 200);
-	if (strncmp(r, "bytes=", 6))
-		return;
-	r += 6;
-
-	/* The low end of range */
-	has_low = low = 0;
-	if (!vct_isdigit(*r) && *r != '-')
-		return;
-	while (vct_isdigit(*r)) {
-		has_low = 1;
-		low *= 10;
-		low += *r - '0';
-		r++;
-	}
-
-	if (low >= req->obj->len)
-		return;
-
-	if (*r != '-')
-		return;
-	r++;
-
-	/* The high end of range */
-	if (vct_isdigit(*r)) {
-		high = 0;
-		while (vct_isdigit(*r)) {
-			high *= 10;
-			high += *r - '0';
-			r++;
-		}
-		if (!has_low) {
-			low = req->obj->len - high;
-			high = req->obj->len - 1;
-		}
-	} else
-		high = req->obj->len - 1;
-	if (*r != '\0')
-		return;
-
-	if (high >= req->obj->len)
-		high = req->obj->len - 1;
-
-	if (low > high)
-		return;
-
-	http_PrintfHeader(req->resp, "Content-Range: bytes %jd-%jd/%jd",
-	    (intmax_t)low, (intmax_t)high, (intmax_t)req->obj->len);
-	http_Unset(req->resp, H_Content_Length);
-	assert(req->res_mode & RES_LEN);
-	http_PrintfHeader(req->resp, "Content-Length: %jd",
-	    (intmax_t)(1 + high - low));
-	http_SetResp(req->resp, "HTTP/1.1", 206, "Partial Content");
-
-	*plow = low;
-	*phigh = high;
-}
-
-/*--------------------------------------------------------------------*/
-
-void
-RES_BuildHttp(struct req *req)
-{
-
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-	CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC);
-
-	req->res_mode = 0;
-
-	if (!req->disable_esi && req->obj->esidata != NULL) {
-		/* In ESI mode, we can't know the aggregate length */
-		req->res_mode &= ~RES_LEN;
-		req->res_mode |= RES_ESI;
-	} else if (req->obj->objcore->busyobj == NULL) {
-		/* XXX: Not happy with this convoluted test */
-		req->res_mode |= RES_LEN;
-		if (!(req->obj->objcore->flags & OC_F_PASS) ||
-		    req->obj->len != 0) {
-			http_Unset(req->resp, H_Content_Length);
-			http_PrintfHeader(req->resp,
-			    "Content-Length: %zd", req->obj->len);
-		}
-		if (cache_param->http_range_support)
-			http_SetHeader(req->resp, "Accept-Ranges: bytes");
-	}
-
-	if (req->esi_level > 0) {
-		/* Included ESI object, always CHUNKED or EOF */
-		req->res_mode &= ~RES_LEN;
-		req->res_mode |= RES_ESI_CHILD;
-	}
-
-	if (cache_param->http_gzip_support && req->obj->gziped &&
-	    !RFC2616_Req_Gzip(req->http)) {
-		/*
-		 * We don't know what it uncompresses to
-		 * XXX: we could cache that
-		 */
-		req->res_mode &= ~RES_LEN;
-		req->res_mode |= RES_GUNZIP;
-	}
-
-	if (!(req->res_mode & (RES_LEN|RES_CHUNKED|RES_EOF))) {
-		/* We havn't chosen yet, do so */
-		if (!req->wantbody) {
-			/* Nothing */
-		} else if (req->http->protover >= 11) {
-			req->res_mode |= RES_CHUNKED;
-		} else {
-			req->res_mode |= RES_EOF;
-			req->doclose = SC_TX_EOF;
-		}
-	}
-	VSLb(req->vsl, SLT_Debug, "RES_MODE %x", req->res_mode);
-
-	if (!(req->res_mode & RES_LEN))
-		http_Unset(req->resp, H_Content_Length);
-
-	if (req->res_mode & RES_GUNZIP)
-		http_Unset(req->resp, H_Content_Encoding);
-
-	if (req->obj->objcore != NULL
-	    && !(req->obj->objcore->flags & OC_F_PASS)
-	    && req->obj->response == 200
-	    && req->http->conds && RFC2616_Do_Cond(req)) {
-		req->wantbody = 0;
-		http_SetResp(req->resp, "HTTP/1.1", 304, "Not Modified");
-		http_Unset(req->resp, H_Content_Length);
-	} else if (req->res_mode & RES_CHUNKED)
-		http_SetHeader(req->resp, "Transfer-Encoding: chunked");
-
-	http_PrintfHeader(req->resp, "Connection: %s",
-	    req->doclose ? "close" : "keep-alive");
-}
-
-/*--------------------------------------------------------------------
- * We have a gzip'ed object and need to ungzip it for a client which
- * does not understand gzip.
- * XXX: handle invalid gzip data better (how ?)
- */
-
-static void
-res_WriteGunzipObj(struct req *req)
-{
-	unsigned u = 0;
-	struct vgz *vg;
-	struct objiter *oi;
-	void *ptr;
-	ssize_t len;
-	int i;
-
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-
-	vg = VGZ_NewUngzip(req->vsl, "U D -");
-	AZ(VGZ_WrwInit(vg));
-
-	oi = ObjIterBegin(req->obj);
-	XXXAN(oi);
-
-	while (ObjIter(oi, &ptr, &len)) {
-		CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-		u += len;
-
-		i = VGZ_WrwGunzip(req, vg, ptr, len);
-		/* XXX: error check */
-		(void)i;
-	}
-	VGZ_WrwFlush(req, vg);
-	(void)VGZ_Destroy(&vg);
-	assert(u == req->obj->len);
-	ObjIterEnd(&oi);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-res_WriteDirObj(struct req *req, ssize_t low, ssize_t high)
-{
-	ssize_t u = 0;
-	ssize_t idx, skip, len;
-	struct objiter *oi;
-	void *ptr;
-
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-
-	oi = ObjIterBegin(req->obj);
-	XXXAN(oi);
-
-	idx = 0;
-	while (ObjIter(oi, &ptr, &len)) {
-		u += len;
-		skip = 0;
-		if (idx + len <= low) {
-			/* This segment is too early */
-			idx += len;
-			continue;
-		}
-		if (idx < low) {
-			/* Chop front of segment off */
-			skip += (low - idx);
-			len -= (low - idx);
-			idx += (low - idx);
-		}
-		if (idx + len > high)
-			/* Chop tail of segment off */
-			len = 1 + high - idx;
-
-		idx += len;
-
-		req->acct_req.bodybytes += len;
-		(void)WRW_Write(req->wrk, (char*)ptr + skip, len);
-	}
-	assert(u == req->obj->len);
-	ObjIterEnd(&oi);
-}
-
-/*--------------------------------------------------------------------
- * Deliver an object.
- * Attempt optimizations like 304 and 206 here.
- */
-
-void
-RES_WriteObj(struct req *req)
-{
-	char *r;
-	ssize_t low, high;
-
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-
-	/*
-	 * If nothing special planned, we can attempt Range support
-	 */
-	low = 0;
-	high = req->obj->len - 1;
-	if (
-	    req->wantbody &&
-	    (req->res_mode & RES_LEN) &&
-	    !(req->res_mode & (RES_ESI|RES_ESI_CHILD|RES_GUNZIP)) &&
-	    cache_param->http_range_support &&
-	    req->obj->response == 200 &&
-	    http_GetHdr(req->http, H_Range, &r))
-		res_dorange(req, r, &low, &high);
-
-	WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp);
-
-	/*
-	 * Send HTTP protocol header, unless interior ESI object
-	 */
-	if (!(req->res_mode & RES_ESI_CHILD))
-		req->acct_req.hdrbytes +=
-		    HTTP1_Write(req->wrk, req->resp, 1);
-
-	if (!req->wantbody)
-		req->res_mode &= ~RES_CHUNKED;
-
-	if (req->res_mode & RES_CHUNKED)
-		WRW_Chunked(req->wrk);
-
-	if (!req->wantbody) {
-		/* This was a HEAD or conditional request */
-	} else if (req->obj->len == 0) {
-		/* Nothing to do here */
-	} else if (req->res_mode & RES_ESI) {
-		ESI_Deliver(req);
-	} else if (req->res_mode & RES_ESI_CHILD && req->gzip_resp) {
-		ESI_DeliverChild(req);
-	} else if (req->res_mode & RES_ESI_CHILD &&
-	    !req->gzip_resp && req->obj->gziped) {
-		res_WriteGunzipObj(req);
-	} else if (req->res_mode & RES_GUNZIP) {
-		res_WriteGunzipObj(req);
-	} else {
-		res_WriteDirObj(req, low, high);
-	}
-
-	if (req->res_mode & RES_CHUNKED &&
-	    !(req->res_mode & RES_ESI_CHILD))
-		WRW_EndChunk(req->wrk);
-
-	if (WRW_FlushRelease(req->wrk) && req->sp->fd >= 0)
-		SES_Close(req->sp, SC_REM_CLOSE);
-}
diff --git a/include/tbl/steps.h b/include/tbl/steps.h
index 30d331c..34a2315 100644
--- a/include/tbl/steps.h
+++ b/include/tbl/steps.h
@@ -44,7 +44,6 @@ REQ_STEP(lookup,	LOOKUP,		(wrk, req))
 REQ_STEP(purge,		PURGE,		(wrk, req))
 REQ_STEP(miss,		MISS,		(wrk, req))
 REQ_STEP(fetch,		FETCH,		(wrk, req))
-REQ_STEP(stream,	STREAM,		(wrk, req))
 REQ_STEP(deliver,	DELIVER,	(wrk, req))
 REQ_STEP(error,		ERROR,		(wrk, req))
 #endif



More information about the varnish-commit mailing list