| // Copyright 2014 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 "components/cast_channel/cast_socket.h" |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/callback_helpers.h" |
| #include "base/files/file_util.h" |
| #include "base/location.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/path_service.h" |
| #include "base/run_loop.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/sys_byteorder.h" |
| #include "base/test/bind.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/timer/mock_timer.h" |
| #include "build/build_config.h" |
| #include "components/cast_channel/cast_auth_util.h" |
| #include "components/cast_channel/cast_framer.h" |
| #include "components/cast_channel/cast_message_util.h" |
| #include "components/cast_channel/cast_test_util.h" |
| #include "components/cast_channel/cast_transport.h" |
| #include "components/cast_channel/logger.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "crypto/rsa_private_key.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "net/base/address_list.h" |
| #include "net/base/net_errors.h" |
| #include "net/cert/pem.h" |
| #include "net/socket/client_socket_factory.h" |
| #include "net/socket/socket_test_util.h" |
| #include "net/socket/ssl_client_socket.h" |
| #include "net/socket/ssl_server_socket.h" |
| #include "net/socket/tcp_client_socket.h" |
| #include "net/socket/tcp_server_socket.h" |
| #include "net/ssl/ssl_info.h" |
| #include "net/ssl/ssl_server_config.h" |
| #include "net/test/cert_test_util.h" |
| #include "net/test/test_data_directory.h" |
| #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "services/network/network_context.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/openscreen/src/cast/common/channel/proto/cast_channel.pb.h" |
| |
| const int64_t kDistantTimeoutMillis = 100000; // 100 seconds (never hit). |
| |
| using ::testing::A; |
| using ::testing::DoAll; |
| using ::testing::Invoke; |
| using ::testing::InvokeArgument; |
| using ::testing::NotNull; |
| using ::testing::Return; |
| using ::testing::SaveArg; |
| using ::testing::_; |
| |
| using ::cast::channel::CastMessage; |
| |
| namespace cast_channel { |
| namespace { |
| const char kAuthNamespace[] = "urn:x-cast:com.google.cast.tp.deviceauth"; |
| |
| // Returns an auth challenge message inline. |
| CastMessage CreateAuthChallenge() { |
| CastMessage output; |
| CreateAuthChallengeMessage(&output, AuthContext::Create()); |
| return output; |
| } |
| |
| // Returns an auth challenge response message inline. |
| CastMessage CreateAuthReply() { |
| CastMessage output; |
| output.set_protocol_version(CastMessage::CASTV2_1_0); |
| output.set_source_id("sender-0"); |
| output.set_destination_id("receiver-0"); |
| output.set_payload_type(CastMessage::BINARY); |
| output.set_payload_binary("abcd"); |
| output.set_namespace_(kAuthNamespace); |
| return output; |
| } |
| |
| CastMessage CreateTestMessage() { |
| CastMessage test_message; |
| test_message.set_protocol_version(CastMessage::CASTV2_1_0); |
| test_message.set_namespace_("ns"); |
| test_message.set_source_id("source"); |
| test_message.set_destination_id("dest"); |
| test_message.set_payload_type(CastMessage::STRING); |
| test_message.set_payload_utf8("payload"); |
| return test_message; |
| } |
| |
| base::FilePath GetTestCertsDirectory() { |
| base::FilePath path; |
| base::PathService::Get(base::DIR_SOURCE_ROOT, &path); |
| path = path.Append(FILE_PATH_LITERAL("components")); |
| path = path.Append(FILE_PATH_LITERAL("test")); |
| path = path.Append(FILE_PATH_LITERAL("data")); |
| path = path.Append(FILE_PATH_LITERAL("cast_channel")); |
| return path; |
| } |
| |
| class MockTCPSocket : public net::MockTCPClientSocket { |
| public: |
| MockTCPSocket(bool do_nothing, net::SocketDataProvider* socket_provider) |
| : net::MockTCPClientSocket(net::AddressList(), nullptr, socket_provider) { |
| do_nothing_ = do_nothing; |
| set_enable_read_if_ready(true); |
| } |
| |
| int Connect(net::CompletionOnceCallback callback) override { |
| if (do_nothing_) { |
| // Stall the I/O event loop. |
| return net::ERR_IO_PENDING; |
| } |
| return net::MockTCPClientSocket::Connect(std::move(callback)); |
| } |
| |
| private: |
| bool do_nothing_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MockTCPSocket); |
| }; |
| |
| class CompleteHandler { |
| public: |
| CompleteHandler() {} |
| MOCK_METHOD1(OnCloseComplete, void(int result)); |
| MOCK_METHOD1(OnConnectComplete, void(CastSocket* socket)); |
| MOCK_METHOD1(OnWriteComplete, void(int result)); |
| MOCK_METHOD1(OnReadComplete, void(int result)); |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(CompleteHandler); |
| }; |
| |
| class TestCastSocketBase : public CastSocketImpl { |
| public: |
| TestCastSocketBase(network::mojom::NetworkContext* network_context, |
| const CastSocketOpenParams& open_params, |
| Logger* logger) |
| : CastSocketImpl(base::BindRepeating( |
| [](network::mojom::NetworkContext* network_context) { |
| return network_context; |
| }, |
| network_context), |
| open_params, |
| logger, |
| AuthContext::Create()), |
| verify_challenge_result_(true), |
| verify_challenge_disallow_(false), |
| mock_timer_(new base::MockOneShotTimer()) { |
| SetPeerCertForTesting( |
| net::ImportCertFromFile(GetTestCertsDirectory(), "self_signed.pem")); |
| } |
| ~TestCastSocketBase() override {} |
| |
| void SetVerifyChallengeResult(bool value) { |
| verify_challenge_result_ = value; |
| } |
| |
| void TriggerTimeout() { mock_timer_->Fire(); } |
| |
| bool TestVerifyChannelPolicyNone() { |
| AuthResult authResult; |
| return VerifyChannelPolicy(authResult); |
| } |
| |
| void DisallowVerifyChallengeResult() { verify_challenge_disallow_ = true; } |
| |
| protected: |
| bool VerifyChallengeReply() override { |
| EXPECT_FALSE(verify_challenge_disallow_); |
| return verify_challenge_result_; |
| } |
| |
| base::OneShotTimer* GetTimer() override { return mock_timer_.get(); } |
| |
| // Simulated result of verifying challenge reply. |
| bool verify_challenge_result_; |
| bool verify_challenge_disallow_; |
| std::unique_ptr<base::MockOneShotTimer> mock_timer_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TestCastSocketBase); |
| }; |
| |
| class MockTestCastSocket : public TestCastSocketBase { |
| public: |
| static std::unique_ptr<MockTestCastSocket> CreateSecure( |
| network::mojom::NetworkContext* network_context, |
| const CastSocketOpenParams& open_params, |
| Logger* logger) { |
| return std::make_unique<MockTestCastSocket>(network_context, open_params, |
| logger); |
| } |
| |
| using TestCastSocketBase::TestCastSocketBase; |
| |
| MockTestCastSocket(network::mojom::NetworkContext* network_context, |
| const CastSocketOpenParams& open_params, |
| Logger* logger) |
| : TestCastSocketBase(network_context, open_params, logger) {} |
| |
| ~MockTestCastSocket() override {} |
| |
| void SetupMockTransport() { |
| mock_transport_ = new MockCastTransport; |
| SetTransportForTesting(base::WrapUnique(mock_transport_)); |
| } |
| |
| bool TestVerifyChannelPolicyAudioOnly() { |
| AuthResult authResult; |
| authResult.channel_policies |= AuthResult::POLICY_AUDIO_ONLY; |
| return VerifyChannelPolicy(authResult); |
| } |
| |
| MockCastTransport* GetMockTransport() { |
| CHECK(mock_transport_); |
| return mock_transport_; |
| } |
| |
| private: |
| MockCastTransport* mock_transport_ = nullptr; |
| |
| DISALLOW_COPY_AND_ASSIGN(MockTestCastSocket); |
| }; |
| |
| // TODO(https://crbug.com/928467): Remove this class. |
| class TestSocketFactory : public net::ClientSocketFactory { |
| public: |
| explicit TestSocketFactory(net::IPEndPoint ip) : ip_(ip) {} |
| ~TestSocketFactory() override = default; |
| |
| // Socket connection helpers. |
| void SetupTcpConnect(net::IoMode mode, int result) { |
| tcp_connect_data_ = std::make_unique<net::MockConnect>(mode, result, ip_); |
| } |
| void SetupSslConnect(net::IoMode mode, int result) { |
| ssl_connect_data_ = std::make_unique<net::MockConnect>(mode, result, ip_); |
| } |
| |
| // Socket I/O helpers. |
| void AddWriteResult(const net::MockWrite& write) { writes_.push_back(write); } |
| void AddWriteResult(net::IoMode mode, int result) { |
| AddWriteResult(net::MockWrite(mode, result)); |
| } |
| void AddWriteResultForData(net::IoMode mode, const std::string& msg) { |
| AddWriteResult(mode, msg.size()); |
| } |
| void AddReadResult(const net::MockRead& read) { reads_.push_back(read); } |
| void AddReadResult(net::IoMode mode, int result) { |
| AddReadResult(net::MockRead(mode, result)); |
| } |
| void AddReadResultForData(net::IoMode mode, const std::string& data) { |
| AddReadResult(net::MockRead(mode, data.c_str(), data.size())); |
| } |
| |
| // Helpers for modifying other connection-related behaviors. |
| void SetupTcpConnectUnresponsive() { tcp_unresponsive_ = true; } |
| |
| void SetTcpSocket( |
| std::unique_ptr<net::TransportClientSocket> tcp_client_socket) { |
| tcp_client_socket_ = std::move(tcp_client_socket); |
| } |
| |
| void SetTLSSocketCreatedClosure(base::OnceClosure closure) { |
| tls_socket_created_ = std::move(closure); |
| } |
| |
| void Pause() { |
| if (socket_data_provider_) |
| socket_data_provider_->Pause(); |
| else |
| socket_data_provider_paused_ = true; |
| } |
| |
| void Resume() { socket_data_provider_->Resume(); } |
| |
| private: |
| std::unique_ptr<net::DatagramClientSocket> CreateDatagramClientSocket( |
| net::DatagramSocket::BindType, |
| net::NetLog*, |
| const net::NetLogSource&) override { |
| NOTIMPLEMENTED(); |
| return nullptr; |
| } |
| std::unique_ptr<net::TransportClientSocket> CreateTransportClientSocket( |
| const net::AddressList&, |
| std::unique_ptr<net::SocketPerformanceWatcher>, |
| net::NetworkQualityEstimator*, |
| net::NetLog*, |
| const net::NetLogSource&) override { |
| if (tcp_client_socket_) |
| return std::move(tcp_client_socket_); |
| |
| if (tcp_unresponsive_) { |
| socket_data_provider_ = std::make_unique<net::StaticSocketDataProvider>(); |
| return std::unique_ptr<net::TransportClientSocket>( |
| new MockTCPSocket(true, socket_data_provider_.get())); |
| } else { |
| socket_data_provider_ = |
| std::make_unique<net::StaticSocketDataProvider>(reads_, writes_); |
| socket_data_provider_->set_connect_data(*tcp_connect_data_); |
| if (socket_data_provider_paused_) |
| socket_data_provider_->Pause(); |
| return std::unique_ptr<net::TransportClientSocket>( |
| new MockTCPSocket(false, socket_data_provider_.get())); |
| } |
| } |
| std::unique_ptr<net::SSLClientSocket> CreateSSLClientSocket( |
| net::SSLClientContext* context, |
| std::unique_ptr<net::StreamSocket> nested_socket, |
| const net::HostPortPair& host_and_port, |
| const net::SSLConfig& ssl_config) override { |
| if (!ssl_connect_data_) { |
| // Test isn't overriding SSL socket creation. |
| return net::ClientSocketFactory::GetDefaultFactory() |
| ->CreateSSLClientSocket(context, std::move(nested_socket), |
| host_and_port, ssl_config); |
| } |
| ssl_socket_data_provider_ = std::make_unique<net::SSLSocketDataProvider>( |
| ssl_connect_data_->mode, ssl_connect_data_->result); |
| |
| if (tls_socket_created_) |
| std::move(tls_socket_created_).Run(); |
| |
| return std::make_unique<net::MockSSLClientSocket>( |
| std::move(nested_socket), net::HostPortPair(), net::SSLConfig(), |
| ssl_socket_data_provider_.get()); |
| } |
| std::unique_ptr<net::ProxyClientSocket> CreateProxyClientSocket( |
| std::unique_ptr<net::StreamSocket> stream_socket, |
| const std::string& user_agent, |
| const net::HostPortPair& endpoint, |
| const net::ProxyServer& proxy_server, |
| net::HttpAuthController* http_auth_controller, |
| bool tunnel, |
| bool using_spdy, |
| net::NextProto negotiated_protocol, |
| net::ProxyDelegate* proxy_delegate, |
| const net::NetworkTrafficAnnotationTag& traffic_annotation) override { |
| NOTIMPLEMENTED(); |
| return nullptr; |
| } |
| |
| net::IPEndPoint ip_; |
| // Simulated connect data |
| std::unique_ptr<net::MockConnect> tcp_connect_data_; |
| std::unique_ptr<net::MockConnect> ssl_connect_data_; |
| // Simulated read / write data |
| std::vector<net::MockWrite> writes_; |
| std::vector<net::MockRead> reads_; |
| std::unique_ptr<net::StaticSocketDataProvider> socket_data_provider_; |
| std::unique_ptr<net::SSLSocketDataProvider> ssl_socket_data_provider_; |
| bool socket_data_provider_paused_ = false; |
| // If true, makes TCP connection process stall. For timeout testing. |
| bool tcp_unresponsive_ = false; |
| std::unique_ptr<net::TransportClientSocket> tcp_client_socket_; |
| base::OnceClosure tls_socket_created_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestSocketFactory); |
| }; |
| |
| class CastSocketTestBase : public testing::Test { |
| protected: |
| CastSocketTestBase() |
| : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), |
| url_request_context_(true), |
| logger_(new Logger()), |
| observer_(new MockCastSocketObserver()), |
| socket_open_params_( |
| CreateIPEndPointForTest(), |
| base::TimeDelta::FromMilliseconds(kDistantTimeoutMillis)), |
| client_socket_factory_(socket_open_params_.ip_endpoint) {} |
| ~CastSocketTestBase() override {} |
| |
| void SetUp() override { |
| EXPECT_CALL(*observer_, OnMessage(_, _)).Times(0); |
| |
| url_request_context_.set_client_socket_factory(&client_socket_factory_); |
| url_request_context_.Init(); |
| network_context_ = std::make_unique<network::NetworkContext>( |
| nullptr, network_context_remote_.BindNewPipeAndPassReceiver(), |
| &url_request_context_, |
| /*cors_exempt_header_list=*/std::vector<std::string>()); |
| } |
| |
| // Runs all pending tasks in the message loop. |
| void RunPendingTasks() { |
| base::RunLoop run_loop; |
| run_loop.RunUntilIdle(); |
| } |
| |
| TestSocketFactory* client_socket_factory() { return &client_socket_factory_; } |
| |
| content::BrowserTaskEnvironment task_environment_; |
| net::TestURLRequestContext url_request_context_; |
| std::unique_ptr<network::NetworkContext> network_context_; |
| mojo::Remote<network::mojom::NetworkContext> network_context_remote_; |
| Logger* logger_; |
| CompleteHandler handler_; |
| std::unique_ptr<MockCastSocketObserver> observer_; |
| CastSocketOpenParams socket_open_params_; |
| TestSocketFactory client_socket_factory_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(CastSocketTestBase); |
| }; |
| |
| class MockCastSocketTest : public CastSocketTestBase { |
| protected: |
| MockCastSocketTest() {} |
| |
| void TearDown() override { |
| if (socket_) { |
| EXPECT_CALL(handler_, OnCloseComplete(net::OK)); |
| socket_->Close(base::BindOnce(&CompleteHandler::OnCloseComplete, |
| base::Unretained(&handler_))); |
| } |
| } |
| |
| void CreateCastSocketSecure() { |
| socket_ = MockTestCastSocket::CreateSecure(network_context_.get(), |
| socket_open_params_, logger_); |
| } |
| |
| void HandleAuthHandshake() { |
| socket_->SetupMockTransport(); |
| CastMessage challenge_proto = CreateAuthChallenge(); |
| EXPECT_CALL(*socket_->GetMockTransport(), |
| SendMessage_(EqualsProto(challenge_proto), _)) |
| .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->AddObserver(observer_.get()); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| socket_->GetMockTransport()->current_delegate()->OnMessage( |
| CreateAuthReply()); |
| RunPendingTasks(); |
| } |
| |
| std::unique_ptr<MockTestCastSocket> socket_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MockCastSocketTest); |
| }; |
| |
| class SslCastSocketTest : public CastSocketTestBase { |
| protected: |
| SslCastSocketTest() {} |
| |
| void TearDown() override { |
| if (socket_) { |
| EXPECT_CALL(handler_, OnCloseComplete(net::OK)); |
| socket_->Close(base::BindOnce(&CompleteHandler::OnCloseComplete, |
| base::Unretained(&handler_))); |
| } |
| } |
| |
| void CreateSockets() { |
| socket_ = std::make_unique<TestCastSocketBase>( |
| network_context_.get(), socket_open_params_, logger_); |
| |
| server_cert_ = |
| net::ImportCertFromFile(GetTestCertsDirectory(), "self_signed.pem"); |
| ASSERT_TRUE(server_cert_); |
| server_private_key_ = ReadTestKeyFromPEM("self_signed.pem"); |
| ASSERT_TRUE(server_private_key_); |
| server_context_ = CreateSSLServerContext( |
| server_cert_.get(), *server_private_key_, server_ssl_config_); |
| |
| tcp_server_socket_ = |
| std::make_unique<net::TCPServerSocket>(nullptr, net::NetLogSource()); |
| ASSERT_EQ(net::OK, |
| tcp_server_socket_->ListenWithAddressAndPort("127.0.0.1", 0, 1)); |
| net::IPEndPoint server_address; |
| ASSERT_EQ(net::OK, tcp_server_socket_->GetLocalAddress(&server_address)); |
| tcp_client_socket_ = std::make_unique<net::TCPClientSocket>( |
| net::AddressList(server_address), nullptr, nullptr, nullptr, |
| net::NetLogSource()); |
| |
| std::unique_ptr<net::StreamSocket> accepted_socket; |
| accept_result_ = tcp_server_socket_->Accept( |
| &accepted_socket, base::BindOnce(&SslCastSocketTest::TcpAcceptCallback, |
| base::Unretained(this))); |
| connect_result_ = tcp_client_socket_->Connect(base::BindOnce( |
| &SslCastSocketTest::TcpConnectCallback, base::Unretained(this))); |
| while (accept_result_ == net::ERR_IO_PENDING || |
| connect_result_ == net::ERR_IO_PENDING) { |
| RunPendingTasks(); |
| } |
| ASSERT_EQ(net::OK, accept_result_); |
| ASSERT_EQ(net::OK, connect_result_); |
| ASSERT_TRUE(accepted_socket); |
| ASSERT_TRUE(tcp_client_socket_->IsConnected()); |
| |
| server_socket_ = |
| server_context_->CreateSSLServerSocket(std::move(accepted_socket)); |
| ASSERT_TRUE(server_socket_); |
| |
| client_socket_factory()->SetTcpSocket(std::move(tcp_client_socket_)); |
| } |
| |
| void ConnectSockets() { |
| socket_->AddObserver(observer_.get()); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| |
| net::TestCompletionCallback handshake_callback; |
| int server_ret = handshake_callback.GetResult( |
| server_socket_->Handshake(handshake_callback.callback())); |
| |
| ASSERT_EQ(net::OK, server_ret); |
| } |
| |
| void TcpAcceptCallback(int result) { accept_result_ = result; } |
| |
| void TcpConnectCallback(int result) { connect_result_ = result; } |
| |
| std::unique_ptr<crypto::RSAPrivateKey> ReadTestKeyFromPEM( |
| const base::StringPiece& name) { |
| base::FilePath key_path = GetTestCertsDirectory().AppendASCII(name); |
| std::string pem_data; |
| if (!base::ReadFileToString(key_path, &pem_data)) { |
| return nullptr; |
| } |
| |
| const std::vector<std::string> headers({"PRIVATE KEY"}); |
| net::PEMTokenizer pem_tokenizer(pem_data, headers); |
| if (!pem_tokenizer.GetNext()) { |
| return nullptr; |
| } |
| std::vector<uint8_t> key_vector(pem_tokenizer.data().begin(), |
| pem_tokenizer.data().end()); |
| std::unique_ptr<crypto::RSAPrivateKey> key( |
| crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector)); |
| return key; |
| } |
| |
| int ReadExactLength(net::IOBuffer* buffer, |
| int buffer_length, |
| net::Socket* socket) { |
| scoped_refptr<net::DrainableIOBuffer> draining_buffer = |
| base::MakeRefCounted<net::DrainableIOBuffer>(buffer, buffer_length); |
| while (draining_buffer->BytesRemaining() > 0) { |
| net::TestCompletionCallback read_callback; |
| int read_result = read_callback.GetResult(server_socket_->Read( |
| draining_buffer.get(), draining_buffer->BytesRemaining(), |
| read_callback.callback())); |
| EXPECT_GT(read_result, 0); |
| draining_buffer->DidConsume(read_result); |
| } |
| return buffer_length; |
| } |
| |
| int WriteExactLength(net::IOBuffer* buffer, |
| int buffer_length, |
| net::Socket* socket) { |
| scoped_refptr<net::DrainableIOBuffer> draining_buffer = |
| base::MakeRefCounted<net::DrainableIOBuffer>(buffer, buffer_length); |
| while (draining_buffer->BytesRemaining() > 0) { |
| net::TestCompletionCallback write_callback; |
| int write_result = write_callback.GetResult(server_socket_->Write( |
| draining_buffer.get(), draining_buffer->BytesRemaining(), |
| write_callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS)); |
| EXPECT_GT(write_result, 0); |
| draining_buffer->DidConsume(write_result); |
| } |
| return buffer_length; |
| } |
| |
| // Result values used for TCP socket setup. These should contain values from |
| // net::Error. |
| int accept_result_; |
| int connect_result_; |
| |
| // Underlying TCP sockets for |socket_| to communicate with |server_socket_| |
| // when testing with the real SSL implementation. |
| std::unique_ptr<net::TransportClientSocket> tcp_client_socket_; |
| std::unique_ptr<net::TCPServerSocket> tcp_server_socket_; |
| |
| std::unique_ptr<TestCastSocketBase> socket_; |
| |
| // |server_socket_| is used for the *RealSSL tests in order to test the |
| // CastSocket over a real SSL socket. The other members below are used to |
| // initialize |server_socket_|. |
| std::unique_ptr<net::SSLServerSocket> server_socket_; |
| std::unique_ptr<net::SSLServerContext> server_context_; |
| std::unique_ptr<crypto::RSAPrivateKey> server_private_key_; |
| scoped_refptr<net::X509Certificate> server_cert_; |
| net::SSLServerConfig server_ssl_config_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SslCastSocketTest); |
| }; |
| |
| } // namespace |
| |
| // Tests that the following connection flow works: |
| // - TCP connection succeeds (async) |
| // - SSL connection succeeds (async) |
| // - Cert is extracted successfully |
| // - Challenge request is sent (async) |
| // - Challenge response is received (async) |
| // - Credentials are verified successfuly |
| TEST_F(MockCastSocketTest, TestConnectFullSecureFlowAsync) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::OK); |
| client_socket_factory()->SetupSslConnect(net::ASYNC, net::OK); |
| |
| HandleAuthHandshake(); |
| |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| } |
| |
| // Tests that the following connection flow works: |
| // - TCP connection succeeds (sync) |
| // - SSL connection succeeds (sync) |
| // - Cert is extracted successfully |
| // - Challenge request is sent (sync) |
| // - Challenge response is received (sync) |
| // - Credentials are verified successfuly |
| TEST_F(MockCastSocketTest, TestConnectFullSecureFlowSync) { |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| |
| CreateCastSocketSecure(); |
| HandleAuthHandshake(); |
| |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| } |
| |
| // Test that an AuthMessage with a mangled namespace triggers cancelation |
| // of the connection event loop. |
| TEST_F(MockCastSocketTest, TestConnectAuthMessageCorrupted) { |
| CreateCastSocketSecure(); |
| socket_->SetupMockTransport(); |
| |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::OK); |
| client_socket_factory()->SetupSslConnect(net::ASYNC, net::OK); |
| |
| CastMessage challenge_proto = CreateAuthChallenge(); |
| EXPECT_CALL(*socket_->GetMockTransport(), |
| SendMessage_(EqualsProto(challenge_proto), _)) |
| .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| CastMessage mangled_auth_reply = CreateAuthReply(); |
| mangled_auth_reply.set_namespace_("BOGUS_NAMESPACE"); |
| |
| socket_->GetMockTransport()->current_delegate()->OnMessage( |
| mangled_auth_reply); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::TRANSPORT_ERROR, socket_->error_state()); |
| |
| // Verifies that the CastSocket's resources were torn down during channel |
| // close. (see http://crbug.com/504078) |
| EXPECT_EQ(nullptr, socket_->transport()); |
| } |
| |
| // Test connection error - TCP connect fails (async) |
| TEST_F(MockCastSocketTest, TestConnectTcpConnectErrorAsync) { |
| CreateCastSocketSecure(); |
| |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::ERR_FAILED); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CONNECT_ERROR, socket_->error_state()); |
| } |
| |
| // Test connection error - TCP connect fails (sync) |
| TEST_F(MockCastSocketTest, TestConnectTcpConnectErrorSync) { |
| CreateCastSocketSecure(); |
| |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::ERR_FAILED); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CONNECT_ERROR, socket_->error_state()); |
| } |
| |
| // Test connection error - timeout |
| TEST_F(MockCastSocketTest, TestConnectTcpTimeoutError) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnectUnresponsive(); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| EXPECT_CALL(*observer_, OnError(_, ChannelError::CONNECT_TIMEOUT)); |
| socket_->AddObserver(observer_.get()); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CONNECTING, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| socket_->TriggerTimeout(); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| } |
| |
| // Test connection error - TCP socket returns timeout |
| TEST_F(MockCastSocketTest, TestConnectTcpSocketTimeoutError) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, |
| net::ERR_CONNECTION_TIMED_OUT); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| EXPECT_CALL(*observer_, OnError(_, ChannelError::CONNECT_TIMEOUT)); |
| socket_->AddObserver(observer_.get()); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| EXPECT_EQ(net::ERR_CONNECTION_TIMED_OUT, |
| logger_->GetLastError(socket_->id()).net_return_value); |
| } |
| |
| // Test connection error - SSL connect fails (async) |
| TEST_F(MockCastSocketTest, TestConnectSslConnectErrorAsync) { |
| CreateCastSocketSecure(); |
| |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::ERR_FAILED); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); |
| } |
| |
| // Test connection error - SSL connect fails (sync) |
| TEST_F(MockCastSocketTest, TestConnectSslConnectErrorSync) { |
| CreateCastSocketSecure(); |
| |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::ERR_FAILED); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); |
| EXPECT_EQ(net::ERR_FAILED, |
| logger_->GetLastError(socket_->id()).net_return_value); |
| } |
| |
| // Test connection error - SSL connect times out (sync) |
| TEST_F(MockCastSocketTest, TestConnectSslConnectTimeoutSync) { |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, |
| net::ERR_CONNECTION_TIMED_OUT); |
| |
| CreateCastSocketSecure(); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| EXPECT_EQ(net::ERR_CONNECTION_TIMED_OUT, |
| logger_->GetLastError(socket_->id()).net_return_value); |
| } |
| |
| // Test connection error - SSL connect times out (async) |
| TEST_F(MockCastSocketTest, TestConnectSslConnectTimeoutAsync) { |
| CreateCastSocketSecure(); |
| |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::OK); |
| client_socket_factory()->SetupSslConnect(net::ASYNC, |
| net::ERR_CONNECTION_TIMED_OUT); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| } |
| |
| // Test connection error - challenge send fails |
| TEST_F(MockCastSocketTest, TestConnectChallengeSendError) { |
| CreateCastSocketSecure(); |
| socket_->SetupMockTransport(); |
| |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| EXPECT_CALL(*socket_->GetMockTransport(), |
| SendMessage_(EqualsProto(CreateAuthChallenge()), _)) |
| .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET)); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CAST_SOCKET_ERROR, socket_->error_state()); |
| } |
| |
| // Test connection error - connection is destroyed after the challenge is |
| // sent, with the async result still lurking in the task queue. |
| TEST_F(MockCastSocketTest, TestConnectDestroyedAfterChallengeSent) { |
| CreateCastSocketSecure(); |
| socket_->SetupMockTransport(); |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| EXPECT_CALL(*socket_->GetMockTransport(), |
| SendMessage_(EqualsProto(CreateAuthChallenge()), _)) |
| .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET)); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| socket_.reset(); |
| RunPendingTasks(); |
| } |
| |
| // Test connection error - challenge reply receive fails |
| TEST_F(MockCastSocketTest, TestConnectChallengeReplyReceiveError) { |
| CreateCastSocketSecure(); |
| socket_->SetupMockTransport(); |
| |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| EXPECT_CALL(*socket_->GetMockTransport(), |
| SendMessage_(EqualsProto(CreateAuthChallenge()), _)) |
| .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| client_socket_factory()->AddReadResult(net::SYNCHRONOUS, net::ERR_FAILED); |
| EXPECT_CALL(*observer_, OnError(_, ChannelError::CAST_SOCKET_ERROR)); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| socket_->AddObserver(observer_.get()); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| socket_->GetMockTransport()->current_delegate()->OnError( |
| ChannelError::CAST_SOCKET_ERROR); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::CAST_SOCKET_ERROR, socket_->error_state()); |
| } |
| |
| TEST_F(MockCastSocketTest, TestConnectChallengeVerificationFails) { |
| CreateCastSocketSecure(); |
| socket_->SetupMockTransport(); |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::OK); |
| client_socket_factory()->SetupSslConnect(net::ASYNC, net::OK); |
| socket_->SetVerifyChallengeResult(false); |
| |
| EXPECT_CALL(*observer_, OnError(_, ChannelError::AUTHENTICATION_ERROR)); |
| CastMessage challenge_proto = CreateAuthChallenge(); |
| EXPECT_CALL(*socket_->GetMockTransport(), |
| SendMessage_(EqualsProto(challenge_proto), _)) |
| .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| socket_->AddObserver(observer_.get()); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| socket_->GetMockTransport()->current_delegate()->OnMessage(CreateAuthReply()); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); |
| } |
| |
| // Sends message data through an actual non-mocked CastTransport object, |
| // testing the two components in integration. |
| TEST_F(MockCastSocketTest, TestConnectEndToEndWithRealTransportAsync) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::OK); |
| client_socket_factory()->SetupSslConnect(net::ASYNC, net::OK); |
| |
| // Set low-level auth challenge expectations. |
| CastMessage challenge = CreateAuthChallenge(); |
| std::string challenge_str; |
| EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); |
| client_socket_factory()->AddWriteResultForData(net::ASYNC, challenge_str); |
| |
| // Set low-level auth reply expectations. |
| CastMessage reply = CreateAuthReply(); |
| std::string reply_str; |
| EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); |
| client_socket_factory()->AddReadResultForData(net::ASYNC, reply_str); |
| client_socket_factory()->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
| // Make sure the data is ready by the TLS socket and not the TCP socket. |
| client_socket_factory()->Pause(); |
| client_socket_factory()->SetTLSSocketCreatedClosure( |
| base::BindLambdaForTesting([&] { client_socket_factory()->Resume(); })); |
| |
| CastMessage test_message = CreateTestMessage(); |
| std::string test_message_str; |
| EXPECT_TRUE(MessageFramer::Serialize(test_message, &test_message_str)); |
| client_socket_factory()->AddWriteResultForData(net::ASYNC, test_message_str); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| |
| // Send the test message through a real transport object. |
| EXPECT_CALL(handler_, OnWriteComplete(net::OK)); |
| socket_->transport()->SendMessage( |
| test_message, base::BindOnce(&CompleteHandler::OnWriteComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| } |
| |
| // Same as TestConnectEndToEndWithRealTransportAsync, except synchronous. |
| TEST_F(MockCastSocketTest, TestConnectEndToEndWithRealTransportSync) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| |
| // Set low-level auth challenge expectations. |
| CastMessage challenge = CreateAuthChallenge(); |
| std::string challenge_str; |
| EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); |
| client_socket_factory()->AddWriteResultForData(net::SYNCHRONOUS, |
| challenge_str); |
| |
| // Set low-level auth reply expectations. |
| CastMessage reply = CreateAuthReply(); |
| std::string reply_str; |
| EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); |
| client_socket_factory()->AddReadResultForData(net::SYNCHRONOUS, reply_str); |
| client_socket_factory()->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
| // Make sure the data is ready by the TLS socket and not the TCP socket. |
| client_socket_factory()->Pause(); |
| client_socket_factory()->SetTLSSocketCreatedClosure( |
| base::BindLambdaForTesting([&] { client_socket_factory()->Resume(); })); |
| |
| CastMessage test_message = CreateTestMessage(); |
| std::string test_message_str; |
| EXPECT_TRUE(MessageFramer::Serialize(test_message, &test_message_str)); |
| client_socket_factory()->AddWriteResultForData(net::SYNCHRONOUS, |
| test_message_str); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| |
| // Send the test message through a real transport object. |
| EXPECT_CALL(handler_, OnWriteComplete(net::OK)); |
| socket_->transport()->SendMessage( |
| test_message, base::BindOnce(&CompleteHandler::OnWriteComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| } |
| |
| TEST_F(MockCastSocketTest, TestObservers) { |
| CreateCastSocketSecure(); |
| // Test AddObserever |
| MockCastSocketObserver observer1; |
| MockCastSocketObserver observer2; |
| socket_->AddObserver(&observer1); |
| socket_->AddObserver(&observer1); |
| socket_->AddObserver(&observer2); |
| socket_->AddObserver(&observer2); |
| |
| // Test notify observers |
| EXPECT_CALL(observer1, OnError(_, cast_channel::ChannelError::CONNECT_ERROR)); |
| EXPECT_CALL(observer2, OnError(_, cast_channel::ChannelError::CONNECT_ERROR)); |
| CastSocketImpl::CastSocketMessageDelegate delegate(socket_.get()); |
| delegate.OnError(cast_channel::ChannelError::CONNECT_ERROR); |
| } |
| |
| TEST_F(MockCastSocketTest, TestOpenChannelConnectingSocket) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnectUnresponsive(); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())).Times(2); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| socket_->TriggerTimeout(); |
| RunPendingTasks(); |
| } |
| |
| TEST_F(MockCastSocketTest, TestOpenChannelConnectedSocket) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::OK); |
| client_socket_factory()->SetupSslConnect(net::ASYNC, net::OK); |
| HandleAuthHandshake(); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| } |
| |
| TEST_F(MockCastSocketTest, TestOpenChannelClosedSocket) { |
| CreateCastSocketSecure(); |
| client_socket_factory()->SetupTcpConnect(net::ASYNC, net::ERR_FAILED); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete, |
| base::Unretained(&handler_))); |
| } |
| |
| // https://crbug.com/874491, flaky on Win and Mac |
| #if defined(OS_WIN) || defined(OS_APPLE) |
| #define MAYBE_TestConnectEndToEndWithRealSSL \ |
| DISABLED_TestConnectEndToEndWithRealSSL |
| #else |
| #define MAYBE_TestConnectEndToEndWithRealSSL TestConnectEndToEndWithRealSSL |
| #endif |
| // Tests connecting through an actual non-mocked CastTransport object and |
| // non-mocked SSLClientSocket, testing the components in integration. |
| TEST_F(SslCastSocketTest, MAYBE_TestConnectEndToEndWithRealSSL) { |
| CreateSockets(); |
| ConnectSockets(); |
| |
| // Set low-level auth challenge expectations. |
| CastMessage challenge = CreateAuthChallenge(); |
| std::string challenge_str; |
| EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); |
| |
| int challenge_buffer_length = challenge_str.size(); |
| scoped_refptr<net::IOBuffer> challenge_buffer = |
| base::MakeRefCounted<net::IOBuffer>(challenge_buffer_length); |
| int read = ReadExactLength(challenge_buffer.get(), challenge_buffer_length, |
| server_socket_.get()); |
| |
| EXPECT_EQ(challenge_buffer_length, read); |
| EXPECT_EQ(challenge_str, |
| std::string(challenge_buffer->data(), challenge_buffer_length)); |
| |
| // Set low-level auth reply expectations. |
| CastMessage reply = CreateAuthReply(); |
| std::string reply_str; |
| EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); |
| |
| scoped_refptr<net::StringIOBuffer> reply_buffer = |
| base::MakeRefCounted<net::StringIOBuffer>(reply_str); |
| int written = WriteExactLength(reply_buffer.get(), reply_buffer->size(), |
| server_socket_.get()); |
| |
| EXPECT_EQ(reply_buffer->size(), written); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| } |
| |
| // Sends message data through an actual non-mocked CastTransport object and |
| // non-mocked SSLClientSocket, testing the components in integration. |
| TEST_F(SslCastSocketTest, DISABLED_TestMessageEndToEndWithRealSSL) { |
| CreateSockets(); |
| ConnectSockets(); |
| |
| // Set low-level auth challenge expectations. |
| CastMessage challenge = CreateAuthChallenge(); |
| std::string challenge_str; |
| EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); |
| |
| int challenge_buffer_length = challenge_str.size(); |
| scoped_refptr<net::IOBuffer> challenge_buffer = |
| base::MakeRefCounted<net::IOBuffer>(challenge_buffer_length); |
| |
| int read = ReadExactLength(challenge_buffer.get(), challenge_buffer_length, |
| server_socket_.get()); |
| |
| EXPECT_EQ(challenge_buffer_length, read); |
| EXPECT_EQ(challenge_str, |
| std::string(challenge_buffer->data(), challenge_buffer_length)); |
| |
| // Set low-level auth reply expectations. |
| CastMessage reply = CreateAuthReply(); |
| std::string reply_str; |
| EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); |
| |
| scoped_refptr<net::StringIOBuffer> reply_buffer = |
| base::MakeRefCounted<net::StringIOBuffer>(reply_str); |
| int written = WriteExactLength(reply_buffer.get(), reply_buffer->size(), |
| server_socket_.get()); |
| |
| EXPECT_EQ(reply_buffer->size(), written); |
| EXPECT_CALL(handler_, OnConnectComplete(socket_.get())); |
| RunPendingTasks(); |
| |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| |
| // Send a test message through the ssl socket. |
| CastMessage test_message = CreateTestMessage(); |
| std::string test_message_str; |
| EXPECT_TRUE(MessageFramer::Serialize(test_message, &test_message_str)); |
| |
| int test_message_length = test_message_str.size(); |
| scoped_refptr<net::IOBuffer> test_message_buffer = |
| base::MakeRefCounted<net::IOBuffer>(test_message_length); |
| |
| EXPECT_CALL(handler_, OnWriteComplete(net::OK)); |
| socket_->transport()->SendMessage( |
| test_message, base::BindOnce(&CompleteHandler::OnWriteComplete, |
| base::Unretained(&handler_))); |
| RunPendingTasks(); |
| |
| read = ReadExactLength(test_message_buffer.get(), test_message_length, |
| server_socket_.get()); |
| |
| EXPECT_EQ(test_message_length, read); |
| EXPECT_EQ(test_message_str, |
| std::string(test_message_buffer->data(), test_message_length)); |
| |
| EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| } |
| |
| } // namespace cast_channel |