summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/BUILD.gn1
-rw-r--r--net/net.gyp1
-rw-r--r--net/quic/quic_http_stream.cc2
-rw-r--r--net/quic/quic_in_memory_cache.cc218
-rw-r--r--net/quic/quic_in_memory_cache.h35
-rw-r--r--net/quic/quic_spdy_server_stream.cc80
-rw-r--r--net/quic/quic_spdy_server_stream.h10
-rw-r--r--net/quic/spdy_utils.cc7
-rw-r--r--net/quic/spdy_utils.h2
-rw-r--r--net/spdy/hpack_huffman_aggregator.cc2
-rw-r--r--net/spdy/spdy_http_stream.cc4
-rw-r--r--net/spdy/spdy_http_utils.cc52
-rw-r--r--net/spdy/spdy_http_utils.h16
-rw-r--r--net/spdy/spdy_proxy_client_socket.cc5
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();