]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/HttpMsg.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / HttpMsg.cc
index d111b048b6fec171cdbb0a205988ae86daf93eae..f6f2f8d8196db216dcbfaa0404133cc5c6b45b8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -10,6 +10,8 @@
 
 #include "squid.h"
 #include "Debug.h"
+#include "http/one/Parser.h"
+#include "HttpHdrCc.h"
 #include "HttpHeaderTools.h"
 #include "HttpMsg.h"
 #include "MemBuf.h"
@@ -23,7 +25,8 @@ HttpMsg::HttpMsg(http_hdr_owner_type owner):
     cache_control(NULL),
     hdr_sz(0),
     content_length(0),
-    pstate(psReadyToParseStartLine)
+    pstate(psReadyToParseStartLine),
+    sources(0)
 {}
 
 HttpMsg::~HttpMsg()
@@ -31,70 +34,30 @@ HttpMsg::~HttpMsg()
     assert(!body_pipe);
 }
 
-HttpMsgParseState &operator++ (HttpMsgParseState &aState)
-{
-    int tmp = (int)aState;
-    aState = (HttpMsgParseState)(++tmp);
-    return aState;
-}
-
-/* find end of headers */
-static int
-httpMsgIsolateHeaders(const char **parse_start, int l, const char **blk_start, const char **blk_end)
+void
+HttpMsg::putCc(const HttpHdrCc *otherCc)
 {
-    /*
-     * parse_start points to the first line of HTTP message *headers*,
-     * not including the request or status lines
-     */
-    size_t end = headersEnd(*parse_start, l);
-    int nnl;
-
-    if (end) {
-        *blk_start = *parse_start;
-        *blk_end = *parse_start + end - 1;
-        /*
-         * leave blk_end pointing to the first character after the
-         * first newline which terminates the headers
-         */
-        assert(**blk_end == '\n');
-
-        while (*(*blk_end - 1) == '\r')
-            --(*blk_end);
-
-        assert(*(*blk_end - 1) == '\n');
-
-        *parse_start += end;
-
-        return 1;
+    // get rid of the old CC, if any
+    if (cache_control) {
+        delete cache_control;
+        cache_control = nullptr;
+        if (!otherCc)
+            header.delById(Http::HdrType::CACHE_CONTROL);
+        // else it will be deleted inside putCc() below
     }
 
-    /*
-     * If we didn't find the end of headers, and parse_start does
-     * NOT point to a CR or NL character, then return failure
-     */
-    if (**parse_start != '\r' && **parse_start != '\n')
-        return 0;       /* failure */
-
-    /*
-     * If we didn't find the end of headers, and parse_start does point
-     * to an empty line, then we have empty headers.  Skip all CR and
-     * NL characters up to the first NL.  Leave parse_start pointing at
-     * the first character after the first NL.
-     */
-    *blk_start = *parse_start;
-
-    *blk_end = *blk_start;
-
-    for (nnl = 0; nnl == 0; ++(*parse_start)) {
-        if (**parse_start == '\r')
-            (void) 0;
-        else if (**parse_start == '\n')
-            ++nnl;
-        else
-            break;
+    // add new CC, if any
+    if (otherCc) {
+        cache_control = new HttpHdrCc(*otherCc);
+        header.putCc(cache_control);
     }
+}
 
-    return 1;
+HttpMsgParseState &operator++ (HttpMsgParseState &aState)
+{
+    int tmp = (int)aState;
+    aState = (HttpMsgParseState)(++tmp);
+    return aState;
 }
 
 /* find first CRLF */
@@ -253,27 +216,14 @@ HttpMsg::httpMsgParseStep(const char *buf, int len, int atEnd)
      * after headers.) Grr.
      */
     if (pstate == psReadyToParseHeaders) {
-        if (!httpMsgIsolateHeaders(&parse_start, parse_len, &blk_start, &blk_end)) {
-            if (atEnd) {
-                blk_start = parse_start;
-                blk_end = blk_start + strlen(blk_start);
-            } else {
-                PROF_stop(HttpMsg_httpMsgParseStep);
-                return 0;
-            }
-        }
-
-        if (!header.parse(blk_start, blk_end-blk_start)) {
+        size_t hsize = 0;
+        const int parsed = header.parse(parse_start, parse_len, atEnd, hsize);
+        if (parsed <= 0) {
             PROF_stop(HttpMsg_httpMsgParseStep);
-            return httpMsgParseError();
+            return !parsed ? 0 : httpMsgParseError();
         }
-
+        hdr_sz += hsize;
         hdrCacheInit();
-
-        *parse_end_ptr = parse_start;
-
-        hdr_sz = *parse_end_ptr - buf;
-
         ++pstate;
     }
 
@@ -281,6 +231,24 @@ HttpMsg::httpMsgParseStep(const char *buf, int len, int atEnd)
     return 1;
 }
 
+bool
+HttpMsg::parseHeader(Http1::Parser &hp)
+{
+    // HTTP/1 message contains "zero or more header fields"
+    // zero does not need parsing
+    // XXX: c_str() reallocates. performance regression.
+    if (hp.headerBlockSize() && !header.parse(hp.mimeHeader().c_str(), hp.headerBlockSize())) {
+        pstate = psError;
+        return false;
+    }
+
+    // XXX: we are just parsing HTTP headers, not the whole message prefix here
+    hdr_sz = hp.messageHeaderSize();
+    pstate = psParsed;
+    hdrCacheInit();
+    return true;
+}
+
 /* handy: resets and returns -1 */
 int
 HttpMsg::httpMsgParseError()
@@ -292,8 +260,8 @@ HttpMsg::httpMsgParseError()
 void
 HttpMsg::setContentLength(int64_t clen)
 {
-    header.delById(HDR_CONTENT_LENGTH); // if any
-    header.putInt64(HDR_CONTENT_LENGTH, clen);
+    header.delById(Http::HdrType::CONTENT_LENGTH); // if any
+    header.putInt64(Http::HdrType::CONTENT_LENGTH, clen);
     content_length = clen;
 }
 
@@ -321,7 +289,7 @@ void HttpMsg::packInto(Packable *p, bool full_uri) const
 
 void HttpMsg::hdrCacheInit()
 {
-    content_length = header.getInt64(HDR_CONTENT_LENGTH);
+    content_length = header.getInt64(Http::HdrType::CONTENT_LENGTH);
     assert(NULL == cache_control);
     cache_control = header.getCc();
 }
@@ -331,8 +299,6 @@ void HttpMsg::hdrCacheInit()
  */
 void HttpMsg::firstLineBuf(MemBuf& mb)
 {
-    Packer p;
-    packerToMemInit(&p, &mb);
-    packFirstLineInto(&p, true);
+    packFirstLineInto(&mb, true);
 }