OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "extensions/browser/api/cast_channel/cast_socket.h" |
| 6 |
| 7 #include <stdint.h> |
| 8 |
| 9 #include <utility> |
| 10 #include <vector> |
| 11 |
| 12 #include "base/location.h" |
| 13 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/memory/weak_ptr.h" |
| 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/run_loop.h" |
| 18 #include "base/single_thread_task_runner.h" |
| 19 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/sys_byteorder.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "base/timer/mock_timer.h" |
| 23 #include "extensions/browser/api/cast_channel/cast_auth_util.h" |
| 24 #include "extensions/browser/api/cast_channel/cast_framer.h" |
| 25 #include "extensions/browser/api/cast_channel/cast_message_util.h" |
| 26 #include "extensions/browser/api/cast_channel/cast_test_util.h" |
| 27 #include "extensions/browser/api/cast_channel/cast_transport.h" |
| 28 #include "extensions/browser/api/cast_channel/logger.h" |
| 29 #include "extensions/common/api/cast_channel/cast_channel.pb.h" |
| 30 #include "extensions/common/api/cast_channel/logging.pb.h" |
| 31 #include "net/base/address_list.h" |
| 32 #include "net/base/net_errors.h" |
| 33 #include "net/log/test_net_log.h" |
| 34 #include "net/socket/socket_test_util.h" |
| 35 #include "net/socket/ssl_client_socket.h" |
| 36 #include "net/socket/tcp_client_socket.h" |
| 37 #include "net/ssl/ssl_info.h" |
| 38 #include "net/test/cert_test_util.h" |
| 39 #include "net/test/test_data_directory.h" |
| 40 #include "testing/gmock/include/gmock/gmock.h" |
| 41 #include "testing/gtest/include/gtest/gtest.h" |
| 42 |
| 43 const int64_t kDistantTimeoutMillis = 100000; // 100 seconds (never hit). |
| 44 |
| 45 using ::cast_channel::ChannelError; |
| 46 using ::cast_channel::ChannelAuthType; |
| 47 using ::cast_channel::ReadyState; |
| 48 using ::testing::_; |
| 49 using ::testing::A; |
| 50 using ::testing::DoAll; |
| 51 using ::testing::Invoke; |
| 52 using ::testing::InvokeArgument; |
| 53 using ::testing::NotNull; |
| 54 using ::testing::Return; |
| 55 using ::testing::SaveArg; |
| 56 |
| 57 namespace extensions { |
| 58 namespace api { |
| 59 namespace cast_channel { |
| 60 const char kAuthNamespace[] = "urn:x-cast:com.google.cast.tp.deviceauth"; |
| 61 |
| 62 // Returns an auth challenge message inline. |
| 63 CastMessage CreateAuthChallenge() { |
| 64 CastMessage output; |
| 65 CreateAuthChallengeMessage(&output, AuthContext::Create()); |
| 66 return output; |
| 67 } |
| 68 |
| 69 // Returns an auth challenge response message inline. |
| 70 CastMessage CreateAuthReply() { |
| 71 CastMessage output; |
| 72 output.set_protocol_version(CastMessage::CASTV2_1_0); |
| 73 output.set_source_id("sender-0"); |
| 74 output.set_destination_id("receiver-0"); |
| 75 output.set_payload_type(CastMessage::BINARY); |
| 76 output.set_payload_binary("abcd"); |
| 77 output.set_namespace_(kAuthNamespace); |
| 78 return output; |
| 79 } |
| 80 |
| 81 CastMessage CreateTestMessage() { |
| 82 CastMessage test_message; |
| 83 test_message.set_protocol_version(CastMessage::CASTV2_1_0); |
| 84 test_message.set_namespace_("ns"); |
| 85 test_message.set_source_id("source"); |
| 86 test_message.set_destination_id("dest"); |
| 87 test_message.set_payload_type(CastMessage::STRING); |
| 88 test_message.set_payload_utf8("payload"); |
| 89 return test_message; |
| 90 } |
| 91 |
| 92 class MockTCPSocket : public net::TCPClientSocket { |
| 93 public: |
| 94 explicit MockTCPSocket(const net::MockConnect& connect_data) |
| 95 : TCPClientSocket(net::AddressList(), |
| 96 nullptr, |
| 97 nullptr, |
| 98 net::NetLogSource()), |
| 99 connect_data_(connect_data), |
| 100 do_nothing_(false) {} |
| 101 |
| 102 explicit MockTCPSocket(bool do_nothing) |
| 103 : TCPClientSocket(net::AddressList(), |
| 104 nullptr, |
| 105 nullptr, |
| 106 net::NetLogSource()) { |
| 107 CHECK(do_nothing); |
| 108 do_nothing_ = do_nothing; |
| 109 } |
| 110 |
| 111 virtual int Connect(const net::CompletionCallback& callback) { |
| 112 if (do_nothing_) { |
| 113 // Stall the I/O event loop. |
| 114 return net::ERR_IO_PENDING; |
| 115 } |
| 116 |
| 117 if (connect_data_.mode == net::ASYNC) { |
| 118 CHECK_NE(connect_data_.result, net::ERR_IO_PENDING); |
| 119 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 120 FROM_HERE, base::Bind(callback, connect_data_.result)); |
| 121 return net::ERR_IO_PENDING; |
| 122 } else { |
| 123 return connect_data_.result; |
| 124 } |
| 125 } |
| 126 |
| 127 virtual bool SetKeepAlive(bool enable, int delay) { |
| 128 // Always return true in tests |
| 129 return true; |
| 130 } |
| 131 |
| 132 virtual bool SetNoDelay(bool no_delay) { |
| 133 // Always return true in tests |
| 134 return true; |
| 135 } |
| 136 |
| 137 MOCK_METHOD3(Read, |
| 138 int(net::IOBuffer*, int, const net::CompletionCallback&)); |
| 139 MOCK_METHOD3(Write, |
| 140 int(net::IOBuffer*, int, const net::CompletionCallback&)); |
| 141 |
| 142 virtual void Disconnect() { |
| 143 // Do nothing in tests |
| 144 } |
| 145 |
| 146 private: |
| 147 net::MockConnect connect_data_; |
| 148 bool do_nothing_; |
| 149 |
| 150 DISALLOW_COPY_AND_ASSIGN(MockTCPSocket); |
| 151 }; |
| 152 |
| 153 class MockDelegate : public CastTransport::Delegate { |
| 154 public: |
| 155 MockDelegate() {} |
| 156 virtual ~MockDelegate() {} |
| 157 MOCK_METHOD1(OnError, void(ChannelError error_state)); |
| 158 MOCK_METHOD1(OnMessage, void(const CastMessage& message)); |
| 159 MOCK_METHOD0(Start, void()); |
| 160 |
| 161 private: |
| 162 DISALLOW_COPY_AND_ASSIGN(MockDelegate); |
| 163 }; |
| 164 |
| 165 class CompleteHandler { |
| 166 public: |
| 167 CompleteHandler() {} |
| 168 MOCK_METHOD1(OnCloseComplete, void(int result)); |
| 169 MOCK_METHOD1(OnConnectComplete, void(ChannelError error_state)); |
| 170 MOCK_METHOD1(OnWriteComplete, void(int result)); |
| 171 MOCK_METHOD1(OnReadComplete, void(int result)); |
| 172 |
| 173 private: |
| 174 DISALLOW_COPY_AND_ASSIGN(CompleteHandler); |
| 175 }; |
| 176 |
| 177 class TestCastSocket : public CastSocketImpl { |
| 178 public: |
| 179 static std::unique_ptr<TestCastSocket> CreateSecure( |
| 180 Logger* logger, |
| 181 uint64_t device_capabilities = cast_channel::CastDeviceCapability::NONE) { |
| 182 return std::unique_ptr<TestCastSocket>(new TestCastSocket( |
| 183 CreateIPEndPointForTest(), ChannelAuthType::SSL_VERIFIED, |
| 184 kDistantTimeoutMillis, logger, device_capabilities)); |
| 185 } |
| 186 |
| 187 TestCastSocket(const net::IPEndPoint& ip_endpoint, |
| 188 ChannelAuthType channel_auth, |
| 189 int64_t timeout_ms, |
| 190 Logger* logger, |
| 191 uint64_t device_capabilities) |
| 192 : TestCastSocket(ip_endpoint, |
| 193 channel_auth, |
| 194 timeout_ms, |
| 195 logger, |
| 196 new net::TestNetLog(), |
| 197 device_capabilities) {} |
| 198 |
| 199 TestCastSocket(const net::IPEndPoint& ip_endpoint, |
| 200 ChannelAuthType channel_auth, |
| 201 int64_t timeout_ms, |
| 202 Logger* logger, |
| 203 net::TestNetLog* capturing_net_log, |
| 204 uint64_t device_capabilities) |
| 205 : CastSocketImpl("some_extension_id", |
| 206 ip_endpoint, |
| 207 channel_auth, |
| 208 capturing_net_log, |
| 209 base::TimeDelta::FromMilliseconds(timeout_ms), |
| 210 false, |
| 211 logger, |
| 212 device_capabilities, |
| 213 AuthContext::Create()), |
| 214 capturing_net_log_(capturing_net_log), |
| 215 ip_(ip_endpoint), |
| 216 extract_cert_result_(true), |
| 217 verify_challenge_result_(true), |
| 218 verify_challenge_disallow_(false), |
| 219 tcp_unresponsive_(false), |
| 220 mock_timer_(new base::MockTimer(false, false)), |
| 221 mock_transport_(nullptr) {} |
| 222 |
| 223 ~TestCastSocket() override {} |
| 224 |
| 225 void SetupMockTransport() { |
| 226 mock_transport_ = new MockCastTransport; |
| 227 SetTransportForTesting(base::WrapUnique(mock_transport_)); |
| 228 } |
| 229 |
| 230 // Socket connection helpers. |
| 231 void SetupTcpConnect(net::IoMode mode, int result) { |
| 232 tcp_connect_data_.reset(new net::MockConnect(mode, result)); |
| 233 } |
| 234 void SetupSslConnect(net::IoMode mode, int result) { |
| 235 ssl_connect_data_.reset(new net::MockConnect(mode, result)); |
| 236 } |
| 237 |
| 238 // Socket I/O helpers. |
| 239 void AddWriteResult(const net::MockWrite& write) { |
| 240 writes_.push_back(write); |
| 241 } |
| 242 void AddWriteResult(net::IoMode mode, int result) { |
| 243 AddWriteResult(net::MockWrite(mode, result)); |
| 244 } |
| 245 void AddWriteResultForData(net::IoMode mode, const std::string& msg) { |
| 246 AddWriteResult(mode, msg.size()); |
| 247 } |
| 248 void AddReadResult(const net::MockRead& read) { |
| 249 reads_.push_back(read); |
| 250 } |
| 251 void AddReadResult(net::IoMode mode, int result) { |
| 252 AddReadResult(net::MockRead(mode, result)); |
| 253 } |
| 254 void AddReadResultForData(net::IoMode mode, const std::string& data) { |
| 255 AddReadResult(net::MockRead(mode, data.c_str(), data.size())); |
| 256 } |
| 257 |
| 258 // Helpers for modifying other connection-related behaviors. |
| 259 void SetupTcpConnectUnresponsive() { tcp_unresponsive_ = true; } |
| 260 |
| 261 void SetExtractCertResult(bool value) { |
| 262 extract_cert_result_ = value; |
| 263 } |
| 264 |
| 265 void SetVerifyChallengeResult(bool value) { |
| 266 verify_challenge_result_ = value; |
| 267 } |
| 268 |
| 269 void TriggerTimeout() { |
| 270 mock_timer_->Fire(); |
| 271 } |
| 272 |
| 273 bool TestVerifyChannelPolicyNone() { |
| 274 AuthResult authResult; |
| 275 return VerifyChannelPolicy(authResult); |
| 276 } |
| 277 |
| 278 bool TestVerifyChannelPolicyAudioOnly() { |
| 279 AuthResult authResult; |
| 280 authResult.channel_policies |= AuthResult::POLICY_AUDIO_ONLY; |
| 281 return VerifyChannelPolicy(authResult); |
| 282 } |
| 283 |
| 284 void DisallowVerifyChallengeResult() { verify_challenge_disallow_ = true; } |
| 285 |
| 286 MockCastTransport* GetMockTransport() { |
| 287 CHECK(mock_transport_); |
| 288 return mock_transport_; |
| 289 } |
| 290 |
| 291 private: |
| 292 std::unique_ptr<net::TCPClientSocket> CreateTcpSocket() override { |
| 293 if (tcp_unresponsive_) { |
| 294 return std::unique_ptr<net::TCPClientSocket>(new MockTCPSocket(true)); |
| 295 } else { |
| 296 net::MockConnect* connect_data = tcp_connect_data_.get(); |
| 297 connect_data->peer_addr = ip_; |
| 298 return std::unique_ptr<net::TCPClientSocket>( |
| 299 new MockTCPSocket(*connect_data)); |
| 300 } |
| 301 } |
| 302 |
| 303 std::unique_ptr<net::SSLClientSocket> CreateSslSocket( |
| 304 std::unique_ptr<net::StreamSocket> socket) override { |
| 305 net::MockConnect* connect_data = ssl_connect_data_.get(); |
| 306 connect_data->peer_addr = ip_; |
| 307 |
| 308 ssl_data_.reset(new net::StaticSocketDataProvider( |
| 309 reads_.data(), reads_.size(), writes_.data(), writes_.size())); |
| 310 ssl_data_->set_connect_data(*connect_data); |
| 311 // NOTE: net::MockTCPClientSocket inherits from net::SSLClientSocket !! |
| 312 return std::unique_ptr<net::SSLClientSocket>(new net::MockTCPClientSocket( |
| 313 net::AddressList(), capturing_net_log_.get(), ssl_data_.get())); |
| 314 } |
| 315 |
| 316 scoped_refptr<net::X509Certificate> ExtractPeerCert() override { |
| 317 return extract_cert_result_ |
| 318 ? net::ImportCertFromFile(net::GetTestCertsDirectory(), |
| 319 "ok_cert.pem") |
| 320 : nullptr; |
| 321 } |
| 322 |
| 323 bool VerifyChallengeReply() override { |
| 324 EXPECT_FALSE(verify_challenge_disallow_); |
| 325 return verify_challenge_result_; |
| 326 } |
| 327 |
| 328 base::Timer* GetTimer() override { return mock_timer_.get(); } |
| 329 |
| 330 std::unique_ptr<net::TestNetLog> capturing_net_log_; |
| 331 net::IPEndPoint ip_; |
| 332 // Simulated connect data |
| 333 std::unique_ptr<net::MockConnect> tcp_connect_data_; |
| 334 std::unique_ptr<net::MockConnect> ssl_connect_data_; |
| 335 // Simulated read / write data |
| 336 std::vector<net::MockWrite> writes_; |
| 337 std::vector<net::MockRead> reads_; |
| 338 std::unique_ptr<net::SocketDataProvider> ssl_data_; |
| 339 // Simulated result of peer cert extraction. |
| 340 bool extract_cert_result_; |
| 341 // Simulated result of verifying challenge reply. |
| 342 bool verify_challenge_result_; |
| 343 bool verify_challenge_disallow_; |
| 344 // If true, makes TCP connection process stall. For timeout testing. |
| 345 bool tcp_unresponsive_; |
| 346 std::unique_ptr<base::MockTimer> mock_timer_; |
| 347 MockCastTransport* mock_transport_; |
| 348 |
| 349 DISALLOW_COPY_AND_ASSIGN(TestCastSocket); |
| 350 }; |
| 351 |
| 352 class CastSocketTest : public testing::Test { |
| 353 public: |
| 354 CastSocketTest() : logger_(new Logger()), delegate_(new MockDelegate) {} |
| 355 ~CastSocketTest() override {} |
| 356 |
| 357 void SetUp() override { EXPECT_CALL(*delegate_, OnMessage(_)).Times(0); } |
| 358 |
| 359 void TearDown() override { |
| 360 if (socket_.get()) { |
| 361 EXPECT_CALL(handler_, OnCloseComplete(net::OK)); |
| 362 socket_->Close(base::Bind(&CompleteHandler::OnCloseComplete, |
| 363 base::Unretained(&handler_))); |
| 364 } |
| 365 } |
| 366 |
| 367 void CreateCastSocketSecure() { |
| 368 socket_ = TestCastSocket::CreateSecure(logger_); |
| 369 } |
| 370 |
| 371 void HandleAuthHandshake() { |
| 372 socket_->SetupMockTransport(); |
| 373 CastMessage challenge_proto = CreateAuthChallenge(); |
| 374 EXPECT_CALL(*socket_->GetMockTransport(), |
| 375 SendMessage(EqualsProto(challenge_proto), _)) |
| 376 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| 377 EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| 378 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::NONE)); |
| 379 socket_->Connect(std::move(delegate_), |
| 380 base::Bind(&CompleteHandler::OnConnectComplete, |
| 381 base::Unretained(&handler_))); |
| 382 RunPendingTasks(); |
| 383 socket_->GetMockTransport()->current_delegate()->OnMessage( |
| 384 CreateAuthReply()); |
| 385 RunPendingTasks(); |
| 386 } |
| 387 |
| 388 protected: |
| 389 // Runs all pending tasks in the message loop. |
| 390 void RunPendingTasks() { |
| 391 base::RunLoop run_loop; |
| 392 run_loop.RunUntilIdle(); |
| 393 } |
| 394 |
| 395 base::MessageLoop message_loop_; |
| 396 Logger* logger_; |
| 397 std::unique_ptr<TestCastSocket> socket_; |
| 398 CompleteHandler handler_; |
| 399 std::unique_ptr<MockDelegate> delegate_; |
| 400 |
| 401 private: |
| 402 DISALLOW_COPY_AND_ASSIGN(CastSocketTest); |
| 403 }; |
| 404 |
| 405 // Tests that the following connection flow works: |
| 406 // - TCP connection succeeds (async) |
| 407 // - SSL connection succeeds (async) |
| 408 // - Cert is extracted successfully |
| 409 // - Challenge request is sent (async) |
| 410 // - Challenge response is received (async) |
| 411 // - Credentials are verified successfuly |
| 412 TEST_F(CastSocketTest, TestConnectFullSecureFlowAsync) { |
| 413 CreateCastSocketSecure(); |
| 414 socket_->SetupTcpConnect(net::ASYNC, net::OK); |
| 415 socket_->SetupSslConnect(net::ASYNC, net::OK); |
| 416 |
| 417 HandleAuthHandshake(); |
| 418 |
| 419 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| 420 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| 421 } |
| 422 |
| 423 // Tests that the following connection flow works: |
| 424 // - TCP connection succeeds (sync) |
| 425 // - SSL connection succeeds (sync) |
| 426 // - Cert is extracted successfully |
| 427 // - Challenge request is sent (sync) |
| 428 // - Challenge response is received (sync) |
| 429 // - Credentials are verified successfuly |
| 430 TEST_F(CastSocketTest, TestConnectFullSecureFlowSync) { |
| 431 CreateCastSocketSecure(); |
| 432 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 433 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| 434 |
| 435 HandleAuthHandshake(); |
| 436 |
| 437 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| 438 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| 439 } |
| 440 |
| 441 // Test that an AuthMessage with a mangled namespace triggers cancelation |
| 442 // of the connection event loop. |
| 443 TEST_F(CastSocketTest, TestConnectAuthMessageCorrupted) { |
| 444 CreateCastSocketSecure(); |
| 445 socket_->SetupMockTransport(); |
| 446 |
| 447 socket_->SetupTcpConnect(net::ASYNC, net::OK); |
| 448 socket_->SetupSslConnect(net::ASYNC, net::OK); |
| 449 |
| 450 CastMessage challenge_proto = CreateAuthChallenge(); |
| 451 EXPECT_CALL(*socket_->GetMockTransport(), |
| 452 SendMessage(EqualsProto(challenge_proto), _)) |
| 453 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| 454 EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| 455 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::TRANSPORT_ERROR)); |
| 456 socket_->Connect(std::move(delegate_), |
| 457 base::Bind(&CompleteHandler::OnConnectComplete, |
| 458 base::Unretained(&handler_))); |
| 459 RunPendingTasks(); |
| 460 CastMessage mangled_auth_reply = CreateAuthReply(); |
| 461 mangled_auth_reply.set_namespace_("BOGUS_NAMESPACE"); |
| 462 |
| 463 socket_->GetMockTransport()->current_delegate()->OnMessage( |
| 464 mangled_auth_reply); |
| 465 RunPendingTasks(); |
| 466 |
| 467 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 468 EXPECT_EQ(ChannelError::TRANSPORT_ERROR, socket_->error_state()); |
| 469 |
| 470 // Verifies that the CastSocket's resources were torn down during channel |
| 471 // close. (see http://crbug.com/504078) |
| 472 EXPECT_EQ(nullptr, socket_->transport()); |
| 473 } |
| 474 |
| 475 // Test connection error - TCP connect fails (async) |
| 476 TEST_F(CastSocketTest, TestConnectTcpConnectErrorAsync) { |
| 477 CreateCastSocketSecure(); |
| 478 |
| 479 socket_->SetupTcpConnect(net::ASYNC, net::ERR_FAILED); |
| 480 |
| 481 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_ERROR)); |
| 482 socket_->Connect(std::move(delegate_), |
| 483 base::Bind(&CompleteHandler::OnConnectComplete, |
| 484 base::Unretained(&handler_))); |
| 485 RunPendingTasks(); |
| 486 |
| 487 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 488 EXPECT_EQ(ChannelError::CONNECT_ERROR, socket_->error_state()); |
| 489 } |
| 490 |
| 491 // Test connection error - TCP connect fails (sync) |
| 492 TEST_F(CastSocketTest, TestConnectTcpConnectErrorSync) { |
| 493 CreateCastSocketSecure(); |
| 494 |
| 495 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::ERR_FAILED); |
| 496 |
| 497 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_ERROR)); |
| 498 socket_->Connect(std::move(delegate_), |
| 499 base::Bind(&CompleteHandler::OnConnectComplete, |
| 500 base::Unretained(&handler_))); |
| 501 RunPendingTasks(); |
| 502 |
| 503 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 504 EXPECT_EQ(ChannelError::CONNECT_ERROR, socket_->error_state()); |
| 505 } |
| 506 |
| 507 // Test connection error - timeout |
| 508 TEST_F(CastSocketTest, TestConnectTcpTimeoutError) { |
| 509 CreateCastSocketSecure(); |
| 510 socket_->SetupTcpConnectUnresponsive(); |
| 511 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); |
| 512 EXPECT_CALL(*delegate_, OnError(ChannelError::CONNECT_TIMEOUT)); |
| 513 socket_->Connect(std::move(delegate_), |
| 514 base::Bind(&CompleteHandler::OnConnectComplete, |
| 515 base::Unretained(&handler_))); |
| 516 RunPendingTasks(); |
| 517 |
| 518 EXPECT_EQ(ReadyState::CONNECTING, socket_->ready_state()); |
| 519 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| 520 socket_->TriggerTimeout(); |
| 521 RunPendingTasks(); |
| 522 |
| 523 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 524 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| 525 } |
| 526 |
| 527 // Test connection error - TCP socket returns timeout |
| 528 TEST_F(CastSocketTest, TestConnectTcpSocketTimeoutError) { |
| 529 CreateCastSocketSecure(); |
| 530 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::ERR_CONNECTION_TIMED_OUT); |
| 531 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); |
| 532 EXPECT_CALL(*delegate_, OnError(ChannelError::CONNECT_TIMEOUT)); |
| 533 socket_->Connect(std::move(delegate_), |
| 534 base::Bind(&CompleteHandler::OnConnectComplete, |
| 535 base::Unretained(&handler_))); |
| 536 RunPendingTasks(); |
| 537 |
| 538 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 539 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| 540 EXPECT_EQ(net::ERR_CONNECTION_TIMED_OUT, |
| 541 logger_->GetLastErrors(socket_->id()).net_return_value); |
| 542 } |
| 543 |
| 544 // Test connection error - SSL connect fails (async) |
| 545 TEST_F(CastSocketTest, TestConnectSslConnectErrorAsync) { |
| 546 CreateCastSocketSecure(); |
| 547 |
| 548 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 549 socket_->SetupSslConnect(net::SYNCHRONOUS, net::ERR_FAILED); |
| 550 |
| 551 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::AUTHENTICATION_ERROR)); |
| 552 socket_->Connect(std::move(delegate_), |
| 553 base::Bind(&CompleteHandler::OnConnectComplete, |
| 554 base::Unretained(&handler_))); |
| 555 RunPendingTasks(); |
| 556 |
| 557 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 558 EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); |
| 559 } |
| 560 |
| 561 // Test connection error - SSL connect fails (sync) |
| 562 TEST_F(CastSocketTest, TestConnectSslConnectErrorSync) { |
| 563 CreateCastSocketSecure(); |
| 564 |
| 565 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 566 socket_->SetupSslConnect(net::SYNCHRONOUS, net::ERR_FAILED); |
| 567 |
| 568 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::AUTHENTICATION_ERROR)); |
| 569 socket_->Connect(std::move(delegate_), |
| 570 base::Bind(&CompleteHandler::OnConnectComplete, |
| 571 base::Unretained(&handler_))); |
| 572 RunPendingTasks(); |
| 573 |
| 574 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 575 EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); |
| 576 EXPECT_EQ(net::ERR_FAILED, |
| 577 logger_->GetLastErrors(socket_->id()).net_return_value); |
| 578 } |
| 579 |
| 580 // Test connection error - SSL connect times out (sync) |
| 581 TEST_F(CastSocketTest, TestConnectSslConnectTimeoutSync) { |
| 582 CreateCastSocketSecure(); |
| 583 |
| 584 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 585 socket_->SetupSslConnect(net::SYNCHRONOUS, net::ERR_CONNECTION_TIMED_OUT); |
| 586 |
| 587 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); |
| 588 socket_->Connect(std::move(delegate_), |
| 589 base::Bind(&CompleteHandler::OnConnectComplete, |
| 590 base::Unretained(&handler_))); |
| 591 RunPendingTasks(); |
| 592 |
| 593 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 594 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| 595 EXPECT_EQ(net::ERR_CONNECTION_TIMED_OUT, |
| 596 logger_->GetLastErrors(socket_->id()).net_return_value); |
| 597 } |
| 598 |
| 599 // Test connection error - SSL connect times out (async) |
| 600 TEST_F(CastSocketTest, TestConnectSslConnectTimeoutAsync) { |
| 601 CreateCastSocketSecure(); |
| 602 |
| 603 socket_->SetupTcpConnect(net::ASYNC, net::OK); |
| 604 socket_->SetupSslConnect(net::ASYNC, net::ERR_CONNECTION_TIMED_OUT); |
| 605 |
| 606 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CONNECT_TIMEOUT)); |
| 607 socket_->Connect(std::move(delegate_), |
| 608 base::Bind(&CompleteHandler::OnConnectComplete, |
| 609 base::Unretained(&handler_))); |
| 610 RunPendingTasks(); |
| 611 |
| 612 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 613 EXPECT_EQ(ChannelError::CONNECT_TIMEOUT, socket_->error_state()); |
| 614 } |
| 615 |
| 616 // Test connection error - challenge send fails |
| 617 TEST_F(CastSocketTest, TestConnectChallengeSendError) { |
| 618 CreateCastSocketSecure(); |
| 619 socket_->SetupMockTransport(); |
| 620 |
| 621 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 622 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| 623 EXPECT_CALL(*socket_->GetMockTransport(), |
| 624 SendMessage(EqualsProto(CreateAuthChallenge()), _)) |
| 625 .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET)); |
| 626 |
| 627 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CAST_SOCKET_ERROR)); |
| 628 socket_->Connect(std::move(delegate_), |
| 629 base::Bind(&CompleteHandler::OnConnectComplete, |
| 630 base::Unretained(&handler_))); |
| 631 RunPendingTasks(); |
| 632 |
| 633 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 634 EXPECT_EQ(ChannelError::CAST_SOCKET_ERROR, socket_->error_state()); |
| 635 } |
| 636 |
| 637 // Test connection error - connection is destroyed after the challenge is |
| 638 // sent, with the async result still lurking in the task queue. |
| 639 TEST_F(CastSocketTest, TestConnectDestroyedAfterChallengeSent) { |
| 640 CreateCastSocketSecure(); |
| 641 socket_->SetupMockTransport(); |
| 642 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 643 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| 644 EXPECT_CALL(*socket_->GetMockTransport(), |
| 645 SendMessage(EqualsProto(CreateAuthChallenge()), _)) |
| 646 .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET)); |
| 647 socket_->Connect(std::move(delegate_), |
| 648 base::Bind(&CompleteHandler::OnConnectComplete, |
| 649 base::Unretained(&handler_))); |
| 650 socket_.reset(); |
| 651 RunPendingTasks(); |
| 652 } |
| 653 |
| 654 // Test connection error - challenge reply receive fails |
| 655 TEST_F(CastSocketTest, TestConnectChallengeReplyReceiveError) { |
| 656 CreateCastSocketSecure(); |
| 657 socket_->SetupMockTransport(); |
| 658 |
| 659 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 660 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| 661 EXPECT_CALL(*socket_->GetMockTransport(), |
| 662 SendMessage(EqualsProto(CreateAuthChallenge()), _)) |
| 663 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| 664 socket_->AddReadResult(net::SYNCHRONOUS, net::ERR_FAILED); |
| 665 EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR)); |
| 666 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::CAST_SOCKET_ERROR)); |
| 667 EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| 668 socket_->Connect(std::move(delegate_), |
| 669 base::Bind(&CompleteHandler::OnConnectComplete, |
| 670 base::Unretained(&handler_))); |
| 671 RunPendingTasks(); |
| 672 socket_->GetMockTransport()->current_delegate()->OnError( |
| 673 ChannelError::CAST_SOCKET_ERROR); |
| 674 RunPendingTasks(); |
| 675 |
| 676 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 677 EXPECT_EQ(ChannelError::CAST_SOCKET_ERROR, socket_->error_state()); |
| 678 } |
| 679 |
| 680 TEST_F(CastSocketTest, TestConnectChallengeVerificationFails) { |
| 681 CreateCastSocketSecure(); |
| 682 socket_->SetupMockTransport(); |
| 683 socket_->SetupTcpConnect(net::ASYNC, net::OK); |
| 684 socket_->SetupSslConnect(net::ASYNC, net::OK); |
| 685 socket_->SetVerifyChallengeResult(false); |
| 686 |
| 687 EXPECT_CALL(*delegate_, OnError(ChannelError::AUTHENTICATION_ERROR)); |
| 688 CastMessage challenge_proto = CreateAuthChallenge(); |
| 689 EXPECT_CALL(*socket_->GetMockTransport(), |
| 690 SendMessage(EqualsProto(challenge_proto), _)) |
| 691 .WillOnce(PostCompletionCallbackTask<1>(net::OK)); |
| 692 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::AUTHENTICATION_ERROR)); |
| 693 EXPECT_CALL(*socket_->GetMockTransport(), Start()); |
| 694 socket_->Connect(std::move(delegate_), |
| 695 base::Bind(&CompleteHandler::OnConnectComplete, |
| 696 base::Unretained(&handler_))); |
| 697 RunPendingTasks(); |
| 698 socket_->GetMockTransport()->current_delegate()->OnMessage(CreateAuthReply()); |
| 699 RunPendingTasks(); |
| 700 |
| 701 EXPECT_EQ(ReadyState::CLOSED, socket_->ready_state()); |
| 702 EXPECT_EQ(ChannelError::AUTHENTICATION_ERROR, socket_->error_state()); |
| 703 } |
| 704 |
| 705 // Sends message data through an actual non-mocked CastTransport object, |
| 706 // testing the two components in integration. |
| 707 TEST_F(CastSocketTest, TestConnectEndToEndWithRealTransportAsync) { |
| 708 CreateCastSocketSecure(); |
| 709 socket_->SetupTcpConnect(net::ASYNC, net::OK); |
| 710 socket_->SetupSslConnect(net::ASYNC, net::OK); |
| 711 |
| 712 // Set low-level auth challenge expectations. |
| 713 CastMessage challenge = CreateAuthChallenge(); |
| 714 std::string challenge_str; |
| 715 EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); |
| 716 socket_->AddWriteResultForData(net::ASYNC, challenge_str); |
| 717 |
| 718 // Set low-level auth reply expectations. |
| 719 CastMessage reply = CreateAuthReply(); |
| 720 std::string reply_str; |
| 721 EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); |
| 722 socket_->AddReadResultForData(net::ASYNC, reply_str); |
| 723 socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
| 724 |
| 725 CastMessage test_message = CreateTestMessage(); |
| 726 std::string test_message_str; |
| 727 EXPECT_TRUE(MessageFramer::Serialize(test_message, &test_message_str)); |
| 728 socket_->AddWriteResultForData(net::ASYNC, test_message_str); |
| 729 |
| 730 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::NONE)); |
| 731 socket_->Connect(std::move(delegate_), |
| 732 base::Bind(&CompleteHandler::OnConnectComplete, |
| 733 base::Unretained(&handler_))); |
| 734 RunPendingTasks(); |
| 735 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| 736 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| 737 |
| 738 // Send the test message through a real transport object. |
| 739 EXPECT_CALL(handler_, OnWriteComplete(net::OK)); |
| 740 socket_->transport()->SendMessage( |
| 741 test_message, base::Bind(&CompleteHandler::OnWriteComplete, |
| 742 base::Unretained(&handler_))); |
| 743 RunPendingTasks(); |
| 744 |
| 745 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| 746 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| 747 } |
| 748 |
| 749 // Same as TestConnectEndToEndWithRealTransportAsync, except synchronous. |
| 750 TEST_F(CastSocketTest, TestConnectEndToEndWithRealTransportSync) { |
| 751 CreateCastSocketSecure(); |
| 752 socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK); |
| 753 socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK); |
| 754 |
| 755 // Set low-level auth challenge expectations. |
| 756 CastMessage challenge = CreateAuthChallenge(); |
| 757 std::string challenge_str; |
| 758 EXPECT_TRUE(MessageFramer::Serialize(challenge, &challenge_str)); |
| 759 socket_->AddWriteResultForData(net::SYNCHRONOUS, challenge_str); |
| 760 |
| 761 // Set low-level auth reply expectations. |
| 762 CastMessage reply = CreateAuthReply(); |
| 763 std::string reply_str; |
| 764 EXPECT_TRUE(MessageFramer::Serialize(reply, &reply_str)); |
| 765 socket_->AddReadResultForData(net::SYNCHRONOUS, reply_str); |
| 766 socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
| 767 |
| 768 CastMessage test_message = CreateTestMessage(); |
| 769 std::string test_message_str; |
| 770 EXPECT_TRUE(MessageFramer::Serialize(test_message, &test_message_str)); |
| 771 socket_->AddWriteResultForData(net::SYNCHRONOUS, test_message_str); |
| 772 |
| 773 EXPECT_CALL(handler_, OnConnectComplete(ChannelError::NONE)); |
| 774 socket_->Connect(std::move(delegate_), |
| 775 base::Bind(&CompleteHandler::OnConnectComplete, |
| 776 base::Unretained(&handler_))); |
| 777 RunPendingTasks(); |
| 778 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| 779 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| 780 |
| 781 // Send the test message through a real transport object. |
| 782 EXPECT_CALL(handler_, OnWriteComplete(net::OK)); |
| 783 socket_->transport()->SendMessage( |
| 784 test_message, base::Bind(&CompleteHandler::OnWriteComplete, |
| 785 base::Unretained(&handler_))); |
| 786 RunPendingTasks(); |
| 787 |
| 788 EXPECT_EQ(ReadyState::OPEN, socket_->ready_state()); |
| 789 EXPECT_EQ(ChannelError::NONE, socket_->error_state()); |
| 790 } |
| 791 |
| 792 } // namespace cast_channel |
| 793 } // namespace api |
| 794 } // namespace extensions |
OLD | NEW |