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 |