Chromium Code Reviews| 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 int64 timeout_ms) : | |
| 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), |
| 79 connect_state_(CONN_STATE_NONE), | 80 connect_state_(CONN_STATE_NONE), |
| 80 write_state_(WRITE_STATE_NONE), | 81 write_state_(WRITE_STATE_NONE), |
| 81 read_state_(READ_STATE_NONE), | 82 read_state_(READ_STATE_NONE), |
| 82 error_state_(CHANNEL_ERROR_NONE), | 83 error_state_(CHANNEL_ERROR_NONE), |
| 83 ready_state_(READY_STATE_NONE) { | 84 ready_state_(READY_STATE_NONE), |
| 85 timeout_interval_ms_(timeout_ms), | |
| 86 timed_out_(false) { | |
| 84 DCHECK(net_log_); | 87 DCHECK(net_log_); |
| 85 DCHECK(channel_auth_ == CHANNEL_AUTH_TYPE_SSL || | 88 DCHECK(channel_auth_ == CHANNEL_AUTH_TYPE_SSL || |
| 86 channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED); | 89 channel_auth_ == CHANNEL_AUTH_TYPE_SSL_VERIFIED); |
| 87 net_log_source_.type = net::NetLog::SOURCE_SOCKET; | 90 net_log_source_.type = net::NetLog::SOURCE_SOCKET; |
| 88 net_log_source_.id = net_log_->NextID(); | 91 net_log_source_.id = net_log_->NextID(); |
| 89 | 92 |
| 90 // Reuse these buffers for each message. | 93 // Reuse these buffers for each message. |
| 91 header_read_buffer_ = new net::GrowableIOBuffer(); | 94 header_read_buffer_ = new net::GrowableIOBuffer(); |
| 92 header_read_buffer_->SetCapacity(MessageHeader::header_size()); | 95 header_read_buffer_->SetCapacity(MessageHeader::header_size()); |
| 93 body_read_buffer_ = new net::GrowableIOBuffer(); | 96 body_read_buffer_ = new net::GrowableIOBuffer(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 void CastSocket::Connect(const net::CompletionCallback& callback) { | 167 void CastSocket::Connect(const net::CompletionCallback& callback) { |
| 165 DCHECK(CalledOnValidThread()); | 168 DCHECK(CalledOnValidThread()); |
| 166 VLOG_WITH_CONNECTION(1) << "Connect readyState = " << ready_state_; | 169 VLOG_WITH_CONNECTION(1) << "Connect readyState = " << ready_state_; |
| 167 if (ready_state_ != READY_STATE_NONE) { | 170 if (ready_state_ != READY_STATE_NONE) { |
| 168 callback.Run(net::ERR_CONNECTION_FAILED); | 171 callback.Run(net::ERR_CONNECTION_FAILED); |
| 169 return; | 172 return; |
| 170 } | 173 } |
| 171 ready_state_ = READY_STATE_CONNECTING; | 174 ready_state_ = READY_STATE_CONNECTING; |
| 172 connect_callback_ = callback; | 175 connect_callback_ = callback; |
| 173 connect_state_ = CONN_STATE_TCP_CONNECT; | 176 connect_state_ = CONN_STATE_TCP_CONNECT; |
| 177 | |
| 178 timeout_callback_.Reset(base::Bind(&CastSocket::Timeout, AsWeakPtr())); | |
| 179 base::MessageLoop::current()->PostDelayedTask( | |
| 180 FROM_HERE, | |
| 181 timeout_callback_.callback(), | |
| 182 base::TimeDelta::FromMilliseconds(timeout_interval_ms_)); | |
| 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::Timeout() { | |
| 195 VLOG(1) << "Timeout while establishing connection."; | |
| 196 CloseWithError(CHANNEL_ERROR_CONNECT_ERROR); | |
|
mark a. foltz
2014/07/15 22:18:15
I would be in favor of adding an error enum CHANNE
Kevin M
2014/07/16 22:59:41
Done.
| |
| 197 timed_out_ = true; | |
|
mark a. foltz
2014/07/15 22:18:15
Is timed_out_ used anywhere?
Kevin M
2014/07/16 22:59:41
No, I ended up using the error state instead. Remo
| |
| 198 DoConnectCallback(net::ERR_TIMED_OUT); | |
| 199 } | |
| 200 | |
| 184 // This method performs the state machine transitions for connection flow. | 201 // This method performs the state machine transitions for connection flow. |
| 185 // There are two entry points to this method: | 202 // There are two entry points to this method: |
| 186 // 1. Connect method: this starts the flow | 203 // 1. Connect method: this starts the flow |
| 187 // 2. Callback from network operations that finish asynchronously | 204 // 2. Callback from network operations that finish asynchronously |
| 188 void CastSocket::DoConnectLoop(int result) { | 205 void CastSocket::DoConnectLoop(int result) { |
| 206 if (error_state_ != CHANNEL_ERROR_NONE) { | |
| 207 VLOG(1) << "Connection timeout; DoConnectLoop aborted."; | |
|
mark a. foltz
2014/07/15 22:18:15
Is this the only possible way error_state_ can be
Kevin M
2014/07/16 22:59:41
Good idea, done.
| |
| 208 return; | |
| 209 } | |
| 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 timeout_callback_.Cancel(); | |
| 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 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 message_proto.SerializeToString(message_data); | 699 message_proto.SerializeToString(message_data); |
| 676 size_t message_size = message_data->size(); | 700 size_t message_size = message_data->size(); |
| 677 if (message_size > MessageHeader::max_message_size()) { | 701 if (message_size > MessageHeader::max_message_size()) { |
| 678 message_data->clear(); | 702 message_data->clear(); |
| 679 return false; | 703 return false; |
| 680 } | 704 } |
| 681 CastSocket::MessageHeader header; | 705 CastSocket::MessageHeader header; |
| 682 header.SetMessageSize(message_size); | 706 header.SetMessageSize(message_size); |
| 683 header.PrependToString(message_data); | 707 header.PrependToString(message_data); |
| 684 return true; | 708 return true; |
| 685 }; | 709 } |
| 686 | 710 |
| 687 void CastSocket::CloseWithError(ChannelError error) { | 711 void CastSocket::CloseWithError(ChannelError error) { |
| 688 DCHECK(CalledOnValidThread()); | 712 DCHECK(CalledOnValidThread()); |
| 689 socket_.reset(NULL); | 713 socket_.reset(NULL); |
| 690 ready_state_ = READY_STATE_CLOSED; | 714 ready_state_ = READY_STATE_CLOSED; |
| 691 error_state_ = error; | 715 error_state_ = error; |
| 692 if (delegate_) | 716 if (delegate_) |
| 693 delegate_->OnError(this, error); | 717 delegate_->OnError(this, error); |
| 694 } | 718 } |
| 695 | 719 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 751 return true; | 775 return true; |
| 752 } | 776 } |
| 753 | 777 |
| 754 CastSocket::WriteRequest::~WriteRequest() { } | 778 CastSocket::WriteRequest::~WriteRequest() { } |
| 755 | 779 |
| 756 } // namespace cast_channel | 780 } // namespace cast_channel |
| 757 } // namespace api | 781 } // namespace api |
| 758 } // namespace extensions | 782 } // namespace extensions |
| 759 | 783 |
| 760 #undef VLOG_WITH_CONNECTION | 784 #undef VLOG_WITH_CONNECTION |
| OLD | NEW |