MINOR: h1: parse the Connection header field

The new function h1_parse_connection_header() is called when facing a
connection header in the generic parser, and it will set up to 3 bits
in h1m->flags indicating if at least one "close", "keep-alive" or "upgrade"
tokens was seen.
diff --git a/include/types/h1.h b/include/types/h1.h
index dd883e8..ec967ac 100644
--- a/include/types/h1.h
+++ b/include/types/h1.h
@@ -141,6 +141,18 @@
 #define H1_MF_RESP              0x00000004 // this message is the response message
 #define H1_MF_TOLOWER           0x00000008 // turn the header names to lower case
 #define H1_MF_VER_11            0x00000010 // message indicates version 1.1 or above
+#define H1_MF_CONN_CLO          0x00000020 // message contains "connection: close"
+#define H1_MF_CONN_KAL          0x00000040 // message contains "connection: keep-alive"
+#define H1_MF_CONN_UPG          0x00000080 // message contains "connection: upgrade"
+
+/* Note: for a connection to be persistent, we need this for the request :
+ *   - one of CLEN or CHNK
+ *   - version 1.0 and KAL and not CLO
+ *   - or version 1.1 and not CLO
+ * For the response it's the same except that UPG must not appear either.
+ * So in short, for a request it's (CLEN|CHNK) > 0 && !CLO && (VER_11 || KAL)
+ * and for a response it's (CLEN|CHNK) > 0 && !(CLO|UPG) && (VER_11 || KAL)
+ */
 
 
 /* basic HTTP/1 message state for use in parsers. The err_pos field is special,
diff --git a/src/h1.c b/src/h1.c
index ec8bb38..b78f584 100644
--- a/src/h1.c
+++ b/src/h1.c
@@ -659,6 +659,44 @@
 	return;
 }
 
+
+/* Parse the Connection: header of an HTTP/1 request, looking for "close",
+ * "keep-alive", and "upgrade" values, and updating h1m->flags according to
+ * what was found there. Note that flags are only added, not removed, so the
+ * function is safe for being called multiple times if multiple occurrences
+ * are found.
+ */
+void h1_parse_connection_header(struct h1m *h1m, struct ist value)
+{
+	char *e, *n;
+	struct ist word;
+
+	word.ptr = value.ptr - 1; // -1 for next loop's pre-increment
+	e = value.ptr + value.len;
+
+	while (++word.ptr < e) {
+		/* skip leading delimitor and blanks */
+		if (HTTP_IS_LWS(*word.ptr))
+			continue;
+
+		n = http_find_hdr_value_end(word.ptr, e); // next comma or end of line
+		word.len = n - word.ptr;
+
+		/* trim trailing blanks */
+		while (word.len && HTTP_IS_LWS(word.ptr[word.len-1]))
+			word.len--;
+
+		if (isteqi(word, ist("keep-alive")))
+			h1m->flags |= H1_MF_CONN_KAL;
+		else if (isteqi(word, ist("close")))
+			h1m->flags |= H1_MF_CONN_CLO;
+		else if (isteqi(word, ist("upgrade")))
+			h1m->flags |= H1_MF_CONN_UPG;
+
+		word.ptr = n;
+	}
+}
+
 /* This function parses a contiguous HTTP/1 headers block starting at <start>
  * and ending before <stop>, at once, and converts it a list of (name,value)
  * pairs representing header fields into the array <hdr> of size <hdr_num>,
@@ -1244,6 +1282,9 @@
 				strl2llrc(v.ptr, v.len, &cl);
 				h1m->curr_len = h1m->body_len = cl;
 			}
+			else if (isteqi(n, ist("connection"))) {
+				h1_parse_connection_header(h1m, v);
+			}
 		}
 
 		sol = ptr - start;