diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-07-14 17:41:05 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-04 12:37:36 +0000 |
commit | 399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (patch) | |
tree | 6b06b60ff365abef0e13b3503d593a0df48d20e8 /chromium/net/quic/spdy_utils.cc | |
parent | 7366110654eec46f21b6824f302356426f48cd74 (diff) | |
download | qtwebengine-chromium-399c965b6064c440ddcf4015f5f8e9d131c7a0a6.tar.gz |
BASELINE: Update Chromium to 52.0.2743.76 and Ninja to 1.7.1
Change-Id: I382f51b959689505a60f8b707255ecb344f7d8b4
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/net/quic/spdy_utils.cc')
-rw-r--r-- | chromium/net/quic/spdy_utils.cc | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/chromium/net/quic/spdy_utils.cc b/chromium/net/quic/spdy_utils.cc index 468c9823e1a..6b9982a31f6 100644 --- a/chromium/net/quic/spdy_utils.cc +++ b/chromium/net/quic/spdy_utils.cc @@ -4,17 +4,20 @@ #include "net/quic/spdy_utils.h" +#include <memory> #include <vector> -#include "base/memory/scoped_ptr.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "net/spdy/spdy_frame_builder.h" #include "net/spdy/spdy_framer.h" #include "net/spdy/spdy_protocol.h" #include "url/gurl.h" +using base::StringPiece; using std::string; using std::vector; @@ -107,6 +110,115 @@ bool SpdyUtils::ParseTrailers(const char* data, return true; } +bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list, + int64_t* content_length, + SpdyHeaderBlock* headers) { + for (const auto& p : header_list) { + const string& name = p.first; + if (name.empty()) { + DVLOG(1) << "Header name must not be empty."; + return false; + } + + if (std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>)) { + DLOG(ERROR) << "Malformed header: Header name " << name + << " contains upper-case characters."; + return false; + } + + auto iter = headers->find(name); + if (iter == headers->end()) { + (*headers)[name] = p.second; + } else if (name == "cookie") { + // Obeys section 8.1.2.5 in RFC 7540 for cookie reconstruction. + headers->ReplaceOrAppendHeader( + name, base::StringPrintf("%s; %s", iter->second.as_string().c_str(), + p.second.c_str())); + } else { + // This header had multiple values, so it must be reconstructed. + string value = base::StringPrintf( + "%s%c%s", iter->second.as_string().c_str(), '\0', p.second.c_str()); + headers->ReplaceOrAppendHeader(name, value); + } + } + + if (ContainsKey(*headers, "content-length")) { + // Check whether multiple values are consistent. + StringPiece content_length_header = (*headers)["content-length"]; + vector<string> values = + base::SplitString(content_length_header, base::StringPiece("\0", 1), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + for (const string& value : values) { + int64_t new_value; + if (!base::StringToInt64(value, &new_value) || new_value < 0) { + DLOG(ERROR) << "Content length was either unparseable or negative."; + return false; + } + if (*content_length < 0) { + *content_length = new_value; + continue; + } + if (new_value != *content_length) { + DLOG(ERROR) << "Parsed content length " << new_value << " is " + << "inconsistent with previously detected content length " + << *content_length; + return false; + } + } + } + + DVLOG(1) << "Successfully parsed headers: " << headers->DebugString(); + return true; +} + +bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list, + size_t* final_byte_offset, + SpdyHeaderBlock* trailers) { + bool found_final_byte_offset = false; + for (const auto& p : header_list) { + const string& name = p.first; + + // Pull out the final offset pseudo header which indicates the number of + // response body bytes expected. + int offset; + if (!found_final_byte_offset && name == kFinalOffsetHeaderKey && + base::StringToInt(p.second, &offset)) { + *final_byte_offset = offset; + found_final_byte_offset = true; + continue; + } + + if (name.empty() || name[0] == ':') { + DVLOG(1) << "Trailers must not be empty, and must not contain pseudo-" + << "headers. Found: '" << name << "'"; + return false; + } + + if (std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>)) { + DVLOG(1) << "Malformed header: Header name " << name + << " contains upper-case characters."; + return false; + } + + if (trailers->find(name) != trailers->end()) { + DVLOG(1) << "Duplicate header '" << name << "' found in trailers."; + return false; + } + + (*trailers)[name] = p.second; + } + + if (!found_final_byte_offset) { + DVLOG(1) << "Required key '" << kFinalOffsetHeaderKey << "' not present"; + return false; + } + + // TODO(rjshade): Check for other forbidden keys, following the HTTP/2 spec. + + DVLOG(1) << "Successfully parsed Trailers: " << trailers->DebugString(); + return true; +} + // static string SpdyUtils::GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers) { SpdyHeaderBlock::const_iterator it = headers.find(":scheme"); |