From: Willy Tarreau Date: Tue, 31 Oct 2017 16:14:16 +0000 (+0100) Subject: MINOR: h1: add a function to measure the trailers length X-Git-Tag: v1.8-rc1~102 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2510f702f923ae83f8324bc94703fc77a37601bc;p=thirdparty%2Fhaproxy.git MINOR: h1: add a function to measure the trailers length This is needed in the H2->H1 gateway so that we know how long the trailers block is in chunked encoding. It returns the number of bytes, or 0 if some are missing, or -1 in case of parse error. --- diff --git a/include/proto/h1.h b/include/proto/h1.h index b7229507b9..4463ad0690 100644 --- a/include/proto/h1.h +++ b/include/proto/h1.h @@ -43,6 +43,7 @@ int http_forward_trailers(struct http_msg *msg); int h1_headers_to_hdr_list(char *start, const char *stop, struct http_hdr *hdr, unsigned int hdr_num, struct h1m *h1m); +int h1_measure_trailers(const struct buffer *buf); #define H1_FLG_CTL 0x01 #define H1_FLG_SEP 0x02 diff --git a/src/h1.c b/src/h1.c index bbfaabcf76..f4d77e38d3 100644 --- a/src/h1.c +++ b/src/h1.c @@ -1202,6 +1202,67 @@ int h1_headers_to_hdr_list(char *start, const char *stop, return -2; } +/* This function performs a very minimal parsing of the trailers block present + * in the output part of , and returns the number of bytes to delete to + * skip the trailers. It may return 0 if it's missing some input data, or < 0 + * in case of parse error (in which case the caller may have to decide how to + * proceed, possibly eating everything). + */ +int h1_measure_trailers(const struct buffer *buf) +{ + int count = 0; + + while (1) { + const char *p1 = NULL, *p2 = NULL; + const char *start = b_ptr(buf, (int)(count - buf->o)); + const char *stop = bo_end(buf); + const char *ptr = start; + int bytes = 0; + + /* scan current line and stop at LF or CRLF */ + while (1) { + if (ptr == stop) + return 0; + + if (*ptr == '\n') { + if (!p1) + p1 = ptr; + p2 = ptr; + break; + } + + if (*ptr == '\r') { + if (p1) + return -1; + p1 = ptr; + } + + ptr++; + if (ptr >= buf->data + buf->size) + ptr = buf->data; + } + + /* after LF; point to beginning of next line */ + p2++; + if (p2 >= buf->data + buf->size) + p2 = buf->data; + + bytes = p2 - start; + if (bytes < 0) + bytes += buf->size; + + count += bytes; + + /* LF/CRLF at beginning of line => end of trailers at p2. + * Everything was scheduled for forwarding, there's nothing left + * from this message. */ + if (p1 == start) + break; + /* OK, next line then */ + } + return count; +} + /* This function skips trailers in the buffer associated with HTTP message * . The first visited position is msg->next. If the end of the trailers is * found, the function returns >0. So, the caller can automatically schedul it