From: Willy Tarreau Date: Thu, 21 Sep 2017 09:33:54 +0000 (+0200) Subject: MEDIUM: http: make the chunk crlf parser only depend on the buffer X-Git-Tag: v1.8-dev3~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b28925675d257db1ac8ec9a3b3d819575554345c;p=thirdparty%2Fhaproxy.git MEDIUM: http: make the chunk crlf parser only depend on the buffer 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. --- diff --git a/include/proto/h1.h b/include/proto/h1.h index b6a4145451..8a0e265419 100644 --- a/include/proto/h1.h +++ b/include/proto/h1.h @@ -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 . 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; } diff --git a/src/proto_http.c b/src/proto_http.c index 3032c7fafc..066204166a 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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 */