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

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

Powered by Google App Engine
This is Rietveld 408576698