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

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

Powered by Google App Engine
This is Rietveld 408576698