summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/net.gyp2
-rw-r--r--net/websockets/websocket_handshake_handler.cc64
-rw-r--r--net/websockets/websocket_handshake_handler.h6
-rw-r--r--net/websockets/websocket_handshake_handler_spdy2_unittest.cc182
-rw-r--r--net/websockets/websocket_handshake_handler_spdy3_unittest.cc189
-rw-r--r--net/websockets/websocket_handshake_handler_unittest.cc147
-rw-r--r--net/websockets/websocket_job.cc8
-rw-r--r--net/websockets/websocket_job.h1
-rw-r--r--net/websockets/websocket_job_spdy3_unittest.cc16
9 files changed, 445 insertions, 170 deletions
diff --git a/net/net.gyp b/net/net.gyp
index 6ed9798..e412ac6 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -1352,6 +1352,8 @@
'websockets/websocket_frame_parser_unittest.cc',
'websockets/websocket_frame_unittest.cc',
'websockets/websocket_handshake_handler_unittest.cc',
+ 'websockets/websocket_handshake_handler_spdy2_unittest.cc',
+ 'websockets/websocket_handshake_handler_spdy3_unittest.cc',
'websockets/websocket_job_spdy2_unittest.cc',
'websockets/websocket_job_spdy3_unittest.cc',
'websockets/websocket_net_log_params_unittest.cc',
diff --git a/net/websockets/websocket_handshake_handler.cc b/net/websockets/websocket_handshake_handler.cc
index 507b53a..991ea31 100644
--- a/net/websockets/websocket_handshake_handler.cc
+++ b/net/websockets/websocket_handshake_handler.cc
@@ -266,13 +266,23 @@ HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo(
}
bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock(
- const GURL& url, SpdyHeaderBlock* headers, std::string* challenge) {
+ const GURL& url,
+ SpdyHeaderBlock* headers,
+ std::string* challenge,
+ int spdy_protocol_version) {
// Construct opening handshake request headers as a SPDY header block.
// For details, see WebSocket Layering over SPDY/3 Draft 8.
- (*headers)["path"] = url.path();
- (*headers)["version"] =
+ if (spdy_protocol_version <= 2) {
+ (*headers)["path"] = url.path();
+ (*headers)["version"] =
base::StringPrintf("%s%d", "WebSocket/", protocol_version_);
- (*headers)["scheme"] = url.scheme();
+ (*headers)["scheme"] = url.scheme();
+ } else {
+ (*headers)[":path"] = url.path();
+ (*headers)[":version"] =
+ base::StringPrintf("%s%d", "WebSocket/", protocol_version_);
+ (*headers)[":scheme"] = url.scheme();
+ }
HttpUtil::HeadersIterator iter(headers_.begin(), headers_.end(), "\r\n");
while (iter.GetNext()) {
@@ -291,10 +301,29 @@ bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock(
*challenge = iter.values();
// Sec-WebSocket-Key is not sent to a server.
continue;
+ } else if (LowerCaseEqualsASCII(iter.name_begin(),
+ iter.name_end(),
+ "host") ||
+ LowerCaseEqualsASCII(iter.name_begin(),
+ iter.name_end(),
+ "origin") ||
+ LowerCaseEqualsASCII(iter.name_begin(),
+ iter.name_end(),
+ "sec-websocket-protocol") ||
+ LowerCaseEqualsASCII(iter.name_begin(),
+ iter.name_end(),
+ "sec-websocket-extensions")) {
+ // TODO(toyoshim): Some WebSocket extensions may not be compatible with
+ // SPDY. We should omit them from a Sec-WebSocket-Extension header.
+ std::string name;
+ if (spdy_protocol_version <= 2)
+ name = StringToLowerASCII(iter.name());
+ else
+ name = ":" + StringToLowerASCII(iter.name());
+ (*headers)[name] = iter.values();
+ continue;
}
// Others should be sent out to |headers|.
- // TODO(toyoshim): Some WebSocket extensions are not compatible with SPDY.
- // We should remove them from a Sec-WebSocket-Extension header.
std::string name = StringToLowerASCII(iter.name());
SpdyHeaderBlock::iterator found = headers->find(name);
if (found == headers->end()) {
@@ -427,11 +456,16 @@ bool WebSocketHandshakeResponseHandler::ParseResponseInfo(
bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock(
const SpdyHeaderBlock& headers,
- const std::string& challenge) {
- std::string response_message;
- SpdyHeaderBlock::const_iterator status = headers.find("status");
+ const std::string& challenge,
+ int spdy_protocol_version) {
+ SpdyHeaderBlock::const_iterator status;
+ if (spdy_protocol_version <= 2)
+ status = headers.find("status");
+ else
+ status = headers.find(":status");
if (status == headers.end())
return false;
+ std::string response_message;
response_message =
base::StringPrintf("%s%s\r\n", "HTTP/1.1 ", status->second.c_str());
response_message += "Upgrade: websocket\r\n";
@@ -449,7 +483,10 @@ bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock(
// For each value, if the server sends a NUL-separated list of values,
// we separate that back out into individual headers for each value
// in the list.
- if (LowerCaseEqualsASCII(iter->first, "status")) {
+ if ((spdy_protocol_version <= 2 &&
+ LowerCaseEqualsASCII(iter->first, "status")) ||
+ (spdy_protocol_version >= 3 &&
+ LowerCaseEqualsASCII(iter->first, ":status"))) {
// The status value is already handled as the first line of
// |response_message|. Just skip here.
continue;
@@ -464,7 +501,12 @@ bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock(
tval = value.substr(start, (end - start));
else
tval = value.substr(start);
- response_message += iter->first + ": " + tval + "\r\n";
+ if (spdy_protocol_version >= 3 &&
+ (LowerCaseEqualsASCII(iter->first, ":sec-websocket-protocol") ||
+ LowerCaseEqualsASCII(iter->first, ":sec-websocket-extensions")))
+ response_message += iter->first.substr(1) + ": " + tval + "\r\n";
+ else
+ response_message += iter->first + ": " + tval + "\r\n";
start = end + 1;
} while (end != std::string::npos);
}
diff --git a/net/websockets/websocket_handshake_handler.h b/net/websockets/websocket_handshake_handler.h
index 2093adb..9ac142b 100644
--- a/net/websockets/websocket_handshake_handler.h
+++ b/net/websockets/websocket_handshake_handler.h
@@ -68,7 +68,8 @@ class NET_EXPORT_PRIVATE WebSocketHandshakeRequestHandler {
// Also, fills challenge data in |challenge|.
bool GetRequestHeaderBlock(const GURL& url,
SpdyHeaderBlock* headers,
- std::string* challenge);
+ std::string* challenge,
+ int spdy_protocol_version);
// Gets WebSocket handshake raw request message to open WebSocket
// connection.
std::string GetRawRequest();
@@ -117,7 +118,8 @@ class NET_EXPORT_PRIVATE WebSocketHandshakeResponseHandler {
const std::string& challenge);
// Parses WebSocket handshake response as SpdyHeaderBlock.
bool ParseResponseHeaderBlock(const SpdyHeaderBlock& headers,
- const std::string& challenge);
+ const std::string& challenge,
+ int spdy_protocol_version);
// Gets the headers value.
void GetHeaders(const char* const headers_to_get[],
diff --git a/net/websockets/websocket_handshake_handler_spdy2_unittest.cc b/net/websockets/websocket_handshake_handler_spdy2_unittest.cc
new file mode 100644
index 0000000..975b366
--- /dev/null
+++ b/net/websockets/websocket_handshake_handler_spdy2_unittest.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_handshake_handler.h"
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/string_util.h"
+#include "googleurl/src/gurl.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace net {
+
+namespace {
+
+TEST(WebSocketHandshakeHandlerSpdy2Test, RequestResponse) {
+ WebSocketHandshakeRequestHandler request_handler;
+
+ static const char kHandshakeRequestMessage[] =
+ "GET /demo HTTP/1.1\r\n"
+ "Host: example.com\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
+ "Origin: http://example.com\r\n"
+ "Sec-WebSocket-Protocol: sample\r\n"
+ "Sec-WebSocket-Extensions: foo\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "\r\n";
+
+ EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
+ strlen(kHandshakeRequestMessage)));
+ EXPECT_EQ(13, request_handler.protocol_version());
+
+ GURL url("ws://example.com/demo");
+ std::string challenge;
+ SpdyHeaderBlock headers;
+ ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url,
+ &headers,
+ &challenge,
+ 2));
+
+ EXPECT_EQ(url.path(), headers["path"]);
+ EXPECT_TRUE(headers.find("upgrade") == headers.end());
+ EXPECT_TRUE(headers.find("Upgrade") == headers.end());
+ EXPECT_TRUE(headers.find("connection") == headers.end());
+ EXPECT_TRUE(headers.find("Connection") == headers.end());
+ EXPECT_TRUE(headers.find("Sec-WebSocket-Key") == headers.end());
+ EXPECT_TRUE(headers.find("sec-websocket-key") == headers.end());
+ EXPECT_TRUE(headers.find("Sec-WebSocket-Version") == headers.end());
+ EXPECT_TRUE(headers.find("sec-webSocket-version") == headers.end());
+ EXPECT_EQ("example.com", headers["host"]);
+ EXPECT_EQ("http://example.com", headers["origin"]);
+ EXPECT_EQ("sample", headers["sec-websocket-protocol"]);
+ EXPECT_EQ("foo", headers["sec-websocket-extensions"]);
+ EXPECT_EQ("ws", headers["scheme"]);
+ EXPECT_EQ("WebSocket/13", headers["version"]);
+
+ static const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
+
+ EXPECT_EQ(expected_challenge, challenge);
+
+ headers.clear();
+
+ headers["status"] = "101 Switching Protocols";
+ headers["sec-websocket-protocol"] = "sample";
+ headers["sec-websocket-extensions"] = "foo";
+
+ WebSocketHandshakeResponseHandler response_handler;
+ response_handler.set_protocol_version(13);
+ EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(headers,
+ challenge,
+ 2));
+ EXPECT_TRUE(response_handler.HasResponse());
+
+ // Note that order of sec-websocket-* is sensitive with hash_map order.
+ static const char kHandshakeResponseExpectedMessage[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "sec-websocket-extensions: foo\r\n"
+ "sec-websocket-protocol: sample\r\n"
+ "\r\n";
+
+ EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
+}
+
+TEST(WebSocketHandshakeHandlerSpdy2Test, RequestResponseWithCookies) {
+ WebSocketHandshakeRequestHandler request_handler;
+
+ // Note that websocket won't use multiple headers in request now.
+ static const char kHandshakeRequestMessage[] =
+ "GET /demo HTTP/1.1\r\n"
+ "Host: example.com\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
+ "Origin: http://example.com\r\n"
+ "Sec-WebSocket-Protocol: sample\r\n"
+ "Sec-WebSocket-Extensions: foo\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
+ "\r\n";
+
+ EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
+ strlen(kHandshakeRequestMessage)));
+ EXPECT_EQ(13, request_handler.protocol_version());
+
+ GURL url("ws://example.com/demo");
+ std::string challenge;
+ SpdyHeaderBlock headers;
+ ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url,
+ &headers,
+ &challenge,
+ 2));
+
+ EXPECT_EQ(url.path(), headers["path"]);
+ EXPECT_TRUE(headers.find("upgrade") == headers.end());
+ EXPECT_TRUE(headers.find("Upgrade") == headers.end());
+ EXPECT_TRUE(headers.find("connection") == headers.end());
+ EXPECT_TRUE(headers.find("Connection") == headers.end());
+ EXPECT_TRUE(headers.find("Sec-WebSocket-Key") == headers.end());
+ EXPECT_TRUE(headers.find("sec-websocket-key") == headers.end());
+ EXPECT_TRUE(headers.find("Sec-WebSocket-Version") == headers.end());
+ EXPECT_TRUE(headers.find("sec-webSocket-version") == headers.end());
+ EXPECT_EQ("example.com", headers["host"]);
+ EXPECT_EQ("http://example.com", headers["origin"]);
+ EXPECT_EQ("sample", headers["sec-websocket-protocol"]);
+ EXPECT_EQ("foo", headers["sec-websocket-extensions"]);
+ EXPECT_EQ("ws", headers["scheme"]);
+ EXPECT_EQ("WebSocket/13", headers["version"]);
+ EXPECT_EQ("WK-websocket-test=1; WK-websocket-test-httponly=1",
+ headers["cookie"]);
+
+ const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
+
+ EXPECT_EQ(expected_challenge, challenge);
+
+ headers.clear();
+
+ headers["status"] = "101 Switching Protocols";
+ headers["sec-websocket-protocol"] = "sample";
+ headers["sec-websocket-extensions"] = "foo";
+ std::string cookie = "WK-websocket-test=1";
+ cookie.append(1, '\0');
+ cookie += "WK-websocket-test-httponly=1; HttpOnly";
+ headers["set-cookie"] = cookie;
+
+
+ WebSocketHandshakeResponseHandler response_handler;
+ response_handler.set_protocol_version(13);
+ EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(headers,
+ challenge,
+ 2));
+ EXPECT_TRUE(response_handler.HasResponse());
+
+ // Note that order of sec-websocket-* is sensitive with hash_map order.
+ static const char kHandshakeResponseExpectedMessage[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "sec-websocket-extensions: foo\r\n"
+ "sec-websocket-protocol: sample\r\n"
+ "set-cookie: WK-websocket-test=1\r\n"
+ "set-cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
+ "\r\n";
+
+ EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/websockets/websocket_handshake_handler_spdy3_unittest.cc b/net/websockets/websocket_handshake_handler_spdy3_unittest.cc
new file mode 100644
index 0000000..3baa12b
--- /dev/null
+++ b/net/websockets/websocket_handshake_handler_spdy3_unittest.cc
@@ -0,0 +1,189 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/websockets/websocket_handshake_handler.h"
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/string_util.h"
+#include "googleurl/src/gurl.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace net {
+
+namespace {
+
+TEST(WebSocketHandshakeHandlerSpdy3Test, RequestResponse) {
+ WebSocketHandshakeRequestHandler request_handler;
+
+ static const char kHandshakeRequestMessage[] =
+ "GET /demo HTTP/1.1\r\n"
+ "Host: example.com\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
+ "Origin: http://example.com\r\n"
+ "Sec-WebSocket-Protocol: sample\r\n"
+ "Sec-WebSocket-Extensions: foo\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "X-Foo: foo\r\n"
+ "\r\n";
+
+ EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
+ strlen(kHandshakeRequestMessage)));
+ EXPECT_EQ(13, request_handler.protocol_version());
+
+ GURL url("ws://example.com/demo");
+ std::string challenge;
+ SpdyHeaderBlock headers;
+ ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url,
+ &headers,
+ &challenge,
+ 3));
+
+ EXPECT_EQ(url.path(), headers[":path"]);
+ EXPECT_TRUE(headers.find(":upgrade") == headers.end());
+ EXPECT_TRUE(headers.find(":Upgrade") == headers.end());
+ EXPECT_TRUE(headers.find(":connection") == headers.end());
+ EXPECT_TRUE(headers.find(":Connection") == headers.end());
+ EXPECT_TRUE(headers.find(":Sec-WebSocket-Key") == headers.end());
+ EXPECT_TRUE(headers.find(":sec-websocket-key") == headers.end());
+ EXPECT_TRUE(headers.find(":Sec-WebSocket-Version") == headers.end());
+ EXPECT_TRUE(headers.find(":sec-webSocket-version") == headers.end());
+ EXPECT_TRUE(headers.find(":x-foo") == headers.end());
+ EXPECT_EQ("example.com", headers[":host"]);
+ EXPECT_EQ("http://example.com", headers[":origin"]);
+ EXPECT_EQ("sample", headers[":sec-websocket-protocol"]);
+ EXPECT_EQ("foo", headers[":sec-websocket-extensions"]);
+ EXPECT_EQ("ws", headers[":scheme"]);
+ EXPECT_EQ("WebSocket/13", headers[":version"]);
+ EXPECT_EQ("foo", headers["x-foo"]);
+
+ static const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
+
+ EXPECT_EQ(expected_challenge, challenge);
+
+ headers.clear();
+
+ headers[":status"] = "101 Switching Protocols";
+ headers[":sec-websocket-protocol"] = "sample";
+ headers[":sec-websocket-extensions"] = "foo";
+ headers["x-bar"] = "bar";
+
+ WebSocketHandshakeResponseHandler response_handler;
+ response_handler.set_protocol_version(13);
+ EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(headers,
+ challenge,
+ 3));
+ EXPECT_TRUE(response_handler.HasResponse());
+
+ // Note that order of sec-websocket-* is sensitive with hash_map order.
+ static const char kHandshakeResponseExpectedMessage[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "sec-websocket-extensions: foo\r\n"
+ "sec-websocket-protocol: sample\r\n"
+ "x-bar: bar\r\n"
+ "\r\n";
+
+ EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
+}
+
+TEST(WebSocketHandshakeHandlerSpdy3Test, RequestResponseWithCookies) {
+ WebSocketHandshakeRequestHandler request_handler;
+
+ // Note that websocket won't use multiple headers in request now.
+ static const char kHandshakeRequestMessage[] =
+ "GET /demo HTTP/1.1\r\n"
+ "Host: example.com\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
+ "Origin: http://example.com\r\n"
+ "Sec-WebSocket-Protocol: sample\r\n"
+ "Sec-WebSocket-Extensions: foo\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
+ "\r\n";
+
+ EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
+ strlen(kHandshakeRequestMessage)));
+ EXPECT_EQ(13, request_handler.protocol_version());
+
+ GURL url("ws://example.com/demo");
+ std::string challenge;
+ SpdyHeaderBlock headers;
+ ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url,
+ &headers,
+ &challenge,
+ 3));
+
+ EXPECT_EQ(url.path(), headers[":path"]);
+ EXPECT_TRUE(headers.find(":upgrade") == headers.end());
+ EXPECT_TRUE(headers.find(":Upgrade") == headers.end());
+ EXPECT_TRUE(headers.find(":connection") == headers.end());
+ EXPECT_TRUE(headers.find(":Connection") == headers.end());
+ EXPECT_TRUE(headers.find(":Sec-WebSocket-Key") == headers.end());
+ EXPECT_TRUE(headers.find(":sec-websocket-key") == headers.end());
+ EXPECT_TRUE(headers.find(":Sec-WebSocket-Version") == headers.end());
+ EXPECT_TRUE(headers.find(":sec-webSocket-version") == headers.end());
+ EXPECT_TRUE(headers.find(":Cookie") == headers.end());
+ EXPECT_TRUE(headers.find(":cookie") == headers.end());
+ EXPECT_EQ("example.com", headers[":host"]);
+ EXPECT_EQ("http://example.com", headers[":origin"]);
+ EXPECT_EQ("sample", headers[":sec-websocket-protocol"]);
+ EXPECT_EQ("foo", headers[":sec-websocket-extensions"]);
+ EXPECT_EQ("ws", headers[":scheme"]);
+ EXPECT_EQ("WebSocket/13", headers[":version"]);
+ EXPECT_EQ("WK-websocket-test=1; WK-websocket-test-httponly=1",
+ headers["cookie"]);
+
+ const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
+
+ EXPECT_EQ(expected_challenge, challenge);
+
+ headers.clear();
+
+ headers[":status"] = "101 Switching Protocols";
+ headers[":sec-websocket-protocol"] = "sample";
+ headers[":sec-websocket-extensions"] = "foo";
+ std::string cookie = "WK-websocket-test=1";
+ cookie.append(1, '\0');
+ cookie += "WK-websocket-test-httponly=1; HttpOnly";
+ headers["set-cookie"] = cookie;
+
+
+ WebSocketHandshakeResponseHandler response_handler;
+ response_handler.set_protocol_version(13);
+ EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(headers,
+ challenge,
+ 3));
+ EXPECT_TRUE(response_handler.HasResponse());
+
+ // Note that order of sec-websocket-* is sensitive with hash_map order.
+ static const char kHandshakeResponseExpectedMessage[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "sec-websocket-extensions: foo\r\n"
+ "sec-websocket-protocol: sample\r\n"
+ "set-cookie: WK-websocket-test=1\r\n"
+ "set-cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
+ "\r\n";
+
+ EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/websockets/websocket_handshake_handler_unittest.cc b/net/websockets/websocket_handshake_handler_unittest.cc
index 4888401..80a0d76 100644
--- a/net/websockets/websocket_handshake_handler_unittest.cc
+++ b/net/websockets/websocket_handshake_handler_unittest.cc
@@ -466,151 +466,4 @@ TEST(WebSocketHandshakeHandlerTest, HttpRequestResponseHybi06Handshake) {
EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
}
-TEST(WebSocketHandshakeHandlerTest, SpdyRequestResponse) {
- WebSocketHandshakeRequestHandler request_handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Extensions: foo\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "\r\n";
-
- EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(13, request_handler.protocol_version());
-
- GURL url("ws://example.com/demo");
- std::string challenge;
- SpdyHeaderBlock headers;
- ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url, &headers, &challenge));
-
- EXPECT_EQ(url.path(), headers["path"]);
- EXPECT_TRUE(headers.find("upgrade") == headers.end());
- EXPECT_TRUE(headers.find("Upgrade") == headers.end());
- EXPECT_TRUE(headers.find("connection") == headers.end());
- EXPECT_TRUE(headers.find("Connection") == headers.end());
- EXPECT_TRUE(headers.find("Sec-WebSocket-Key") == headers.end());
- EXPECT_TRUE(headers.find("sec-websocket-key") == headers.end());
- EXPECT_TRUE(headers.find("Sec-WebSocket-Version") == headers.end());
- EXPECT_TRUE(headers.find("sec-webSocket-version") == headers.end());
- EXPECT_EQ("example.com", headers["host"]);
- EXPECT_EQ("http://example.com", headers["origin"]);
- EXPECT_EQ("sample", headers["sec-websocket-protocol"]);
- EXPECT_EQ("foo", headers["sec-websocket-extensions"]);
- EXPECT_EQ("ws", headers["scheme"]);
- EXPECT_EQ("WebSocket/13", headers["version"]);
-
- const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
-
- EXPECT_EQ(expected_challenge, challenge);
-
- headers.clear();
-
- headers["status"] = "101 Switching Protocols";
- headers["sec-websocket-protocol"] = "sample";
- headers["sec-websocket-extensions"] = "foo";
-
- WebSocketHandshakeResponseHandler response_handler;
- response_handler.set_protocol_version(13);
- EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(headers, challenge));
- EXPECT_TRUE(response_handler.HasResponse());
-
- // Note that order of sec-websocket-* is sensitive with hash_map order.
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "sec-websocket-extensions: foo\r\n"
- "sec-websocket-protocol: sample\r\n"
- "\r\n";
-
- EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeHandlerTest, SpdyRequestResponseWithCookies) {
- WebSocketHandshakeRequestHandler request_handler;
-
- // Note that websocket won't use multiple headers in request now.
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
- "Origin: http://example.com\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Extensions: foo\r\n"
- "Sec-WebSocket-Version: 13\r\n"
- "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
- "\r\n";
-
- EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(13, request_handler.protocol_version());
-
- GURL url("ws://example.com/demo");
- std::string challenge;
- SpdyHeaderBlock headers;
- ASSERT_TRUE(request_handler.GetRequestHeaderBlock(url, &headers, &challenge));
-
- EXPECT_EQ(url.path(), headers["path"]);
- EXPECT_TRUE(headers.find("upgrade") == headers.end());
- EXPECT_TRUE(headers.find("Upgrade") == headers.end());
- EXPECT_TRUE(headers.find("connection") == headers.end());
- EXPECT_TRUE(headers.find("Connection") == headers.end());
- EXPECT_TRUE(headers.find("Sec-WebSocket-Key") == headers.end());
- EXPECT_TRUE(headers.find("sec-websocket-key") == headers.end());
- EXPECT_TRUE(headers.find("Sec-WebSocket-Version") == headers.end());
- EXPECT_TRUE(headers.find("sec-webSocket-version") == headers.end());
- EXPECT_EQ("example.com", headers["host"]);
- EXPECT_EQ("http://example.com", headers["origin"]);
- EXPECT_EQ("sample", headers["sec-websocket-protocol"]);
- EXPECT_EQ("foo", headers["sec-websocket-extensions"]);
- EXPECT_EQ("ws", headers["scheme"]);
- EXPECT_EQ("WebSocket/13", headers["version"]);
- EXPECT_EQ("WK-websocket-test=1; WK-websocket-test-httponly=1",
- headers["cookie"]);
-
- const char expected_challenge[] = "dGhlIHNhbXBsZSBub25jZQ==";
-
- EXPECT_EQ(expected_challenge, challenge);
-
- headers.clear();
-
- headers["status"] = "101 Switching Protocols";
- headers["sec-websocket-protocol"] = "sample";
- headers["sec-websocket-extensions"] = "foo";
- std::string cookie = "WK-websocket-test=1";
- cookie.append(1, '\0');
- cookie += "WK-websocket-test-httponly=1; HttpOnly";
- headers["set-cookie"] = cookie;
-
-
- WebSocketHandshakeResponseHandler response_handler;
- response_handler.set_protocol_version(13);
- EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(headers, challenge));
- EXPECT_TRUE(response_handler.HasResponse());
-
- // Note that order of sec-websocket-* is sensitive with hash_map order.
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 Switching Protocols\r\n"
- "Upgrade: websocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
- "sec-websocket-extensions: foo\r\n"
- "sec-websocket-protocol: sample\r\n"
- "set-cookie: WK-websocket-test=1\r\n"
- "set-cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
- "\r\n";
-
- EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
-}
-
} // namespace net
diff --git a/net/websockets/websocket_job.cc b/net/websockets/websocket_job.cc
index 56faefb..ff60ebe 100644
--- a/net/websockets/websocket_job.cc
+++ b/net/websockets/websocket_job.cc
@@ -80,6 +80,7 @@ WebSocketJob::WebSocketJob(SocketStream::Delegate* delegate)
started_to_send_handshake_request_(false),
handshake_request_sent_(0),
response_cookies_save_index_(0),
+ spdy_protocol_version_(0),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_for_send_pending_(this)) {
}
@@ -312,7 +313,9 @@ int WebSocketJob::OnReceivedSpdyResponseHeader(
if (status != OK)
return status;
// TODO(toyoshim): Fallback to non-spdy connection?
- handshake_response_->ParseResponseHeaderBlock(headers, challenge_);
+ handshake_response_->ParseResponseHeaderBlock(headers,
+ challenge_,
+ spdy_protocol_version_);
SaveCookiesAndNotifyHeaderComplete();
return OK;
@@ -389,7 +392,7 @@ void WebSocketJob::DoSendData() {
if (spdy_websocket_stream_.get()) {
scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
handshake_request_->GetRequestHeaderBlock(
- socket_->url(), headers.get(), &challenge_);
+ socket_->url(), headers.get(), &challenge_, spdy_protocol_version_);
spdy_websocket_stream_->SendRequest(headers.Pass());
} else {
const std::string& handshake_request =
@@ -567,6 +570,7 @@ int WebSocketJob::TrySpdyStream() {
return OK;
// Create SpdyWebSocketStream.
+ spdy_protocol_version_ = spdy_session->GetProtocolVersion();
spdy_websocket_stream_.reset(new SpdyWebSocketStream(spdy_session, this));
int result = spdy_websocket_stream_->InitializeStream(
diff --git a/net/websockets/websocket_job.h b/net/websockets/websocket_job.h
index 7e20441..614a8e4 100644
--- a/net/websockets/websocket_job.h
+++ b/net/websockets/websocket_job.h
@@ -138,6 +138,7 @@ class NET_EXPORT WebSocketJob
scoped_refptr<DrainableIOBuffer> current_send_buffer_;
std::vector<char> received_data_after_handshake_;
+ int spdy_protocol_version_;
scoped_ptr<SpdyWebSocketStream> spdy_websocket_stream_;
std::string challenge_;
diff --git a/net/websockets/websocket_job_spdy3_unittest.cc b/net/websockets/websocket_job_spdy3_unittest.cc
index a05c094..b758252 100644
--- a/net/websockets/websocket_job_spdy3_unittest.cc
+++ b/net/websockets/websocket_job_spdy3_unittest.cc
@@ -544,17 +544,17 @@ const char WebSocketJobSpdy3Test::kDataHello[] = "Hello, ";
const char WebSocketJobSpdy3Test::kDataWorld[] = "World!\n";
const char* const WebSocketJobSpdy3Test::kHandshakeRequestForSpdy[] = {
- "path", "/demo",
- "version", "WebSocket/13",
- "scheme", "ws",
- "host", "example.com",
- "origin", "http://example.com",
- "sec-websocket-protocol", "sample"
+ ":path", "/demo",
+ ":version", "WebSocket/13",
+ ":scheme", "ws",
+ ":host", "example.com",
+ ":origin", "http://example.com",
+ ":sec-websocket-protocol", "sample"
};
const char* const WebSocketJobSpdy3Test::kHandshakeResponseForSpdy[] = {
- "status", "101 Switching Protocols",
- "sec-websocket-protocol", "sample"
+ ":status", "101 Switching Protocols",
+ ":sec-websocket-protocol", "sample"
};
const size_t WebSocketJobSpdy3Test::kHandshakeRequestWithoutCookieLength =