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

Side by Side Diff: net/socket/tcp_client_socket.cc

Issue 23881002: Windows only: Move client socket functionality from TCPClientSocket into TCPSocket. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 "net/socket/tcp_client_socket.h" 5 #include "net/socket/tcp_client_socket.h"
6 6
7 #include "base/callback_helpers.h"
7 #include "base/file_util.h" 8 #include "base/file_util.h"
8 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/ip_endpoint.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/net_util.h"
9 15
10 namespace net { 16 namespace net {
11 17
12 namespace { 18 namespace {
13 19
14 #if defined(OS_LINUX) 20 #if defined(OS_LINUX)
15 21
16 // Checks to see if the system supports TCP FastOpen. Notably, it requires 22 // Checks to see if the system supports TCP FastOpen. Notably, it requires
17 // kernel support. Additionally, this checks system configuration to ensure that 23 // kernel support. Additionally, this checks system configuration to ensure that
18 // it's enabled. 24 // it's enabled.
(...skipping 30 matching lines...) Expand all
49 static bool g_tcp_fastopen_enabled = false; 55 static bool g_tcp_fastopen_enabled = false;
50 56
51 void SetTCPFastOpenEnabled(bool value) { 57 void SetTCPFastOpenEnabled(bool value) {
52 g_tcp_fastopen_enabled = value && SystemSupportsTCPFastOpen(); 58 g_tcp_fastopen_enabled = value && SystemSupportsTCPFastOpen();
53 } 59 }
54 60
55 bool IsTCPFastOpenEnabled() { 61 bool IsTCPFastOpenEnabled() {
56 return g_tcp_fastopen_enabled; 62 return g_tcp_fastopen_enabled;
57 } 63 }
58 64
65 #if defined(OS_WIN)
66
67 TCPClientSocket::TCPClientSocket(const AddressList& addresses,
68 net::NetLog* net_log,
69 const net::NetLog::Source& source)
70 : socket_(new TCPSocket(net_log, source)),
71 addresses_(addresses),
72 current_address_index_(-1),
73 next_connect_state_(CONNECT_STATE_NONE),
74 previously_disconnected_(false) {
75 }
76
77 TCPClientSocket::TCPClientSocket(scoped_ptr<TCPSocket> connected_socket,
78 const IPEndPoint& peer_address)
79 : socket_(connected_socket.Pass()),
80 addresses_(AddressList(peer_address)),
81 current_address_index_(0),
82 next_connect_state_(CONNECT_STATE_NONE),
83 previously_disconnected_(false) {
84 DCHECK(socket_);
85
86 socket_->SetDefaultOptionsForClient();
87 use_history_.set_was_ever_connected();
88 }
89
90 TCPClientSocket::~TCPClientSocket() {
91 }
92
93 int TCPClientSocket::Bind(const IPEndPoint& address) {
94 if (current_address_index_ >= 0 || bind_address_) {
95 // Cannot bind the socket if we are already connected or connecting.
96 NOTREACHED();
97 return ERR_UNEXPECTED;
98 }
99
100 int result = OK;
101 if (!socket_->IsValid()) {
102 result = OpenSocket(address.GetFamily());
103 if (result != OK)
104 return result;
105 }
106
107 result = socket_->Bind(address);
108 if (result != OK)
109 return result;
110
111 bind_address_.reset(new IPEndPoint(address));
112 return OK;
113 }
114
115 int TCPClientSocket::Connect(const CompletionCallback& callback) {
116 DCHECK(!callback.is_null());
117
118 // If connecting or already connected, then just return OK.
119 if (socket_->IsValid() && current_address_index_ >= 0)
120 return OK;
121
122 socket_->StartLoggingMultipleConnectAttempts(addresses_);
123
124 // We will try to connect to each address in addresses_. Start with the
125 // first one in the list.
126 next_connect_state_ = CONNECT_STATE_CONNECT;
127 current_address_index_ = 0;
128
129 int rv = DoConnectLoop(OK);
130 if (rv == ERR_IO_PENDING) {
131 connect_callback_ = callback;
132 } else {
133 socket_->EndLoggingMultipleConnectAttempts(rv);
134 }
135
136 return rv;
137 }
138
139 int TCPClientSocket::DoConnectLoop(int result) {
140 DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
141
142 int rv = result;
143 do {
144 ConnectState state = next_connect_state_;
145 next_connect_state_ = CONNECT_STATE_NONE;
146 switch (state) {
147 case CONNECT_STATE_CONNECT:
148 DCHECK_EQ(OK, rv);
149 rv = DoConnect();
150 break;
151 case CONNECT_STATE_CONNECT_COMPLETE:
152 rv = DoConnectComplete(rv);
153 break;
154 default:
155 NOTREACHED() << "bad state " << state;
156 rv = ERR_UNEXPECTED;
157 break;
158 }
159 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
160
161 return rv;
162 }
163
164 int TCPClientSocket::DoConnect() {
165 DCHECK_GE(current_address_index_, 0);
166 DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
167
168 const IPEndPoint& endpoint = addresses_[current_address_index_];
169
170 if (previously_disconnected_) {
171 use_history_.Reset();
172 previously_disconnected_ = false;
173 }
174
175 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
176
177 if (socket_->IsValid()) {
178 DCHECK(bind_address_);
179 } else {
180 int result = OpenSocket(endpoint.GetFamily());
181 if (result != OK)
182 return result;
183
184 if (bind_address_) {
185 result = socket_->Bind(*bind_address_);
186 if (result != OK) {
187 socket_->Close();
188 return result;
189 }
190 }
191 }
192
193 // |socket_| is owned by this class and the callback won't be run once
194 // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
195 return socket_->Connect(endpoint,
196 base::Bind(&TCPClientSocket::DidCompleteConnect,
197 base::Unretained(this)));
198 }
199
200 int TCPClientSocket::DoConnectComplete(int result) {
201 if (result == OK) {
202 use_history_.set_was_ever_connected();
203 return OK; // Done!
204 }
205
206 // Close whatever partially connected socket we currently have.
207 DoDisconnect();
208
209 // Try to fall back to the next address in the list.
210 if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) {
211 next_connect_state_ = CONNECT_STATE_CONNECT;
212 ++current_address_index_;
213 return OK;
214 }
215
216 // Otherwise there is nothing to fall back to, so give up.
217 return result;
218 }
219
220 void TCPClientSocket::Disconnect() {
221 DoDisconnect();
222 current_address_index_ = -1;
223 bind_address_.reset();
224 }
225
226 void TCPClientSocket::DoDisconnect() {
227 // If connecting or already connected, record that the socket has been
228 // disconnected.
229 previously_disconnected_ = socket_->IsValid() && current_address_index_ >= 0;
230 socket_->Close();
231 }
232
233 bool TCPClientSocket::IsConnected() const {
234 return socket_->IsConnected();
235 }
236
237 bool TCPClientSocket::IsConnectedAndIdle() const {
238 return socket_->IsConnectedAndIdle();
239 }
240
241 int TCPClientSocket::GetPeerAddress(IPEndPoint* address) const {
242 return socket_->GetPeerAddress(address);
243 }
244
245 int TCPClientSocket::GetLocalAddress(IPEndPoint* address) const {
246 DCHECK(address);
247
248 if (!socket_->IsValid()) {
249 if (bind_address_) {
250 *address = *bind_address_;
251 return OK;
252 }
253 return ERR_SOCKET_NOT_CONNECTED;
254 }
255
256 return socket_->GetLocalAddress(address);
257 }
258
259 const BoundNetLog& TCPClientSocket::NetLog() const {
260 return socket_->net_log();
261 }
262
263 void TCPClientSocket::SetSubresourceSpeculation() {
264 use_history_.set_subresource_speculation();
265 }
266
267 void TCPClientSocket::SetOmniboxSpeculation() {
268 use_history_.set_omnibox_speculation();
269 }
270
271 bool TCPClientSocket::WasEverUsed() const {
272 return use_history_.was_used_to_convey_data();
273 }
274
275 bool TCPClientSocket::UsingTCPFastOpen() const {
276 return socket_->UsingTCPFastOpen();
277 }
278
279 bool TCPClientSocket::WasNpnNegotiated() const {
280 return false;
281 }
282
283 NextProto TCPClientSocket::GetNegotiatedProtocol() const {
284 return kProtoUnknown;
285 }
286
287 bool TCPClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
288 return false;
289 }
290
291 int TCPClientSocket::Read(IOBuffer* buf,
292 int buf_len,
293 const CompletionCallback& callback) {
294 DCHECK(!callback.is_null());
295
296 // |socket_| is owned by this class and the callback won't be run once
297 // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
298 CompletionCallback read_callback = base::Bind(
299 &TCPClientSocket::DidCompleteReadWrite, base::Unretained(this), callback);
300 int result = socket_->Read(buf, buf_len, read_callback);
301 if (result > 0)
302 use_history_.set_was_used_to_convey_data();
303
304 return result;
305 }
306
307 int TCPClientSocket::Write(IOBuffer* buf,
308 int buf_len,
309 const CompletionCallback& callback) {
310 DCHECK(!callback.is_null());
311
312 // |socket_| is owned by this class and the callback won't be run once
313 // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
314 CompletionCallback write_callback = base::Bind(
315 &TCPClientSocket::DidCompleteReadWrite, base::Unretained(this), callback);
316 int result = socket_->Write(buf, buf_len, write_callback);
317 if (result > 0)
318 use_history_.set_was_used_to_convey_data();
319
320 return result;
321 }
322
323 bool TCPClientSocket::SetReceiveBufferSize(int32 size) {
324 return socket_->SetReceiveBufferSize(size);
325 }
326
327 bool TCPClientSocket::SetSendBufferSize(int32 size) {
328 return socket_->SetSendBufferSize(size);
329 }
330
331 bool TCPClientSocket::SetKeepAlive(bool enable, int delay) {
332 return socket_->SetKeepAlive(enable, delay);
333 }
334
335 bool TCPClientSocket::SetNoDelay(bool no_delay) {
336 return socket_->SetNoDelay(no_delay);
337 }
338
339 void TCPClientSocket::DidCompleteConnect(int result) {
340 DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
341 DCHECK_NE(result, ERR_IO_PENDING);
342 DCHECK(!connect_callback_.is_null());
343
344 result = DoConnectLoop(result);
345 if (result != ERR_IO_PENDING) {
346 socket_->EndLoggingMultipleConnectAttempts(result);
347 base::ResetAndReturn(&connect_callback_).Run(result);
348 }
349 }
350
351 void TCPClientSocket::DidCompleteReadWrite(const CompletionCallback& callback,
352 int result) {
353 if (result > 0)
354 use_history_.set_was_used_to_convey_data();
355
356 callback.Run(result);
357 }
358
359 int TCPClientSocket::OpenSocket(AddressFamily family) {
360 DCHECK(!socket_->IsValid());
361
362 int result = socket_->Open(family);
363 if (result != OK)
364 return result;
365
366 socket_->SetDefaultOptionsForClient();
367
368 return OK;
369 }
370
371 #endif
372
59 } // namespace net 373 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698