]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h1: add a function to measure the trailers length
authorWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 16:14:16 +0000 (17:14 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 16:18:10 +0000 (17:18 +0100)
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.

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

index b7229507b9dd9c3499a905d24ef143818ecbae9b..4463ad06905ac2364111af00d819a63de46a68ba 100644 (file)
@@ -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
index bbfaabcf76000b7979d08044cbef38423b22a9ca..f4d77e38d38832b6b9458bd25032ac6081724375 100644 (file)
--- 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 <buf>, 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
  * <msg>. 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