[master] e19208d Now that HTTP/2 seems to have confirmed they will not make Content-Length part of the transport protocol (don't even get me started!) we need to lift it out of HTTP/1 space and into the RFC processing.

Poul-Henning Kamp phk at FreeBSD.org
Wed Jul 9 12:14:46 CEST 2014


commit e19208d9091dbe453cf4b81bdf6c9e85c85ba513
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Jul 9 10:13:26 2014 +0000

    Now that HTTP/2 seems to have confirmed they will not make Content-Length
    part of the transport protocol (don't even get me started!) we need to
    lift it out of HTTP/1 space and into the RFC processing.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index bdc9554..0efc30e 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -490,7 +490,7 @@ struct busyobj {
 
 	struct pool_task	fetch_task;
 
-	char			*h_content_length;
+	ssize_t			content_length;
 
 #define BO_FLAG(l, r, w, d) unsigned	l:1;
 #include "tbl/bo_flags.h"
@@ -780,7 +780,7 @@ void VBO_waitstate(struct busyobj *bo, enum busyobj_state_e want);
 
 /* cache_http1_fetch.c [V1F] */
 int V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req);
-ssize_t V1F_Setup_Fetch(struct busyobj *bo);
+void V1F_Setup_Fetch(struct busyobj *bo);
 
 /* cache_http1_fsm.c [HTTP1] */
 typedef int (req_body_iter_f)(struct req *, void *priv, void *ptr, size_t);
@@ -883,7 +883,7 @@ struct storage *VFP_GetStorage(struct busyobj *, ssize_t sz);
 enum vfp_status VFP_Error(struct busyobj *, const char *fmt, ...)
     __printflike(2, 3);
 void VFP_Init(void);
-void VFP_Fetch_Body(struct busyobj *bo, ssize_t est);
+void VFP_Fetch_Body(struct busyobj *bo);
 void VFP_Push(struct busyobj *, const struct vfp *, intptr_t priv);
 enum vfp_status VFP_Suck(struct busyobj *, void *p, ssize_t *lp);
 
diff --git a/bin/varnishd/cache/cache_busyobj.c b/bin/varnishd/cache/cache_busyobj.c
index 0483579..e49b88e 100644
--- a/bin/varnishd/cache/cache_busyobj.c
+++ b/bin/varnishd/cache/cache_busyobj.c
@@ -150,6 +150,7 @@ VBO_GetBusyObj(struct worker *wrk, const struct req *req)
 	VTAILQ_INIT(&bo->vfp);
 
 	bo->t_first = bo->t_prev = NAN;
+	bo->content_length = -1;
 
 	return (bo);
 }
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index b2665e2..64ae86e 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -343,7 +343,7 @@ vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo)
 	if (bo->htc.body_status == BS_ERROR) {
 		AN (bo->vbc);
 		VDI_CloseFd(&bo->vbc, &bo->acct);
-		VSLb(bo->vsl, SLT_VCL_Error, "Body cannot be fetched");
+		VSLb(bo->vsl, SLT_Error, "Body cannot be fetched");
 		return (F_STP_ERROR);
 	}
 
