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

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

Issue 348803003: Refactor tcp socket and unix domain socket. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Revert the behavior change of calling RecordFastOpenStatus() Created 6 years, 5 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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_socket.h" 5 #include "net/socket/tcp_socket.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h>
9 #include <netdb.h>
10 #include <netinet/in.h>
11 #include <netinet/tcp.h> 8 #include <netinet/tcp.h>
12 #include <sys/socket.h> 9 #include <sys/socket.h>
13 10
14 #include "base/callback_helpers.h" 11 #include "base/bind.h"
15 #include "base/logging.h" 12 #include "base/logging.h"
16 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
17 #include "base/metrics/stats_counters.h" 14 #include "base/metrics/stats_counters.h"
18 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
19 #include "build/build_config.h"
20 #include "net/base/address_list.h" 16 #include "net/base/address_list.h"
21 #include "net/base/connection_type_histograms.h" 17 #include "net/base/connection_type_histograms.h"
22 #include "net/base/io_buffer.h" 18 #include "net/base/io_buffer.h"
23 #include "net/base/ip_endpoint.h" 19 #include "net/base/ip_endpoint.h"
24 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
25 #include "net/base/net_util.h" 21 #include "net/base/net_util.h"
26 #include "net/base/network_change_notifier.h" 22 #include "net/base/network_change_notifier.h"
23 #include "net/socket/socket_libevent.h"
27 #include "net/socket/socket_net_log_params.h" 24 #include "net/socket/socket_net_log_params.h"
28 25
29 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one. 26 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one.
30 #ifndef TCPI_OPT_SYN_DATA 27 #ifndef TCPI_OPT_SYN_DATA
31 #define TCPI_OPT_SYN_DATA 32 28 #define TCPI_OPT_SYN_DATA 32
32 #endif 29 #endif
33 30
34 namespace net { 31 namespace net {
35 32
36 namespace { 33 namespace {
(...skipping 28 matching lines...) Expand all
65 } 62 }
66 // Set seconds between TCP keep alives. 63 // Set seconds between TCP keep alives.
67 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) { 64 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) {
68 PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd; 65 PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd;
69 return false; 66 return false;
70 } 67 }
71 #endif 68 #endif
72 return true; 69 return true;
73 } 70 }
74 71
75 int MapAcceptError(int os_error) {
76 switch (os_error) {
77 // If the client aborts the connection before the server calls accept,
78 // POSIX specifies accept should fail with ECONNABORTED. The server can
79 // ignore the error and just call accept again, so we map the error to
80 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
81 // 5.11, "Connection Abort before accept Returns".
82 case ECONNABORTED:
83 return ERR_IO_PENDING;
84 default:
85 return MapSystemError(os_error);
86 }
87 }
88
89 int MapConnectError(int os_error) {
90 switch (os_error) {
91 case EACCES:
92 return ERR_NETWORK_ACCESS_DENIED;
93 case ETIMEDOUT:
94 return ERR_CONNECTION_TIMED_OUT;
95 default: {
96 int net_error = MapSystemError(os_error);
97 if (net_error == ERR_FAILED)
98 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
99
100 // Give a more specific error when the user is offline.
101 if (net_error == ERR_ADDRESS_UNREACHABLE &&
102 NetworkChangeNotifier::IsOffline()) {
103 return ERR_INTERNET_DISCONNECTED;
104 }
105 return net_error;
106 }
107 }
108 }
109
110 } // namespace 72 } // namespace
111 73
112 //----------------------------------------------------------------------------- 74 //-----------------------------------------------------------------------------
113 75
114 TCPSocketLibevent::Watcher::Watcher(
115 const base::Closure& read_ready_callback,
116 const base::Closure& write_ready_callback)
117 : read_ready_callback_(read_ready_callback),
118 write_ready_callback_(write_ready_callback) {
119 }
120
121 TCPSocketLibevent::Watcher::~Watcher() {
122 }
123
124 void TCPSocketLibevent::Watcher::OnFileCanReadWithoutBlocking(int /* fd */) {
125 if (!read_ready_callback_.is_null())
126 read_ready_callback_.Run();
127 else
128 NOTREACHED();
129 }
130
131 void TCPSocketLibevent::Watcher::OnFileCanWriteWithoutBlocking(int /* fd */) {
132 if (!write_ready_callback_.is_null())
133 write_ready_callback_.Run();
134 else
135 NOTREACHED();
136 }
137
138 TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log, 76 TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log,
139 const NetLog::Source& source) 77 const NetLog::Source& source)
140 : socket_(kInvalidSocket), 78 : use_tcp_fastopen_(IsTCPFastOpenEnabled()),
141 accept_watcher_(base::Bind(&TCPSocketLibevent::DidCompleteAccept,
142 base::Unretained(this)),
143 base::Closure()),
144 accept_socket_(NULL),
145 accept_address_(NULL),
146 read_watcher_(base::Bind(&TCPSocketLibevent::DidCompleteRead,
147 base::Unretained(this)),
148 base::Closure()),
149 write_watcher_(base::Closure(),
150 base::Bind(&TCPSocketLibevent::DidCompleteConnectOrWrite,
151 base::Unretained(this))),
152 read_buf_len_(0),
153 write_buf_len_(0),
154 use_tcp_fastopen_(IsTCPFastOpenEnabled()),
155 tcp_fastopen_connected_(false), 79 tcp_fastopen_connected_(false),
156 fast_open_status_(FAST_OPEN_STATUS_UNKNOWN), 80 fast_open_status_(FAST_OPEN_STATUS_UNKNOWN),
157 waiting_connect_(false),
158 connect_os_error_(0),
159 logging_multiple_connect_attempts_(false), 81 logging_multiple_connect_attempts_(false),
160 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 82 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
161 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 83 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
162 source.ToEventParametersCallback()); 84 source.ToEventParametersCallback());
163 } 85 }
164 86
165 TCPSocketLibevent::~TCPSocketLibevent() { 87 TCPSocketLibevent::~TCPSocketLibevent() {
166 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 88 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
167 if (tcp_fastopen_connected_) { 89 if (tcp_fastopen_connected_) {
168 UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection", 90 UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection",
169 fast_open_status_, FAST_OPEN_MAX_VALUE); 91 fast_open_status_, FAST_OPEN_MAX_VALUE);
170 } 92 }
171 Close();
172 } 93 }
173 94
174 int TCPSocketLibevent::Open(AddressFamily family) { 95 int TCPSocketLibevent::Open(AddressFamily family) {
175 DCHECK(CalledOnValidThread()); 96 DCHECK(!socket_);
176 DCHECK_EQ(socket_, kInvalidSocket); 97 socket_.reset(new SocketLibevent);
98 int rv = socket_->Open(ConvertAddressFamily(family));
99 if (rv != OK)
100 socket_.reset();
101 return rv;
102 }
177 103
178 socket_ = CreatePlatformSocket(ConvertAddressFamily(family), SOCK_STREAM, 104 int TCPSocketLibevent::AdoptConnectedSocket(int socket_fd,
179 IPPROTO_TCP); 105 const IPEndPoint& peer_address) {
180 if (socket_ < 0) { 106 DCHECK(!socket_);
181 PLOG(ERROR) << "CreatePlatformSocket() returned an error"; 107
182 return MapSystemError(errno); 108 SockaddrStorage storage;
109 if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len) &&
110 // For backward compatibility, allows the empty address.
111 !(peer_address == IPEndPoint())) {
112 return ERR_ADDRESS_INVALID;
183 } 113 }
184 114
185 if (SetNonBlocking(socket_)) { 115 socket_.reset(new SocketLibevent);
186 int result = MapSystemError(errno); 116 int rv = socket_->AdoptConnectedSocket(socket_fd, storage);
187 Close(); 117 if (rv != OK)
188 return result; 118 socket_.reset();
189 } 119 return rv;
190
191 return OK;
192 }
193
194 int TCPSocketLibevent::AdoptConnectedSocket(int socket,
195 const IPEndPoint& peer_address) {
196 DCHECK(CalledOnValidThread());
197 DCHECK_EQ(socket_, kInvalidSocket);
198
199 socket_ = socket;
200
201 if (SetNonBlocking(socket_)) {
202 int result = MapSystemError(errno);
203 Close();
204 return result;
205 }
206
207 peer_address_.reset(new IPEndPoint(peer_address));
208
209 return OK;
210 } 120 }
211 121
212 int TCPSocketLibevent::Bind(const IPEndPoint& address) { 122 int TCPSocketLibevent::Bind(const IPEndPoint& address) {
213 DCHECK(CalledOnValidThread()); 123 DCHECK(socket_);
214 DCHECK_NE(socket_, kInvalidSocket);
215 124
216 SockaddrStorage storage; 125 SockaddrStorage storage;
217 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 126 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
218 return ERR_ADDRESS_INVALID; 127 return ERR_ADDRESS_INVALID;
219 128
220 int result = bind(socket_, storage.addr, storage.addr_len); 129 return socket_->Bind(storage);
221 if (result < 0) {
222 PLOG(ERROR) << "bind() returned an error";
223 return MapSystemError(errno);
224 }
225
226 return OK;
227 } 130 }
228 131
229 int TCPSocketLibevent::Listen(int backlog) { 132 int TCPSocketLibevent::Listen(int backlog) {
230 DCHECK(CalledOnValidThread()); 133 DCHECK(socket_);
231 DCHECK_GT(backlog, 0); 134 return socket_->Listen(backlog);
232 DCHECK_NE(socket_, kInvalidSocket);
233
234 int result = listen(socket_, backlog);
235 if (result < 0) {
236 PLOG(ERROR) << "listen() returned an error";
237 return MapSystemError(errno);
238 }
239
240 return OK;
241 } 135 }
242 136
243 int TCPSocketLibevent::Accept(scoped_ptr<TCPSocketLibevent>* socket, 137 int TCPSocketLibevent::Accept(scoped_ptr<TCPSocketLibevent>* tcp_socket,
244 IPEndPoint* address, 138 IPEndPoint* address,
245 const CompletionCallback& callback) { 139 const CompletionCallback& callback) {
246 DCHECK(CalledOnValidThread()); 140 DCHECK(tcp_socket);
247 DCHECK(socket);
248 DCHECK(address);
249 DCHECK(!callback.is_null()); 141 DCHECK(!callback.is_null());
250 DCHECK(accept_callback_.is_null()); 142 DCHECK(socket_);
143 DCHECK(!accept_socket_);
251 144
252 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); 145 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT);
253 146
254 int result = AcceptInternal(socket, address); 147 int rv = socket_->Accept(
255 148 &accept_socket_,
256 if (result == ERR_IO_PENDING) { 149 base::Bind(&TCPSocketLibevent::AcceptCompleted,
257 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 150 base::Unretained(this), tcp_socket, address, callback));
258 socket_, true, base::MessageLoopForIO::WATCH_READ, 151 if (rv != ERR_IO_PENDING)
259 &accept_socket_watcher_, &accept_watcher_)) { 152 rv = HandleAcceptCompleted(tcp_socket, address, rv);
260 PLOG(ERROR) << "WatchFileDescriptor failed on read"; 153 return rv;
261 return MapSystemError(errno);
262 }
263
264 accept_socket_ = socket;
265 accept_address_ = address;
266 accept_callback_ = callback;
267 }
268
269 return result;
270 } 154 }
271 155
272 int TCPSocketLibevent::Connect(const IPEndPoint& address, 156 int TCPSocketLibevent::Connect(const IPEndPoint& address,
273 const CompletionCallback& callback) { 157 const CompletionCallback& callback) {
274 DCHECK(CalledOnValidThread()); 158 DCHECK(socket_);
275 DCHECK_NE(socket_, kInvalidSocket);
276 DCHECK(!waiting_connect_);
277
278 // |peer_address_| will be non-NULL if Connect() has been called. Unless
279 // Close() is called to reset the internal state, a second call to Connect()
280 // is not allowed.
281 // Please note that we don't allow a second Connect() even if the previous
282 // Connect() has failed. Connecting the same |socket_| again after a
283 // connection attempt failed results in unspecified behavior according to
284 // POSIX.
285 DCHECK(!peer_address_);
286 159
287 if (!logging_multiple_connect_attempts_) 160 if (!logging_multiple_connect_attempts_)
288 LogConnectBegin(AddressList(address)); 161 LogConnectBegin(AddressList(address));
289 162
290 peer_address_.reset(new IPEndPoint(address)); 163 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
164 CreateNetLogIPEndPointCallback(&address));
291 165
292 int rv = DoConnect(); 166 SockaddrStorage storage;
293 if (rv == ERR_IO_PENDING) { 167 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
294 // Synchronous operation not supported. 168 return ERR_ADDRESS_INVALID;
295 DCHECK(!callback.is_null()); 169
296 write_callback_ = callback; 170 if (use_tcp_fastopen_) {
297 waiting_connect_ = true; 171 // With TCP FastOpen, we pretend that the socket is connected.
298 } else { 172 DCHECK(!tcp_fastopen_connected_);
299 DoConnectComplete(rv); 173 socket_->SetPeerAddress(storage);
174 return OK;
300 } 175 }
301 176
177 int rv = socket_->Connect(storage,
178 base::Bind(&TCPSocketLibevent::ConnectCompleted,
179 base::Unretained(this), callback));
180 if (rv != ERR_IO_PENDING)
181 rv = HandleConnectCompleted(rv);
302 return rv; 182 return rv;
303 } 183 }
304 184
305 bool TCPSocketLibevent::IsConnected() const { 185 bool TCPSocketLibevent::IsConnected() const {
306 DCHECK(CalledOnValidThread()); 186 if (!socket_)
307
308 if (socket_ == kInvalidSocket || waiting_connect_)
309 return false; 187 return false;
310 188
311 if (use_tcp_fastopen_ && !tcp_fastopen_connected_ && peer_address_) { 189 if (use_tcp_fastopen_ && !tcp_fastopen_connected_ &&
190 socket_->HasPeerAddress()) {
312 // With TCP FastOpen, we pretend that the socket is connected. 191 // With TCP FastOpen, we pretend that the socket is connected.
313 // This allows GetPeerAddress() to return peer_address_. 192 // This allows GetPeerAddress() to return peer_address_.
314 return true; 193 return true;
315 } 194 }
316 195
317 // Check if connection is alive. 196 return socket_->IsConnected();
318 char c;
319 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
320 if (rv == 0)
321 return false;
322 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
323 return false;
324
325 return true;
326 } 197 }
327 198
328 bool TCPSocketLibevent::IsConnectedAndIdle() const { 199 bool TCPSocketLibevent::IsConnectedAndIdle() const {
329 DCHECK(CalledOnValidThread());
330
331 if (socket_ == kInvalidSocket || waiting_connect_)
332 return false;
333
334 // TODO(wtc): should we also handle the TCP FastOpen case here, 200 // TODO(wtc): should we also handle the TCP FastOpen case here,
335 // as we do in IsConnected()? 201 // as we do in IsConnected()?
336 202 return socket_ && socket_->IsConnectedAndIdle();
337 // Check if connection is alive and we haven't received any data
338 // unexpectedly.
339 char c;
340 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
341 if (rv >= 0)
342 return false;
343 if (errno != EAGAIN && errno != EWOULDBLOCK)
344 return false;
345
346 return true;
347 } 203 }
348 204
349 int TCPSocketLibevent::Read(IOBuffer* buf, 205 int TCPSocketLibevent::Read(IOBuffer* buf,
350 int buf_len, 206 int buf_len,
351 const CompletionCallback& callback) { 207 const CompletionCallback& callback) {
352 DCHECK(CalledOnValidThread()); 208 DCHECK(socket_);
353 DCHECK_NE(kInvalidSocket, socket_);
354 DCHECK(!waiting_connect_);
355 DCHECK(read_callback_.is_null());
356 // Synchronous operation not supported
357 DCHECK(!callback.is_null()); 209 DCHECK(!callback.is_null());
358 DCHECK_GT(buf_len, 0);
359 210
360 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); 211 int rv = socket_->Read(
361 if (nread >= 0) { 212 buf, buf_len,
362 base::StatsCounter read_bytes("tcp.read_bytes"); 213 base::Bind(&TCPSocketLibevent::ReadCompleted,
363 read_bytes.Add(nread); 214 base::Unretained(this), base::Unretained(buf), callback));
364 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, 215 if (rv >= 0)
365 buf->data());
366 RecordFastOpenStatus(); 216 RecordFastOpenStatus();
367 return nread; 217 if (rv != ERR_IO_PENDING)
368 } 218 rv = HandleReadCompleted(buf, rv);
369 if (errno != EAGAIN && errno != EWOULDBLOCK) { 219 return rv;
370 int net_error = MapSystemError(errno);
371 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
372 CreateNetLogSocketErrorCallback(net_error, errno));
373 return net_error;
374 }
375
376 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
377 socket_, true, base::MessageLoopForIO::WATCH_READ,
378 &read_socket_watcher_, &read_watcher_)) {
379 DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno;
380 return MapSystemError(errno);
381 }
382
383 read_buf_ = buf;
384 read_buf_len_ = buf_len;
385 read_callback_ = callback;
386 return ERR_IO_PENDING;
387 } 220 }
388 221
389 int TCPSocketLibevent::Write(IOBuffer* buf, 222 int TCPSocketLibevent::Write(IOBuffer* buf,
390 int buf_len, 223 int buf_len,
391 const CompletionCallback& callback) { 224 const CompletionCallback& callback) {
392 DCHECK(CalledOnValidThread()); 225 DCHECK(socket_);
393 DCHECK_NE(kInvalidSocket, socket_);
394 DCHECK(!waiting_connect_);
395 DCHECK(write_callback_.is_null());
396 // Synchronous operation not supported
397 DCHECK(!callback.is_null()); 226 DCHECK(!callback.is_null());
398 DCHECK_GT(buf_len, 0);
399 227
400 int nwrite = InternalWrite(buf, buf_len); 228 CompletionCallback write_callback =
401 if (nwrite >= 0) { 229 base::Bind(&TCPSocketLibevent::WriteCompleted,
402 base::StatsCounter write_bytes("tcp.write_bytes"); 230 base::Unretained(this), base::Unretained(buf), callback);
403 write_bytes.Add(nwrite); 231 int rv;
404 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, 232 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
405 buf->data()); 233 rv = TcpFastOpenWrite(buf, buf_len, write_callback);
406 return nwrite; 234 } else {
407 } 235 rv = socket_->Write(buf, buf_len, write_callback);
408 if (errno != EAGAIN && errno != EWOULDBLOCK) {
409 int net_error = MapSystemError(errno);
410 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
411 CreateNetLogSocketErrorCallback(net_error, errno));
412 return net_error;
413 } 236 }
414 237
415 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 238 if (rv != ERR_IO_PENDING)
416 socket_, true, base::MessageLoopForIO::WATCH_WRITE, 239 rv = HandleWriteCompleted(buf, rv);
417 &write_socket_watcher_, &write_watcher_)) { 240 return rv;
418 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
419 return MapSystemError(errno);
420 }
421
422 write_buf_ = buf;
423 write_buf_len_ = buf_len;
424 write_callback_ = callback;
425 return ERR_IO_PENDING;
426 } 241 }
427 242
428 int TCPSocketLibevent::GetLocalAddress(IPEndPoint* address) const { 243 int TCPSocketLibevent::GetLocalAddress(IPEndPoint* address) const {
429 DCHECK(CalledOnValidThread());
430 DCHECK(address); 244 DCHECK(address);
431 245
246 if (!socket_)
247 return ERR_SOCKET_NOT_CONNECTED;
248
432 SockaddrStorage storage; 249 SockaddrStorage storage;
433 if (getsockname(socket_, storage.addr, &storage.addr_len) < 0) 250 int rv = socket_->GetLocalAddress(&storage);
434 return MapSystemError(errno); 251 if (rv != OK)
252 return rv;
253
435 if (!address->FromSockAddr(storage.addr, storage.addr_len)) 254 if (!address->FromSockAddr(storage.addr, storage.addr_len))
436 return ERR_ADDRESS_INVALID; 255 return ERR_ADDRESS_INVALID;
437 256
438 return OK; 257 return OK;
439 } 258 }
440 259
441 int TCPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 260 int TCPSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
442 DCHECK(CalledOnValidThread());
443 DCHECK(address); 261 DCHECK(address);
262
444 if (!IsConnected()) 263 if (!IsConnected())
445 return ERR_SOCKET_NOT_CONNECTED; 264 return ERR_SOCKET_NOT_CONNECTED;
446 *address = *peer_address_; 265
266 SockaddrStorage storage;
267 int rv = socket_->GetPeerAddress(&storage);
268 if (rv != OK)
269 return rv;
270
271 if (!address->FromSockAddr(storage.addr, storage.addr_len))
272 return ERR_ADDRESS_INVALID;
273
447 return OK; 274 return OK;
448 } 275 }
449 276
450 int TCPSocketLibevent::SetDefaultOptionsForServer() { 277 int TCPSocketLibevent::SetDefaultOptionsForServer() {
451 DCHECK(CalledOnValidThread()); 278 DCHECK(socket_);
452 return SetAddressReuse(true); 279 return SetAddressReuse(true);
453 } 280 }
454 281
455 void TCPSocketLibevent::SetDefaultOptionsForClient() { 282 void TCPSocketLibevent::SetDefaultOptionsForClient() {
456 DCHECK(CalledOnValidThread()); 283 DCHECK(socket_);
457 284
458 // This mirrors the behaviour on Windows. See the comment in 285 // This mirrors the behaviour on Windows. See the comment in
459 // tcp_socket_win.cc after searching for "NODELAY". 286 // tcp_socket_win.cc after searching for "NODELAY".
460 SetTCPNoDelay(socket_, true); // If SetTCPNoDelay fails, we don't care. 287 // If SetTCPNoDelay fails, we don't care.
288 SetTCPNoDelay(socket_->socket_fd(), true);
461 289
462 // TCP keep alive wakes up the radio, which is expensive on mobile. Do not 290 // TCP keep alive wakes up the radio, which is expensive on mobile. Do not
463 // enable it there. It's useful to prevent TCP middleboxes from timing out 291 // enable it there. It's useful to prevent TCP middleboxes from timing out
464 // connection mappings. Packets for timed out connection mappings at 292 // connection mappings. Packets for timed out connection mappings at
465 // middleboxes will either lead to: 293 // middleboxes will either lead to:
466 // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this 294 // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this
467 // and retry. The HTTP network transaction code does this. 295 // and retry. The HTTP network transaction code does this.
468 // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP 296 // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP
469 // stack retransmitting packets per TCP stack retransmission timeouts, which 297 // stack retransmitting packets per TCP stack retransmission timeouts, which
470 // are very high (on the order of seconds). Given the number of 298 // are very high (on the order of seconds). Given the number of
471 // retransmissions required before killing the connection, this can lead to 299 // retransmissions required before killing the connection, this can lead to
472 // tens of seconds or even minutes of delay, depending on OS. 300 // tens of seconds or even minutes of delay, depending on OS.
473 #if !defined(OS_ANDROID) && !defined(OS_IOS) 301 #if !defined(OS_ANDROID) && !defined(OS_IOS)
474 const int kTCPKeepAliveSeconds = 45; 302 const int kTCPKeepAliveSeconds = 45;
475 303
476 SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); 304 SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds);
477 #endif 305 #endif
478 } 306 }
479 307
480 int TCPSocketLibevent::SetAddressReuse(bool allow) { 308 int TCPSocketLibevent::SetAddressReuse(bool allow) {
481 DCHECK(CalledOnValidThread()); 309 DCHECK(socket_);
482 310
483 // SO_REUSEADDR is useful for server sockets to bind to a recently unbound 311 // SO_REUSEADDR is useful for server sockets to bind to a recently unbound
484 // port. When a socket is closed, the end point changes its state to TIME_WAIT 312 // port. When a socket is closed, the end point changes its state to TIME_WAIT
485 // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer 313 // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer
486 // acknowledges its closure. For server sockets, it is usually safe to 314 // acknowledges its closure. For server sockets, it is usually safe to
487 // bind to a TIME_WAIT end point immediately, which is a widely adopted 315 // bind to a TIME_WAIT end point immediately, which is a widely adopted
488 // behavior. 316 // behavior.
489 // 317 //
490 // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to 318 // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to
491 // an end point that is already bound by another socket. To do that one must 319 // an end point that is already bound by another socket. To do that one must
492 // set SO_REUSEPORT instead. This option is not provided on Linux prior 320 // set SO_REUSEPORT instead. This option is not provided on Linux prior
493 // to 3.9. 321 // to 3.9.
494 // 322 //
495 // SO_REUSEPORT is provided in MacOS X and iOS. 323 // SO_REUSEPORT is provided in MacOS X and iOS.
496 int boolean_value = allow ? 1 : 0; 324 int boolean_value = allow ? 1 : 0;
497 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &boolean_value, 325 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_REUSEADDR,
498 sizeof(boolean_value)); 326 &boolean_value, sizeof(boolean_value));
499 if (rv < 0) 327 if (rv < 0)
500 return MapSystemError(errno); 328 return MapSystemError(errno);
501 return OK; 329 return OK;
502 } 330 }
503 331
504 int TCPSocketLibevent::SetReceiveBufferSize(int32 size) { 332 int TCPSocketLibevent::SetReceiveBufferSize(int32 size) {
505 DCHECK(CalledOnValidThread()); 333 DCHECK(socket_);
506 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 334 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_RCVBUF,
507 reinterpret_cast<const char*>(&size), sizeof(size)); 335 reinterpret_cast<const char*>(&size), sizeof(size));
508 return (rv == 0) ? OK : MapSystemError(errno); 336 return (rv == 0) ? OK : MapSystemError(errno);
509 } 337 }
510 338
511 int TCPSocketLibevent::SetSendBufferSize(int32 size) { 339 int TCPSocketLibevent::SetSendBufferSize(int32 size) {
512 DCHECK(CalledOnValidThread()); 340 DCHECK(socket_);
513 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 341 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_SNDBUF,
514 reinterpret_cast<const char*>(&size), sizeof(size)); 342 reinterpret_cast<const char*>(&size), sizeof(size));
515 return (rv == 0) ? OK : MapSystemError(errno); 343 return (rv == 0) ? OK : MapSystemError(errno);
516 } 344 }
517 345
518 bool TCPSocketLibevent::SetKeepAlive(bool enable, int delay) { 346 bool TCPSocketLibevent::SetKeepAlive(bool enable, int delay) {
519 DCHECK(CalledOnValidThread()); 347 DCHECK(socket_);
520 return SetTCPKeepAlive(socket_, enable, delay); 348 return SetTCPKeepAlive(socket_->socket_fd(), enable, delay);
521 } 349 }
522 350
523 bool TCPSocketLibevent::SetNoDelay(bool no_delay) { 351 bool TCPSocketLibevent::SetNoDelay(bool no_delay) {
524 DCHECK(CalledOnValidThread()); 352 DCHECK(socket_);
525 return SetTCPNoDelay(socket_, no_delay); 353 return SetTCPNoDelay(socket_->socket_fd(), no_delay);
526 } 354 }
527 355
528 void TCPSocketLibevent::Close() { 356 void TCPSocketLibevent::Close() {
529 DCHECK(CalledOnValidThread()); 357 socket_.reset();
530
531 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
532 DCHECK(ok);
533 ok = read_socket_watcher_.StopWatchingFileDescriptor();
534 DCHECK(ok);
535 ok = write_socket_watcher_.StopWatchingFileDescriptor();
536 DCHECK(ok);
537
538 if (socket_ != kInvalidSocket) {
539 if (IGNORE_EINTR(close(socket_)) < 0)
540 PLOG(ERROR) << "close";
541 socket_ = kInvalidSocket;
542 }
543
544 if (!accept_callback_.is_null()) {
545 accept_socket_ = NULL;
546 accept_address_ = NULL;
547 accept_callback_.Reset();
548 }
549
550 if (!read_callback_.is_null()) {
551 read_buf_ = NULL;
552 read_buf_len_ = 0;
553 read_callback_.Reset();
554 }
555
556 if (!write_callback_.is_null()) {
557 write_buf_ = NULL;
558 write_buf_len_ = 0;
559 write_callback_.Reset();
560 }
561
562 tcp_fastopen_connected_ = false; 358 tcp_fastopen_connected_ = false;
563 fast_open_status_ = FAST_OPEN_STATUS_UNKNOWN; 359 fast_open_status_ = FAST_OPEN_STATUS_UNKNOWN;
564 waiting_connect_ = false;
565 peer_address_.reset();
566 connect_os_error_ = 0;
567 } 360 }
568 361
569 bool TCPSocketLibevent::UsingTCPFastOpen() const { 362 bool TCPSocketLibevent::UsingTCPFastOpen() const {
570 return use_tcp_fastopen_; 363 return use_tcp_fastopen_;
571 } 364 }
572 365
366 bool TCPSocketLibevent::IsValid() const {
367 return socket_ != NULL && socket_->socket_fd() != kInvalidSocket;
368 }
369
573 void TCPSocketLibevent::StartLoggingMultipleConnectAttempts( 370 void TCPSocketLibevent::StartLoggingMultipleConnectAttempts(
574 const AddressList& addresses) { 371 const AddressList& addresses) {
575 if (!logging_multiple_connect_attempts_) { 372 if (!logging_multiple_connect_attempts_) {
576 logging_multiple_connect_attempts_ = true; 373 logging_multiple_connect_attempts_ = true;
577 LogConnectBegin(addresses); 374 LogConnectBegin(addresses);
578 } else { 375 } else {
579 NOTREACHED(); 376 NOTREACHED();
580 } 377 }
581 } 378 }
582 379
583 void TCPSocketLibevent::EndLoggingMultipleConnectAttempts(int net_error) { 380 void TCPSocketLibevent::EndLoggingMultipleConnectAttempts(int net_error) {
584 if (logging_multiple_connect_attempts_) { 381 if (logging_multiple_connect_attempts_) {
585 LogConnectEnd(net_error); 382 LogConnectEnd(net_error);
586 logging_multiple_connect_attempts_ = false; 383 logging_multiple_connect_attempts_ = false;
587 } else { 384 } else {
588 NOTREACHED(); 385 NOTREACHED();
589 } 386 }
590 } 387 }
591 388
592 int TCPSocketLibevent::AcceptInternal(scoped_ptr<TCPSocketLibevent>* socket, 389 void TCPSocketLibevent::AcceptCompleted(
593 IPEndPoint* address) { 390 scoped_ptr<TCPSocketLibevent>* tcp_socket,
594 SockaddrStorage storage; 391 IPEndPoint* address,
595 int new_socket = HANDLE_EINTR(accept(socket_, 392 const CompletionCallback& callback,
596 storage.addr, 393 int rv) {
597 &storage.addr_len)); 394 DCHECK_NE(ERR_IO_PENDING, rv);
598 if (new_socket < 0) { 395 callback.Run(HandleAcceptCompleted(tcp_socket, address, rv));
599 int net_error = MapAcceptError(errno); 396 }
600 if (net_error != ERR_IO_PENDING) 397
601 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); 398 int TCPSocketLibevent::HandleAcceptCompleted(
602 return net_error; 399 scoped_ptr<TCPSocketLibevent>* tcp_socket,
400 IPEndPoint* address,
401 int rv) {
402 if (rv == OK)
403 rv = BuildTcpSocketLibevent(tcp_socket, address);
404
405 if (rv == OK) {
406 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
407 CreateNetLogIPEndPointCallback(address));
408 } else {
409 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, rv);
603 } 410 }
604 411
605 IPEndPoint ip_end_point; 412 return rv;
606 if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { 413 }
607 NOTREACHED(); 414
608 if (IGNORE_EINTR(close(new_socket)) < 0) 415 int TCPSocketLibevent::BuildTcpSocketLibevent(
609 PLOG(ERROR) << "close"; 416 scoped_ptr<TCPSocketLibevent>* tcp_socket,
610 int net_error = ERR_ADDRESS_INVALID; 417 IPEndPoint* address) {
611 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error); 418 DCHECK(accept_socket_);
612 return net_error; 419
420 SockaddrStorage storage;
421 if (accept_socket_->GetPeerAddress(&storage) != OK ||
422 !address->FromSockAddr(storage.addr, storage.addr_len)) {
423 accept_socket_.reset();
424 return ERR_ADDRESS_INVALID;
613 } 425 }
614 scoped_ptr<TCPSocketLibevent> tcp_socket(new TCPSocketLibevent( 426
615 net_log_.net_log(), net_log_.source())); 427 tcp_socket->reset(new TCPSocketLibevent(net_log_.net_log(),
616 int adopt_result = tcp_socket->AdoptConnectedSocket(new_socket, ip_end_point); 428 net_log_.source()));
617 if (adopt_result != OK) { 429 (*tcp_socket)->socket_.reset(accept_socket_.release());
618 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result);
619 return adopt_result;
620 }
621 *socket = tcp_socket.Pass();
622 *address = ip_end_point;
623 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
624 CreateNetLogIPEndPointCallback(&ip_end_point));
625 return OK; 430 return OK;
626 } 431 }
627 432
628 int TCPSocketLibevent::DoConnect() { 433 void TCPSocketLibevent::ConnectCompleted(const CompletionCallback& callback,
629 DCHECK_EQ(0, connect_os_error_); 434 int rv) const {
630 435 DCHECK_NE(ERR_IO_PENDING, rv);
631 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 436 callback.Run(HandleConnectCompleted(rv));
632 CreateNetLogIPEndPointCallback(peer_address_.get()));
633
634 // Connect the socket.
635 if (!use_tcp_fastopen_) {
636 SockaddrStorage storage;
637 if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len))
638 return ERR_ADDRESS_INVALID;
639
640 if (!HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len))) {
641 // Connected without waiting!
642 return OK;
643 }
644 } else {
645 // With TCP FastOpen, we pretend that the socket is connected.
646 DCHECK(!tcp_fastopen_connected_);
647 return OK;
648 }
649
650 // Check if the connect() failed synchronously.
651 connect_os_error_ = errno;
652 if (connect_os_error_ != EINPROGRESS)
653 return MapConnectError(connect_os_error_);
654
655 // Otherwise the connect() is going to complete asynchronously, so watch
656 // for its completion.
657 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
658 socket_, true, base::MessageLoopForIO::WATCH_WRITE,
659 &write_socket_watcher_, &write_watcher_)) {
660 connect_os_error_ = errno;
661 DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_;
662 return MapSystemError(connect_os_error_);
663 }
664
665 return ERR_IO_PENDING;
666 } 437 }
667 438
668 void TCPSocketLibevent::DoConnectComplete(int result) { 439 int TCPSocketLibevent::HandleConnectCompleted(int rv) const {
669 // Log the end of this attempt (and any OS error it threw). 440 // Log the end of this attempt (and any OS error it threw).
670 int os_error = connect_os_error_; 441 if (rv != OK) {
671 connect_os_error_ = 0;
672 if (result != OK) {
673 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 442 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
674 NetLog::IntegerCallback("os_error", os_error)); 443 NetLog::IntegerCallback("os_error", errno));
675 } else { 444 } else {
676 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); 445 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT);
677 } 446 }
678 447
448 // Give a more specific error when the user is offline.
449 if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline())
450 rv = ERR_INTERNET_DISCONNECTED;
451
679 if (!logging_multiple_connect_attempts_) 452 if (!logging_multiple_connect_attempts_)
680 LogConnectEnd(result); 453 LogConnectEnd(rv);
454
455 return rv;
681 } 456 }
682 457
683 void TCPSocketLibevent::LogConnectBegin(const AddressList& addresses) { 458 void TCPSocketLibevent::LogConnectBegin(const AddressList& addresses) const {
684 base::StatsCounter connects("tcp.connect"); 459 base::StatsCounter connects("tcp.connect");
685 connects.Increment(); 460 connects.Increment();
686 461
687 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 462 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
688 addresses.CreateNetLogCallback()); 463 addresses.CreateNetLogCallback());
689 } 464 }
690 465
691 void TCPSocketLibevent::LogConnectEnd(int net_error) { 466 void TCPSocketLibevent::LogConnectEnd(int net_error) const {
692 if (net_error == OK)
693 UpdateConnectionTypeHistograms(CONNECTION_ANY);
694
695 if (net_error != OK) { 467 if (net_error != OK) {
696 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 468 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
697 return; 469 return;
698 } 470 }
699 471
472 UpdateConnectionTypeHistograms(CONNECTION_ANY);
473
700 SockaddrStorage storage; 474 SockaddrStorage storage;
701 int rv = getsockname(socket_, storage.addr, &storage.addr_len); 475 int rv = socket_->GetLocalAddress(&storage);
702 if (rv != 0) { 476 if (rv != OK) {
703 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; 477 PLOG(ERROR) << "GetLocalAddress() [rv: " << rv << "] error: ";
704 NOTREACHED(); 478 NOTREACHED();
705 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 479 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
706 return; 480 return;
707 } 481 }
708 482
709 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, 483 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT,
710 CreateNetLogSourceAddressCallback(storage.addr, 484 CreateNetLogSourceAddressCallback(storage.addr,
711 storage.addr_len)); 485 storage.addr_len));
712 } 486 }
713 487
714 void TCPSocketLibevent::DidCompleteRead() { 488 void TCPSocketLibevent::ReadCompleted(IOBuffer* buf,
489 const CompletionCallback& callback,
490 int rv) {
491 DCHECK_NE(ERR_IO_PENDING, rv);
492 // Records fast open status regardless of error in asynchronous case.
493 // TODO(rdsmith,jri): Change histogram name to indicate it could be called on
494 // error.
715 RecordFastOpenStatus(); 495 RecordFastOpenStatus();
716 if (read_callback_.is_null()) 496 callback.Run(HandleReadCompleted(buf, rv));
717 return; 497 }
718 498
719 int bytes_transferred; 499 int TCPSocketLibevent::HandleReadCompleted(IOBuffer* buf, int rv) {
720 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), 500 if (rv < 0) {
721 read_buf_len_)); 501 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
722 502 CreateNetLogSocketErrorCallback(rv, errno));
723 int result; 503 return rv;
724 if (bytes_transferred >= 0) {
725 result = bytes_transferred;
726 base::StatsCounter read_bytes("tcp.read_bytes");
727 read_bytes.Add(bytes_transferred);
728 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, result,
729 read_buf_->data());
730 } else {
731 result = MapSystemError(errno);
732 if (result != ERR_IO_PENDING) {
733 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
734 CreateNetLogSocketErrorCallback(result, errno));
735 }
736 } 504 }
737 505
738 if (result != ERR_IO_PENDING) { 506 base::StatsCounter read_bytes("tcp.read_bytes");
739 read_buf_ = NULL; 507 read_bytes.Add(rv);
740 read_buf_len_ = 0; 508 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
741 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 509 buf->data());
742 DCHECK(ok); 510 return rv;
743 base::ResetAndReturn(&read_callback_).Run(result);
744 }
745 } 511 }
746 512
747 void TCPSocketLibevent::DidCompleteWrite() { 513 void TCPSocketLibevent::WriteCompleted(IOBuffer* buf,
748 if (write_callback_.is_null()) 514 const CompletionCallback& callback,
749 return; 515 int rv) const {
516 DCHECK_NE(ERR_IO_PENDING, rv);
517 callback.Run(HandleWriteCompleted(buf, rv));
518 }
750 519
751 int bytes_transferred; 520 int TCPSocketLibevent::HandleWriteCompleted(IOBuffer* buf, int rv) const {
752 bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), 521 if (rv < 0) {
753 write_buf_len_)); 522 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
754 523 CreateNetLogSocketErrorCallback(rv, errno));
755 int result; 524 return rv;
756 if (bytes_transferred >= 0) {
757 result = bytes_transferred;
758 base::StatsCounter write_bytes("tcp.write_bytes");
759 write_bytes.Add(bytes_transferred);
760 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, result,
761 write_buf_->data());
762 } else {
763 result = MapSystemError(errno);
764 if (result != ERR_IO_PENDING) {
765 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
766 CreateNetLogSocketErrorCallback(result, errno));
767 }
768 } 525 }
769 526
770 if (result != ERR_IO_PENDING) { 527 base::StatsCounter write_bytes("tcp.write_bytes");
771 write_buf_ = NULL; 528 write_bytes.Add(rv);
772 write_buf_len_ = 0; 529 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv,
773 write_socket_watcher_.StopWatchingFileDescriptor(); 530 buf->data());
774 base::ResetAndReturn(&write_callback_).Run(result); 531 return rv;
775 }
776 } 532 }
777 533
778 void TCPSocketLibevent::DidCompleteConnect() { 534 int TCPSocketLibevent::TcpFastOpenWrite(
779 DCHECK(waiting_connect_); 535 IOBuffer* buf,
536 int buf_len,
537 const CompletionCallback& callback) {
538 SockaddrStorage storage;
539 int rv = socket_->GetPeerAddress(&storage);
540 if (rv != OK)
541 return rv;
780 542
781 // Get the error that connect() completed with. 543 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN.
782 int os_error = 0; 544 #if defined(OS_LINUX)
783 socklen_t len = sizeof(os_error); 545 // sendto() will fail with EPIPE when the system doesn't support TCP Fast
784 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0) 546 // Open. Theoretically that shouldn't happen since the caller should check
785 os_error = errno; 547 // for system support on startup, but users may dynamically disable TCP Fast
548 // Open via sysctl.
549 flags |= MSG_NOSIGNAL;
550 #endif // defined(OS_LINUX)
551 rv = HANDLE_EINTR(sendto(socket_->socket_fd(),
552 buf->data(),
553 buf_len,
554 flags,
555 storage.addr,
556 storage.addr_len));
557 tcp_fastopen_connected_ = true;
786 558
787 int result = MapConnectError(os_error); 559 if (rv >= 0) {
788 connect_os_error_ = os_error; 560 fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN;
789 if (result != ERR_IO_PENDING) { 561 return rv;
790 DoConnectComplete(result);
791 waiting_connect_ = false;
792 write_socket_watcher_.StopWatchingFileDescriptor();
793 base::ResetAndReturn(&write_callback_).Run(result);
794 } 562 }
795 }
796 563
797 void TCPSocketLibevent::DidCompleteConnectOrWrite() { 564 DCHECK_NE(EPIPE, errno);
798 if (waiting_connect_)
799 DidCompleteConnect();
800 else
801 DidCompleteWrite();
802 }
803 565
804 void TCPSocketLibevent::DidCompleteAccept() { 566 // If errno == EINPROGRESS, that means the kernel didn't have a cookie
805 DCHECK(CalledOnValidThread()); 567 // and would block. The kernel is internally doing a connect() though.
568 // Remap EINPROGRESS to EAGAIN so we treat this the same as our other
569 // asynchronous cases. Note that the user buffer has not been copied to
570 // kernel space.
571 if (errno == EINPROGRESS) {
572 rv = ERR_IO_PENDING;
573 } else {
574 rv = MapSystemError(errno);
575 }
806 576
807 int result = AcceptInternal(accept_socket_, accept_address_); 577 if (rv != ERR_IO_PENDING) {
808 if (result != ERR_IO_PENDING) { 578 fast_open_status_ = FAST_OPEN_ERROR;
809 accept_socket_ = NULL; 579 return rv;
810 accept_address_ = NULL;
811 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
812 DCHECK(ok);
813 CompletionCallback callback = accept_callback_;
814 accept_callback_.Reset();
815 callback.Run(result);
816 } 580 }
817 }
818 581
819 int TCPSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { 582 fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN;
820 int nwrite; 583 return socket_->WaitForWrite(buf, buf_len, callback);
821 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
822 SockaddrStorage storage;
823 if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len)) {
824 // Set errno to EADDRNOTAVAIL so that MapSystemError will map it to
825 // ERR_ADDRESS_INVALID later.
826 errno = EADDRNOTAVAIL;
827 return -1;
828 }
829
830 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN.
831 #if defined(OS_LINUX)
832 // sendto() will fail with EPIPE when the system doesn't support TCP Fast
833 // Open. Theoretically that shouldn't happen since the caller should check
834 // for system support on startup, but users may dynamically disable TCP Fast
835 // Open via sysctl.
836 flags |= MSG_NOSIGNAL;
837 #endif // defined(OS_LINUX)
838 nwrite = HANDLE_EINTR(sendto(socket_,
839 buf->data(),
840 buf_len,
841 flags,
842 storage.addr,
843 storage.addr_len));
844 tcp_fastopen_connected_ = true;
845
846 if (nwrite < 0) {
847 DCHECK_NE(EPIPE, errno);
848
849 // If errno == EINPROGRESS, that means the kernel didn't have a cookie
850 // and would block. The kernel is internally doing a connect() though.
851 // Remap EINPROGRESS to EAGAIN so we treat this the same as our other
852 // asynchronous cases. Note that the user buffer has not been copied to
853 // kernel space.
854 if (errno == EINPROGRESS) {
855 errno = EAGAIN;
856 fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN;
857 } else {
858 fast_open_status_ = FAST_OPEN_ERROR;
859 }
860 } else {
861 fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN;
862 }
863 } else {
864 nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
865 }
866 return nwrite;
867 } 584 }
868 585
869 void TCPSocketLibevent::RecordFastOpenStatus() { 586 void TCPSocketLibevent::RecordFastOpenStatus() {
870 if (use_tcp_fastopen_ && 587 if (use_tcp_fastopen_ &&
871 (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN || 588 (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ||
872 fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) { 589 fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) {
873 DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_); 590 DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_);
874 bool getsockopt_success(false); 591 bool getsockopt_success(false);
875 bool server_acked_data(false); 592 bool server_acked_data(false);
876 #if defined(TCP_INFO) 593 #if defined(TCP_INFO)
877 // Probe to see the if the socket used TCP Fast Open. 594 // Probe to see the if the socket used TCP Fast Open.
878 tcp_info info; 595 tcp_info info;
879 socklen_t info_len = sizeof(tcp_info); 596 socklen_t info_len = sizeof(tcp_info);
880 getsockopt_success = 597 getsockopt_success =
881 getsockopt(socket_, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0 && 598 getsockopt(socket_->socket_fd(), IPPROTO_TCP, TCP_INFO,
599 &info, &info_len) == 0 &&
882 info_len == sizeof(tcp_info); 600 info_len == sizeof(tcp_info);
883 server_acked_data = getsockopt_success && 601 server_acked_data = getsockopt_success &&
884 (info.tcpi_options & TCPI_OPT_SYN_DATA); 602 (info.tcpi_options & TCPI_OPT_SYN_DATA);
885 #endif 603 #endif
886 if (getsockopt_success) { 604 if (getsockopt_success) {
887 if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) { 605 if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) {
888 fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK : 606 fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK :
889 FAST_OPEN_SYN_DATA_NACK); 607 FAST_OPEN_SYN_DATA_NACK);
890 } else { 608 } else {
891 fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK : 609 fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK :
892 FAST_OPEN_NO_SYN_DATA_NACK); 610 FAST_OPEN_NO_SYN_DATA_NACK);
893 } 611 }
894 } else { 612 } else {
895 fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ? 613 fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ?
896 FAST_OPEN_SYN_DATA_FAILED : 614 FAST_OPEN_SYN_DATA_FAILED :
897 FAST_OPEN_NO_SYN_DATA_FAILED); 615 FAST_OPEN_NO_SYN_DATA_FAILED);
898 } 616 }
899 } 617 }
900 } 618 }
901 619
902 } // namespace net 620 } // namespace net
OLDNEW
« device/bluetooth/bluetooth_socket_net.cc ('K') | « net/socket/tcp_socket_libevent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698