[master] 6cdf30e Start splitting "generic HTTP", whatever that might be or become, from HTTP1 specific functionality.

Poul-Henning Kamp phk at varnish-cache.org
Mon Jan 28 09:14:18 CET 2013


commit 6cdf30ed9f69dce360385d77c0b20ffba49e864a
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Jan 28 08:13:49 2013 +0000

    Start splitting "generic HTTP", whatever that might be or become,
    from HTTP1 specific functionality.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index cb5b24f..5237991 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -867,14 +867,14 @@ double http_GetHdrQ(const struct http *hp, const char *hdr, const char *field);
 uint16_t http_GetStatus(const struct http *hp);
 const char *http_GetReq(const struct http *hp);
 int http_HdrIs(const struct http *hp, const char *hdr, const char *val);
-uint16_t http_DissectRequest(struct req *);
-uint16_t http_DissectResponse(struct http *sp, const struct http_conn *htc);
 enum sess_close http_DoConnection(const struct http *);
 void http_CopyHome(const struct http *hp);
 void http_Unset(struct http *hp, const char *hdr);
 void http_CollectHdr(struct http *hp, const char *hdr);
+void http_VSLH(const struct http *hp, unsigned hdr);
+
+/* cache_http1_proto.c */
 
-/* cache_httpconn.c */
 enum htc_status_e {
 	HTC_ALL_WHITESPACE =	-3,
 	HTC_OVERFLOW =		-2,
@@ -889,6 +889,8 @@ enum htc_status_e HTC_Reinit(struct http_conn *htc);
 enum htc_status_e HTC_Rx(struct http_conn *htc);
 ssize_t HTC_Read(struct http_conn *htc, void *d, size_t len);
 enum htc_status_e HTC_Complete(struct http_conn *htc);
+uint16_t HTC_DissectRequest(struct req *);
+uint16_t HTC_DissectResponse(struct http *sp, const struct http_conn *htc);
 
 #define HTTPH(a, b, c) extern char b[];
 #include "tbl/http_headers.h"
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index c2ebbea..2713571 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -504,7 +504,7 @@ FetchHdr(struct req *req, int need_host_hdr, int sendbody)
 
 	hp = bo->beresp;
 
-	if (http_DissectResponse(hp, htc)) {
+	if (HTC_DissectResponse(hp, htc)) {
 		VSLb(req->vsl, SLT_FetchError, "http format error");
 		VDI_CloseFd(&bo->vbc);
 		/* XXX: other cleanup ? */
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index eb5ad7e..c46cb15 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -61,7 +61,7 @@ http2shmlog(const struct http *hp, int t)
 	return ((enum VSL_tag_e)(foo[hp->logtag] + t));
 }
 
-static void
+void
 http_VSLH(const struct http *hp, unsigned hdr)
 {
 
@@ -477,265 +477,6 @@ http_GetReq(const struct http *hp)
 	return (hp->hd[HTTP_HDR_METHOD].b);
 }
 
-/*--------------------------------------------------------------------
- * Dissect the headers of the HTTP protocol message.
- * Detect conditionals (headers which start with '^[Ii][Ff]-')
- */
-
-static uint16_t
-http_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc)
-{
-	char *q, *r;
-	txt t = htc->rxbuf;
-
-	if (*p == '\r')
-		p++;
-
-	hp->nhd = HTTP_HDR_FIRST;
-	hp->conds = 0;
-	r = NULL;		/* For FlexeLint */
-	for (; p < t.e; p = r) {
-
-		/* Find end of next header */
-		q = r = p;
-		while (r < t.e) {
-			if (!vct_iscrlf(*r)) {
-				r++;
-				continue;
-			}
-			q = r;
-			assert(r < t.e);
-			r += vct_skipcrlf(r);
-			if (r >= t.e)
-				break;
-			/* If line does not continue: got it. */
-			if (!vct_issp(*r))
-				break;
-
-			/* Clear line continuation LWS to spaces */
-			while (vct_islws(*q))
-				*q++ = ' ';
-		}
-
-		if (q - p > htc->maxhdr) {
-			VSLb(hp->vsl, SLT_BogoHeader, "%.*s",
-			    (int)(q - p > 20 ? 20 : q - p), p);
-			return (413);
-		}
-
-		/* Empty header = end of headers */
-		if (p == q)
-			break;
-
-		if ((p[0] == 'i' || p[0] == 'I') &&
-		    (p[1] == 'f' || p[1] == 'F') &&
-		    p[2] == '-')
-			hp->conds = 1;
-
-		while (q > p && vct_issp(q[-1]))
-			q--;
-		*q = '\0';
-
-		if (hp->nhd < hp->shd) {
-			hp->hdf[hp->nhd] = 0;
-			hp->hd[hp->nhd].b = p;
-			hp->hd[hp->nhd].e = q;
-			http_VSLH(hp, hp->nhd);
-			hp->nhd++;
-		} else {
-			VSLb(hp->vsl, SLT_BogoHeader, "%.*s",
-			    (int)(q - p > 20 ? 20 : q - p), p);
-			return (413);
-		}
-	}
-	return (0);
-}
-
-/*--------------------------------------------------------------------
- * Deal with first line of HTTP protocol message.
- */
-
-static uint16_t
-http_splitline(struct http *hp, const struct http_conn *htc, int req)
-{
-	char *p, *q;
-	int h1, h2, h3;
-
-	if (req) {
-		h1 = HTTP_HDR_METHOD;
-		h2 = HTTP_HDR_URL;
-		h3 = HTTP_HDR_PROTO;
-	} else {
-		h1 = HTTP_HDR_PROTO;
-		h2 = HTTP_HDR_STATUS;
-		h3 = HTTP_HDR_RESPONSE;
-	}
-
-	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
-	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
-
-	/* XXX: Assert a NUL at rx.e ? */
-	Tcheck(htc->rxbuf);
-
-	/* Skip leading LWS */
-	for (p = htc->rxbuf.b ; vct_islws(*p); p++)
-		continue;
-
-	/* First field cannot contain SP, CRLF or CTL */
-	q = p;
-	for (; !vct_issp(*p); p++) {
-		if (vct_isctl(*p))
-			return (400);
-	}
-	hp->hd[h1].b = q;
-	hp->hd[h1].e = p;
-
-	/* Skip SP */
-	for (; vct_issp(*p); p++) {
-		if (vct_isctl(*p))
-			return (400);
-	}
-
-	/* Second field cannot contain LWS or CTL */
-	q = p;
-	for (; !vct_islws(*p); p++) {
-		if (vct_isctl(*p))
-			return (400);
-	}
-	hp->hd[h2].b = q;
-	hp->hd[h2].e = p;
-
-	if (!Tlen(hp->hd[h2]))
-		return (413);
-
-	/* Skip SP */
-	for (; vct_issp(*p); p++) {
-		if (vct_isctl(*p))
-			return (400);
-	}
-
-	/* Third field is optional and cannot contain CTL */
-	q = p;
-	if (!vct_iscrlf(*p)) {
-		for (; !vct_iscrlf(*p); p++)
-			if (!vct_issep(*p) && vct_isctl(*p))
-				return (400);
-	}
-	hp->hd[h3].b = q;
-	hp->hd[h3].e = p;
-
-	/* Skip CRLF */
-	p += vct_skipcrlf(p);
-
-	*hp->hd[h1].e = '\0';
-	http_VSLH(hp, h1);
-
-	*hp->hd[h2].e = '\0';
-	http_VSLH(hp, h2);
-
-	if (hp->hd[h3].e != NULL) {
-		*hp->hd[h3].e = '\0';
-		http_VSLH(hp, h3);
-	}
-
-	return (http_dissect_hdrs(hp, p, htc));
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-http_ProtoVer(struct http *hp)
-{
-
-	if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.0"))
-		hp->protover = 10;
-	else if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
-		hp->protover = 11;
-	else
-		hp->protover = 9;
-}
-
-
-/*--------------------------------------------------------------------*/
-
-uint16_t
-http_DissectRequest(struct req *req)
-{
-	struct http_conn *htc;
-	struct http *hp;
-	uint16_t retval;
-
-	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-	htc = req->htc;
-	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
-	hp = req->http;
-	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
-
-	retval = http_splitline(hp, htc, 1);
-	if (retval != 0) {
-		VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
-		return (retval);
-	}
-	http_ProtoVer(hp);
-	return (retval);
-}
-
-/*--------------------------------------------------------------------*/
-
-uint16_t
-http_DissectResponse(struct http *hp, const struct http_conn *htc)
-{
-	int j;
-	uint16_t retval = 0;
-	char *p;
-
-
-	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
-	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
-
-	if (http_splitline(hp, htc, 0))
-		retval = 503;
-
-	if (retval == 0 && memcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.", 7))
-		retval = 503;
-
-	if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
-		retval = 503;
-
-	if (retval == 0) {
-		hp->status = 0;
-		p = hp->hd[HTTP_HDR_STATUS].b;
-		for (j = 100; j != 0; j /= 10) {
-			if (!vct_isdigit(*p)) {
-				retval = 503;
-				break;
-			}
-			hp->status += (uint16_t)(j * (*p - '0'));
-			p++;
-		}
-		if (*p != '\0')
-			retval = 503;
-	}
-
-	if (retval != 0) {
-		VSLbt(hp->vsl, SLT_HttpGarbage, htc->rxbuf);
-		assert(retval >= 100 && retval <= 999);
-		hp->status = retval;
-	} else {
-		http_ProtoVer(hp);
-	}
-
-	if (hp->hd[HTTP_HDR_RESPONSE].b == NULL ||
-	    !Tlen(hp->hd[HTTP_HDR_RESPONSE])) {
-		/* Backend didn't send a response string, use the standard */
-		hp->hd[HTTP_HDR_RESPONSE].b =
-		    TRUST_ME(http_StatusMessage(hp->status));
-		hp->hd[HTTP_HDR_RESPONSE].e =
-		    strchr(hp->hd[HTTP_HDR_RESPONSE].b, '\0');
-	}
-	return (retval);
-}
-
 /*--------------------------------------------------------------------*/
 
 void
diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c
index 83b0914..07fd810 100644
--- a/bin/varnishd/cache/cache_http1_fsm.c
+++ b/bin/varnishd/cache/cache_http1_fsm.c
@@ -260,7 +260,7 @@ http1_dissect(struct worker *wrk, struct req *req)
 	wrk->vcl = NULL;
 
 	HTTP_Setup(req->http, req->ws, req->vsl, HTTP_Method);
-	req->err_code = http_DissectRequest(req);
+	req->err_code = HTC_DissectRequest(req);
 
 	/* If we could not even parse the request, just close */
 	if (req->err_code == 400) {
diff --git a/bin/varnishd/cache/cache_http1_proto.c b/bin/varnishd/cache/cache_http1_proto.c
index 8b331af..42c2269 100644
--- a/bin/varnishd/cache/cache_http1_proto.c
+++ b/bin/varnishd/cache/cache_http1_proto.c
@@ -209,3 +209,259 @@ HTC_Read(struct http_conn *htc, void *d, size_t len)
 	}
 	return (i + l);
 }
+
+/*--------------------------------------------------------------------
+ * Dissect the headers of the HTTP protocol message.
+ * Detect conditionals (headers which start with '^[Ii][Ff]-')
+ */
+
+static uint16_t
+htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc)
+{
+	char *q, *r;
+	txt t = htc->rxbuf;
+
+	if (*p == '\r')
+		p++;
+
+	hp->nhd = HTTP_HDR_FIRST;
+	hp->conds = 0;
+	r = NULL;		/* For FlexeLint */
+	for (; p < t.e; p = r) {
+
+		/* Find end of next header */
+		q = r = p;
+		while (r < t.e) {
+			if (!vct_iscrlf(*r)) {
+				r++;
+				continue;
+			}
+			q = r;
+			assert(r < t.e);
+			r += vct_skipcrlf(r);
+			if (r >= t.e)
+				break;
+			/* If line does not continue: got it. */
+			if (!vct_issp(*r))
+				break;
+
+			/* Clear line continuation LWS to spaces */
+			while (vct_islws(*q))
+				*q++ = ' ';
+		}
+
+		if (q - p > htc->maxhdr) {
+			VSLb(hp->vsl, SLT_BogoHeader, "%.*s",
+			    (int)(q - p > 20 ? 20 : q - p), p);
+			return (413);
+		}
+
+		/* Empty header = end of headers */
+		if (p == q)
+			break;
+
+		if ((p[0] == 'i' || p[0] == 'I') &&
+		    (p[1] == 'f' || p[1] == 'F') &&
+		    p[2] == '-')
+			hp->conds = 1;
+
+		while (q > p && vct_issp(q[-1]))
+			q--;
+		*q = '\0';
+
+		if (hp->nhd < hp->shd) {
+			hp->hdf[hp->nhd] = 0;
+			hp->hd[hp->nhd].b = p;
+			hp->hd[hp->nhd].e = q;
+			http_VSLH(hp, hp->nhd);
+			hp->nhd++;
+		} else {
+			VSLb(hp->vsl, SLT_BogoHeader, "%.*s",
+			    (int)(q - p > 20 ? 20 : q - p), p);
+			return (413);
+		}
+	}
+	return (0);
+}
+
+/*--------------------------------------------------------------------
+ * Deal with first line of HTTP protocol message.
+ */
+
+static uint16_t
+htc_splitline(struct http *hp, const struct http_conn *htc, int req)
+{
+	char *p, *q;
+	int h1, h2, h3;
+
+	if (req) {
+		h1 = HTTP_HDR_METHOD;
+		h2 = HTTP_HDR_URL;
+		h3 = HTTP_HDR_PROTO;
+	} else {
+		h1 = HTTP_HDR_PROTO;
+		h2 = HTTP_HDR_STATUS;
+		h3 = HTTP_HDR_RESPONSE;
+	}
+
+	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
+	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
+
+	/* XXX: Assert a NUL at rx.e ? */
+	Tcheck(htc->rxbuf);
+
+	/* Skip leading LWS */
+	for (p = htc->rxbuf.b ; vct_islws(*p); p++)
+		continue;
+
+	/* First field cannot contain SP, CRLF or CTL */
+	q = p;
+	for (; !vct_issp(*p); p++) {
+		if (vct_isctl(*p))
+			return (400);
+	}
+	hp->hd[h1].b = q;
+	hp->hd[h1].e = p;
+
+	/* Skip SP */
+	for (; vct_issp(*p); p++) {
+		if (vct_isctl(*p))
+			return (400);
+	}
+
+	/* Second field cannot contain LWS or CTL */
+	q = p;
+	for (; !vct_islws(*p); p++) {
+		if (vct_isctl(*p))
+			return (400);
+	}
+	hp->hd[h2].b = q;
+	hp->hd[h2].e = p;
+
+	if (!Tlen(hp->hd[h2]))
+		return (413);
+
+	/* Skip SP */
+	for (; vct_issp(*p); p++) {
+		if (vct_isctl(*p))
+			return (400);
+	}
+
+	/* Third field is optional and cannot contain CTL */
+	q = p;
+	if (!vct_iscrlf(*p)) {
+		for (; !vct_iscrlf(*p); p++)
+			if (!vct_issep(*p) && vct_isctl(*p))
+				return (400);
+	}
+	hp->hd[h3].b = q;
+	hp->hd[h3].e = p;
+
+	/* Skip CRLF */
+	p += vct_skipcrlf(p);
+
+	*hp->hd[h1].e = '\0';
+	http_VSLH(hp, h1);
+
+	*hp->hd[h2].e = '\0';
+	http_VSLH(hp, h2);
+
+	if (hp->hd[h3].e != NULL) {
+		*hp->hd[h3].e = '\0';
+		http_VSLH(hp, h3);
+	}
+
+	return (htc_dissect_hdrs(hp, p, htc));
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+htc_proto_ver(struct http *hp)
+{
+	if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.0"))
+		hp->protover = 10;
+	else if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
+		hp->protover = 11;
+	else
+		hp->protover = 9;
+}
+
+/*--------------------------------------------------------------------*/
+
+uint16_t
+HTC_DissectRequest(struct req *req)
+{
+	struct http_conn *htc;
+	struct http *hp;
+	uint16_t retval;
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	htc = req->htc;
+	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
+	hp = req->http;
+	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
+
+	retval = htc_splitline(hp, htc, 1);
+	if (retval != 0) {
+		VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
+		return (retval);
+	}
+	htc_proto_ver(hp);
+	return (retval);
+}
+/*--------------------------------------------------------------------*/
+
+uint16_t
+HTC_DissectResponse(struct http *hp, const struct http_conn *htc)
+{
+	int j;
+	uint16_t retval = 0;
+	char *p;
+
+
+	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
+	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
+
+	if (htc_splitline(hp, htc, 0))
+		retval = 503;
+
+	if (retval == 0 && memcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.", 7))
+		retval = 503;
+
+	if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
+		retval = 503;
+
+	if (retval == 0) {
+		hp->status = 0;
+		p = hp->hd[HTTP_HDR_STATUS].b;
+		for (j = 100; j != 0; j /= 10) {
+			if (!vct_isdigit(*p)) {
+				retval = 503;
+				break;
+			}
+			hp->status += (uint16_t)(j * (*p - '0'));
+			p++;
+		}
+		if (*p != '\0')
+			retval = 503;
+	}
+
+	if (retval != 0) {
+		VSLbt(hp->vsl, SLT_HttpGarbage, htc->rxbuf);
+		assert(retval >= 100 && retval <= 999);
+		hp->status = retval;
+	} else
+		htc_proto_ver(hp);
+
+	if (hp->hd[HTTP_HDR_RESPONSE].b == NULL ||
+	    !Tlen(hp->hd[HTTP_HDR_RESPONSE])) {
+		/* Backend didn't send a response string, use the standard */
+		hp->hd[HTTP_HDR_RESPONSE].b =
+		    TRUST_ME(http_StatusMessage(hp->status));
+		hp->hd[HTTP_HDR_RESPONSE].e =
+		    strchr(hp->hd[HTTP_HDR_RESPONSE].b, '\0');
+	}
+	return (retval);
+}
+



More information about the varnish-commit mailing list