@@ -403,7 +403,6 @@ static enum fetch_step
 vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 {
 	struct object *obj;
-	ssize_t est;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
@@ -421,7 +420,6 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 	 *	no Content-Encoding		--> object is not gzip'ed.
 	 *	anything else			--> do nothing wrt gzip
 	 *
-	 * XXX: BS_NONE/cl==0 should avoid gzip/gunzip
 	 */
 
 	/* We do nothing unless the param is set */
@@ -444,9 +442,10 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 		bo->do_gzip = 0;
 
 	AN(bo->vbc);
-	est = V1F_Setup_Fetch(bo);
+	if (bo->htc.body_status != BS_NONE)
+		V1F_Setup_Fetch(bo);
 
-	if (est == 0) {
+	if (bo->content_length == 0) {
 		/*
 		 * If the length is known to be zero, it's not gziped.
 		 * A similar issue exists for chunked encoding but we
@@ -529,8 +528,8 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 	    bo->do_stream ? "stream" : "-");
 
 	if (bo->htc.body_status != BS_NONE) {
-		assert(bo->htc.body_status  != BS_ERROR);
-		VFP_Fetch_Body(bo, est);
+		assert(bo->htc.body_status != BS_ERROR);
+		VFP_Fetch_Body(bo);
 	}
 
 	if (bo->failed && !bo->do_stream) {
diff --git a/bin/varnishd/cache/cache_fetch_proc.c b/bin/varnishd/cache/cache_fetch_proc.c
index 8a58fe1..a6d6df1 100644
--- a/bin/varnishd/cache/cache_fetch_proc.c
+++ b/bin/varnishd/cache/cache_fetch_proc.c
@@ -183,16 +183,18 @@ VFP_Suck(struct busyobj *bo, void *p, ssize_t *lp)
  */
 
 void
-VFP_Fetch_Body(struct busyobj *bo, ssize_t est)
+VFP_Fetch_Body(struct busyobj *bo)
 {
 	ssize_t l;
 	enum vfp_status vfps = VFP_ERROR;
 	struct storage *st = NULL;
+	ssize_t est;
 
 	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
 
 	AN(bo->vfp_nxt);
 
+	est = bo->content_length;
 	if (est < 0)
 		est = 0;
 
diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c
index 22d801a..3a381af 100644
--- a/bin/varnishd/cache/cache_http1_fetch.c
+++ b/bin/varnishd/cache/cache_http1_fetch.c
@@ -29,7 +29,6 @@
 
 #include "config.h"
 
-#include <inttypes.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,29 +42,6 @@
 #include "vtcp.h"
 #include "vtim.h"
 
-/*--------------------------------------------------------------------
- * Convert a string to a size_t safely
- */
-
-static ssize_t
-vbf_fetch_number(const char *nbr, int radix)
-{
-	uintmax_t cll;
-	ssize_t cl;
-	char *q;
-
-	if (*nbr == '\0')
-		return (-1);
-	cll = strtoumax(nbr, &q, radix);
-	if (q == NULL || *q != '\0')
-		return (-1);
-
-	cl = (ssize_t)cll;
-	if((uintmax_t)cl != cll) /* Protect against bogusly large values */
-		return (-1);
-	return (cl);
-}
-
 /*--------------------------------------------------------------------*/
 
 static enum vfp_status __match_proto__(vfp_pull_f)
@@ -172,11 +148,10 @@ static const struct vfp v1f_eof = {
 /*--------------------------------------------------------------------
  */
 
-ssize_t
+void
 V1F_Setup_Fetch(struct busyobj *bo)
 {
 	struct http_conn *htc;
-	ssize_t cl;
 
 	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
 	htc = &bo->htc;
@@ -185,19 +160,22 @@ V1F_Setup_Fetch(struct busyobj *bo)
 
 	switch(htc->body_status) {
 	case BS_EOF:
+		assert(bo->content_length == -1);
 		VFP_Push(bo, &v1f_eof, 0);
-		return(-1);
+		break;
 	case BS_LENGTH:
-		cl = vbf_fetch_number(bo->h_content_length, 10);
-		VFP_Push(bo, &v1f_straight, cl);
-		return (cl);
+		assert(bo->content_length > 0);
+		VFP_Push(bo, &v1f_straight, bo->content_length);
+		break;
 	case BS_CHUNKED:
+		assert(bo->content_length == -1);
 		VFP_Push(bo, &v1f_chunked, -1);
-		return (-1);
+		break;
 	default:
+		WRONG("Wrong body_status");
 		break;
 	}
-	return (-1);
+	return;
 }
 
 /*--------------------------------------------------------------------
diff --git a/bin/varnishd/cache/cache_rfc2616.c b/bin/varnishd/cache/cache_rfc2616.c
index 8ada968..7969769 100644
--- a/bin/varnishd/cache/cache_rfc2616.c
+++ b/bin/varnishd/cache/cache_rfc2616.c
@@ -35,6 +35,7 @@
 #include "cache.h"
 
 #include "vtim.h"
+#include "vct.h"
 
 /*--------------------------------------------------------------------
  * TTL and Age calculation in Varnish
@@ -192,6 +193,7 @@ RFC2616_Body(struct busyobj *bo, struct dstat *stats)
 {
 	struct http *hp;
 	char *b;
+	ssize_t cll;
 
 	hp = bo->beresp;
 
@@ -245,13 +247,42 @@ RFC2616_Body(struct busyobj *bo, struct dstat *stats)
 	}
 
 	if (http_GetHdr(hp, H_Transfer_Encoding, &b)) {
+		VSLb(bo->vsl, SLT_Error, "Illegal Transfer-Encoding:");
 		stats->fetch_bad++;
 		return (BS_ERROR);
 	}
 
-	if (http_GetHdr(hp, H_Content_Length, &bo->h_content_length)) {
+	if (http_GetHdr(hp, H_Content_Length, &b)) {
+		bo->content_length = 0;
+		if (!vct_isdigit(*b)) {
+			VSLb(bo->vsl, SLT_Error, "Empty Content-Length:");
+			stats->fetch_bad++;
+			return (BS_ERROR);
+		}
+		for (;vct_isdigit(*b); b++) {
+			cll = bo->content_length;
+			bo->content_length *= 10;
+			bo->content_length += *b - '0';
+			if (cll > bo->content_length) {
+				VSLb(bo->vsl, SLT_Error,
+				    "Content-Length: too large");
+				stats->fetch_bad++;
+				return (BS_ERROR);
+			}
+		}
+		while (vct_islws(*b))
+			b++;
+		if (*b != '\0') {
+			VSLb(bo->vsl, SLT_Error,
+			    "Illegal Content-Length: (0x%02x)", *b);
+			stats->fetch_bad++;
+			return (BS_ERROR);
+		}
 		stats->fetch_length++;
-		return (BS_LENGTH);
+		if (bo->content_length == 0)
+			return (BS_NONE);
+		else
+			return (BS_LENGTH);
 	}
 
 	if (http_HdrIs(hp, H_Connection, "keep-alive")) {



More information about the varnish-commit mailing list