[master] 06cea07 Move HTTP1 VFPs to their own file, and integrate chunked helper function

Poul-Henning Kamp phk at FreeBSD.org
Tue Sep 9 08:35:38 CEST 2014


commit 06cea072ba587be9c538d34aac885c21d288fba4
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Sep 9 06:35:16 2014 +0000

    Move HTTP1 VFPs to their own file, and integrate chunked helper function

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index bcfe989..ddbd1d2 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -29,6 +29,7 @@ varnishd_SOURCES = \
 	cache/cache_http1_fetch.c \
 	cache/cache_http1_fsm.c \
 	cache/cache_http1_proto.c \
+	cache/cache_http1_vfp.c \
 	cache/cache_lck.c \
 	cache/cache_main.c \
 	cache/cache_mempool.c \
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 1f0e512..c006ca6 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -814,14 +814,6 @@ int HTTP1_CacheReqBody(struct req *req, ssize_t maxsize);
 int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv);
 extern const int HTTP1_Req[3];
 extern const int HTTP1_Resp[3];
-enum http1_chunked_ret {
-	H1CR_ERROR,
-	H1CR_MORE,
-	H1CR_END,
-};
-enum http1_chunked_ret
-HTTP1_Chunked(struct http_conn *htc, intptr_t *priv, const char **error,
-    uint64_t *statp, void *ptr, ssize_t *lp);
 
 /* cache_http1_deliver.c */
 unsigned V1D_FlushReleaseAcct(struct req *req);
diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c
index 6df8fcf..9555bbc 100644
--- a/bin/varnishd/cache/cache_http1_fetch.c
+++ b/bin/varnishd/cache/cache_http1_fetch.c
@@ -42,147 +42,6 @@
 #include "vtcp.h"
 #include "vtim.h"
 
-/*--------------------------------------------------------------------*/
-
-static enum vfp_status __match_proto__(vfp_pull_f)
-v1f_pull_straight(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
-    ssize_t *lp)
-{
-	ssize_t l, lr;
-	struct http_conn *htc;
-
-	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
-	CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
-	CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
-	AN(p);
-	AN(lp);
-
-	l = *lp;
-	*lp = 0;
-
-	if (vfe->priv2 == 0) // XXX: Optimize Content-Len: 0 out earlier
-		return (VFP_END);
-	if (vfe->priv2 < l)
-		l = vfe->priv2;
-	lr = HTTP1_Read(htc, p, l);
-	vc->bodybytes += lr;
-	if (lr <= 0)
-		return (VFP_Error(vc, "straight insufficient bytes"));
-	*lp = lr;
-	vfe->priv2 -= lr;
-	if (vfe->priv2 == 0)
-		return (VFP_END);
-	return (VFP_OK);
-}
-
-static const struct vfp v1f_straight = {
-	.name = "V1F_STRAIGHT",
-	.pull = v1f_pull_straight,
-};
-
-/*--------------------------------------------------------------------
- * Read a chunked HTTP object.
- *
- * XXX: Reading one byte at a time is pretty pessimal.
- */
-
-static enum vfp_status __match_proto__(vfp_pull_f)
-v1f_pull_chunked(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
-    ssize_t *lp)
-{
-	const char *err;
-	struct http_conn *htc;
-
-	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
-	CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
-	CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
-	AN(p);
-	AN(lp);
-
-	switch (HTTP1_Chunked(htc, &vfe->priv2, &err, &vc->bodybytes, p, lp)) {
-	case H1CR_ERROR:
-		return (VFP_Error(vc, "%s", err));
-	case H1CR_MORE:
-		return (VFP_OK);
-	case H1CR_END:
-		return (VFP_END);
-	default:
-		WRONG("invalid HTTP1_Chunked return");
-	}
-}
-
-static const struct vfp v1f_chunked = {
-	.name = "V1F_CHUNKED",
-	.pull = v1f_pull_chunked,
-};
-
-/*--------------------------------------------------------------------*/
-
-static enum vfp_status __match_proto__(vfp_pull_f)
-v1f_pull_eof(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
-    ssize_t *lp)
-{
-	ssize_t l, lr;
-	struct http_conn *htc;
-
-	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
-	CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
-	CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
-	AN(p);
-
-	AN(lp);
-
-	l = *lp;
-	*lp = 0;
-	lr = HTTP1_Read(htc, p, l);
-	if (lr < 0)
-		return (VFP_Error(vc, "eof socket fail"));
-	if (lr == 0)
-		return (VFP_END);
-	*lp = lr;
-	vc->bodybytes += lr;
-	return (VFP_OK);
-}
-
-static const struct vfp v1f_eof = {
-	.name = "V1F_EOF",
-	.pull = v1f_pull_eof,
-};
-
-/*--------------------------------------------------------------------
- */
-
-void
-V1F_Setup_Fetch(struct vfp_ctx *vfc, struct http_conn *htc)
-{
-	struct vfp_entry *vfe;
-
-	CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
-	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
-
-	switch(htc->body_status) {
-	case BS_EOF:
-		assert(htc->content_length == -1);
-		vfe = VFP_Push(vfc, &v1f_eof, 0);
-		vfe->priv2 = 0;
-		break;
-	case BS_LENGTH:
-		assert(htc->content_length > 0);
-		vfe = VFP_Push(vfc, &v1f_straight, 0);
-		vfe->priv2 = htc->content_length;
-		break;
-	case BS_CHUNKED:
-		assert(htc->content_length == -1);
-		vfe = VFP_Push(vfc, &v1f_chunked, 0);
-		vfe->priv2 = -1;
-		break;
-	default:
-		WRONG("Wrong body_status");
-		break;
-	}
-	vfe->priv1 = htc;
-}
-
 /*--------------------------------------------------------------------
  * Pass the request body to the backend with chunks
  */
