/*
- * 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.
#include "squid.h"
#include "Debug.h"
+#include "http/one/Parser.h"
+#include "HttpHdrCc.h"
#include "HttpHeaderTools.h"
#include "HttpMsg.h"
#include "MemBuf.h"
cache_control(NULL),
hdr_sz(0),
content_length(0),
- pstate(psReadyToParseStartLine)
+ pstate(psReadyToParseStartLine),
+ sources(0)
{}
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 */
* 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;
}
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()