1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_handshake.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gmock/include/gmock/gmock.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "testing/gtest/include/gtest/gtest.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/platform_test.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebSocketHandshakeTest : public testing::Test { 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void SetUpParameter(WebSocketHandshake* handshake, 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint32 number_1, uint32 number_2, 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key_1, const std::string& key_2, 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key_3) { 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebSocketHandshake::Parameter* parameter = 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake::Parameter; 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parameter->number_1_ = number_1; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parameter->number_2_ = number_2; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parameter->key_1_ = key_1; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parameter->key_2_ = key_2; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parameter->key_3_ = key_3; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake->parameter_.reset(parameter); 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void ExpectHeaderEquals(const std::string& expected, 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& actual) { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> expected_lines; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Tokenize(expected, "\r\n", &expected_lines); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> actual_lines; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Tokenize(actual, "\r\n", &actual_lines); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Request lines. 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(expected_lines[0], actual_lines[0]); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> expected_headers; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 1; i < expected_lines.size(); i++) { 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Finish at first CRLF CRLF. Note that /key_3/ might include CRLF. 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (expected_lines[i] == "") 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expected_headers.push_back(expected_lines[i]); 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sort(expected_headers.begin(), expected_headers.end()); 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> actual_headers; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 1; i < actual_lines.size(); i++) { 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Finish at first CRLF CRLF. Note that /key_3/ might include CRLF. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (actual_lines[i] == "") 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch actual_headers.push_back(actual_lines[i]); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sort(actual_headers.begin(), actual_headers.end()); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(expected_headers.size(), actual_headers.size()) 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "expected:" << expected 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "\nactual:" << actual; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < expected_headers.size(); i++) { 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(expected_headers[i], actual_headers[i]); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void ExpectHandshakeMessageEquals(const std::string& expected, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& actual) { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Headers. 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpectHeaderEquals(expected, actual); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compare tailing \r\n\r\n<key3> (4 + 8 bytes). 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_GT(expected.size(), 12U); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* expected_key3 = expected.data() + expected.size() - 12; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_GT(actual.size(), 12U); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (actual.size() <= 12U) 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* actual_key3 = actual.data() + actual.size() - 12; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(memcmp(expected_key3, actual_key3, 12) == 0) 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "expected_key3:" << DumpKey(expected_key3, 12) 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << ", actual_key3:" << DumpKey(actual_key3, 12); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::string DumpKey(const char* buf, int len) { 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string s; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < len; i++) { 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (isprint(buf[i])) 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick s += base::StringPrintf("%c", buf[i]); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick s += base::StringPrintf("\\x%02x", buf[i]); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return s; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::string GetResourceName(WebSocketHandshake* handshake) { 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return handshake->GetResourceName(); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::string GetHostFieldValue(WebSocketHandshake* handshake) { 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return handshake->GetHostFieldValue(); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::string GetOriginFieldValue(WebSocketHandshake* handshake) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return handshake->GetOriginFieldValue(); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, Connect) { 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string kExpectedClientHandshakeMessage = 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "GET /demo HTTP/1.1\r\n" 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Upgrade: WebSocket\r\n" 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Connection: Upgrade\r\n" 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Host: example.com\r\n" 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Origin: http://example.com\r\n" 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Protocol: sample\r\n" 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Key1: 388P O503D&ul7 {K%gX( %7 15\r\n" 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Key2: 1 N ?|k UT0or 3o 4 I97N 5-S3O 31\r\n" 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\r\n" 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\x47\x30\x22\x2D\x5A\x3F\x47\x58"; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://example.com/demo"), 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ws://example.com/demo", 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetUpParameter(handshake.get(), 777007543U, 114997259U, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "388P O503D&ul7 {K%gX( %7 15", 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "1 N ?|k UT0or 3o 4 I97N 5-S3O 31", 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string("\x47\x30\x22\x2D\x5A\x3F\x47\x58", 8)); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpectHandshakeMessageEquals( 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kExpectedClientHandshakeMessage, 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake->CreateClientHandshakeMessage()); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kResponse[] = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Upgrade: WebSocket\r\n" 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Connection: Upgrade\r\n" 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Origin: http://example.com\r\n" 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Location: ws://example.com/demo\r\n" 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Protocol: sample\r\n" 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\r\n" 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\x30\x73\x74\x33\x52\x6C\x26\x71\x2D\x32\x5A\x55\x5E\x77\x65\x75"; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> response_lines; 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::SplitStringDontTrim(kResponse, '\n', &response_lines); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // too short 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(-1, handshake->ReadServerHandshake(kResponse, 16)); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // only status line 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string response = response_lines[0]; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(-1, handshake->ReadServerHandshake( 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response.data(), response.size())); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // by upgrade header 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response += response_lines[1]; 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(-1, handshake->ReadServerHandshake( 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response.data(), response.size())); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // by connection header 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response += response_lines[2]; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(-1, handshake->ReadServerHandshake( 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response.data(), response.size())); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response += response_lines[3]; // Sec-WebSocket-Origin 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response += response_lines[4]; // Sec-WebSocket-Location 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response += response_lines[5]; // Sec-WebSocket-Protocol 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(-1, handshake->ReadServerHandshake( 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response.data(), response.size())); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response += response_lines[6]; // \r\n 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(-1, handshake->ReadServerHandshake( 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response.data(), response.size())); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int handshake_length = sizeof(kResponse) - 1; // -1 for terminating \0 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(handshake_length, handshake->ReadServerHandshake( 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kResponse, handshake_length)); // -1 for terminating \0 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_CONNECTED, handshake->mode()); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, ServerSentData) { 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string kExpectedClientHandshakeMessage = 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "GET /demo HTTP/1.1\r\n" 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Upgrade: WebSocket\r\n" 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Connection: Upgrade\r\n" 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Host: example.com\r\n" 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Origin: http://example.com\r\n" 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Protocol: sample\r\n" 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Key1: 388P O503D&ul7 {K%gX( %7 15\r\n" 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Key2: 1 N ?|k UT0or 3o 4 I97N 5-S3O 31\r\n" 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\r\n" 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\x47\x30\x22\x2D\x5A\x3F\x47\x58"; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://example.com/demo"), 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ws://example.com/demo", 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetUpParameter(handshake.get(), 777007543U, 114997259U, 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "388P O503D&ul7 {K%gX( %7 15", 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "1 N ?|k UT0or 3o 4 I97N 5-S3O 31", 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string("\x47\x30\x22\x2D\x5A\x3F\x47\x58", 8)); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode()); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpectHandshakeMessageEquals( 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kExpectedClientHandshakeMessage, 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake->CreateClientHandshakeMessage()); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char kResponse[] = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Upgrade: WebSocket\r\n" 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Connection: Upgrade\r\n" 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Origin: http://example.com\r\n" 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Location: ws://example.com/demo\r\n" 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Sec-WebSocket-Protocol: sample\r\n" 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\r\n" 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\x30\x73\x74\x33\x52\x6C\x26\x71\x2D\x32\x5A\x55\x5E\x77\x65\x75" 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\0Hello\xff"; 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int handshake_length = strlen(kResponse); // key3 doesn't contain \0. 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(handshake_length, handshake->ReadServerHandshake( 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kResponse, sizeof(kResponse) - 1)); // -1 for terminating \0 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(WebSocketHandshake::MODE_CONNECTED, handshake->mode()); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, is_secure_false) { 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://example.com/demo"), 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ws://example.com/demo", 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(handshake->is_secure()); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, is_secure_true) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // wss:// is secure. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("wss://example.com/demo"), 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "wss://example.com/demo", 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(handshake->is_secure()); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_ResourceName) { 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://example.com/Test?q=xxx&p=%20"), 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ws://example.com/demo", 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Path and query should be preserved as-is. 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("/Test?q=xxx&p=%20", GetResourceName(handshake.get())); 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_Host) { 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://Example.Com/demo"), 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://Example.Com", 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ws://Example.Com/demo", 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Host should be lowercased 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("example.com", GetHostFieldValue(handshake.get())); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("http://example.com", GetOriginFieldValue(handshake.get())); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_TrimPort80) { 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://example.com:80/demo"), 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ws://example.com/demo", 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // :80 should be trimmed as it's the default port for ws://. 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("example.com", GetHostFieldValue(handshake.get())); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_TrimPort443) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("wss://example.com:443/demo"), 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "wss://example.com/demo", 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // :443 should be trimmed as it's the default port for wss://. 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("example.com", GetHostFieldValue(handshake.get())); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateClientHandshakeMessage_NonDefaultPortForWs) { 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://example.com:8080/demo"), 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "wss://example.com/demo", 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // :8080 should be preserved as it's not the default port for ws://. 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("example.com:8080", GetHostFieldValue(handshake.get())); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateClientHandshakeMessage_NonDefaultPortForWss) { 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("wss://example.com:4443/demo"), 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "wss://example.com/demo", 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // :4443 should be preserved as it's not the default port for wss://. 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("example.com:4443", GetHostFieldValue(handshake.get())); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_WsBut443) { 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("ws://example.com:443/demo"), 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ws://example.com/demo", 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // :443 should be preserved as it's not the default port for ws://. 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("example.com:443", GetHostFieldValue(handshake.get())); 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketHandshakeTest, CreateClientHandshakeMessage_WssBut80) { 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<WebSocketHandshake> handshake( 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new WebSocketHandshake(GURL("wss://example.com:80/demo"), 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://example.com", 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "wss://example.com/demo", 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sample")); 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // :80 should be preserved as it's not the default port for wss://. 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ("example.com:80", GetHostFieldValue(handshake.get())); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace net 331