diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/BUILD.gn | 1 | ||||
-rw-r--r-- | net/net.gyp | 1 | ||||
-rw-r--r-- | net/quic/quic_http_stream.cc | 2 | ||||
-rw-r--r-- | net/quic/quic_in_memory_cache.cc | 218 | ||||
-rw-r--r-- | net/quic/quic_in_memory_cache.h | 35 | ||||
-rw-r--r-- | net/quic/quic_spdy_server_stream.cc | 80 | ||||
-rw-r--r-- | net/quic/quic_spdy_server_stream.h | 10 | ||||
-rw-r--r-- | net/quic/spdy_utils.cc | 7 | ||||
-rw-r--r-- | net/quic/spdy_utils.h | 2 | ||||
-rw-r--r-- | net/spdy/hpack_huffman_aggregator.cc | 2 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream.cc | 4 | ||||
-rw-r--r-- | net/spdy/spdy_http_utils.cc | 52 | ||||
-rw-r--r-- | net/spdy/spdy_http_utils.h | 16 | ||||
-rw-r--r-- | net/spdy/spdy_proxy_client_socket.cc | 5 |
14 files changed, 214 insertions, 221 deletions
diff --git a/net/BUILD.gn b/net/BUILD.gn index 06ab3f8..db3e631 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -1041,7 +1041,6 @@ source_set("quic_tools") { "quic/quic_time_wait_list_manager.h", ] deps = [ - ":balsa", ":net", "//base", "//base/third_party/dynamic_annotations", diff --git a/net/net.gyp b/net/net.gyp index bfe78d7..db7f277 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -1124,7 +1124,6 @@ '../base/base.gyp:base', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../url/url.gyp:url_lib', - 'balsa', 'net', ], 'sources': [ diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 20b60de..36eac6a 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc @@ -112,7 +112,7 @@ int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, stream_->set_priority(priority); // Store the serialized request headers. CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, - &request_headers_, SPDY3, /*direct=*/true); + SPDY3, /*direct=*/true, &request_headers_); // Store the request body. request_body_stream_ = request_info_->upload_data_stream; diff --git a/net/quic/quic_in_memory_cache.cc b/net/quic/quic_in_memory_cache.cc index 9d40fa5..58c6e90 100644 --- a/net/quic/quic_in_memory_cache.cc +++ b/net/quic/quic_in_memory_cache.cc @@ -7,7 +7,9 @@ #include "base/files/file_enumerator.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" -#include "net/tools/balsa/balsa_headers.h" +#include "base/strings/string_util.h" +#include "net/http/http_util.h" +#include "url/gurl.h" using base::FilePath; using base::StringPiece; @@ -21,45 +23,11 @@ namespace net { FilePath::StringType g_quic_in_memory_cache_dir = FILE_PATH_LITERAL(""); -namespace { - -// BalsaVisitor implementation (glue) which caches response bodies. -class CachingBalsaVisitor : public NoOpBalsaVisitor { - public: - CachingBalsaVisitor() : done_framing_(false) {} - virtual void ProcessBodyData(const char* input, size_t size) OVERRIDE { - AppendToBody(input, size); - } - virtual void MessageDone() OVERRIDE { - done_framing_ = true; - } - virtual void HandleHeaderError(BalsaFrame* framer) OVERRIDE { - UnhandledError(); - } - virtual void HandleHeaderWarning(BalsaFrame* framer) OVERRIDE { - UnhandledError(); - } - virtual void HandleChunkingError(BalsaFrame* framer) OVERRIDE { - UnhandledError(); - } - virtual void HandleBodyError(BalsaFrame* framer) OVERRIDE { - UnhandledError(); - } - void UnhandledError() { - LOG(DFATAL) << "Unhandled error framing HTTP."; - } - void AppendToBody(const char* input, size_t size) { - body_.append(input, size); - } - bool done_framing() const { return done_framing_; } - const string& body() const { return body_; } - - private: - bool done_framing_; - string body_; -}; +QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) { +} -} // namespace +QuicInMemoryCache::Response::~Response() { +} // static QuicInMemoryCache* QuicInMemoryCache::GetInstance() { @@ -67,58 +35,56 @@ QuicInMemoryCache* QuicInMemoryCache::GetInstance() { } const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse( - const BalsaHeaders& request_headers) const { - ResponseMap::const_iterator it = responses_.find(GetKey(request_headers)); + const GURL& url) const { + ResponseMap::const_iterator it = responses_.find(GetKey(url)); if (it == responses_.end()) { return NULL; } return it->second; } -void QuicInMemoryCache::AddSimpleResponse(StringPiece method, - StringPiece path, +void QuicInMemoryCache::AddSimpleResponse(StringPiece path, StringPiece version, StringPiece response_code, StringPiece response_detail, StringPiece body) { - BalsaHeaders request_headers, response_headers; - request_headers.SetRequestFirstlineFromStringPieces(method, - path, - version); - response_headers.SetRequestFirstlineFromStringPieces(version, - response_code, - response_detail); - response_headers.AppendHeader( - "content-length", - base::Uint64ToString(static_cast<uint64>(body.length()))); - - AddResponse(request_headers, response_headers, body); + GURL url("http://" + path.as_string()); + + string status_line = version.as_string() + " " + + response_code.as_string() + " " + + response_detail.as_string(); + + string header = "content-length: " + + base::Uint64ToString(static_cast<uint64>(body.length())); + + scoped_refptr<HttpResponseHeaders> response_headers = + new HttpResponseHeaders(status_line + '\0' + header + '\0' + '\0'); + + AddResponse(url, response_headers, body); } -void QuicInMemoryCache::AddResponse(const BalsaHeaders& request_headers, - const BalsaHeaders& response_headers, - StringPiece response_body) { - VLOG(1) << "Adding response for: " << GetKey(request_headers); - if (ContainsKey(responses_, GetKey(request_headers))) { +void QuicInMemoryCache::AddResponse( + const GURL& url, + scoped_refptr<HttpResponseHeaders> response_headers, + StringPiece response_body) { + string key = GetKey(url); + VLOG(1) << "Adding response for: " << key; + if (ContainsKey(responses_, key)) { LOG(DFATAL) << "Response for given request already exists!"; return; } Response* new_response = new Response(); new_response->set_headers(response_headers); new_response->set_body(response_body); - responses_[GetKey(request_headers)] = new_response; + responses_[key] = new_response; } -void QuicInMemoryCache::AddSpecialResponse(StringPiece method, - StringPiece path, - StringPiece version, +void QuicInMemoryCache::AddSpecialResponse(StringPiece path, SpecialResponseType response_type) { - BalsaHeaders request_headers, response_headers; - request_headers.SetRequestFirstlineFromStringPieces(method, - path, - version); - AddResponse(request_headers, response_headers, ""); - responses_[GetKey(request_headers)]->response_type_ = response_type; + GURL url("http://" + path.as_string()); + + AddResponse(url, NULL, string()); + responses_[GetKey(url)]->response_type_ = response_type; } QuicInMemoryCache::QuicInMemoryCache() { @@ -145,78 +111,63 @@ void QuicInMemoryCache::Initialize() { base::FileEnumerator::FILES); FilePath file = file_list.Next(); - while (!file.empty()) { + for (; !file.empty(); file = file_list.Next()) { // Need to skip files in .svn directories - if (file.value().find(FILE_PATH_LITERAL("/.svn/")) != std::string::npos) { - file = file_list.Next(); + if (file.value().find(FILE_PATH_LITERAL("/.svn/")) != string::npos) { continue; } - BalsaHeaders request_headers, response_headers; - string file_contents; base::ReadFileToString(file, &file_contents); - // Frame HTTP. - CachingBalsaVisitor caching_visitor; - BalsaFrame framer; - framer.set_balsa_headers(&response_headers); - framer.set_balsa_visitor(&caching_visitor); - size_t processed = 0; - while (processed < file_contents.length() && - !caching_visitor.done_framing()) { - processed += framer.ProcessInput(file_contents.c_str() + processed, - file_contents.length() - processed); + if (file_contents.length() > INT_MAX) { + LOG(WARNING) << "File '" << file.value() << "' too large: " + << file_contents.length(); + continue; } + int file_len = static_cast<int>(file_contents.length()); - string response_headers_str; - response_headers.DumpToString(&response_headers_str); - if (!caching_visitor.done_framing()) { - LOG(DFATAL) << "Did not frame entire message from file: " << file.value() - << " (" << processed << " of " << file_contents.length() - << " bytes)."; - } - if (processed < file_contents.length()) { - // Didn't frame whole file. Assume remainder is body. - // This sometimes happens as a result of incompatibilities between - // BalsaFramer and wget's serialization of HTTP sans content-length. - caching_visitor.AppendToBody(file_contents.c_str() + processed, - file_contents.length() - processed); - processed += file_contents.length(); + int headers_end = HttpUtil::LocateEndOfHeaders(file_contents.data(), + file_len); + if (headers_end < 1) { + LOG(DFATAL) << "Headers invalid or empty, ignoring: " << file.value(); + continue; } - string utf8_file = file.AsUTF8Unsafe(); - StringPiece base = utf8_file; - if (response_headers.HasHeader("X-Original-Url")) { - base = response_headers.GetHeader("X-Original-Url"); - response_headers.RemoveAllOfHeader("X-Original-Url"); - // Remove the protocol so that the string is of the form host + path, - // which is parsed properly below. - if (StringPieceUtils::StartsWithIgnoreCase(base, "https://")) { - base.remove_prefix(8); - } else if (StringPieceUtils::StartsWithIgnoreCase(base, "http://")) { - base.remove_prefix(7); + string raw_headers = + HttpUtil::AssembleRawHeaders(file_contents.data(), headers_end); + + scoped_refptr<HttpResponseHeaders> response_headers = + new HttpResponseHeaders(raw_headers); + + string base; + if (response_headers->GetNormalizedHeader("X-Original-Url", &base)) { + response_headers->RemoveHeader("X-Original-Url"); + // Remove the protocol so we can add it below. + if (StartsWithASCII(base, "https://", false)) { + base = base.substr(8); + } else if (StartsWithASCII(base, "http://", false)) { + base = base.substr(7); } + } else { + base = file.AsUTF8Unsafe(); + } + if (base.length() == 0 || base[0] == '/') { + LOG(DFATAL) << "Invalid path, ignoring: " << base; + continue; } - size_t path_start = base.find_first_of('/'); - DCHECK_LT(0U, path_start); - StringPiece host(base.substr(0, path_start)); - StringPiece path(base.substr(path_start)); - if (path[path.length() - 1] == ',') { - path.remove_suffix(1); + if (base[base.length() - 1] == ',') { + base = base.substr(0, base.length() - 1); } - // Set up request headers. Assume method is GET and protocol is HTTP/1.1. - request_headers.SetRequestFirstlineFromStringPieces("GET", - path, - "HTTP/1.1"); - request_headers.ReplaceOrAppendHeader("host", host); - VLOG(1) << "Inserting 'http://" << GetKey(request_headers) - << "' into QuicInMemoryCache."; + GURL url("http://" + base); - AddResponse(request_headers, response_headers, caching_visitor.body()); + VLOG(1) << "Inserting '" << GetKey(url) << "' into QuicInMemoryCache."; - file = file_list.Next(); + StringPiece body(file_contents.data() + headers_end, + file_contents.size() - headers_end); + + AddResponse(url, response_headers, body); } } @@ -224,20 +175,9 @@ QuicInMemoryCache::~QuicInMemoryCache() { STLDeleteValues(&responses_); } -string QuicInMemoryCache::GetKey(const BalsaHeaders& request_headers) const { - StringPiece uri = request_headers.request_uri(); - if (uri.size() == 0) { - return ""; - } - StringPiece host; - if (uri[0] == '/') { - host = request_headers.GetHeader("host"); - } else if (StringPieceUtils::StartsWithIgnoreCase(uri, "https://")) { - uri.remove_prefix(8); - } else if (StringPieceUtils::StartsWithIgnoreCase(uri, "http://")) { - uri.remove_prefix(7); - } - return host.as_string() + uri.as_string(); +string QuicInMemoryCache::GetKey(const GURL& url) const { + // Take everything but the scheme portion of the URL. + return url.host() + url.PathForRequest(); } } // namespace net diff --git a/net/quic/quic_in_memory_cache.h b/net/quic/quic_in_memory_cache.h index 32dc8d4..e37ce2b 100644 --- a/net/quic/quic_in_memory_cache.h +++ b/net/quic/quic_in_memory_cache.h @@ -11,12 +11,10 @@ #include "base/file_util.h" #include "base/memory/singleton.h" #include "base/strings/string_piece.h" -#include "net/base/net_export.h" -#include "net/tools/balsa/balsa_frame.h" -#include "net/tools/balsa/balsa_headers.h" -#include "net/tools/balsa/noop_balsa_visitor.h" +#include "net/http/http_response_headers.h" template <typename T> struct DefaultSingletonTraits; +class GURL; namespace net { @@ -42,25 +40,25 @@ class QuicInMemoryCache { // Container for response header/body pairs. class Response { public: - Response() : response_type_(REGULAR_RESPONSE) {} - ~Response() {} + Response(); + ~Response(); SpecialResponseType response_type() const { return response_type_; } - const BalsaHeaders& headers() const { return headers_; } + const HttpResponseHeaders& headers() const { return *headers_; } const base::StringPiece body() const { return base::StringPiece(body_); } private: friend class QuicInMemoryCache; - void set_headers(const BalsaHeaders& headers) { - headers_.CopyFrom(headers); + void set_headers(scoped_refptr<HttpResponseHeaders> headers) { + headers_ = headers; } void set_body(base::StringPiece body) { body.CopyToString(&body_); } SpecialResponseType response_type_; - BalsaHeaders headers_; + scoped_refptr<HttpResponseHeaders> headers_; std::string body_; DISALLOW_COPY_AND_ASSIGN(Response); @@ -72,26 +70,23 @@ class QuicInMemoryCache { // Retrieve a response from this cache for a given request. // If no appropriate response exists, NULL is returned. // Currently, responses are selected based on request URI only. - const Response* GetResponse(const BalsaHeaders& request_headers) const; + const Response* GetResponse(const GURL& url) const; // Adds a simple response to the cache. The response headers will - // only contain the "content-length" header with the lenght of |body|. - void AddSimpleResponse(base::StringPiece method, - base::StringPiece path, + // only contain the "content-length" header with the length of |body|. + void AddSimpleResponse(base::StringPiece path, base::StringPiece version, base::StringPiece response_code, base::StringPiece response_detail, base::StringPiece body); // Add a response to the cache. - void AddResponse(const BalsaHeaders& request_headers, - const BalsaHeaders& response_headers, + void AddResponse(const GURL& url, + scoped_refptr<HttpResponseHeaders> response_headers, base::StringPiece response_body); // Simulate a special behavior at a particular path. - void AddSpecialResponse(base::StringPiece method, - base::StringPiece path, - base::StringPiece version, + void AddSpecialResponse(base::StringPiece path, SpecialResponseType response_type); private: @@ -106,7 +101,7 @@ class QuicInMemoryCache { void Initialize(); - std::string GetKey(const BalsaHeaders& response_headers) const; + std::string GetKey(const GURL& url) const; // Cached responses. ResponseMap responses_; diff --git a/net/quic/quic_spdy_server_stream.cc b/net/quic/quic_spdy_server_stream.cc index de6917d..bc67bb9 100644 --- a/net/quic/quic_spdy_server_stream.cc +++ b/net/quic/quic_spdy_server_stream.cc @@ -5,14 +5,16 @@ #include "net/quic/quic_spdy_server_stream.h" #include "base/memory/singleton.h" +#include "base/strings/string_number_conversions.h" #include "net/quic/quic_in_memory_cache.h" #include "net/quic/quic_session.h" +#include "net/quic/spdy_utils.h" #include "net/spdy/spdy_framer.h" -#include "net/tools/quic/spdy_utils.h" +#include "net/spdy/spdy_header_block.h" +#include "net/spdy/spdy_http_utils.h" using base::StringPiece; using std::string; -using net::tools::SpdyUtils; namespace net { @@ -23,26 +25,26 @@ QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id, : QuicDataStream(id, session), read_buf_(new GrowableIOBuffer()), request_headers_received_(false) { + read_buf_->SetCapacity(kHeaderBufInitialSize); } QuicSpdyServerStream::~QuicSpdyServerStream() { } uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) { - uint32 total_bytes_processed = 0; - // Are we still reading the request headers. if (!request_headers_received_) { // Grow the read buffer if necessary. - if (read_buf_->RemainingCapacity() < (int)data_len) { - read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); + while (read_buf_->RemainingCapacity() < (int)data_len) { + read_buf_->SetCapacity(read_buf_->capacity() * 2); } memcpy(read_buf_->data(), data, data_len); read_buf_->set_offset(read_buf_->offset() + data_len); + // Try parsing the request headers. This will set request_headers_received_ + // if successful; if not, it will be tried again with more data. ParseRequestHeaders(); } else { - body_.append(data + total_bytes_processed, - data_len - total_bytes_processed); + body_.append(data, data_len); } return data_len; } @@ -55,44 +57,57 @@ void QuicSpdyServerStream::OnFinRead() { if (!request_headers_received_) { SendErrorResponse(); // We're not done reading headers. - } else if ((headers_.content_length_status() == - BalsaHeadersEnums::VALID_CONTENT_LENGTH) && - body_.size() != headers_.content_length()) { + return; + } + + SpdyHeaderBlock::const_iterator it = headers_.find("content-length"); + size_t content_length; + if (it != headers_.end() && + (!base::StringToSizeT(it->second, &content_length) || + body_.size() != content_length)) { SendErrorResponse(); // Invalid content length - } else { - SendResponse(); + return; } + + SendResponse(); } -size_t QuicSpdyServerStream::ParseRequestHeaders() { - size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); - SpdyFramer framer(SPDY3); - SpdyHeaderBlock headers; +// Try parsing the request headers. If successful, sets +// request_headers_received_. If not successful, it can just be tried again once +// there's more data. +void QuicSpdyServerStream::ParseRequestHeaders() { + SpdyFramer framer((kDefaultSpdyMajorVersion)); char* data = read_buf_->StartOfBuffer(); - size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), - &headers); + size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); + size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_len, &headers_); if (len == 0) { - return -1; + // Not enough data yet, presumably. (If we still don't succeed by the end of + // the stream, then we'll error above.) + return; } - if (!SpdyUtils::FillBalsaRequestHeaders(headers, &headers_)) { + // Headers received and parsed: extract the request URL. + request_url_ = GetUrlFromHeaderBlock(headers_, + kDefaultSpdyMajorVersion, + false); + if (!request_url_.is_valid()) { SendErrorResponse(); - return -1; + return; } + // Add any data past the headers to the request body. size_t delta = read_buf_len - len; if (delta > 0) { body_.append(data + len, delta); } request_headers_received_ = true; - return len; } void QuicSpdyServerStream::SendResponse() { // Find response in cache. If not found, send error response. const QuicInMemoryCache::Response* response = - QuicInMemoryCache::GetInstance()->GetResponse(headers_); + QuicInMemoryCache::GetInstance()->GetResponse(request_url_); if (response == NULL) { SendErrorResponse(); return; @@ -115,23 +130,24 @@ void QuicSpdyServerStream::SendResponse() { void QuicSpdyServerStream::SendErrorResponse() { DVLOG(1) << "Sending error response for stream " << id(); - BalsaHeaders headers; - headers.SetResponseFirstlineFromStringPieces( - "HTTP/1.1", "500", "Server Error"); - headers.ReplaceOrAppendHeader("content-length", "3"); - SendHeadersAndBody(headers, "bad"); + scoped_refptr<HttpResponseHeaders> headers + = new HttpResponseHeaders(string("HTTP/1.1 500 Server Error") + '\0' + + "content-length: 3" + '\0' + '\0'); + SendHeadersAndBody(*headers, "bad"); } void QuicSpdyServerStream::SendHeadersAndBody( - const BalsaHeaders& response_headers, + const HttpResponseHeaders& response_headers, StringPiece body) { // We only support SPDY and HTTP, and neither handles bidirectional streaming. if (!read_side_closed()) { CloseReadSide(); } - SpdyHeaderBlock header_block = - SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers); + SpdyHeaderBlock header_block; + CreateSpdyHeadersFromHttpResponse(response_headers, + kDefaultSpdyMajorVersion, + &header_block); WriteHeaders(header_block, body.empty(), NULL); diff --git a/net/quic/quic_spdy_server_stream.h b/net/quic/quic_spdy_server_stream.h index 31d750c..3cecb6b 100644 --- a/net/quic/quic_spdy_server_stream.h +++ b/net/quic/quic_spdy_server_stream.h @@ -11,10 +11,11 @@ #include "net/base/io_buffer.h" #include "net/quic/quic_data_stream.h" #include "net/quic/quic_protocol.h" -#include "net/tools/balsa/balsa_headers.h" +#include "url/gurl.h" namespace net { +class HttpResponseHeaders; class QuicSession; namespace test { @@ -33,7 +34,7 @@ class QuicSpdyServerStream : public QuicDataStream { virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE; virtual void OnFinRead() OVERRIDE; - size_t ParseRequestHeaders(); + void ParseRequestHeaders(); private: friend class test::QuicSpdyServerStreamPeer; @@ -46,11 +47,12 @@ class QuicSpdyServerStream : public QuicDataStream { // for the body void SendErrorResponse(); - void SendHeadersAndBody(const BalsaHeaders& response_headers, + void SendHeadersAndBody(const HttpResponseHeaders& response_headers, base::StringPiece body); - BalsaHeaders headers_; + SpdyHeaderBlock headers_; string body_; + GURL request_url_; // Buffer into which response header data is read. scoped_refptr<GrowableIOBuffer> read_buf_; diff --git a/net/quic/spdy_utils.cc b/net/quic/spdy_utils.cc index c0894d5..d863746 100644 --- a/net/quic/spdy_utils.cc +++ b/net/quic/spdy_utils.cc @@ -15,9 +15,10 @@ namespace net { // static string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) { - int length = SpdyFramer::GetSerializedLength(SPDY3, &headers); - SpdyFrameBuilder builder(length, SPDY3); - SpdyFramer::WriteHeaderBlock(&builder, SPDY3, &headers); + int length = SpdyFramer::GetSerializedLength(kDefaultSpdyMajorVersion, + &headers); + SpdyFrameBuilder builder(length, kDefaultSpdyMajorVersion); + SpdyFramer::WriteHeaderBlock(&builder, kDefaultSpdyMajorVersion, &headers); scoped_ptr<SpdyFrame> block(builder.take()); return string(block->data(), length); } diff --git a/net/quic/spdy_utils.h b/net/quic/spdy_utils.h index 14d3300..efb72a0 100644 --- a/net/quic/spdy_utils.h +++ b/net/quic/spdy_utils.h @@ -12,6 +12,8 @@ namespace net { +const SpdyMajorVersion kDefaultSpdyMajorVersion = SPDY3; + class NET_EXPORT_PRIVATE SpdyUtils { public: static std::string SerializeUncompressedHeaders( diff --git a/net/spdy/hpack_huffman_aggregator.cc b/net/spdy/hpack_huffman_aggregator.cc index 507f872..a54f5cd 100644 --- a/net/spdy/hpack_huffman_aggregator.cc +++ b/net/spdy/hpack_huffman_aggregator.cc @@ -58,7 +58,7 @@ void HpackHuffmanAggregator::AggregateTransactionCharacterCounts( { SpdyHeaderBlock headers; CreateSpdyHeadersFromHttpRequest( - request, request_headers, &headers, SPDY4, false); + request, request_headers, SPDY4, false, &headers); std::string tmp_out; encoder->EncodeHeaderSet(headers, &tmp_out); diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index 055d46f..7ae8441 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc @@ -263,8 +263,8 @@ int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); CreateSpdyHeadersFromHttpRequest( *request_info_, request_headers, - headers.get(), stream_->GetProtocolVersion(), - direct_); + stream_->GetProtocolVersion(), direct_, + headers.get()); stream_->net_log().AddEvent( NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); diff --git a/net/spdy/spdy_http_utils.cc b/net/spdy/spdy_http_utils.cc index 448c82f..55f0395 100644 --- a/net/spdy/spdy_http_utils.cc +++ b/net/spdy/spdy_http_utils.cc @@ -20,6 +20,20 @@ namespace net { +namespace { + +void AddSpdyHeader(const std::string& name, + const std::string& value, + SpdyHeaderBlock* headers) { + if (headers->find(name) == headers->end()) { + (*headers)[name] = value; + } else { + (*headers)[name] += '\0' + value; + } +} + +} // namespace + bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers, SpdyMajorVersion protocol_version, HttpResponseInfo* response) { @@ -85,9 +99,9 @@ bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers, void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, const HttpRequestHeaders& request_headers, - SpdyHeaderBlock* headers, SpdyMajorVersion protocol_version, - bool direct) { + bool direct, + SpdyHeaderBlock* headers) { HttpRequestHeaders::Iterator it(request_headers); while (it.GetNext()) { @@ -96,14 +110,7 @@ void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, name == "transfer-encoding" || name == "host") { continue; } - if (headers->find(name) == headers->end()) { - (*headers)[name] = it.value(); - } else { - std::string new_value = (*headers)[name]; - new_value.append(1, '\0'); // +=() doesn't append 0's - new_value += it.value(); - (*headers)[name] = new_value; - } + AddSpdyHeader(name, it.value(), headers); } static const char kHttpProtocolVersion[] = "HTTP/1.1"; @@ -129,6 +136,31 @@ void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, } } +void CreateSpdyHeadersFromHttpResponse( + const HttpResponseHeaders& response_headers, + SpdyMajorVersion protocol_version, + SpdyHeaderBlock* headers) { + std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status"; + std::string version_key = + (protocol_version >= SPDY3) ? ":version" : "version"; + + const std::string status_line = response_headers.GetStatusLine(); + std::string::const_iterator after_version = + std::find(status_line.begin(), status_line.end(), ' '); + if (protocol_version < SPDY4) { + (*headers)[version_key] = std::string(status_line.begin(), after_version); + } + (*headers)[status_key] = std::string(after_version + 1, status_line.end()); + + void* iter = NULL; + std::string raw_name, value; + while (response_headers.EnumerateHeaderLines(&iter, &raw_name, &value)) { + std::string name = StringToLowerASCII(raw_name); + AddSpdyHeader(name, value, headers); + } +} + + COMPILE_ASSERT(HIGHEST - LOWEST < 4 && HIGHEST - MINIMUM_PRIORITY < 5, request_priority_incompatible_with_spdy); diff --git a/net/spdy/spdy_http_utils.h b/net/spdy/spdy_http_utils.h index d15b6c7..a5c907b 100644 --- a/net/spdy/spdy_http_utils.h +++ b/net/spdy/spdy_http_utils.h @@ -17,6 +17,7 @@ namespace net { class HttpResponseInfo; struct HttpRequestInfo; class HttpRequestHeaders; +class HttpResponseHeaders; // Convert a SpdyHeaderBlock into an HttpResponseInfo. // |headers| input parameter with the SpdyHeaderBlock. @@ -27,14 +28,19 @@ bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers, SpdyMajorVersion protocol_version, HttpResponseInfo* response); -// Create a SpdyHeaderBlock for a Spdy SYN_STREAM Frame from -// HttpRequestInfo and HttpRequestHeaders. -void NET_EXPORT_PRIVATE CreateSpdyHeadersFromHttpRequest( +// Create a SpdyHeaderBlock from HttpRequestInfo and HttpRequestHeaders. +NET_EXPORT_PRIVATE void CreateSpdyHeadersFromHttpRequest( const HttpRequestInfo& info, const HttpRequestHeaders& request_headers, - SpdyHeaderBlock* headers, SpdyMajorVersion protocol_version, - bool direct); + bool direct, + SpdyHeaderBlock* headers); + +// Create a SpdyHeaderBlock from HttpResponseHeaders. +NET_EXPORT_PRIVATE void CreateSpdyHeadersFromHttpResponse( + const HttpResponseHeaders& response_headers, + SpdyMajorVersion protocol_version, + SpdyHeaderBlock* headers); // Returns the URL associated with the |headers| by assembling the // scheme, host and path from the protocol specific keys. diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc index d268a4d..afc1953 100644 --- a/net/spdy/spdy_proxy_client_socket.cc +++ b/net/spdy/spdy_proxy_client_socket.cc @@ -367,8 +367,9 @@ int SpdyProxyClientSocket::DoSendRequest() { request_.extra_headers.MergeFrom(request_headers); scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock()); - CreateSpdyHeadersFromHttpRequest(request_, request_headers, headers.get(), - spdy_stream_->GetProtocolVersion(), true); + CreateSpdyHeadersFromHttpRequest(request_, request_headers, + spdy_stream_->GetProtocolVersion(), true, + headers.get()); // Reset the URL to be the endpoint of the connection if (spdy_stream_->GetProtocolVersion() > 2) { (*headers)[":path"] = endpoint_.ToString(); |