Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: chrome/browser/extensions/api/cast_channel/cast_socket.cc

Issue 393023003: Added connection timeout functionality to CastSocket. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added missing initializer for CastSocket unit tests. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698