]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: h1: remove the useless H1_MSG_BODY state
authorWilly Tarreau <w@1wt.eu>
Wed, 12 Sep 2018 15:25:32 +0000 (17:25 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 12 Sep 2018 15:38:25 +0000 (17:38 +0200)
This state was only a delimiter between headers and body but it now
causes more harm than good because it requires someone to change it.
Since the H1 parser knows if we're in DATA or CHUNK_SIZE, simply let
it set the right next state so that h1m->state constantly matches
what is expected afterwards.

include/proto/h1.h
include/types/h1.h
src/h1.c
src/mux_h2.c

index e6a4204ff30fe4a9b16908b42e9b2f1b87e151ac..fb040d1388268cddb86be0f0812c6c7c2d4b5e12 100644 (file)
@@ -150,7 +150,6 @@ static inline const char *h1m_state_str(enum h1_state msg_state)
        case H1_MSG_HDR_L2_LF:   return "MSG_HDR_L2_LF";
        case H1_MSG_HDR_L2_LWS:  return "MSG_HDR_L2_LWS";
        case H1_MSG_LAST_LF:     return "MSG_LAST_LF";
-       case H1_MSG_BODY:        return "MSG_BODY";
        case H1_MSG_CHUNK_SIZE:  return "MSG_CHUNK_SIZE";
        case H1_MSG_DATA:        return "MSG_DATA";
        case H1_MSG_CHUNK_CRLF:  return "MSG_CHUNK_CRLF";
index c6c97dcbdc78d17d60fe6a830dee0033933f2f77..26eafd3397db1c12e7b238f1e7968ebe9c2da83f 100644 (file)
@@ -120,21 +120,17 @@ enum h1m_state {
        H1_MSG_HDR_L2_LF    = 23, // parsing header LWS (LF) inside/after value
        H1_MSG_HDR_L2_LWS   = 24, // checking whether it's a new header or an LWS
 
-       H1_MSG_LAST_LF      = 25, // parsing last LF
+       H1_MSG_LAST_LF      = 25, // parsing last LF, last state for headers
 
-       /* Body processing.
-        * The state H1_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.
-        */
-       H1_MSG_BODY         = 26, // parsing body at end of headers
-       H1_MSG_CHUNK_SIZE   = 27, // parsing the chunk size (RFC7230 #4.1)
-       H1_MSG_DATA         = 28, // skipping data chunk / content-length data
-       H1_MSG_CHUNK_CRLF   = 29, // skipping CRLF after data chunk
-       H1_MSG_TRAILERS     = 30, // trailers (post-data entity headers)
+       /* Body processing. */
+
+       H1_MSG_CHUNK_SIZE   = 26, // parsing the chunk size (RFC7230 #4.1)
+       H1_MSG_DATA         = 27, // skipping data chunk / content-length data
+       H1_MSG_CHUNK_CRLF   = 28, // skipping CRLF after data chunk
+       H1_MSG_TRAILERS     = 29, // trailers (post-data entity headers)
        /* we enter this state when we've received the end of the current message */
-       H1_MSG_DONE         = 31, // message end received, waiting for resync or close
-       H1_MSG_TUNNEL       = 32, // tunneled data after DONE
+       H1_MSG_DONE         = 30, // message end received, waiting for resync or close
+       H1_MSG_TUNNEL       = 31, // tunneled data after DONE
 } __attribute__((packed));
 
 
index d88408efe11e49a790ecb0f50e97dcc13fce285f..fc0b8da58b84ad868024d206867e230ed91de751 100644 (file)
--- a/src/h1.c
+++ b/src/h1.c
@@ -1073,7 +1073,21 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
                        }
                        http_set_hdr(&hdr[hdr_count++], ist(""), ist(""));
                }
-               state = H1_MSG_BODY;
+
+               /* reaching here we've parsed the whole message. We may detect
+                * that we were already continuing an interrupted parsing pass
+                * so we were silently looking for the end of message not
+                * updating anything before deciding to parse it fully at once.
+                * It's guaranteed that we won't match this test twice in a row
+                * since restarting will turn zero.
+                */
+               if (restarting)
+                       goto restart;
+
+               if (h1m->flags & H1_MF_CHNK)
+                       state = H1_MSG_CHUNK_SIZE;
+               else
+                       state = H1_MSG_DATA;
                break;
 
        default:
@@ -1081,14 +1095,9 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
                goto http_msg_invalid;
        }
 
-       /* reaching here, we've parsed the whole message and the state is
-        * H1_MSG_BODY. We may discover that we were already continuing an
-        * interrupted parsing session, thus we were silently looking for
-        * the end of message before deciding to parse it fully at once.
-        * We won't come there again since restarting will turn zero.
+       /* Now we've left the headers state and are either in H1_MSG_DATA or
+        * H1_MSG_CHUNK_SIZE.
         */
-       if (restarting)
-               goto restart;
 
        if (slp && !skip_update)
                *slp = sl;
index d842cd8d2e5fbbec3e7286ed657eab418c5b2b21..922cabefe43678043a755c1098c852578de44946 100644 (file)
@@ -3237,8 +3237,8 @@ static size_t h2s_frt_make_resp_headers(struct h2s *h2s, const struct buffer *bu
                h1m->err_pos = -1; // don't care about errors on the response path
                goto end;
        }
-       else
-               h1m->state = (h1m->flags & H1_MF_CHNK) ? H1_MSG_CHUNK_SIZE : H1_MSG_BODY;
+
+       /* now the h1m state is either H1_MSG_CHUNK_SIZE or H1_MSG_DATA */
 
  end:
        //fprintf(stderr, "[%d] sent simple H2 response (sid=%d) = %d bytes (%d in, ep=%u, es=%s)\n", h2c->st0, h2s->id, outbuf.len, ret, h1m->err_pos, h1_msg_state_str(h1m->err_state));
@@ -3568,7 +3568,7 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun
                h2s->flags |= H2_SF_OUTGOING_DATA;
 
        while (h2s->h1m.state < H1_MSG_DONE && count) {
-               if (h2s->h1m.state < H1_MSG_BODY) {
+               if (h2s->h1m.state <= H1_MSG_LAST_LF) {
                        ret = h2s_frt_make_resp_headers(h2s, buf, total, count);
                }
                else if (h2s->h1m.state < H1_MSG_TRAILERS) {