1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/socket/websocket_transport_connect_sub_job.h" 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/logging.h" 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/ip_endpoint.h" 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/net_errors.h" 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/net_log.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/socket/client_socket_factory.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/socket/websocket_endpoint_lock_manager.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace net { 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 16116680a4aac90f2aa7413d9095a592090648e557Ben MurdochWebSocketTransportConnectSubJob::WebSocketTransportConnectSubJob( 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const AddressList& addresses, 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WebSocketTransportConnectJob* parent_job, 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SubJobType type) 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : parent_job_(parent_job), 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch addresses_(addresses), 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch current_address_index_(0), 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_(STATE_NONE), 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch type_(type) {} 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 26116680a4aac90f2aa7413d9095a592090648e557Ben MurdochWebSocketTransportConnectSubJob::~WebSocketTransportConnectSubJob() { 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // We don't worry about cancelling the TCP connect, since ~StreamSocket will 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // take care of it. 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (next()) { 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(STATE_OBTAIN_LOCK_COMPLETE, next_state_); 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The ~Waiter destructor will remove this object from the waiting list. 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (next_state_ == STATE_TRANSPORT_CONNECT_COMPLETE) { 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WebSocketEndpointLockManager::GetInstance()->UnlockEndpoint( 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CurrentAddress()); 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Start connecting. 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint WebSocketTransportConnectSubJob::Start() { 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(STATE_NONE, next_state_); 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ = STATE_OBTAIN_LOCK; 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return DoLoop(OK); 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Called by WebSocketEndpointLockManager when the lock becomes available. 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid WebSocketTransportConnectSubJob::GotEndpointLock() { 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(STATE_OBTAIN_LOCK_COMPLETE, next_state_); 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch OnIOComplete(OK); 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 51116680a4aac90f2aa7413d9095a592090648e557Ben MurdochLoadState WebSocketTransportConnectSubJob::GetLoadState() const { 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (next_state_) { 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_OBTAIN_LOCK: 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_OBTAIN_LOCK_COMPLETE: 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(ricea): Add a WebSocket-specific LOAD_STATE ? 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET; 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_TRANSPORT_CONNECT: 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_TRANSPORT_CONNECT_COMPLETE: 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_DONE: 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return LOAD_STATE_CONNECTING; 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_NONE: 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return LOAD_STATE_IDLE; 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NOTREACHED(); 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return LOAD_STATE_IDLE; 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 68116680a4aac90f2aa7413d9095a592090648e557Ben MurdochClientSocketFactory* WebSocketTransportConnectSubJob::client_socket_factory() 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const { 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return parent_job_->helper_.client_socket_factory(); 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst BoundNetLog& WebSocketTransportConnectSubJob::net_log() const { 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return parent_job_->net_log(); 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst IPEndPoint& WebSocketTransportConnectSubJob::CurrentAddress() const { 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_LT(current_address_index_, addresses_.size()); 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return addresses_[current_address_index_]; 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid WebSocketTransportConnectSubJob::OnIOComplete(int result) { 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = DoLoop(result); 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != ERR_IO_PENDING) 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch parent_job_->OnSubJobComplete(rv, this); // |this| deleted 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint WebSocketTransportConnectSubJob::DoLoop(int result) { 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_NE(next_state_, STATE_NONE); 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = result; 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch do { 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch State state = next_state_; 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ = STATE_NONE; 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (state) { 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_OBTAIN_LOCK: 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(OK, rv); 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = DoEndpointLock(); 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_OBTAIN_LOCK_COMPLETE: 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(OK, rv); 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = DoEndpointLockComplete(); 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_TRANSPORT_CONNECT: 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(OK, rv); 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = DoTransportConnect(); 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case STATE_TRANSPORT_CONNECT_COMPLETE: 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = DoTransportConnectComplete(rv); 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NOTREACHED(); 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = ERR_FAILED; 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE && 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ != STATE_DONE); 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint WebSocketTransportConnectSubJob::DoEndpointLock() { 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = WebSocketEndpointLockManager::GetInstance()->LockEndpoint( 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CurrentAddress(), this); 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ = STATE_OBTAIN_LOCK_COMPLETE; 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint WebSocketTransportConnectSubJob::DoEndpointLockComplete() { 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ = STATE_TRANSPORT_CONNECT; 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return OK; 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint WebSocketTransportConnectSubJob::DoTransportConnect() { 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(ricea): Update global g_last_connect_time and report 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // ConnectInterval. 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddressList one_address(CurrentAddress()); 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch transport_socket_ = client_socket_factory()->CreateTransportClientSocket( 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch one_address, net_log().net_log(), net_log().source()); 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // This use of base::Unretained() is safe because transport_socket_ is 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // destroyed in the destructor. 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return transport_socket_->Connect(base::Bind( 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &WebSocketTransportConnectSubJob::OnIOComplete, base::Unretained(this))); 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint WebSocketTransportConnectSubJob::DoTransportConnectComplete(int result) { 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ = STATE_DONE; 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WebSocketEndpointLockManager* endpoint_lock_manager = 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WebSocketEndpointLockManager::GetInstance(); 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result != OK) { 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch endpoint_lock_manager->UnlockEndpoint(CurrentAddress()); 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_address_index_ + 1 < addresses_.size()) { 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Try falling back to the next address in the list. 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch next_state_ = STATE_OBTAIN_LOCK; 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++current_address_index_; 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result = OK; 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch endpoint_lock_manager->RememberSocket(transport_socket_.get(), 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CurrentAddress()); 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace net 171