diff --git a/bin/varnishd/cache/cache_http1_proto.c b/bin/varnishd/cache/cache_http1_proto.c
index b502fbd..ab01b35 100644
--- a/bin/varnishd/cache/cache_http1_proto.c
+++ b/bin/varnishd/cache/cache_http1_proto.c
@@ -45,8 +45,6 @@
 
 #include "config.h"
 
-#include <inttypes.h>
-
 #include "cache.h"
 
 #include "vct.h"
@@ -623,106 +621,3 @@ HTTP1_Write(const struct worker *w, const struct http *hp, const int *hf)
 	l += WRW_Write(w, "\r\n", -1);
 	return (l);
 }
-
-/*--------------------------------------------------------------------
- * Read a chunked body.
- *
- * XXX: Reading one byte at a time is pretty pessimal.
- */
-
-enum http1_chunked_ret
-HTTP1_Chunked(struct http_conn *htc, intptr_t *priv, const char **error,
-    uint64_t *statp, void *ptr, ssize_t *lp)
-{
-	int i;
-	char buf[20];		/* XXX: 20 is arbitrary */
-	char *q;
-	unsigned u;
-	uintmax_t cll;
-	ssize_t cl, l, lr;
-
-#define  ERR(x) do { *error = (x); return (H1CR_ERROR); } while (0)
-
-	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
-	AN(priv);
-	AN(error);
-	AN(statp);
-	AN(ptr);
-	AN(lp);
-	l = *lp;
-	*lp = 0;
-	if (*priv == -1) {
-		/* Skip leading whitespace */
-		do {
-			lr = HTTP1_Read(htc, buf, 1);
-			if (lr <= 0)
-				ERR("chunked read err");
-			*statp += lr;
-		} while (vct_islws(buf[0]));
-
-		if (!vct_ishex(buf[0]))
-			 ERR("chunked header non-hex");
-
-		/* Collect hex digits, skipping leading zeros */
-		for (u = 1; u < sizeof buf; u++) {
-			do {
-				lr = HTTP1_Read(htc, buf + u, 1);
-				if (lr <= 0)
-					ERR("chunked read err");
-				*statp += lr;
-			} while (u == 1 && buf[0] == '0' && buf[u] == '0');
-			if (!vct_ishex(buf[u]))
-				break;
-		}
-
-		if (u >= sizeof buf)
-			ERR("chunked header too long");
-
-		/* Skip trailing white space */
-		while(vct_islws(buf[u]) && buf[u] != '\n') {
-			lr = HTTP1_Read(htc, buf + u, 1);
-			if (lr <= 0)
-				ERR("chunked read err");
-			*statp += lr;
-		}
-
-		if (buf[u] != '\n')
-			ERR("chunked header no NL");
-
-		buf[u] = '\0';
-
-		cll = strtoumax(buf, &q, 16);
-		if (q == NULL || *q != '\0')
-			ERR("chunked header number syntax");
-		cl = (ssize_t)cll;
-		if((uintmax_t)cl != cll)
-			ERR("bogusly large chunk size");
-
-		*priv = cl;
-	}
-	if (*priv > 0) {
-		if (*priv < l)
-			l = *priv;
-		lr = HTTP1_Read(htc, ptr, l);
-		if (lr <= 0)
-			ERR("straight insufficient bytes");
-		*statp += lr;
-		*lp = lr;
-		*priv -= lr;
-		if (*priv == 0)
-			*priv = -1;
-		return (H1CR_MORE);
-	}
-	AZ(*priv);
-	i = HTTP1_Read(htc, buf, 1);
-	if (i <= 0)
-		ERR("chunked read err");
-	*statp += i;
-	if (buf[0] == '\r' && HTTP1_Read(htc, buf, 1) <= 0)
-		ERR("chunked read err");
-	if (buf[0] != '\n')
-		ERR("chunked tail no NL");
-	return (H1CR_END);
-#undef ERR
-}
-
diff --git a/bin/varnishd/cache/cache_http1_vfp.c b/bin/varnishd/cache/cache_http1_vfp.c
new file mode 100644
index 0000000..4e2fa29
--- /dev/null
+++ b/bin/varnishd/cache/cache_http1_vfp.c
@@ -0,0 +1,256 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2014 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.
+ *
+ * HTTP1 Fetch Filters
+ *
+ * These filters are used for both req.body and beresp.body to handle
+ * the HTTP/1 aspects (C-L/Chunked/EOF)
+ *
+ */
+
+#include "config.h"
+
+#include <inttypes.h>
+
+#include "cache.h"
+
+#include "vct.h"
+
+/*--------------------------------------------------------------------
+ * Read a chunked HTTP object.
+ *
+ * XXX: Reading one byte at a time is pretty pessimal.
+ */
+
+static enum vfp_status __match_proto__(vfp_pull_f)
+v1f_pull_chunked(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr,
+    ssize_t *lp)
+{
+	struct http_conn *htc;
+	int i;
+	char buf[20];		/* XXX: 20 is arbitrary */
+	char *q;
+	unsigned u;
+	uintmax_t cll;
+	ssize_t cl, l, lr;
+
+	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
+	CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
+	AN(ptr);
+	AN(lp);
+
+	AN(ptr);
+	AN(lp);
+	l = *lp;
+	*lp = 0;
+	if (vfe->priv2 == -1) {
+		/* Skip leading whitespace */
+		do {
+			lr = HTTP1_Read(htc, buf, 1);
+			if (lr <= 0)
+				return (VFP_Error(vc, "chunked read err"));
+			vc->bodybytes += lr;
+		} while (vct_islws(buf[0]));
+
+		if (!vct_ishex(buf[0]))
+			 return (VFP_Error(vc, "chunked header non-hex"));
+
+		/* Collect hex digits, skipping leading zeros */
+		for (u = 1; u < sizeof buf; u++) {
+			do {
+				lr = HTTP1_Read(htc, buf + u, 1);
+				if (lr <= 0)
+					return (VFP_Error(vc,
+					    "chunked read err"));
+				vc->bodybytes += lr;
+			} while (u == 1 && buf[0] == '0' && buf[u] == '0');
+			if (!vct_ishex(buf[u]))
+				break;
+		}
+
+		if (u >= sizeof buf)
+			return (VFP_Error(vc, "chunked header too long"));
+
+		/* Skip trailing white space */
+		while(vct_islws(buf[u]) && buf[u] != '\n') {
+			lr = HTTP1_Read(htc, buf + u, 1);
+			if (lr <= 0)
+				return (VFP_Error(vc, "chunked read err"));
+			vc->bodybytes += lr;
+		}
+
+		if (buf[u] != '\n')
+			return (VFP_Error(vc, "chunked header no NL"));
+
+		buf[u] = '\0';
+
+		cll = strtoumax(buf, &q, 16);
+		if (q == NULL || *q != '\0')
+			return (VFP_Error(vc, "chunked header number syntax"));
+		cl = (ssize_t)cll;
+		if((uintmax_t)cl != cll)
+			return (VFP_Error(vc, "bogusly large chunk size"));
+
+		vfe->priv2 = cl;
+	}
+	if (vfe->priv2 > 0) {
+		if (vfe->priv2 < l)
+			l = vfe->priv2;
+		lr = HTTP1_Read(htc, ptr, l);
+		if (lr <= 0)
+			return (VFP_Error(vc, "straight insufficient bytes"));
+		vc->bodybytes += lr;
+		*lp = lr;
+		vfe->priv2 -= lr;
+		if (vfe->priv2 == 0)
+			vfe->priv2 = -1;
+		return (VFP_OK);
+	}
+	AZ(vfe->priv2);
+	i = HTTP1_Read(htc, buf, 1);
+	if (i <= 0)
+		return (VFP_Error(vc, "chunked read err"));
+	vc->bodybytes += i;
+	if (buf[0] == '\r' && HTTP1_Read(htc, buf, 1) <= 0)
+		return (VFP_Error(vc, "chunked read err"));
+	if (buf[0] != '\n')
+		return (VFP_Error(vc, "chunked tail no NL"));
+	return (VFP_END);
+}
+
+static const struct vfp v1f_chunked = {
+	.name = "V1F_CHUNKED",
+	.pull = v1f_pull_chunked,
+};
+
+
+/*--------------------------------------------------------------------*/
+
+static enum vfp_status __match_proto__(vfp_pull_f)
+v1f_pull_straight(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
+    ssize_t *lp)
+{
+	ssize_t l, lr;
+	struct http_conn *htc;
+
+	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
+	CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
+	AN(p);
+	AN(lp);
+
+	l = *lp;
+	*lp = 0;
+
+	if (vfe->priv2 == 0) // XXX: Optimize Content-Len: 0 out earlier
+		return (VFP_END);
+	if (vfe->priv2 < l)
+		l = vfe->priv2;
+	lr = HTTP1_Read(htc, p, l);
+	vc->bodybytes += lr;
+	if (lr <= 0)
+		return (VFP_Error(vc, "straight insufficient bytes"));
+	*lp = lr;
+	vfe->priv2 -= lr;
+	if (vfe->priv2 == 0)
+		return (VFP_END);
+	return (VFP_OK);
+}
+
+static const struct vfp v1f_straight = {
+	.name = "V1F_STRAIGHT",
+	.pull = v1f_pull_straight,
+};
+
+/*--------------------------------------------------------------------*/
+
+static enum vfp_status __match_proto__(vfp_pull_f)
+v1f_pull_eof(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
+    ssize_t *lp)
+{
+	ssize_t l, lr;
+	struct http_conn *htc;
+
+	CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
+	CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
+	AN(p);
+
+	AN(lp);
+
+	l = *lp;
+	*lp = 0;
+	lr = HTTP1_Read(htc, p, l);
+	if (lr < 0)
+		return (VFP_Error(vc, "eof socket fail"));
+	if (lr == 0)
+		return (VFP_END);
+	*lp = lr;
+	vc->bodybytes += lr;
+	return (VFP_OK);
+}
+
+static const struct vfp v1f_eof = {
+	.name = "V1F_EOF",
+	.pull = v1f_pull_eof,
+};
+
+/*--------------------------------------------------------------------
+ */
+
+void
+V1F_Setup_Fetch(struct vfp_ctx *vfc, struct http_conn *htc)
+{
+	struct vfp_entry *vfe;
+
+	CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
+
+	switch(htc->body_status) {
+	case BS_EOF:
+		assert(htc->content_length == -1);
+		vfe = VFP_Push(vfc, &v1f_eof, 0);
+		vfe->priv2 = 0;
+		break;
+	case BS_LENGTH:
+		assert(htc->content_length > 0);
+		vfe = VFP_Push(vfc, &v1f_straight, 0);
+		vfe->priv2 = htc->content_length;
+		break;
+	case BS_CHUNKED:
+		assert(htc->content_length == -1);
+		vfe = VFP_Push(vfc, &v1f_chunked, 0);
+		vfe->priv2 = -1;
+		break;
+	default:
+		WRONG("Wrong body_status");
+		break;
+	}
+	vfe->priv1 = htc;
+}



More information about the varnish-commit mailing list