1 // Copyright 2013 The Chromium Authors
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/tcp_socket.h"
6
7 #include <errno.h>
8 #include <netinet/tcp.h>
9 #include <sys/socket.h>
10
11 #include <algorithm>
12 #include <memory>
13
14 #include "base/atomicops.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/functional/bind.h"
18 #include "base/lazy_instance.h"
19 #include "base/logging.h"
20 #include "base/metrics/histogram_macros.h"
21 #include "base/posix/eintr_wrapper.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_piece.h"
24 #include "base/time/time.h"
25 #include "build/build_config.h"
26 #include "net/base/address_list.h"
27 #include "net/base/io_buffer.h"
28 #include "net/base/ip_endpoint.h"
29 #include "net/base/net_errors.h"
30 #include "net/base/network_activity_monitor.h"
31 #include "net/base/network_change_notifier.h"
32 #include "net/base/sockaddr_storage.h"
33 #include "net/base/sys_addrinfo.h"
34 #include "net/base/tracing.h"
35 #include "net/http/http_util.h"
36 #include "net/log/net_log.h"
37 #include "net/log/net_log_event_type.h"
38 #include "net/log/net_log_source.h"
39 #include "net/log/net_log_source_type.h"
40 #include "net/log/net_log_values.h"
41 #include "net/socket/socket_net_log_params.h"
42 #include "net/socket/socket_options.h"
43 #include "net/socket/socket_posix.h"
44 #include "net/socket/socket_tag.h"
45 #include "net/traffic_annotation/network_traffic_annotation.h"
46
47 #if BUILDFLAG(IS_ANDROID)
48 #include "net/android/network_library.h"
49 #endif // BUILDFLAG(IS_ANDROID)
50
51 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one.
52 #if !defined(TCPI_OPT_SYN_DATA)
53 #define TCPI_OPT_SYN_DATA 32
54 #endif
55
56 // Fuchsia defines TCP_INFO, but it's not implemented.
57 // TODO(crbug.com/758294): Enable TCP_INFO on Fuchsia once it's implemented
58 // there (see NET-160).
59 #if defined(TCP_INFO) && !BUILDFLAG(IS_FUCHSIA)
60 #define HAVE_TCP_INFO
61 #endif
62
63 namespace net {
64
65 namespace {
66
67 // SetTCPKeepAlive sets SO_KEEPALIVE.
SetTCPKeepAlive(int fd,bool enable,int delay)68 bool SetTCPKeepAlive(int fd, bool enable, int delay) {
69 // Enabling TCP keepalives is the same on all platforms.
70 int on = enable ? 1 : 0;
71 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) {
72 PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd;
73 return false;
74 }
75
76 // If we disabled TCP keep alive, our work is done here.
77 if (!enable)
78 return true;
79
80 // A delay of 0 doesn't work, and is the default, so ignore that and rely on
81 // whatever the OS defaults are once we turned it on above.
82 if (delay) {
83 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
84 // Setting the keepalive interval varies by platform.
85
86 // Set seconds until first TCP keep alive.
87 if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) {
88 PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd;
89 return false;
90 }
91 // Set seconds between TCP keep alives.
92 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) {
93 PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd;
94 return false;
95 }
96 #elif BUILDFLAG(IS_APPLE)
97 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay))) {
98 PLOG(ERROR) << "Failed to set TCP_KEEPALIVE on fd: " << fd;
99 return false;
100 }
101 #endif
102 }
103
104 return true;
105 }
106
107 #if defined(HAVE_TCP_INFO)
108 // Returns a zero value if the transport RTT is unavailable.
GetTransportRtt(SocketDescriptor fd)109 base::TimeDelta GetTransportRtt(SocketDescriptor fd) {
110 // It is possible for the value returned by getsockopt(TCP_INFO) to be
111 // legitimately zero due to the way the RTT is calculated where fractions are
112 // rounded down. This is specially true for virtualized environments with
113 // paravirtualized clocks.
114 //
115 // If getsockopt(TCP_INFO) succeeds and the tcpi_rtt is zero, this code
116 // assumes that the RTT got rounded down to zero and rounds it back up to this
117 // value so that callers can assume that no packets defy the laws of physics.
118 constexpr uint32_t kMinValidRttMicros = 1;
119
120 tcp_info info;
121 // Reset |tcpi_rtt| to verify if getsockopt() actually updates |tcpi_rtt|.
122 info.tcpi_rtt = 0;
123
124 socklen_t info_len = sizeof(tcp_info);
125 if (getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &info_len) != 0)
126 return base::TimeDelta();
127
128 // Verify that |tcpi_rtt| in tcp_info struct was updated. Note that it's
129 // possible that |info_len| is shorter than |sizeof(tcp_info)| which implies
130 // that only a subset of values in |info| may have been updated by
131 // getsockopt().
132 if (info_len < static_cast<socklen_t>(offsetof(tcp_info, tcpi_rtt) +
133 sizeof(info.tcpi_rtt))) {
134 return base::TimeDelta();
135 }
136
137 return base::Microseconds(std::max(info.tcpi_rtt, kMinValidRttMicros));
138 }
139
140 #endif // defined(TCP_INFO)
141
142 #if BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
143 // Returns true if `socket` is connected to 0.0.0.0, false otherwise.
144 // For detecting slow socket close due to a MacOS bug
145 // (https://crbug.com/1194888).
PeerIsZeroIPv4(const TCPSocketPosix & socket)146 bool PeerIsZeroIPv4(const TCPSocketPosix& socket) {
147 IPEndPoint peer;
148 if (socket.GetPeerAddress(&peer) != OK)
149 return false;
150 return peer.address().IsIPv4() && peer.address().IsZero();
151 }
152 #endif // BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
153
154 } // namespace
155
156 //-----------------------------------------------------------------------------
157
TCPSocketPosix(std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,NetLog * net_log,const NetLogSource & source)158 TCPSocketPosix::TCPSocketPosix(
159 std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
160 NetLog* net_log,
161 const NetLogSource& source)
162 : socket_performance_watcher_(std::move(socket_performance_watcher)),
163 net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {
164 net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source);
165 }
166
TCPSocketPosix(std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,NetLogWithSource net_log_source)167 TCPSocketPosix::TCPSocketPosix(
168 std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
169 NetLogWithSource net_log_source)
170 : socket_performance_watcher_(std::move(socket_performance_watcher)),
171 net_log_(net_log_source) {
172 net_log_.BeginEvent(NetLogEventType::SOCKET_ALIVE);
173 }
174
~TCPSocketPosix()175 TCPSocketPosix::~TCPSocketPosix() {
176 net_log_.EndEvent(NetLogEventType::SOCKET_ALIVE);
177 Close();
178 }
179
Open(AddressFamily family)180 int TCPSocketPosix::Open(AddressFamily family) {
181 DCHECK(!socket_);
182 socket_ = std::make_unique<SocketPosix>();
183 int rv = socket_->Open(ConvertAddressFamily(family));
184 if (rv != OK)
185 socket_.reset();
186 if (rv == OK && tag_ != SocketTag())
187 tag_.Apply(socket_->socket_fd());
188 return rv;
189 }
190
BindToNetwork(handles::NetworkHandle network)191 int TCPSocketPosix::BindToNetwork(handles::NetworkHandle network) {
192 DCHECK(IsValid());
193 DCHECK(!IsConnected());
194 #if BUILDFLAG(IS_ANDROID)
195 return net::android::BindToNetwork(socket_->socket_fd(), network);
196 #else
197 NOTIMPLEMENTED();
198 return ERR_NOT_IMPLEMENTED;
199 #endif // BUILDFLAG(IS_ANDROID)
200 }
201
AdoptConnectedSocket(SocketDescriptor socket,const IPEndPoint & peer_address)202 int TCPSocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
203 const IPEndPoint& peer_address) {
204 DCHECK(!socket_);
205
206 SockaddrStorage storage;
207 if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len) &&
208 // For backward compatibility, allows the empty address.
209 !(peer_address == IPEndPoint())) {
210 return ERR_ADDRESS_INVALID;
211 }
212
213 socket_ = std::make_unique<SocketPosix>();
214 int rv = socket_->AdoptConnectedSocket(socket, storage);
215 if (rv != OK)
216 socket_.reset();
217 if (rv == OK && tag_ != SocketTag())
218 tag_.Apply(socket_->socket_fd());
219 return rv;
220 }
221
AdoptUnconnectedSocket(SocketDescriptor socket)222 int TCPSocketPosix::AdoptUnconnectedSocket(SocketDescriptor socket) {
223 DCHECK(!socket_);
224
225 socket_ = std::make_unique<SocketPosix>();
226 int rv = socket_->AdoptUnconnectedSocket(socket);
227 if (rv != OK)
228 socket_.reset();
229 if (rv == OK && tag_ != SocketTag())
230 tag_.Apply(socket_->socket_fd());
231 return rv;
232 }
233
Bind(const IPEndPoint & address)234 int TCPSocketPosix::Bind(const IPEndPoint& address) {
235 DCHECK(socket_);
236
237 SockaddrStorage storage;
238 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
239 return ERR_ADDRESS_INVALID;
240
241 return socket_->Bind(storage);
242 }
243
Listen(int backlog)244 int TCPSocketPosix::Listen(int backlog) {
245 DCHECK(socket_);
246 return socket_->Listen(backlog);
247 }
248
Accept(std::unique_ptr<TCPSocketPosix> * tcp_socket,IPEndPoint * address,CompletionOnceCallback callback)249 int TCPSocketPosix::Accept(std::unique_ptr<TCPSocketPosix>* tcp_socket,
250 IPEndPoint* address,
251 CompletionOnceCallback callback) {
252 DCHECK(tcp_socket);
253 DCHECK(!callback.is_null());
254 DCHECK(socket_);
255 DCHECK(!accept_socket_);
256
257 net_log_.BeginEvent(NetLogEventType::TCP_ACCEPT);
258
259 int rv = socket_->Accept(
260 &accept_socket_,
261 base::BindOnce(&TCPSocketPosix::AcceptCompleted, base::Unretained(this),
262 tcp_socket, address, std::move(callback)));
263 if (rv != ERR_IO_PENDING)
264 rv = HandleAcceptCompleted(tcp_socket, address, rv);
265 return rv;
266 }
267
Connect(const IPEndPoint & address,CompletionOnceCallback callback)268 int TCPSocketPosix::Connect(const IPEndPoint& address,
269 CompletionOnceCallback callback) {
270 DCHECK(socket_);
271
272 if (!logging_multiple_connect_attempts_)
273 LogConnectBegin(AddressList(address));
274
275 net_log_.BeginEvent(NetLogEventType::TCP_CONNECT_ATTEMPT,
276 [&] { return CreateNetLogIPEndPointParams(&address); });
277
278 SockaddrStorage storage;
279 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
280 return ERR_ADDRESS_INVALID;
281
282 int rv = socket_->Connect(
283 storage, base::BindOnce(&TCPSocketPosix::ConnectCompleted,
284 base::Unretained(this), std::move(callback)));
285 if (rv != ERR_IO_PENDING)
286 rv = HandleConnectCompleted(rv);
287 return rv;
288 }
289
IsConnected() const290 bool TCPSocketPosix::IsConnected() const {
291 if (!socket_)
292 return false;
293
294 return socket_->IsConnected();
295 }
296
IsConnectedAndIdle() const297 bool TCPSocketPosix::IsConnectedAndIdle() const {
298 return socket_ && socket_->IsConnectedAndIdle();
299 }
300
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)301 int TCPSocketPosix::Read(IOBuffer* buf,
302 int buf_len,
303 CompletionOnceCallback callback) {
304 DCHECK(socket_);
305 DCHECK(!callback.is_null());
306
307 int rv = socket_->Read(
308 buf, buf_len,
309 base::BindOnce(
310 &TCPSocketPosix::ReadCompleted,
311 // Grab a reference to |buf| so that ReadCompleted() can still
312 // use it when Read() completes, as otherwise, this transfers
313 // ownership of buf to socket.
314 base::Unretained(this), base::WrapRefCounted(buf),
315 std::move(callback)));
316 if (rv != ERR_IO_PENDING)
317 rv = HandleReadCompleted(buf, rv);
318 return rv;
319 }
320
ReadIfReady(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)321 int TCPSocketPosix::ReadIfReady(IOBuffer* buf,
322 int buf_len,
323 CompletionOnceCallback callback) {
324 DCHECK(socket_);
325 DCHECK(!callback.is_null());
326
327 int rv = socket_->ReadIfReady(
328 buf, buf_len,
329 base::BindOnce(&TCPSocketPosix::ReadIfReadyCompleted,
330 base::Unretained(this), std::move(callback)));
331 if (rv != ERR_IO_PENDING)
332 rv = HandleReadCompleted(buf, rv);
333 return rv;
334 }
335
CancelReadIfReady()336 int TCPSocketPosix::CancelReadIfReady() {
337 DCHECK(socket_);
338
339 return socket_->CancelReadIfReady();
340 }
341
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)342 int TCPSocketPosix::Write(
343 IOBuffer* buf,
344 int buf_len,
345 CompletionOnceCallback callback,
346 const NetworkTrafficAnnotationTag& traffic_annotation) {
347 DCHECK(socket_);
348 DCHECK(!callback.is_null());
349
350 CompletionOnceCallback write_callback = base::BindOnce(
351 &TCPSocketPosix::WriteCompleted,
352 // Grab a reference to |buf| so that WriteCompleted() can still
353 // use it when Write() completes, as otherwise, this transfers
354 // ownership of buf to socket.
355 base::Unretained(this), base::WrapRefCounted(buf), std::move(callback));
356 int rv;
357
358 rv = socket_->Write(buf, buf_len, std::move(write_callback),
359 traffic_annotation);
360
361 if (rv != ERR_IO_PENDING)
362 rv = HandleWriteCompleted(buf, rv);
363 return rv;
364 }
365
GetLocalAddress(IPEndPoint * address) const366 int TCPSocketPosix::GetLocalAddress(IPEndPoint* address) const {
367 DCHECK(address);
368
369 if (!socket_)
370 return ERR_SOCKET_NOT_CONNECTED;
371
372 SockaddrStorage storage;
373 int rv = socket_->GetLocalAddress(&storage);
374 if (rv != OK)
375 return rv;
376
377 if (!address->FromSockAddr(storage.addr, storage.addr_len))
378 return ERR_ADDRESS_INVALID;
379
380 return OK;
381 }
382
GetPeerAddress(IPEndPoint * address) const383 int TCPSocketPosix::GetPeerAddress(IPEndPoint* address) const {
384 DCHECK(address);
385
386 if (!IsConnected())
387 return ERR_SOCKET_NOT_CONNECTED;
388
389 SockaddrStorage storage;
390 int rv = socket_->GetPeerAddress(&storage);
391 if (rv != OK)
392 return rv;
393
394 if (!address->FromSockAddr(storage.addr, storage.addr_len))
395 return ERR_ADDRESS_INVALID;
396
397 return OK;
398 }
399
SetDefaultOptionsForServer()400 int TCPSocketPosix::SetDefaultOptionsForServer() {
401 DCHECK(socket_);
402 return AllowAddressReuse();
403 }
404
SetDefaultOptionsForClient()405 void TCPSocketPosix::SetDefaultOptionsForClient() {
406 DCHECK(socket_);
407
408 // This mirrors the behaviour on Windows. See the comment in
409 // tcp_socket_win.cc after searching for "NODELAY".
410 // If SetTCPNoDelay fails, we don't care.
411 SetTCPNoDelay(socket_->socket_fd(), true);
412
413 // TCP keep alive wakes up the radio, which is expensive on mobile. Do not
414 // enable it there. It's useful to prevent TCP middleboxes from timing out
415 // connection mappings. Packets for timed out connection mappings at
416 // middleboxes will either lead to:
417 // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this
418 // and retry. The HTTP network transaction code does this.
419 // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP
420 // stack retransmitting packets per TCP stack retransmission timeouts, which
421 // are very high (on the order of seconds). Given the number of
422 // retransmissions required before killing the connection, this can lead to
423 // tens of seconds or even minutes of delay, depending on OS.
424 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
425 const int kTCPKeepAliveSeconds = 45;
426
427 SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds);
428 #endif
429 }
430
AllowAddressReuse()431 int TCPSocketPosix::AllowAddressReuse() {
432 DCHECK(socket_);
433
434 return SetReuseAddr(socket_->socket_fd(), true);
435 }
436
SetReceiveBufferSize(int32_t size)437 int TCPSocketPosix::SetReceiveBufferSize(int32_t size) {
438 DCHECK(socket_);
439
440 return SetSocketReceiveBufferSize(socket_->socket_fd(), size);
441 }
442
SetSendBufferSize(int32_t size)443 int TCPSocketPosix::SetSendBufferSize(int32_t size) {
444 DCHECK(socket_);
445
446 return SetSocketSendBufferSize(socket_->socket_fd(), size);
447 }
448
SetKeepAlive(bool enable,int delay)449 bool TCPSocketPosix::SetKeepAlive(bool enable, int delay) {
450 if (!socket_)
451 return false;
452
453 return SetTCPKeepAlive(socket_->socket_fd(), enable, delay);
454 }
455
SetNoDelay(bool no_delay)456 bool TCPSocketPosix::SetNoDelay(bool no_delay) {
457 if (!socket_)
458 return false;
459
460 return SetTCPNoDelay(socket_->socket_fd(), no_delay) == OK;
461 }
462
SetIPv6Only(bool ipv6_only)463 int TCPSocketPosix::SetIPv6Only(bool ipv6_only) {
464 CHECK(socket_);
465 return ::net::SetIPv6Only(socket_->socket_fd(), ipv6_only);
466 }
467
Close()468 void TCPSocketPosix::Close() {
469 #if BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
470 // A MacOS bug can cause sockets to 0.0.0.0 to take 1 second to close. Log a
471 // trace event for this case so that it can be correlated with jank in traces.
472 // Use the "base" category since "net" isn't enabled by default. See
473 // https://crbug.com/1194888.
474 TRACE_EVENT("base", PeerIsZeroIPv4(*this)
475 ? perfetto::StaticString{"CloseSocketTCP.PeerIsZero"}
476 : perfetto::StaticString{"CloseSocketTCP"});
477 #endif // BUILDFLAG(IS_APPLE) && !BUILDFLAG(CRONET_BUILD)
478 socket_.reset();
479 tag_ = SocketTag();
480 }
481
IsValid() const482 bool TCPSocketPosix::IsValid() const {
483 return socket_ != nullptr && socket_->socket_fd() != kInvalidSocket;
484 }
485
DetachFromThread()486 void TCPSocketPosix::DetachFromThread() {
487 socket_->DetachFromThread();
488 }
489
StartLoggingMultipleConnectAttempts(const AddressList & addresses)490 void TCPSocketPosix::StartLoggingMultipleConnectAttempts(
491 const AddressList& addresses) {
492 if (!logging_multiple_connect_attempts_) {
493 logging_multiple_connect_attempts_ = true;
494 LogConnectBegin(addresses);
495 } else {
496 NOTREACHED();
497 }
498 }
499
EndLoggingMultipleConnectAttempts(int net_error)500 void TCPSocketPosix::EndLoggingMultipleConnectAttempts(int net_error) {
501 if (logging_multiple_connect_attempts_) {
502 LogConnectEnd(net_error);
503 logging_multiple_connect_attempts_ = false;
504 } else {
505 NOTREACHED();
506 }
507 }
508
ReleaseSocketDescriptorForTesting()509 SocketDescriptor TCPSocketPosix::ReleaseSocketDescriptorForTesting() {
510 SocketDescriptor socket_descriptor = socket_->ReleaseConnectedSocket();
511 socket_.reset();
512 return socket_descriptor;
513 }
514
SocketDescriptorForTesting() const515 SocketDescriptor TCPSocketPosix::SocketDescriptorForTesting() const {
516 return socket_->socket_fd();
517 }
518
ApplySocketTag(const SocketTag & tag)519 void TCPSocketPosix::ApplySocketTag(const SocketTag& tag) {
520 if (IsValid() && tag != tag_) {
521 tag.Apply(socket_->socket_fd());
522 }
523 tag_ = tag;
524 }
525
AcceptCompleted(std::unique_ptr<TCPSocketPosix> * tcp_socket,IPEndPoint * address,CompletionOnceCallback callback,int rv)526 void TCPSocketPosix::AcceptCompleted(
527 std::unique_ptr<TCPSocketPosix>* tcp_socket,
528 IPEndPoint* address,
529 CompletionOnceCallback callback,
530 int rv) {
531 DCHECK_NE(ERR_IO_PENDING, rv);
532 std::move(callback).Run(HandleAcceptCompleted(tcp_socket, address, rv));
533 }
534
HandleAcceptCompleted(std::unique_ptr<TCPSocketPosix> * tcp_socket,IPEndPoint * address,int rv)535 int TCPSocketPosix::HandleAcceptCompleted(
536 std::unique_ptr<TCPSocketPosix>* tcp_socket,
537 IPEndPoint* address,
538 int rv) {
539 if (rv == OK)
540 rv = BuildTcpSocketPosix(tcp_socket, address);
541
542 if (rv == OK) {
543 net_log_.EndEvent(NetLogEventType::TCP_ACCEPT,
544 [&] { return CreateNetLogIPEndPointParams(address); });
545 } else {
546 net_log_.EndEventWithNetErrorCode(NetLogEventType::TCP_ACCEPT, rv);
547 }
548
549 return rv;
550 }
551
BuildTcpSocketPosix(std::unique_ptr<TCPSocketPosix> * tcp_socket,IPEndPoint * address)552 int TCPSocketPosix::BuildTcpSocketPosix(
553 std::unique_ptr<TCPSocketPosix>* tcp_socket,
554 IPEndPoint* address) {
555 DCHECK(accept_socket_);
556
557 SockaddrStorage storage;
558 if (accept_socket_->GetPeerAddress(&storage) != OK ||
559 !address->FromSockAddr(storage.addr, storage.addr_len)) {
560 accept_socket_.reset();
561 return ERR_ADDRESS_INVALID;
562 }
563
564 *tcp_socket = std::make_unique<TCPSocketPosix>(nullptr, net_log_.net_log(),
565 net_log_.source());
566 (*tcp_socket)->socket_ = std::move(accept_socket_);
567 return OK;
568 }
569
ConnectCompleted(CompletionOnceCallback callback,int rv)570 void TCPSocketPosix::ConnectCompleted(CompletionOnceCallback callback, int rv) {
571 DCHECK_NE(ERR_IO_PENDING, rv);
572 std::move(callback).Run(HandleConnectCompleted(rv));
573 }
574
HandleConnectCompleted(int rv)575 int TCPSocketPosix::HandleConnectCompleted(int rv) {
576 // Log the end of this attempt (and any OS error it threw).
577 if (rv != OK) {
578 net_log_.EndEventWithIntParams(NetLogEventType::TCP_CONNECT_ATTEMPT,
579 "os_error", errno);
580 tag_ = SocketTag();
581 } else {
582 net_log_.EndEvent(NetLogEventType::TCP_CONNECT_ATTEMPT);
583 NotifySocketPerformanceWatcher();
584 }
585
586 // Give a more specific error when the user is offline.
587 if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline())
588 rv = ERR_INTERNET_DISCONNECTED;
589
590 if (!logging_multiple_connect_attempts_)
591 LogConnectEnd(rv);
592
593 return rv;
594 }
595
LogConnectBegin(const AddressList & addresses) const596 void TCPSocketPosix::LogConnectBegin(const AddressList& addresses) const {
597 net_log_.BeginEvent(NetLogEventType::TCP_CONNECT,
598 [&] { return addresses.NetLogParams(); });
599 }
600
LogConnectEnd(int net_error) const601 void TCPSocketPosix::LogConnectEnd(int net_error) const {
602 if (net_error != OK) {
603 net_log_.EndEventWithNetErrorCode(NetLogEventType::TCP_CONNECT, net_error);
604 return;
605 }
606
607 net_log_.EndEvent(NetLogEventType::TCP_CONNECT, [&] {
608 net::IPEndPoint local_address;
609 int net_error = GetLocalAddress(&local_address);
610 net::IPEndPoint remote_address;
611 if (net_error == net::OK)
612 net_error = GetPeerAddress(&remote_address);
613 if (net_error != net::OK)
614 return NetLogParamsWithInt("get_address_net_error", net_error);
615 return CreateNetLogAddressPairParams(local_address, remote_address);
616 });
617 }
618
ReadCompleted(const scoped_refptr<IOBuffer> & buf,CompletionOnceCallback callback,int rv)619 void TCPSocketPosix::ReadCompleted(const scoped_refptr<IOBuffer>& buf,
620 CompletionOnceCallback callback,
621 int rv) {
622 DCHECK_NE(ERR_IO_PENDING, rv);
623
624 std::move(callback).Run(HandleReadCompleted(buf.get(), rv));
625 }
626
ReadIfReadyCompleted(CompletionOnceCallback callback,int rv)627 void TCPSocketPosix::ReadIfReadyCompleted(CompletionOnceCallback callback,
628 int rv) {
629 DCHECK_NE(ERR_IO_PENDING, rv);
630 DCHECK_GE(OK, rv);
631
632 HandleReadCompletedHelper(rv);
633 std::move(callback).Run(rv);
634 }
635
HandleReadCompleted(IOBuffer * buf,int rv)636 int TCPSocketPosix::HandleReadCompleted(IOBuffer* buf, int rv) {
637 HandleReadCompletedHelper(rv);
638
639 if (rv < 0)
640 return rv;
641
642 // Notify the watcher only if at least 1 byte was read.
643 if (rv > 0)
644 NotifySocketPerformanceWatcher();
645
646 net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, rv,
647 buf->data());
648 activity_monitor::IncrementBytesReceived(rv);
649
650 return rv;
651 }
652
HandleReadCompletedHelper(int rv)653 void TCPSocketPosix::HandleReadCompletedHelper(int rv) {
654 if (rv < 0) {
655 NetLogSocketError(net_log_, NetLogEventType::SOCKET_READ_ERROR, rv, errno);
656 }
657 }
658
WriteCompleted(const scoped_refptr<IOBuffer> & buf,CompletionOnceCallback callback,int rv)659 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf,
660 CompletionOnceCallback callback,
661 int rv) {
662 DCHECK_NE(ERR_IO_PENDING, rv);
663 std::move(callback).Run(HandleWriteCompleted(buf.get(), rv));
664 }
665
HandleWriteCompleted(IOBuffer * buf,int rv)666 int TCPSocketPosix::HandleWriteCompleted(IOBuffer* buf, int rv) {
667 if (rv < 0) {
668 NetLogSocketError(net_log_, NetLogEventType::SOCKET_WRITE_ERROR, rv, errno);
669 return rv;
670 }
671
672 // Notify the watcher only if at least 1 byte was written.
673 if (rv > 0)
674 NotifySocketPerformanceWatcher();
675
676 net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_SENT, rv,
677 buf->data());
678 return rv;
679 }
680
NotifySocketPerformanceWatcher()681 void TCPSocketPosix::NotifySocketPerformanceWatcher() {
682 #if defined(HAVE_TCP_INFO)
683 // Check if |socket_performance_watcher_| is interested in receiving a RTT
684 // update notification.
685 if (!socket_performance_watcher_ ||
686 !socket_performance_watcher_->ShouldNotifyUpdatedRTT()) {
687 return;
688 }
689
690 base::TimeDelta rtt = GetTransportRtt(socket_->socket_fd());
691 if (rtt.is_zero())
692 return;
693
694 socket_performance_watcher_->OnUpdatedRTTAvailable(rtt);
695 #endif // defined(TCP_INFO)
696 }
697
GetEstimatedRoundTripTime(base::TimeDelta * out_rtt) const698 bool TCPSocketPosix::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const {
699 DCHECK(out_rtt);
700 if (!socket_)
701 return false;
702
703 #if defined(HAVE_TCP_INFO)
704 base::TimeDelta rtt = GetTransportRtt(socket_->socket_fd());
705 if (rtt.is_zero())
706 return false;
707 *out_rtt = rtt;
708 return true;
709 #else
710 return false;
711 #endif // defined(TCP_INFO)
712 }
713
714 } // namespace net
715