summaryrefslogtreecommitdiffstats
path: root/net/tools/flip_server
diff options
context:
space:
mode:
authoryhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-05 10:58:03 +0000
committeryhirano@chromium.org <yhirano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-05 10:58:03 +0000
commita0ac817e277134e9d442f10370690bb8831e7e51 (patch)
treeeec247eb9272e104e771ea8ebb62a4b246844ae3 /net/tools/flip_server
parentcc6093317d1beb650bbb168c0640c75bfddbbb5d (diff)
downloadchromium_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.h4
-rw-r--r--net/tools/flip_server/sm_connection.cc22
-rw-r--r--net/tools/flip_server/sm_connection.h3
-rw-r--r--net/tools/flip_server/spdy_interface.cc154
-rw-r--r--net/tools/flip_server/spdy_interface.h3
-rw-r--r--net/tools/flip_server/spdy_interface_test.cc219
-rw-r--r--net/tools/flip_server/spdy_ssl.cc9
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
-