| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h" | 5 #include "chrome/browser/extensions/api/cast_channel/cast_socket.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 return g_factory.Pointer(); | 60 return g_factory.Pointer(); |
| 61 } | 61 } |
| 62 | 62 |
| 63 namespace api { | 63 namespace api { |
| 64 namespace cast_channel { | 64 namespace cast_channel { |
| 65 | 65 |
| 66 CastSocket::CastSocket(const std::string& owner_extension_id, | 66 CastSocket::CastSocket(const std::string& owner_extension_id, |
| 67 const net::IPEndPoint& ip_endpoint, | 67 const net::IPEndPoint& ip_endpoint, |
| 68 ChannelAuthType channel_auth, | 68 ChannelAuthType channel_auth, |
| 69 CastSocket::Delegate* delegate, | 69 CastSocket::Delegate* delegate, |
| 70 net::NetLog* net_log) : | 70 net::NetLog* net_log, |
| 71 const base::TimeDelta& timeout) : |
| 71 ApiResource(owner_extension_id), | 72 ApiResource(owner_extension_id), |
| 72 channel_id_(0), | 73 channel_id_(0), |
| 73 ip_endpoint_(ip_endpoint), | 74 ip_endpoint_(ip_endpoint), |
| 74 channel_auth_(channel_auth), | 75 channel_auth_(channel_auth), |
| 75 delegate_(delegate), | 76 delegate_(delegate), |
| 76 current_message_size_(0), | 77 current_message_size_(0), |
| 77 current_message_(new CastMessage()), | 78 current_message_(new CastMessage()), |
| 78 net_log_(net_log), | 79 net_log_(net_log), |
| 80 connect_timeout_(timeout), |
| 81 connect_timeout_timer_(new base::OneShotTimer<CastSocket>), |
| 82 is_canceled_(false), |
| 79 connect_state_(CONN_STATE_NONE), | 83 connect_state_(CONN_STATE_NONE), |
| 80 write_state_(WRITE_STATE_NONE), | 84 write_state_(WRITE_STATE_NONE), |
| 81 read_state_(READ_STATE_NONE), | 85 read_state_(READ_STATE_NONE), |
| 82 error_state_(CHANNEL_ERROR_NONE), | 86 error_state_(CHANNEL_ERROR_NONE), |
| 83 ready_state_(READY_STATE_NONE) { | 87 ready_state_(READY_STATE_NONE) { |
| 84 DCHECK(net_log_); | 88 DCHECK(net_log_); |
| 85 DCHECK(channel_auth_ == CHANNEL_AUTH_TYPE_SSL || | 89 DCHECK(channel_auth_ == CHANNEL_AUTH_TYPE_SSL || |
| 86 channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED); | 90 channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED); |
| 87 net_log_source_.type = net::NetLog::SOURCE_SOCKET; | 91 net_log_source_.type = net::NetLog::SOURCE_SOCKET; |
| 88 net_log_source_.id = net_log_->NextID(); | 92 net_log_source_.id = net_log_->NextID(); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 void CastSocket::Connect(const net::CompletionCallback& callback) { | 168 void CastSocket::Connect(const net::CompletionCallback& callback) { |
| 165 DCHECK(CalledOnValidThread()); | 169 DCHECK(CalledOnValidThread()); |
| 166 VLOG_WITH_CONNECTION(1) << "Connect readyState = " << ready_state_; | 170 VLOG_WITH_CONNECTION(1) << "Connect readyState = " << ready_state_; |
| 167 if (ready_state_ != READY_STATE_NONE) { | 171 if (ready_state_ != READY_STATE_NONE) { |
| 168 callback.Run(net::ERR_CONNECTION_FAILED); | 172 callback.Run(net::ERR_CONNECTION_FAILED); |
| 169 return; | 173 return; |
| 170 } | 174 } |
| 171 ready_state_ = READY_STATE_CONNECTING; | 175 ready_state_ = READY_STATE_CONNECTING; |
| 172 connect_callback_ = callback; | 176 connect_callback_ = callback; |
| 173 connect_state_ = CONN_STATE_TCP_CONNECT; | 177 connect_state_ = CONN_STATE_TCP_CONNECT; |
| 178 if (connect_timeout_.InMicroseconds() > 0) { |
| 179 GetTimer()->Start( |
| 180 FROM_HERE, |
| 181 connect_timeout_, |
| 182 base::Bind(&CastSocket::CancelConnect, AsWeakPtr())); |
| 183 } |
| 174 DoConnectLoop(net::OK); | 184 DoConnectLoop(net::OK); |
| 175 } | 185 } |
| 176 | 186 |
| 177 void CastSocket::PostTaskToStartConnectLoop(int result) { | 187 void CastSocket::PostTaskToStartConnectLoop(int result) { |
| 178 DCHECK(CalledOnValidThread()); | 188 DCHECK(CalledOnValidThread()); |
| 179 base::MessageLoop::current()->PostTask( | 189 base::MessageLoop::current()->PostTask( |
| 180 FROM_HERE, | 190 FROM_HERE, |
| 181 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr(), result)); | 191 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr(), result)); |
| 182 } | 192 } |
| 183 | 193 |
| 194 void CastSocket::CancelConnect() { |
| 195 DCHECK(CalledOnValidThread()); |
| 196 // Stop all pending connection setup tasks and report back to the client. |
| 197 is_canceled_ = true; |
| 198 VLOG_WITH_CONNECTION(1) << "Timeout while establishing a connection."; |
| 199 DoConnectCallback(net::ERR_TIMED_OUT); |
| 200 } |
| 201 |
| 184 // This method performs the state machine transitions for connection flow. | 202 // This method performs the state machine transitions for connection flow. |
| 185 // There are two entry points to this method: | 203 // There are two entry points to this method: |
| 186 // 1. Connect method: this starts the flow | 204 // 1. Connect method: this starts the flow |
| 187 // 2. Callback from network operations that finish asynchronously | 205 // 2. Callback from network operations that finish asynchronously |
| 188 void CastSocket::DoConnectLoop(int result) { | 206 void CastSocket::DoConnectLoop(int result) { |
| 207 if (is_canceled_) { |
| 208 LOG(ERROR) << "CANCELLED - Aborting DoConnectLoop."; |
| 209 return; |
| 210 } |
| 189 // Network operations can either finish synchronously or asynchronously. | 211 // Network operations can either finish synchronously or asynchronously. |
| 190 // This method executes the state machine transitions in a loop so that | 212 // This method executes the state machine transitions in a loop so that |
| 191 // correct state transitions happen even when network operations finish | 213 // correct state transitions happen even when network operations finish |
| 192 // synchronously. | 214 // synchronously. |
| 193 int rv = result; | 215 int rv = result; |
| 194 do { | 216 do { |
| 195 ConnectionState state = connect_state_; | 217 ConnectionState state = connect_state_; |
| 196 // Default to CONN_STATE_NONE, which breaks the processing loop if any | 218 // Default to CONN_STATE_NONE, which breaks the processing loop if any |
| 197 // handler fails to transition to another state to continue processing. | 219 // handler fails to transition to another state to continue processing. |
| 198 connect_state_ = CONN_STATE_NONE; | 220 connect_state_ = CONN_STATE_NONE; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 222 default: | 244 default: |
| 223 NOTREACHED() << "BUG in connect flow. Unknown state: " << state; | 245 NOTREACHED() << "BUG in connect flow. Unknown state: " << state; |
| 224 break; | 246 break; |
| 225 } | 247 } |
| 226 } while (rv != net::ERR_IO_PENDING && connect_state_ != CONN_STATE_NONE); | 248 } while (rv != net::ERR_IO_PENDING && connect_state_ != CONN_STATE_NONE); |
| 227 // Get out of the loop either when: | 249 // Get out of the loop either when: |
| 228 // a. A network operation is pending, OR | 250 // a. A network operation is pending, OR |
| 229 // b. The Do* method called did not change state | 251 // b. The Do* method called did not change state |
| 230 | 252 |
| 231 // Connect loop is finished: if there is no pending IO invoke the callback. | 253 // Connect loop is finished: if there is no pending IO invoke the callback. |
| 232 if (rv != net::ERR_IO_PENDING) | 254 if (rv != net::ERR_IO_PENDING) { |
| 255 GetTimer()->Stop(); |
| 233 DoConnectCallback(rv); | 256 DoConnectCallback(rv); |
| 257 } |
| 234 } | 258 } |
| 235 | 259 |
| 236 int CastSocket::DoTcpConnect() { | 260 int CastSocket::DoTcpConnect() { |
| 237 VLOG_WITH_CONNECTION(1) << "DoTcpConnect"; | 261 VLOG_WITH_CONNECTION(1) << "DoTcpConnect"; |
| 238 connect_state_ = CONN_STATE_TCP_CONNECT_COMPLETE; | 262 connect_state_ = CONN_STATE_TCP_CONNECT_COMPLETE; |
| 239 tcp_socket_ = CreateTcpSocket(); | 263 tcp_socket_ = CreateTcpSocket(); |
| 240 return tcp_socket_->Connect( | 264 return tcp_socket_->Connect( |
| 241 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())); | 265 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr())); |
| 242 } | 266 } |
| 243 | 267 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE; | 301 connect_state_ = CONN_STATE_AUTH_CHALLENGE_SEND_COMPLETE; |
| 278 CastMessage challenge_message; | 302 CastMessage challenge_message; |
| 279 CreateAuthChallengeMessage(&challenge_message); | 303 CreateAuthChallengeMessage(&challenge_message); |
| 280 VLOG_WITH_CONNECTION(1) << "Sending challenge: " | 304 VLOG_WITH_CONNECTION(1) << "Sending challenge: " |
| 281 << CastMessageToString(challenge_message); | 305 << CastMessageToString(challenge_message); |
| 282 // Post a task to send auth challenge so that DoWriteLoop is not nested inside | 306 // Post a task to send auth challenge so that DoWriteLoop is not nested inside |
| 283 // DoConnectLoop. This is not strictly necessary but keeps the write loop | 307 // DoConnectLoop. This is not strictly necessary but keeps the write loop |
| 284 // code decoupled from connect loop code. | 308 // code decoupled from connect loop code. |
| 285 base::MessageLoop::current()->PostTask( | 309 base::MessageLoop::current()->PostTask( |
| 286 FROM_HERE, | 310 FROM_HERE, |
| 287 base::Bind(&CastSocket::SendCastMessageInternal, AsWeakPtr(), | 311 base::Bind(&CastSocket::SendCastMessageInternal, |
| 312 AsWeakPtr(), |
| 288 challenge_message, | 313 challenge_message, |
| 289 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr()))); | 314 base::Bind(&CastSocket::DoConnectLoop, AsWeakPtr()))); |
| 290 // Always return IO_PENDING since the result is always asynchronous. | 315 // Always return IO_PENDING since the result is always asynchronous. |
| 291 return net::ERR_IO_PENDING; | 316 return net::ERR_IO_PENDING; |
| 292 } | 317 } |
| 293 | 318 |
| 294 int CastSocket::DoAuthChallengeSendComplete(int result) { | 319 int CastSocket::DoAuthChallengeSendComplete(int result) { |
| 295 VLOG_WITH_CONNECTION(1) << "DoAuthChallengeSendComplete: " << result; | 320 VLOG_WITH_CONNECTION(1) << "DoAuthChallengeSendComplete: " << result; |
| 296 if (result < 0) | 321 if (result < 0) |
| 297 return result; | 322 return result; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 309 if (result < 0) | 334 if (result < 0) |
| 310 return result; | 335 return result; |
| 311 if (!VerifyChallengeReply()) | 336 if (!VerifyChallengeReply()) |
| 312 return net::ERR_FAILED; | 337 return net::ERR_FAILED; |
| 313 VLOG_WITH_CONNECTION(1) << "Auth challenge verification succeeded"; | 338 VLOG_WITH_CONNECTION(1) << "Auth challenge verification succeeded"; |
| 314 return net::OK; | 339 return net::OK; |
| 315 } | 340 } |
| 316 | 341 |
| 317 void CastSocket::DoConnectCallback(int result) { | 342 void CastSocket::DoConnectCallback(int result) { |
| 318 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED; | 343 ready_state_ = (result == net::OK) ? READY_STATE_OPEN : READY_STATE_CLOSED; |
| 319 error_state_ = (result == net::OK) ? | 344 if (result == net::OK) { |
| 320 CHANNEL_ERROR_NONE : CHANNEL_ERROR_CONNECT_ERROR; | 345 error_state_ = CHANNEL_ERROR_NONE; |
| 321 if (result == net::OK) // Start the read loop | |
| 322 PostTaskToStartReadLoop(); | 346 PostTaskToStartReadLoop(); |
| 347 } else if (result == net::ERR_TIMED_OUT) { |
| 348 error_state_ = CHANNEL_ERROR_CONNECT_TIMEOUT; |
| 349 } else { |
| 350 error_state_ = CHANNEL_ERROR_CONNECT_ERROR; |
| 351 } |
| 352 VLOG_WITH_CONNECTION(1) << "Calling Connect_Callback"; |
| 323 base::ResetAndReturn(&connect_callback_).Run(result); | 353 base::ResetAndReturn(&connect_callback_).Run(result); |
| 324 } | 354 } |
| 325 | 355 |
| 326 void CastSocket::Close(const net::CompletionCallback& callback) { | 356 void CastSocket::Close(const net::CompletionCallback& callback) { |
| 327 DCHECK(CalledOnValidThread()); | 357 DCHECK(CalledOnValidThread()); |
| 328 VLOG_WITH_CONNECTION(1) << "Close ReadyState = " << ready_state_; | 358 VLOG_WITH_CONNECTION(1) << "Close ReadyState = " << ready_state_; |
| 329 tcp_socket_.reset(); | 359 tcp_socket_.reset(); |
| 330 socket_.reset(); | 360 socket_.reset(); |
| 331 cert_verifier_.reset(); | 361 cert_verifier_.reset(); |
| 332 transport_security_state_.reset(); | 362 transport_security_state_.reset(); |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 message_proto.SerializeToString(message_data); | 705 message_proto.SerializeToString(message_data); |
| 676 size_t message_size = message_data->size(); | 706 size_t message_size = message_data->size(); |
| 677 if (message_size > MessageHeader::max_message_size()) { | 707 if (message_size > MessageHeader::max_message_size()) { |
| 678 message_data->clear(); | 708 message_data->clear(); |
| 679 return false; | 709 return false; |
| 680 } | 710 } |
| 681 CastSocket::MessageHeader header; | 711 CastSocket::MessageHeader header; |
| 682 header.SetMessageSize(message_size); | 712 header.SetMessageSize(message_size); |
| 683 header.PrependToString(message_data); | 713 header.PrependToString(message_data); |
| 684 return true; | 714 return true; |
| 685 }; | 715 } |
| 686 | 716 |
| 687 void CastSocket::CloseWithError(ChannelError error) { | 717 void CastSocket::CloseWithError(ChannelError error) { |
| 688 DCHECK(CalledOnValidThread()); | 718 DCHECK(CalledOnValidThread()); |
| 689 socket_.reset(NULL); | 719 socket_.reset(NULL); |
| 690 ready_state_ = READY_STATE_CLOSED; | 720 ready_state_ = READY_STATE_CLOSED; |
| 691 error_state_ = error; | 721 error_state_ = error; |
| 692 if (delegate_) | 722 if (delegate_) |
| 693 delegate_->OnError(this, error); | 723 delegate_->OnError(this, error); |
| 694 } | 724 } |
| 695 | 725 |
| 696 std::string CastSocket::CastUrl() const { | 726 std::string CastSocket::CastUrl() const { |
| 697 return ((channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED) ? | 727 return ((channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED) ? |
| 698 "casts://" : "cast://") + ip_endpoint_.ToString(); | 728 "casts://" : "cast://") + ip_endpoint_.ToString(); |
| 699 } | 729 } |
| 700 | 730 |
| 701 bool CastSocket::CalledOnValidThread() const { | 731 bool CastSocket::CalledOnValidThread() const { |
| 702 return thread_checker_.CalledOnValidThread(); | 732 return thread_checker_.CalledOnValidThread(); |
| 703 } | 733 } |
| 704 | 734 |
| 735 base::Timer* CastSocket::GetTimer() { |
| 736 return connect_timeout_timer_.get(); |
| 737 } |
| 738 |
| 705 CastSocket::MessageHeader::MessageHeader() : message_size(0) { } | 739 CastSocket::MessageHeader::MessageHeader() : message_size(0) { } |
| 706 | 740 |
| 707 void CastSocket::MessageHeader::SetMessageSize(size_t size) { | 741 void CastSocket::MessageHeader::SetMessageSize(size_t size) { |
| 708 DCHECK(size < static_cast<size_t>(kuint32max)); | 742 DCHECK(size < static_cast<size_t>(kuint32max)); |
| 709 DCHECK(size > 0); | 743 DCHECK(size > 0); |
| 710 message_size = static_cast<size_t>(size); | 744 message_size = static_cast<size_t>(size); |
| 711 } | 745 } |
| 712 | 746 |
| 713 // TODO(mfoltz): Investigate replacing header serialization with base::Pickle, | 747 // TODO(mfoltz): Investigate replacing header serialization with base::Pickle, |
| 714 // if bit-for-bit compatible. | 748 // if bit-for-bit compatible. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 return true; | 785 return true; |
| 752 } | 786 } |
| 753 | 787 |
| 754 CastSocket::WriteRequest::~WriteRequest() { } | 788 CastSocket::WriteRequest::~WriteRequest() { } |
| 755 | 789 |
| 756 } // namespace cast_channel | 790 } // namespace cast_channel |
| 757 } // namespace api | 791 } // namespace api |
| 758 } // namespace extensions | 792 } // namespace extensions |
| 759 | 793 |
| 760 #undef VLOG_WITH_CONNECTION | 794 #undef VLOG_WITH_CONNECTION |
| OLD | NEW |