OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/socket/websocket_transport_connect_sub_job.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "net/base/ip_endpoint.h" | |
9 #include "net/base/net_errors.h" | |
10 #include "net/base/net_log.h" | |
11 #include "net/socket/client_socket_factory.h" | |
12 #include "net/socket/websocket_endpoint_lock_manager.h" | |
13 | |
14 namespace net { | |
15 | |
16 WebSocketTransportConnectSubJob::WebSocketTransportConnectSubJob( | |
17 const AddressList& addresses, | |
18 WebSocketTransportConnectJob* parent_job, | |
19 SubJobType type) | |
20 : parent_job_(parent_job), | |
21 addresses_(addresses), | |
22 current_address_index_(0), | |
23 next_state_(STATE_NONE), | |
24 type_(type) {} | |
25 | |
26 WebSocketTransportConnectSubJob::~WebSocketTransportConnectSubJob() { | |
27 // We don't worry about cancelling the TCP connect, since ~StreamSocket will | |
28 // take care of it. | |
29 if (next()) { | |
30 DCHECK_EQ(STATE_OBTAIN_LOCK_COMPLETE, next_state_); | |
31 // The ~Waiter destructor will remove this object from the waiting list. | |
32 } else if (next_state_ == STATE_TRANSPORT_CONNECT_COMPLETE) { | |
33 WebSocketEndpointLockManager::GetInstance()->UnlockEndpoint( | |
34 CurrentAddress()); | |
35 } | |
36 } | |
37 | |
38 // Start connecting. | |
39 int WebSocketTransportConnectSubJob::Start() { | |
40 DCHECK_EQ(STATE_NONE, next_state_); | |
41 next_state_ = STATE_OBTAIN_LOCK; | |
42 return DoLoop(OK); | |
43 } | |
44 | |
45 // Called by WebSocketEndpointLockManager when the lock becomes available. | |
46 void WebSocketTransportConnectSubJob::GotEndpointLock() { | |
47 DCHECK_EQ(STATE_OBTAIN_LOCK_COMPLETE, next_state_); | |
48 OnIOComplete(OK); | |
49 } | |
50 | |
51 LoadState WebSocketTransportConnectSubJob::GetLoadState() const { | |
52 switch (next_state_) { | |
53 case STATE_OBTAIN_LOCK: | |
54 case STATE_OBTAIN_LOCK_COMPLETE: | |
55 // TODO(ricea): Add a WebSocket-specific LOAD_STATE ? | |
56 return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET; | |
57 case STATE_TRANSPORT_CONNECT: | |
58 case STATE_TRANSPORT_CONNECT_COMPLETE: | |
59 return LOAD_STATE_CONNECTING; | |
60 case STATE_NONE: | |
61 return LOAD_STATE_IDLE; | |
62 } | |
63 NOTREACHED(); | |
64 return LOAD_STATE_IDLE; | |
65 } | |
66 | |
67 ClientSocketFactory* WebSocketTransportConnectSubJob::client_socket_factory() | |
68 const { | |
69 return parent_job_->helper_.client_socket_factory(); | |
70 } | |
71 | |
72 const BoundNetLog& WebSocketTransportConnectSubJob::net_log() const { | |
73 return parent_job_->net_log(); | |
74 } | |
75 | |
76 const IPEndPoint& WebSocketTransportConnectSubJob::CurrentAddress() const { | |
77 DCHECK_LT(current_address_index_, addresses_.size()); | |
78 return addresses_[current_address_index_]; | |
79 } | |
80 | |
81 void WebSocketTransportConnectSubJob::OnIOComplete(int result) { | |
82 int rv = DoLoop(result); | |
83 if (rv != ERR_IO_PENDING) | |
84 parent_job_->OnSubJobComplete(rv, this); // |this| deleted | |
85 } | |
86 | |
87 int WebSocketTransportConnectSubJob::DoLoop(int result) { | |
88 DCHECK_NE(next_state_, STATE_NONE); | |
89 | |
90 int rv = result; | |
91 do { | |
92 State state = next_state_; | |
93 next_state_ = STATE_NONE; | |
94 switch (state) { | |
95 case STATE_OBTAIN_LOCK: | |
96 DCHECK_EQ(OK, rv); | |
97 rv = DoEndpointLock(); | |
98 break; | |
99 case STATE_OBTAIN_LOCK_COMPLETE: | |
100 DCHECK_EQ(OK, rv); | |
101 rv = DoEndpointLockComplete(); | |
102 break; | |
103 case STATE_TRANSPORT_CONNECT: | |
104 DCHECK_EQ(OK, rv); | |
105 rv = DoTransportConnect(); | |
106 break; | |
107 case STATE_TRANSPORT_CONNECT_COMPLETE: | |
108 rv = DoTransportConnectComplete(rv); | |
109 break; | |
110 default: | |
111 NOTREACHED(); | |
112 rv = ERR_FAILED; | |
113 break; | |
114 } | |
115 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
116 | |
117 return rv; | |
118 } | |
119 | |
120 int WebSocketTransportConnectSubJob::DoEndpointLock() { | |
121 int rv = WebSocketEndpointLockManager::GetInstance()->LockEndpoint( | |
122 CurrentAddress(), this); | |
123 next_state_ = STATE_OBTAIN_LOCK_COMPLETE; | |
124 return rv; | |
125 } | |
126 | |
127 int WebSocketTransportConnectSubJob::DoEndpointLockComplete() { | |
128 next_state_ = STATE_TRANSPORT_CONNECT; | |
129 return OK; | |
130 } | |
131 | |
132 int WebSocketTransportConnectSubJob::DoTransportConnect() { | |
133 // TODO(ricea): Update global g_last_connect_time and report | |
134 // ConnectInterval. | |
135 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; | |
136 AddressList one_address(CurrentAddress()); | |
137 transport_socket_ = client_socket_factory()->CreateTransportClientSocket( | |
138 one_address, net_log().net_log(), net_log().source()); | |
139 // This use of base::Unretained() is safe because transport_socket_ is | |
140 // destroyed in the destructor. | |
141 return transport_socket_->Connect(base::Bind( | |
142 &WebSocketTransportConnectSubJob::OnIOComplete, base::Unretained(this))); | |
143 } | |
144 | |
145 int WebSocketTransportConnectSubJob::DoTransportConnectComplete(int result) { | |
146 next_state_ = STATE_NONE; | |
tyoshino (SeeGerritForStatus)
2014/06/20 12:12:07
thanks. but is it ok to make started() return fals
Adam Rice
2014/06/23 10:06:26
Currently it is, because we always exit synchronou
| |
147 WebSocketEndpointLockManager* endpoint_lock_manager = | |
148 WebSocketEndpointLockManager::GetInstance(); | |
149 if (result != OK) { | |
150 endpoint_lock_manager->UnlockEndpoint(CurrentAddress()); | |
151 | |
152 if (current_address_index_ + 1 < addresses_.size()) { | |
153 // Try falling back to the next address in the list. | |
154 next_state_ = STATE_OBTAIN_LOCK; | |
155 ++current_address_index_; | |
156 result = OK; | |
157 } | |
158 | |
159 return result; | |
160 } | |
161 | |
162 endpoint_lock_manager->RememberSocket(transport_socket_.get(), | |
163 CurrentAddress()); | |
164 | |
165 return result; | |
166 } | |
167 | |
168 } // namespace net | |
OLD | NEW |