diff options
author | yhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-05 10:58:03 +0000 |
---|---|---|
committer | yhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-05 10:58:03 +0000 |
commit | a0ac817e277134e9d442f10370690bb8831e7e51 (patch) | |
tree | eec247eb9272e104e771ea8ebb62a4b246844ae3 /net/tools/flip_server | |
parent | cc6093317d1beb650bbb168c0640c75bfddbbb5d (diff) | |
download | chromium_src-a0ac817e277134e9d442f10370690bb8831e7e51.zip chromium_src-a0ac817e277134e9d442f10370690bb8831e7e51.tar.gz chromium_src-a0ac817e277134e9d442f10370690bb8831e7e51.tar.bz2 |
Support SPDY3 on Flip Server.
Flip Server now roughly supprots SPDY3 and SPDY4a2.
Some control frames are currently not supported yet.
BUG=267354
R=rch@chromium.org
Review URL: https://codereview.chromium.org/90623002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238930 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/tools/flip_server')
-rw-r--r-- | net/tools/flip_server/constants.h | 4 | ||||
-rw-r--r-- | net/tools/flip_server/sm_connection.cc | 22 | ||||
-rw-r--r-- | net/tools/flip_server/sm_connection.h | 3 | ||||
-rw-r--r-- | net/tools/flip_server/spdy_interface.cc | 154 | ||||
-rw-r--r-- | net/tools/flip_server/spdy_interface.h | 3 | ||||
-rw-r--r-- | net/tools/flip_server/spdy_interface_test.cc | 219 | ||||
-rw-r--r-- | net/tools/flip_server/spdy_ssl.cc | 9 |
7 files changed, 347 insertions, 67 deletions
diff --git a/net/tools/flip_server/constants.h b/net/tools/flip_server/constants.h index 8b770a6..cc07d61 100644 --- a/net/tools/flip_server/constants.h +++ b/net/tools/flip_server/constants.h @@ -18,10 +18,6 @@ const int kSpdySegmentSize = kSSLSegmentSize - kSpdyOverhead; acceptor_->listen_ip_ << ":" \ << acceptor_->listen_port_ << " " -#define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0" - -#define SSL_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH" - #define IPV4_PRINTABLE_FORMAT(IP) (((IP)>>0)&0xff), (((IP)>>8)&0xff), \ (((IP)>>16)&0xff), (((IP)>>24)&0xff) diff --git a/net/tools/flip_server/sm_connection.cc b/net/tools/flip_server/sm_connection.cc index bb15d71..062e44e 100644 --- a/net/tools/flip_server/sm_connection.cc +++ b/net/tools/flip_server/sm_connection.cc @@ -309,7 +309,8 @@ void SMConnection::HandleEvents() { } // Decide if SPDY was negotiated. -bool SMConnection::WasSpdyNegotiated() { +bool SMConnection::WasSpdyNegotiated(SpdyMajorVersion* version_negotiated) { + *version_negotiated = SPDY3; if (force_spdy()) return true; @@ -323,8 +324,20 @@ bool SMConnection::WasSpdyNegotiated() { VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "NPN protocol detected: " << npn_proto_str; if (!strncmp(reinterpret_cast<const char*>(npn_proto), - "spdy/2", npn_proto_len)) + "spdy/2", npn_proto_len)) { + *version_negotiated = SPDY2; return true; + } + if (!strncmp(reinterpret_cast<const char*>(npn_proto), + "spdy/3", npn_proto_len)) { + *version_negotiated = SPDY3; + return true; + } + if (!strncmp(reinterpret_cast<const char*>(npn_proto), + "spdy/4a2", npn_proto_len)) { + *version_negotiated = SPDY4; + return true; + } } } @@ -335,7 +348,8 @@ bool SMConnection::SetupProtocolInterfaces() { DCHECK(!protocol_detected_); protocol_detected_ = true; - bool spdy_negotiated = WasSpdyNegotiated(); + SpdyMajorVersion version; + bool spdy_negotiated = WasSpdyNegotiated(&version); bool using_ssl = ssl_ != NULL; if (using_ssl) @@ -394,7 +408,7 @@ bool SMConnection::SetupProtocolInterfaces() { epoll_server_, memory_cache_, acceptor_, - SPDY2); + version); sm_interface_ = sm_spdy_interface_; } break; diff --git a/net/tools/flip_server/sm_connection.h b/net/tools/flip_server/sm_connection.h index a79dca9..20961cd 100644 --- a/net/tools/flip_server/sm_connection.h +++ b/net/tools/flip_server/sm_connection.h @@ -12,6 +12,7 @@ #include <string> #include "base/compiler_specific.h" +#include "net/spdy/spdy_protocol.h" #include "net/tools/epoll_server/epoll_server.h" #include "net/tools/flip_server/create_listener.h" #include "net/tools/flip_server/mem_cache.h" @@ -99,7 +100,7 @@ class SMConnection : public SMConnectionInterface, private: // Decide if SPDY was negotiated. - bool WasSpdyNegotiated(); + bool WasSpdyNegotiated(SpdyMajorVersion* version_negotiated); // Initialize the protocol interfaces we'll need for this connection. // Returns true if successful, false otherwise. diff --git a/net/tools/flip_server/spdy_interface.cc b/net/tools/flip_server/spdy_interface.cc index e533c48..23646bd 100644 --- a/net/tools/flip_server/spdy_interface.cc +++ b/net/tools/flip_server/spdy_interface.cc @@ -23,7 +23,7 @@ std::string SpdySM::forward_ip_header_; class SpdyFrameDataFrame : public DataFrame { public: explicit SpdyFrameDataFrame(SpdyFrame* spdy_frame) - : frame(spdy_frame) { + : frame(spdy_frame) { data = spdy_frame->data(); size = spdy_frame->size(); } @@ -75,11 +75,11 @@ void SpdySM::InitSMConnection(SMConnectionPoolInterface* connection_pool, SMInterface* SpdySM::NewConnectionInterface() { SMConnection* server_connection = - SMConnection::NewSMConnection(epoll_server_, - NULL, - memory_cache_, - acceptor_, - "http_conn: "); + SMConnection::NewSMConnection(epoll_server_, + NULL, + memory_cache_, + acceptor_, + "http_conn: "); if (server_connection == NULL) { LOG(ERROR) << "SpdySM: Could not create server connection"; return NULL; @@ -137,49 +137,87 @@ int SpdySM::SpdyHandleNewStream( VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: # headers: " << headers.size(); - SpdyHeaderBlock::const_iterator url = headers.find("url"); - SpdyHeaderBlock::const_iterator method = headers.find("method"); - if (url == headers.end() || method == headers.end()) { - VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: didn't find method or url " - << "or method. Not creating stream"; - return 0; + SpdyHeaderBlock supplement; + SpdyHeaderBlock::const_iterator method = headers.end(); + SpdyHeaderBlock::const_iterator host = headers.end(); + SpdyHeaderBlock::const_iterator path = headers.end(); + SpdyHeaderBlock::const_iterator scheme = headers.end(); + SpdyHeaderBlock::const_iterator version = headers.end(); + SpdyHeaderBlock::const_iterator url = headers.end(); + + if (spdy_version() == SPDY2) { + url = headers.find("url"); + method = headers.find("method"); + version = headers.find("version"); + scheme = headers.find("scheme"); + if (url == headers.end() || method == headers.end() || + version == headers.end() || scheme == headers.end()) { + VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: A mandatory header is " + << "missing. Not creating stream"; + return 0; + } + // url->second here only ever seems to contain just the path. When this + // path contains a query string with a http:// in one of its values, + // UrlUtilities::GetUrlPath will fail and always return a / breaking + // the request. GetUrlPath assumes the absolute URL is being passed in. + std::string path_string = UrlUtilities::GetUrlPath(url->second); + std::string host_string = UrlUtilities::GetUrlHost(url->second); + path = supplement.insert(std::make_pair(":path", path_string)).first; + host = supplement.insert(std::make_pair(":host", host_string)).first; + } else { + method = headers.find(":method"); + host = headers.find(":host"); + path = headers.find(":path"); + scheme = headers.find(":scheme"); + version = supplement.insert(std::make_pair(":version", "HTTP/1.1")).first; + if (method == headers.end() || host == headers.end() || + path == headers.end() || scheme == headers.end()) { + VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: A mandatory header is " + << "missing. Not creating stream"; + return 0; + } } - SpdyHeaderBlock::const_iterator scheme = headers.find("scheme"); if (scheme->second.compare("https") == 0) { *is_https_scheme = true; } - // url->second here only ever seems to contain just the path. When this - // path contains a query string with a http:// in one of its values, - // UrlUtilities::GetUrlPath will fail and always return a / breaking - // the request. GetUrlPath assumes the absolute URL is being passed in. - std::string uri; - if (url->second.compare(0, 4, "http") == 0) - uri = UrlUtilities::GetUrlPath(url->second); - else - uri = std::string(url->second); if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) { - std::string host = UrlUtilities::GetUrlHost(url->second); VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second - << " " << uri; - std::string filename = EncodeURL(uri, host, method->second); + << " " << path->second; + std::string filename = EncodeURL(path->second, + host->second, + method->second); NewStream(stream_id, priority, filename); } else { - SpdyHeaderBlock::const_iterator version = headers.find("version"); - http_data += method->second + " " + uri + " " + version->second + "\r\n"; + http_data += + method->second + " " + path->second + " " + version->second + "\r\n"; VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second << " " - << uri << " " << version->second; + << path->second << " " << version->second; + http_data += "Host: " + (*is_https_scheme ? + acceptor_->https_server_ip_ : + acceptor_->http_server_ip_) + "\r\n"; for (SpdyHeaderBlock::const_iterator i = headers.begin(); i != headers.end(); ++i) { - http_data += i->first + ": " + i->second + "\r\n"; - VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":" - << i->second.c_str(); + if ((i->first.size() > 0 && i->first[0] == ':') || + i->first == "host" || + i == method || + i == host || + i == path || + i == scheme || + i == version || + i == url) { + // Ignore the entry. + } else { + http_data += i->first + ": " + i->second + "\r\n"; + VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":" + << i->second.c_str(); + } } if (forward_ip_header_.length()) { // X-Client-Cluster-IP header http_data += forward_ip_header_ + ": " + - connection_->client_ip() + "\r\n"; + connection_->client_ip() + "\r\n"; } http_data += "\r\n"; } @@ -361,7 +399,7 @@ size_t SpdySM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) { } void SpdySM::SendDataFrame(uint32 stream_id, const char* data, int64 len, - uint32 flags, bool compress) { + uint32 flags, bool compress) { SpdyDataFlags spdy_flags = static_cast<SpdyDataFlags>(flags); SendDataFrameImpl(stream_id, data, len, spdy_flags, compress); } @@ -387,7 +425,7 @@ void SpdySM::KillStream(uint32 stream_id) { void SpdySM::CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) { for (BalsaHeaders::const_header_lines_iterator hi = - headers.header_lines_begin(); + headers.header_lines_begin(); hi != headers.header_lines_end(); ++hi) { // It is illegal to send SPDY headers with empty value or header @@ -416,16 +454,34 @@ void SpdySM::CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) { size_t SpdySM::SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) { SpdyHeaderBlock block; - block["method"] = headers.request_method().as_string(); - if (!headers.HasHeader("version")) - block["version"] =headers.request_version().as_string(); - if (headers.HasHeader("X-Original-Url")) { - std::string original_url = headers.GetHeader("X-Original-Url").as_string(); - block["url"] = UrlUtilities::GetUrlPath(original_url); + CopyHeaders(block, headers); + if (spdy_version() == SPDY2) { + block["method"] = headers.request_method().as_string(); + if (!headers.HasHeader("version")) + block["version"] = headers.request_version().as_string(); + if (headers.HasHeader("X-Original-Url")) { + std::string original_url = + headers.GetHeader("X-Original-Url").as_string(); + block["url"] = UrlUtilities::GetUrlPath(original_url); + } else { + block["url"] = headers.request_uri().as_string(); + } } else { - block["url"] = headers.request_uri().as_string(); + block[":method"] = headers.request_method().as_string(); + block[":version"] = headers.request_version().as_string(); + if (headers.HasHeader("X-Original-Url")) { + std::string original_url = + headers.GetHeader("X-Original-Url").as_string(); + block[":path"] = UrlUtilities::GetUrlPath(original_url); + block[":host"] = UrlUtilities::GetUrlPath(original_url); + } else { + block[":path"] = headers.request_uri().as_string(); + if (block.find("host") != block.end()) { + block[":host"] = headers.GetHeader("Host").as_string(); + block.erase("host"); + } + } } - CopyHeaders(block, headers); SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynStream( stream_id, 0, 0, 0, CONTROL_FLAG_NONE, &block); @@ -440,9 +496,15 @@ size_t SpdySM::SendSynStreamImpl(uint32 stream_id, size_t SpdySM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) { SpdyHeaderBlock block; CopyHeaders(block, headers); - block["status"] = headers.response_code().as_string() + " " + - headers.response_reason_phrase().as_string(); - block["version"] = headers.response_version().as_string(); + if (spdy_version() == SPDY2) { + block["status"] = headers.response_code().as_string() + " " + + headers.response_reason_phrase().as_string(); + block["version"] = headers.response_version().as_string(); + } else { + block[":status"] = headers.response_code().as_string() + " " + + headers.response_reason_phrase().as_string(); + block[":version"] = headers.response_version().as_string(); + } SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynReply( stream_id, CONTROL_FLAG_NONE, &block); @@ -455,7 +517,7 @@ size_t SpdySM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) { } void SpdySM::SendDataFrameImpl(uint32 stream_id, const char* data, int64 len, - SpdyDataFlags flags, bool compress) { + SpdyDataFlags flags, bool compress) { // TODO(mbelshe): We can't compress here - before going into the // priority queue. Compression needs to be done // with late binding. diff --git a/net/tools/flip_server/spdy_interface.h b/net/tools/flip_server/spdy_interface.h index b7cc772..6abbdb9 100644 --- a/net/tools/flip_server/spdy_interface.h +++ b/net/tools/flip_server/spdy_interface.h @@ -162,6 +162,9 @@ class SpdySM : public BufferedSpdyFramerVisitorInterface, static void set_forward_ip_header(const std::string& value) { forward_ip_header_ = value; } + SpdyMajorVersion spdy_version() const { + return buffered_spdy_framer_->protocol_version(); + } private: void SendEOFImpl(uint32 stream_id); diff --git a/net/tools/flip_server/spdy_interface_test.cc b/net/tools/flip_server/spdy_interface_test.cc index 660bf6c..bbe7455 100644 --- a/net/tools/flip_server/spdy_interface_test.cc +++ b/net/tools/flip_server/spdy_interface_test.cc @@ -220,21 +220,24 @@ TEST_P(SpdySMProxyTest, InitSMConnection) { false); } -TEST_P(SpdySMProxyTest, OnSynStream) { +TEST_P(SpdySMProxyTest, OnSynStream_SPDY2) { + if (GetParam() != SPDY2) { + // This test case is for SPDY2. + return; + } BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface); uint32 stream_id = 92; uint32 associated_id = 43; std::string expected = "GET /path HTTP/1.0\r\n" - "method: GET\r\n" - "scheme: http\r\n" - "url: http://www.example.com/path\r\n" - "version: HTTP/1.0\r\n\r\n"; + "Host: 127.0.0.1\r\n" + "hoge: fuga\r\n\r\n"; SpdyHeaderBlock block; block["method"] = "GET"; - block["url"] = "http://www.example.com/path"; + block["url"] = "/path"; block["scheme"] = "http"; block["version"] = "HTTP/1.0"; + block["hoge"] = "fuga"; StringSaver saver; { InSequence s; @@ -252,7 +255,46 @@ TEST_P(SpdySMProxyTest, OnSynStream) { ASSERT_EQ(expected, saver.string); } -TEST_P(SpdySMProxyTest, OnStreamFrameData) { +TEST_P(SpdySMProxyTest, OnSynStream) { + if (GetParam() == SPDY2) { + // This test case is not for SPDY2. + return; + } + BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); + scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface); + uint32 stream_id = 92; + uint32 associated_id = 43; + std::string expected = "GET /path HTTP/1.1\r\n" + "Host: 127.0.0.1\r\n" + "foo: bar\r\n\r\n"; + SpdyHeaderBlock block; + block[":method"] = "GET"; + block[":host"] = "www.example.com"; + block[":path"] = "/path"; + block[":scheme"] = "http"; + block["foo"] = "bar"; + StringSaver saver; + { + InSequence s; + EXPECT_CALL(*interface_, + FindOrMakeNewSMConnectionInterface(_, _)) + .WillOnce(Return(mock_interface.get())); + EXPECT_CALL(*mock_interface, SetStreamID(stream_id)); + EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)) + .WillOnce(DoAll(SaveArg<0>(&saver.data), + SaveArg<1>(&saver.size), + InvokeWithoutArgs(&saver, &StringSaver::Save), + Return(0))); + } + visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block); + ASSERT_EQ(expected, saver.string); +} + +TEST_P(SpdySMProxyTest, OnStreamFrameData_SPDY2) { + if (GetParam() != SPDY2) { + // This test case is for SPDY2. + return; + } BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface); uint32 stream_id = 92; @@ -282,6 +324,41 @@ TEST_P(SpdySMProxyTest, OnStreamFrameData) { visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true); } +TEST_P(SpdySMProxyTest, OnStreamFrameData) { + if (GetParam() == SPDY2) { + // This test case is not for SPDY2. + return; + } + BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); + scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface); + uint32 stream_id = 92; + uint32 associated_id = 43; + SpdyHeaderBlock block; + testing::MockFunction<void(int)> checkpoint; // NOLINT + + scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12)); + block[":method"] = "GET"; + block[":host"] = "www.example.com"; + block[":path"] = "/path"; + block[":scheme"] = "http"; + block["foo"] = "bar"; + { + InSequence s; + EXPECT_CALL(*interface_, + FindOrMakeNewSMConnectionInterface(_, _)) + .WillOnce(Return(mock_interface.get())); + EXPECT_CALL(*mock_interface, SetStreamID(stream_id)); + EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1); + EXPECT_CALL(checkpoint, Call(0)); + EXPECT_CALL(*mock_interface, + ProcessWriteInput(frame->data(), frame->size())).Times(1); + } + + visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block); + checkpoint.Call(0); + visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true); +} + TEST_P(SpdySMProxyTest, OnRstStream) { BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); uint32 stream_id = 82; @@ -370,7 +447,11 @@ TEST_P(SpdySMProxyTest, AddToOutputOrder) { ASSERT_TRUE(HasStream(stream_id)); } -TEST_P(SpdySMProxyTest, SendErrorNotFound) { +TEST_P(SpdySMProxyTest, SendErrorNotFound_SPDY2) { + if (GetParam() != SPDY2) { + // This test is for SPDY2. + return; + } uint32 stream_id = 82; SpdyHeaderBlock actual_header_block; const char* actual_data; @@ -409,7 +490,54 @@ TEST_P(SpdySMProxyTest, SendErrorNotFound) { ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size)); } -TEST_P(SpdySMProxyTest, SendSynStream) { +TEST_P(SpdySMProxyTest, SendErrorNotFound) { + if (GetParam() == SPDY2) { + // This test is not for SPDY2. + return; + } + uint32 stream_id = 82; + SpdyHeaderBlock actual_header_block; + const char* actual_data; + size_t actual_size; + testing::MockFunction<void(int)> checkpoint; // NOLINT + + interface_->SendErrorNotFound(stream_id); + + ASSERT_EQ(2u, connection_->output_list()->size()); + + { + InSequence s; + EXPECT_CALL(*spdy_framer_visitor_, + OnSynReply(stream_id, false, _)) + .WillOnce(SaveArg<2>(&actual_header_block)); + EXPECT_CALL(checkpoint, Call(0)); + EXPECT_CALL(*spdy_framer_visitor_, + OnStreamFrameData(stream_id, _, _, false)).Times(1) + .WillOnce(DoAll(SaveArg<1>(&actual_data), + SaveArg<2>(&actual_size))); + EXPECT_CALL(*spdy_framer_visitor_, + OnStreamFrameData(stream_id, NULL, 0, true)).Times(1); + } + + std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); + DataFrame* df = *i++; + spdy_framer_->ProcessInput(df->data, df->size); + checkpoint.Call(0); + df = *i++; + spdy_framer_->ProcessInput(df->data, df->size); + + ASSERT_EQ(2, spdy_framer_->frames_received()); + ASSERT_EQ(2u, actual_header_block.size()); + ASSERT_EQ("404 Not Found", actual_header_block[":status"]); + ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]); + ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size)); +} + +TEST_P(SpdySMProxyTest, SendSynStream_SPDY2) { + if (GetParam() != SPDY2) { + // This test is for SPDY2. + return; + } uint32 stream_id = 82; BalsaHeaders headers; SpdyHeaderBlock actual_header_block; @@ -438,7 +566,46 @@ TEST_P(SpdySMProxyTest, SendSynStream) { ASSERT_EQ("value1", actual_header_block["key1"]); } -TEST_P(SpdySMProxyTest, SendSynReply) { +TEST_P(SpdySMProxyTest, SendSynStream) { + if (GetParam() == SPDY2) { + // This test is not for SPDY2. + return; + } + uint32 stream_id = 82; + BalsaHeaders headers; + SpdyHeaderBlock actual_header_block; + headers.AppendHeader("key1", "value1"); + headers.AppendHeader("Host", "www.example.com"); + headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.1"); + + interface_->SendSynStream(stream_id, headers); + + ASSERT_EQ(1u, connection_->output_list()->size()); + std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); + DataFrame* df = *i++; + + { + InSequence s; + EXPECT_CALL(*spdy_framer_visitor_, + OnSynStream(stream_id, 0, _, _, false, false, _)) + .WillOnce(SaveArg<6>(&actual_header_block)); + } + + spdy_framer_->ProcessInput(df->data, df->size); + ASSERT_EQ(1, spdy_framer_->frames_received()); + ASSERT_EQ(5u, actual_header_block.size()); + ASSERT_EQ("GET", actual_header_block[":method"]); + ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]); + ASSERT_EQ("/path", actual_header_block[":path"]); + ASSERT_EQ("www.example.com", actual_header_block[":host"]); + ASSERT_EQ("value1", actual_header_block["key1"]); +} + +TEST_P(SpdySMProxyTest, SendSynReply_SPDY2) { + if (GetParam() != SPDY2) { + // This test is for SPDY2. + return; + } uint32 stream_id = 82; BalsaHeaders headers; SpdyHeaderBlock actual_header_block; @@ -465,6 +632,37 @@ TEST_P(SpdySMProxyTest, SendSynReply) { ASSERT_EQ("value1", actual_header_block["key1"]); } +TEST_P(SpdySMProxyTest, SendSynReply) { + if (GetParam() == SPDY2) { + // This test is not for SPDY2. + return; + } + uint32 stream_id = 82; + BalsaHeaders headers; + SpdyHeaderBlock actual_header_block; + headers.AppendHeader("key1", "value1"); + headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK"); + + interface_->SendSynReply(stream_id, headers); + + ASSERT_EQ(1u, connection_->output_list()->size()); + std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); + DataFrame* df = *i++; + + { + InSequence s; + EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _)) + .WillOnce(SaveArg<2>(&actual_header_block)); + } + + spdy_framer_->ProcessInput(df->data, df->size); + ASSERT_EQ(1, spdy_framer_->frames_received()); + ASSERT_EQ(3u, actual_header_block.size()); + ASSERT_EQ("200 OK", actual_header_block[":status"]); + ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]); + ASSERT_EQ("value1", actual_header_block["key1"]); +} + TEST_P(SpdySMProxyTest, SendDataFrame) { uint32 stream_id = 133; SpdyDataFlags flags = DATA_FLAG_NONE; @@ -586,6 +784,7 @@ TEST_P(SpdySMServerTest, OnSynStream) { spdy_headers["url"] = "http://www.example.com/path"; spdy_headers["method"] = "GET"; spdy_headers["scheme"] = "http"; + spdy_headers["version"] = "HTTP/1.1"; { BalsaHeaders headers; diff --git a/net/tools/flip_server/spdy_ssl.cc b/net/tools/flip_server/spdy_ssl.cc index 292bbe0..dac3d02 100644 --- a/net/tools/flip_server/spdy_ssl.cc +++ b/net/tools/flip_server/spdy_ssl.cc @@ -10,7 +10,13 @@ namespace net { -#define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0" +// Each element consists of <the length of the string><string> . +#define NEXT_PROTO_STRING \ + "\x08spdy/4a2" \ + "\x06spdy/3" \ + "\x06spdy/2" \ + "\x08http/1.1" \ + "\x08http/1.0" #define SSL_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH" int ssl_set_npn_callback(SSL *s, @@ -107,4 +113,3 @@ void PrintSslError() { } } // namespace net - |