]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] http: create new MSG_BODY sub-states
authorWilly Tarreau <w@1wt.eu>
Sun, 8 Nov 2009 12:10:58 +0000 (13:10 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 8 Nov 2009 12:10:58 +0000 (13:10 +0100)
An HTTP message can be decomposed into several sub-states depending
on the transfer-encoding. We'll have to keep these state information
while parsing chunks, so we must extend the values. In order not to
change everything, we'll now consider that anything >= MSG_BODY is
the body, and that the value indicates the precise state. The
MSG_ERROR status which was greater than MSG_BODY was moved for this.

include/types/proto_http.h
src/proto_http.c

index 35114a8152612b3825c5d60eead5f679aa405399..93376e56f6c0ee1d72bafde3381515b57802d051 100644 (file)
 #define HTTP_MSG_HDR_L2_LWS   24 // checking whether it's a new header or an LWS
 
 #define HTTP_MSG_LAST_LF      25 // parsing last LF
-#define HTTP_MSG_BODY         26 // parsing body at end of headers
-#define HTTP_MSG_ERROR        27 // an error occurred
+
+/* error state : must be before HTTP_MSG_BODY so that (>=BODY) always indicates
+ * that data are being processed.
+ */
+
+#define HTTP_MSG_ERROR        26 // an error occurred
+
+/* Body processing.
+ * The state HTTP_MSG_BODY is a delimiter to know if we're waiting for headers
+ * or body. All the sub-states below also indicate we're processing the body,
+ * with some additional information.
+ */
+#define HTTP_MSG_BODY         27 // parsing body at end of headers
+#define HTTP_MSG_100_SENT     28 // parsing body after a 100-Continue was sent
+#define HTTP_MSG_CHUNK_SIZE   29 // parsing the chunk size (RFC2616 #3.6.1)
+#define HTTP_MSG_DATA         30 // skipping data chunk / content-length data
+#define HTTP_MSG_DATA_CRLF    31 // skipping CRLF after data chunk
+#define HTTP_MSG_TRAILERS     32 // trailers (post-data entity headers)
 
 
 /* various data sources for the responses */
index b78fc53f5defab5875af50a48547674d812abb72..3aa8f5a59cccd96a362b8046995b3fb6b70cdc11 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * HTTP protocol analyzer
  *
- * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -1791,7 +1791,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
        /* 1: we might have to print this header in debug mode */
        if (unlikely((global.mode & MODE_DEBUG) &&
                     (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
-                    (msg->msg_state == HTTP_MSG_BODY || msg->msg_state == HTTP_MSG_ERROR))) {
+                    (msg->msg_state >= HTTP_MSG_BODY || msg->msg_state == HTTP_MSG_ERROR))) {
                char *eol, *sol;
 
                sol = req->data + msg->som;
@@ -1814,12 +1814,12 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
         * Now we quickly check if we have found a full valid request.
         * If not so, we check the FD and buffer states before leaving.
         * A full request is indicated by the fact that we have seen
-        * the double LF/CRLF, so the state is HTTP_MSG_BODY. Invalid
+        * the double LF/CRLF, so the state is >= HTTP_MSG_BODY. Invalid
         * requests are checked first.
         *
         */
 
-       if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
+       if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
                /*
                 * First, let's catch bad requests.
                 */
@@ -2137,7 +2137,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
        struct redirect_rule *rule;
        int cur_idx;
 
-       if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
+       if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
                /* we need more data */
                buffer_dont_connect(req);
                return 0;
@@ -2439,7 +2439,7 @@ int http_process_request(struct session *s, struct buffer *req, int an_bit)
        struct http_txn *txn = &s->txn;
        struct http_msg *msg = &txn->req;
 
-       if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
+       if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
                /* we need more data */
                buffer_dont_connect(req);
                return 0;
@@ -2769,7 +2769,7 @@ int http_process_request_body(struct session *s, struct buffer *req, int an_bit)
        unsigned long body = msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 : msg->eoh + 1;
        long long limit = s->be->url_param_post_limit;
 
-       if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
+       if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
                /* we need more data */
                buffer_dont_connect(req);
                return 0;
@@ -2891,7 +2891,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
        /* 1: we might have to print this header in debug mode */
        if (unlikely((global.mode & MODE_DEBUG) &&
                     (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
-                    (msg->msg_state == HTTP_MSG_BODY || msg->msg_state == HTTP_MSG_ERROR))) {
+                    (msg->msg_state >= HTTP_MSG_BODY || msg->msg_state == HTTP_MSG_ERROR))) {
                char *eol, *sol;
 
                sol = rep->data + msg->som;
@@ -2913,7 +2913,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
         * Now we quickly check if we have found a full valid response.
         * If not so, we check the FD and buffer states before leaving.
         * A full response is indicated by the fact that we have seen
-        * the double LF/CRLF, so the state is HTTP_MSG_BODY. Invalid
+        * the double LF/CRLF, so the state is >= HTTP_MSG_BODY. Invalid
         * responses are checked first.
         *
         * Depending on whether the client is still there or not, we
@@ -2922,7 +2922,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
         * errors somewhere else.
         */
 
-       if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
+       if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
                /* Invalid response */
                if (unlikely(msg->msg_state == HTTP_MSG_ERROR)) {
                        /* we detected a parsing error. We want to archive this response
@@ -3217,7 +3217,7 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
                rep->l,
                rep->analysers);
 
-       if (unlikely(msg->msg_state != HTTP_MSG_BODY))  /* we need more data */
+       if (unlikely(msg->msg_state < HTTP_MSG_BODY))   /* we need more data */
                return 0;
 
        rep->analysers &= ~an_bit;
@@ -4885,7 +4885,7 @@ acl_fetch_meth(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        meth = txn->meth;
@@ -4945,7 +4945,7 @@ acl_fetch_rqver(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        len = txn->req.sl.rq.v_l;
@@ -4973,7 +4973,7 @@ acl_fetch_stver(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->rsp.msg_state != HTTP_MSG_BODY)
+       if (txn->rsp.msg_state < HTTP_MSG_BODY)
                return 0;
 
        len = txn->rsp.sl.st.v_l;
@@ -5002,7 +5002,7 @@ acl_fetch_stcode(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->rsp.msg_state != HTTP_MSG_BODY)
+       if (txn->rsp.msg_state < HTTP_MSG_BODY)
                return 0;
 
        len = txn->rsp.sl.st.c_l;
@@ -5023,7 +5023,7 @@ acl_fetch_url(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5047,7 +5047,7 @@ acl_fetch_url_ip(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5079,7 +5079,7 @@ acl_fetch_url_port(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5137,7 +5137,7 @@ acl_fetch_chdr(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5156,7 +5156,7 @@ acl_fetch_shdr(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->rsp.msg_state != HTTP_MSG_BODY)
+       if (txn->rsp.msg_state < HTTP_MSG_BODY)
                return 0;
 
        return acl_fetch_hdr(px, l4, txn, txn->rsp.sol, expr, test);
@@ -5196,7 +5196,7 @@ acl_fetch_chdr_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5215,7 +5215,7 @@ acl_fetch_shdr_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->rsp.msg_state != HTTP_MSG_BODY)
+       if (txn->rsp.msg_state < HTTP_MSG_BODY)
                return 0;
 
        return acl_fetch_hdr_cnt(px, l4, txn, txn->rsp.sol, expr, test);
@@ -5261,7 +5261,7 @@ acl_fetch_chdr_val(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5280,7 +5280,7 @@ acl_fetch_shdr_val(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->rsp.msg_state != HTTP_MSG_BODY)
+       if (txn->rsp.msg_state < HTTP_MSG_BODY)
                return 0;
 
        return acl_fetch_hdr_val(px, l4, txn, txn->rsp.sol, expr, test);
@@ -5329,7 +5329,7 @@ acl_fetch_chdr_ip(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5348,7 +5348,7 @@ acl_fetch_shdr_ip(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->rsp.msg_state != HTTP_MSG_BODY)
+       if (txn->rsp.msg_state < HTTP_MSG_BODY)
                return 0;
 
        return acl_fetch_hdr_ip(px, l4, txn, txn->rsp.sol, expr, test);
@@ -5367,7 +5367,7 @@ acl_fetch_path(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!txn)
                return 0;
 
-       if (txn->req.msg_state != HTTP_MSG_BODY)
+       if (txn->req.msg_state < HTTP_MSG_BODY)
                return 0;
 
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
@@ -5407,7 +5407,7 @@ acl_fetch_proto_http(struct proxy *px, struct session *s, void *l7, int dir,
        if (!s || !req)
                return 0;
 
-       if (unlikely(msg->msg_state == HTTP_MSG_BODY)) {
+       if (unlikely(msg->msg_state >= HTTP_MSG_BODY)) {
                /* Already decoded as OK */
                test->flags |= ACL_TEST_F_SET_RES_PASS;
                return 1;
@@ -5417,7 +5417,7 @@ acl_fetch_proto_http(struct proxy *px, struct session *s, void *l7, int dir,
        if (likely(req->lr < req->r))
                http_msg_analyzer(req, msg, &txn->hdr_idx);
 
-       if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
+       if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
                if ((msg->msg_state == HTTP_MSG_ERROR) || (req->flags & BF_FULL)) {
                        test->flags |= ACL_TEST_F_SET_RES_FAIL;
                        return 1;