| Index: chrome/browser/extensions/api/cast_channel/cast_socket.cc
|
| diff --git a/chrome/browser/extensions/api/cast_channel/cast_socket.cc b/chrome/browser/extensions/api/cast_channel/cast_socket.cc
|
| index 6130d92e18755dc825880177b785f7536baf5afc..db128d9efe901cd63dcf4cec37a9675c50399d84 100644
|
| --- a/chrome/browser/extensions/api/cast_channel/cast_socket.cc
|
| +++ b/chrome/browser/extensions/api/cast_channel/cast_socket.cc
|
| @@ -67,7 +67,8 @@ CastSocket::CastSocket(const std::string& owner_extension_id,
|
| const net::IPEndPoint& ip_endpoint,
|
| ChannelAuthType channel_auth,
|
| CastSocket::Delegate* delegate,
|
| - net::NetLog* net_log) :
|
| + net::NetLog* net_log,
|
| + const base::TimeDelta& timeout) :
|
| ApiResource(owner_extension_id),
|
| channel_id_(0),
|
| ip_endpoint_(ip_endpoint),
|
| @@ -76,6 +77,9 @@ CastSocket::CastSocket(const std::string& owner_extension_id,
|
| current_message_size_(0),
|
| current_message_(new CastMessage()),
|
| net_log_(net_log),
|
| + connect_timeout_(timeout),
|
| + connect_timeout_timer_(new base::OneShotTimer<CastSocket>),
|
| + is_canceled_(false),
|
| connect_state_(CONN_STATE_NONE),
|
| write_state_(WRITE_STATE_NONE),
|
| read_state_(READ_STATE_NONE),
|
| @@ -171,6 +175,12 @@ void CastSocket::Connect(const net::CompletionCallback& callback) {
|
| ready_state_ = READY_STATE_CONNECTING;
|
| connect_callback_ = callback;
|
| connect_state_ = CONN_STATE_TCP_CONNECT;
|
| + if (connect_timeout_.InMicroseconds() > 0) {
|
| + GetTimer()->Start(
|
| + FROM_HERE,
|
| + connect_timeout_,
|
| + base::Bind(&CastSocket::CancelConnect, AsWeakPtr()));
|
| + }
|
| DoConnectLoop(net::OK);
|
| }
|
|
|
| @@ -181,11 +191,23 @@ void CastSocket::PostTaskToStartConnectLoop(int result) {
|
| base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr(), result));
|
| }
|
|
|
| +void CastSocket::CancelConnect() {
|
| + DCHECK(CalledOnValidThread());
|
| + // Stop all pending connection setup tasks and report back to the client.
|
| + is_canceled_ = true;
|
| + VLOG_WITH_CONNECTION(1) << "Timeout while establishing a connection.";
|
| + DoConnectCallback(net::ERR_TIMED_OUT);
|
| +}
|
| +
|
| // This method performs the state machine transitions for connection flow.
|
| // There are two entry points to this method:
|
| // 1. Connect method: this starts the flow
|
| // 2. Callback from network operations that finish asynchronously
|
| void CastSocket::DoConnectLoop(int result) {
|
| + if (is_canceled_) {
|
| + LOG(ERROR) << "CANCELLED - Aborting DoConnectLoop.";
|
| + return;
|
| + }
|
| // Network operations can either finish synchronously or asynchronously.
|
| // This method executes the state machine transitions in a loop so that
|
| // correct state transitions happen even when network operations finish
|
| @@ -229,8 +251,10 @@ void CastSocket::DoConnectLoop(int result) {
|
| // b. The Do* method called did not change state
|
|
|
| // Connect loop is finished: if there is no pending IO invoke the callback.
|
| - if (rv != net::ERR_IO_PENDING)
|
| + if (rv != net::ERR_IO_PENDING) {
|
| + GetTimer()->Stop();
|
| DoConnectCallback(rv);
|
| + }
|
| }
|
|
|
| int CastSocket::DoTcpConnect() {
|
| @@ -284,7 +308,8 @@ int CastSocket::DoAuthChallengeSend() {
|
| // code decoupled from connect loop code.
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&CastSocket::SendCastMessageInternal, AsWeakPtr(),
|
| + base::Bind(&CastSocket::SendCastMessageInternal,
|
| + AsWeakPtr(),
|
| challenge_message,
|
| base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())));
|
| // Always return IO_PENDING since the result is always asynchronous.
|
| @@ -316,10 +341,15 @@ int CastSocket::DoAuthChallengeReplyComplete(int result) {
|
|
|
| void CastSocket::DoConnectCallback(int result) {
|
| ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED;
|
| - error_state_ = (result == net::OK) ?
|
| - CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR;
|
| - if (result == net::OK) // Start the read loop
|
| + if (result == net::OK) {
|
| + error_state_ = CHANNEL_ERROR_NONE;
|
| PostTaskToStartReadLoop();
|
| + } else if (result == net::ERR_TIMED_OUT) {
|
| + error_state_ = CHANNEL_ERROR_CONNECT_TIMEOUT;
|
| + } else {
|
| + error_state_ = CHANNEL_ERROR_CONNECT_ERROR;
|
| + }
|
| + VLOG_WITH_CONNECTION(1) << "Calling Connect_Callback";
|
| base::ResetAndReturn(&connect_callback_).Run(result);
|
| }
|
|
|
| @@ -682,7 +712,7 @@ bool CastSocket::Serialize(const CastMessage& message_proto,
|
| header.SetMessageSize(message_size);
|
| header.PrependToString(message_data);
|
| return true;
|
| -};
|
| +}
|
|
|
| void CastSocket::CloseWithError(ChannelError error) {
|
| DCHECK(CalledOnValidThread());
|
| @@ -702,6 +732,10 @@ bool CastSocket::CalledOnValidThread() const {
|
| return thread_checker_.CalledOnValidThread();
|
| }
|
|
|
| +base::Timer* CastSocket::GetTimer() {
|
| + return connect_timeout_timer_.get();
|
| +}
|
| +
|
| CastSocket::MessageHeader::MessageHeader() : message_size(0) { }
|
|
|
| void CastSocket::MessageHeader::SetMessageSize(size_t size) {
|
|
|