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