[master] 972273f Set the protocol-specific body status in http_conn for both req and resp.

Poul-Henning Kamp phk at FreeBSD.org
Mon Sep 8 10:18:38 CEST 2014


commit 972273fbe4d32e70e1b85e1a43e4c46d2f9188df
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Sep 8 08:18:15 2014 +0000

    Set the protocol-specific body status in http_conn for both req and resp.

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index b422d9b..1bf2918 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -218,6 +218,7 @@ struct http_conn {
 	struct ws		*ws;
 	txt			rxbuf;
 	txt			pipeline;
+	ssize_t			content_length;
 	enum body_status	body_status;
 };
 
@@ -1000,8 +1001,8 @@ enum http1_status_e HTTP1_Reinit(struct http_conn *htc);
 enum http1_status_e HTTP1_Rx(struct http_conn *htc);
 ssize_t HTTP1_Read(struct http_conn *htc, void *d, size_t len);
 enum http1_status_e HTTP1_Complete(struct http_conn *htc);
-uint16_t HTTP1_DissectRequest(struct req *);
-uint16_t HTTP1_DissectResponse(struct http *sp, const struct http_conn *htc);
+uint16_t HTTP1_DissectRequest(struct http_conn *htc, struct http *hp);
+uint16_t HTTP1_DissectResponse(struct http *sp, struct http_conn *htc);
 unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int*);
 
 #define HTTPH(a, b, c) extern char b[];
diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c
index b0c5299..af7442a 100644
--- a/bin/varnishd/cache/cache_http1_fsm.c
+++ b/bin/varnishd/cache/cache_http1_fsm.c
@@ -322,10 +322,11 @@ http1_dissect(struct worker *wrk, struct req *req)
 	wrk->vcl = NULL;
 
 	HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod);
-	req->err_code = HTTP1_DissectRequest(req);
+	req->err_code = HTTP1_DissectRequest(req->htc, req->http);
 
 	/* If we could not even parse the request, just close */
 	if (req->err_code != 0) {
+		VSLbt(req->vsl, SLT_HttpGarbage, req->htc->rxbuf);
 		wrk->stats.client_req_400++;
 		r = write(req->sp->fd, r_400, strlen(r_400));
 		if (r > 0)
diff --git a/bin/varnishd/cache/cache_http1_proto.c b/bin/varnishd/cache/cache_http1_proto.c
index 03563fd..8b872fc 100644
--- a/bin/varnishd/cache/cache_http1_proto.c
+++ b/bin/varnishd/cache/cache_http1_proto.c
@@ -373,6 +373,61 @@ http1_splitline(struct http *hp, const struct http_conn *htc, const int *hf)
 
 /*--------------------------------------------------------------------*/
 
+static enum body_status
+http1_body_status(const struct http *hp, struct http_conn *htc)
+{
+	ssize_t cl;
+	char *b;
+
+	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
+	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
+
+	htc->content_length = -1;
+
+	if (http_HdrIs(hp, H_Transfer_Encoding, "chunked"))
+		return (BS_CHUNKED);
+
+	if (http_GetHdr(hp, H_Transfer_Encoding, &b))
+		return (BS_ERROR);
+
+	cl = http_GetContentLength(hp);
+	if (cl == -2)
+		return (BS_ERROR);
+	if (cl >= 0) {
+		htc->content_length = cl;
+		return (cl == 0 ? BS_NONE : BS_LENGTH);
+	}
+
+	if (http_HdrIs(hp, H_Connection, "keep-alive")) {
+		/*
+		 * Keep alive with neither TE=Chunked or C-Len is impossible.
+		 * We assume a zero length body.
+		 */
+		return (BS_NONE);
+	}
+
+	if (http_HdrIs(hp, H_Connection, "close")) {
+		/*
+		 * In this case, it is safe to just read what comes.
+		 */
+		return (BS_EOF);
+	}
+
+	if (hp->protover < 11) {
+		/*
+		 * With no Connection header, assume EOF.
+		 */
+		return (BS_EOF);
+	}
+
+	/*
+	 * Fall back to EOF transfer.
+	 */
+	return (BS_EOF);
+}
+
+/*--------------------------------------------------------------------*/
+
 static uint16_t
 http1_request_check_host_hdr(const struct http *hp)
 {
@@ -453,24 +508,17 @@ http1_DoConnection(struct http *hp)
 /*--------------------------------------------------------------------*/
 
 uint16_t
-HTTP1_DissectRequest(struct req *req)
+HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
 {
-	struct http_conn *htc;
-	struct http *hp;
 	uint16_t retval;
 	char *b, *e;
 
-	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 = http1_splitline(hp, htc, HTTP1_Req);
-	if (retval != 0) {
-		VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
+	if (retval != 0)
 		return (retval);
-	}
 	http1_proto_ver(hp);
 
 	retval = http1_request_check_host_hdr(hp);
@@ -490,6 +538,8 @@ HTTP1_DissectRequest(struct req *req)
 		}
 	}
 
+	htc->body_status = http1_body_status(hp, htc);
+
 	hp->doclose = http1_DoConnection(hp);
 
 	return (retval);
@@ -498,7 +548,7 @@ HTTP1_DissectRequest(struct req *req)
 /*--------------------------------------------------------------------*/
 
 uint16_t
-HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
+HTTP1_DissectResponse(struct http *hp, struct http_conn *htc)
 {
 	uint16_t retval = 0;
 	char *p;
@@ -544,6 +594,8 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
 	    !Tlen(hp->hd[HTTP_HDR_REASON]))
 		http_SetH(hp, HTTP_HDR_REASON, http_Status2Reason(hp->status));
 
+	htc->body_status = http1_body_status(hp, htc);
+
 	hp->doclose = http1_DoConnection(hp);
 
 	return (retval);



More information about the varnish-commit mailing list