]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http: make the chunk crlf parser only depend on the buffer
authorWilly Tarreau <w@1wt.eu>
Thu, 21 Sep 2017 09:33:54 +0000 (11:33 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 22 Oct 2017 07:54:14 +0000 (09:54 +0200)
The chunk crlf parser used to depend on the channel and on the HTTP
message, eventhough it's not really needed. Let's remove this dependency
so that it can be used within the H2 to H1 gateway.

As part of this small API change, it was renamed to h1_skip_chunk_crlf()
to mention that it doesn't depend on http_msg anymore.

include/proto/h1.h
src/proto_http.c

index b6a41454514bac898caba6d7de10ca59a1767f0e..8a0e265419caeb994956b756e02626fdafc0a052 100644 (file)
@@ -139,22 +139,19 @@ static inline const char *h1_msg_state_str(enum h1_state msg_state)
  * caller must ensure that ->p points to the first byte to parse.  It returns
  * the number of bytes parsed on success, so the caller can set msg_state to
  * HTTP_MSG_CHUNK_SIZE. If not enough data are available, the function does not
- * change anything and returns zero. If a parse error is encountered, the
- * function returns < 0. Note: this function is designed to parse wrapped CRLF
- * at the end of the buffer.
+ * change anything and returns zero. Otherwise it returns a negative value
+ * indicating the error positionn relative to <stop>. Note: this function is
+ * designed to parse wrapped CRLF at the end of the buffer.
  */
-static inline int http_skip_chunk_crlf(struct http_msg *msg)
+static inline int h1_skip_chunk_crlf(const struct buffer *buf, int start, int stop)
 {
-       const struct buffer *buf = msg->chn->buf;
-       const char *ptr;
-       int bytes;
+       const char *ptr = b_ptr(buf, start);
+       int bytes = 1;
 
        /* NB: we'll check data availabilty at the end. It's not a
         * problem because whatever we match first will be checked
         * against the correct length.
         */
-       bytes = 1;
-       ptr = b_ptr(buf, msg->next);
        if (*ptr == '\r') {
                bytes++;
                ptr++;
@@ -162,13 +159,12 @@ static inline int http_skip_chunk_crlf(struct http_msg *msg)
                        ptr = buf->data;
        }
 
-       if (msg->next + bytes > buf->i)
+       if (bytes > stop - start)
                return 0;
 
-       if (*ptr != '\n') {
-               msg->err_pos = buffer_count(buf, buf->p, ptr);
-               return -1;
-       }
+       if (*ptr != '\n')
+               return -buffer_count(buf, ptr, b_ptr(buf, stop));
+
        return bytes;
 }
 
index 3032c7fafc044c7be0dff4bac7657dd6d6c7e8b4..066204166a6feaee5df4a7e5970915a942141bff 100644 (file)
@@ -6156,11 +6156,15 @@ http_msg_forward_chunked_body(struct stream *s, struct http_msg *msg)
 
                case HTTP_MSG_CHUNK_CRLF:
                        /* we want the CRLF after the data */
-                       ret = http_skip_chunk_crlf(msg);
+                       ret = h1_skip_chunk_crlf(chn->buf, msg->next, chn->buf->i);
                        if (ret == 0)
                                goto missing_data_or_waiting;
-                       if (ret < 0)
+                       if (ret < 0) {
+                               msg->err_pos = chn->buf->i + ret;
+                               if (msg->err_pos < 0)
+                                       msg->err_pos += chn->buf->size;
                                goto chunk_parsing_error;
+                       }
                        msg->next += ret;
                        msg->msg_state = HTTP_MSG_CHUNK_SIZE;
                        /* fall through for HTTP_MSG_CHUNK_SIZE */