[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