1 // Copyright 2014 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/socket_posix.h"
6
7 #include <errno.h>
8 #include <netinet/in.h>
9 #include <sys/socket.h>
10
11 #include <memory>
12 #include <utility>
13
14 #include "base/files/file_util.h"
15 #include "base/functional/bind.h"
16 #include "base/functional/callback_helpers.h"
17 #include "base/logging.h"
18 #include "base/posix/eintr_wrapper.h"
19 #include "base/task/current_thread.h"
20 #include "build/build_config.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/ip_endpoint.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/sockaddr_storage.h"
25 #include "net/base/trace_constants.h"
26 #include "net/base/tracing.h"
27 #include "net/traffic_annotation/network_traffic_annotation.h"
28
29 #if BUILDFLAG(IS_FUCHSIA)
30 #include <poll.h>
31 #include <sys/ioctl.h>
32 #endif // BUILDFLAG(IS_FUCHSIA)
33
34 namespace net {
35
36 namespace {
37
MapAcceptError(int os_error)38 int MapAcceptError(int os_error) {
39 switch (os_error) {
40 // If the client aborts the connection before the server calls accept,
41 // POSIX specifies accept should fail with ECONNABORTED. The server can
42 // ignore the error and just call accept again, so we map the error to
43 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
44 // 5.11, "Connection Abort before accept Returns".
45 case ECONNABORTED:
46 return ERR_IO_PENDING;
47 default:
48 return MapSystemError(os_error);
49 }
50 }
51
MapConnectError(int os_error)52 int MapConnectError(int os_error) {
53 switch (os_error) {
54 case EINPROGRESS:
55 return ERR_IO_PENDING;
56 case EACCES:
57 return ERR_NETWORK_ACCESS_DENIED;
58 case ETIMEDOUT:
59 return ERR_CONNECTION_TIMED_OUT;
60 default: {
61 int net_error = MapSystemError(os_error);
62 if (net_error == ERR_FAILED)
63 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
64 return net_error;
65 }
66 }
67 }
68
69 } // namespace
70
SocketPosix()71 SocketPosix::SocketPosix()
72 : socket_fd_(kInvalidSocket),
73 accept_socket_watcher_(FROM_HERE),
74 read_socket_watcher_(FROM_HERE),
75 write_socket_watcher_(FROM_HERE) {}
76
~SocketPosix()77 SocketPosix::~SocketPosix() {
78 Close();
79 }
80
Open(int address_family)81 int SocketPosix::Open(int address_family) {
82 DCHECK(thread_checker_.CalledOnValidThread());
83 DCHECK_EQ(kInvalidSocket, socket_fd_);
84 DCHECK(address_family == AF_INET ||
85 address_family == AF_INET6 ||
86 address_family == AF_UNIX);
87
88 socket_fd_ = CreatePlatformSocket(
89 address_family,
90 SOCK_STREAM,
91 address_family == AF_UNIX ? 0 : IPPROTO_TCP);
92 if (socket_fd_ < 0) {
93 PLOG(ERROR) << "CreatePlatformSocket() failed";
94 return MapSystemError(errno);
95 }
96
97 if (!base::SetNonBlocking(socket_fd_)) {
98 int rv = MapSystemError(errno);
99 Close();
100 return rv;
101 }
102
103 return OK;
104 }
105
AdoptConnectedSocket(SocketDescriptor socket,const SockaddrStorage & address)106 int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
107 const SockaddrStorage& address) {
108 int rv = AdoptUnconnectedSocket(socket);
109 if (rv != OK)
110 return rv;
111
112 SetPeerAddress(address);
113 return OK;
114 }
115
AdoptUnconnectedSocket(SocketDescriptor socket)116 int SocketPosix::AdoptUnconnectedSocket(SocketDescriptor socket) {
117 DCHECK(thread_checker_.CalledOnValidThread());
118 DCHECK_EQ(kInvalidSocket, socket_fd_);
119
120 socket_fd_ = socket;
121
122 if (!base::SetNonBlocking(socket_fd_)) {
123 int rv = MapSystemError(errno);
124 Close();
125 return rv;
126 }
127
128 return OK;
129 }
130
ReleaseConnectedSocket()131 SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
132 // It's not safe to release a socket with a pending write.
133 DCHECK(!write_buf_);
134
135 StopWatchingAndCleanUp(false /* close_socket */);
136 SocketDescriptor socket_fd = socket_fd_;
137 socket_fd_ = kInvalidSocket;
138 return socket_fd;
139 }
140
Bind(const SockaddrStorage & address)141 int SocketPosix::Bind(const SockaddrStorage& address) {
142 DCHECK(thread_checker_.CalledOnValidThread());
143 DCHECK_NE(kInvalidSocket, socket_fd_);
144
145 int rv = bind(socket_fd_, address.addr, address.addr_len);
146 if (rv < 0) {
147 PLOG(ERROR) << "bind() failed";
148 return MapSystemError(errno);
149 }
150
151 return OK;
152 }
153
Listen(int backlog)154 int SocketPosix::Listen(int backlog) {
155 DCHECK(thread_checker_.CalledOnValidThread());
156 DCHECK_NE(kInvalidSocket, socket_fd_);
157 DCHECK_LT(0, backlog);
158
159 int rv = listen(socket_fd_, backlog);
160 if (rv < 0) {
161 PLOG(ERROR) << "listen() failed";
162 return MapSystemError(errno);
163 }
164
165 return OK;
166 }
167
Accept(std::unique_ptr<SocketPosix> * socket,CompletionOnceCallback callback)168 int SocketPosix::Accept(std::unique_ptr<SocketPosix>* socket,
169 CompletionOnceCallback callback) {
170 DCHECK(thread_checker_.CalledOnValidThread());
171 DCHECK_NE(kInvalidSocket, socket_fd_);
172 DCHECK(accept_callback_.is_null());
173 DCHECK(socket);
174 DCHECK(!callback.is_null());
175
176 int rv = DoAccept(socket);
177 if (rv != ERR_IO_PENDING)
178 return rv;
179
180 if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
181 socket_fd_, true, base::MessagePumpForIO::WATCH_READ,
182 &accept_socket_watcher_, this)) {
183 PLOG(ERROR) << "WatchFileDescriptor failed on accept";
184 return MapSystemError(errno);
185 }
186
187 accept_socket_ = socket;
188 accept_callback_ = std::move(callback);
189 return ERR_IO_PENDING;
190 }
191
Connect(const SockaddrStorage & address,CompletionOnceCallback callback)192 int SocketPosix::Connect(const SockaddrStorage& address,
193 CompletionOnceCallback callback) {
194 DCHECK(thread_checker_.CalledOnValidThread());
195 DCHECK_NE(kInvalidSocket, socket_fd_);
196 DCHECK(!waiting_connect_);
197 DCHECK(!callback.is_null());
198
199 SetPeerAddress(address);
200
201 int rv = DoConnect();
202 if (rv != ERR_IO_PENDING)
203 return rv;
204
205 if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
206 socket_fd_, true, base::MessagePumpForIO::WATCH_WRITE,
207 &write_socket_watcher_, this)) {
208 PLOG(ERROR) << "WatchFileDescriptor failed on connect";
209 return MapSystemError(errno);
210 }
211
212 // There is a race-condition in the above code if the kernel receive a RST
213 // packet for the "connect" call before the registration of the socket file
214 // descriptor to the message loop pump. On most platform it is benign as the
215 // message loop pump is awakened for that socket in an error state, but on
216 // iOS this does not happens. Check the status of the socket at this point
217 // and if in error, consider the connection as failed.
218 int os_error = 0;
219 socklen_t len = sizeof(os_error);
220 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
221 // TCPSocketPosix expects errno to be set.
222 errno = os_error;
223 }
224
225 rv = MapConnectError(errno);
226 if (rv != OK && rv != ERR_IO_PENDING) {
227 write_socket_watcher_.StopWatchingFileDescriptor();
228 return rv;
229 }
230
231 write_callback_ = std::move(callback);
232 waiting_connect_ = true;
233 return ERR_IO_PENDING;
234 }
235
IsConnected() const236 bool SocketPosix::IsConnected() const {
237 DCHECK(thread_checker_.CalledOnValidThread());
238
239 if (socket_fd_ == kInvalidSocket || waiting_connect_)
240 return false;
241
242 // Checks if connection is alive.
243 char c;
244 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
245 if (rv == 0)
246 return false;
247 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
248 return false;
249
250 return true;
251 }
252
IsConnectedAndIdle() const253 bool SocketPosix::IsConnectedAndIdle() const {
254 DCHECK(thread_checker_.CalledOnValidThread());
255
256 if (socket_fd_ == kInvalidSocket || waiting_connect_)
257 return false;
258
259 // Check if connection is alive and we haven't received any data
260 // unexpectedly.
261 char c;
262 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
263 if (rv >= 0)
264 return false;
265 if (errno != EAGAIN && errno != EWOULDBLOCK)
266 return false;
267
268 return true;
269 }
270
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)271 int SocketPosix::Read(IOBuffer* buf,
272 int buf_len,
273 CompletionOnceCallback callback) {
274 // Use base::Unretained() is safe here because OnFileCanReadWithoutBlocking()
275 // won't be called if |this| is gone.
276 int rv = ReadIfReady(
277 buf, buf_len,
278 base::BindOnce(&SocketPosix::RetryRead, base::Unretained(this)));
279 if (rv == ERR_IO_PENDING) {
280 read_buf_ = buf;
281 read_buf_len_ = buf_len;
282 read_callback_ = std::move(callback);
283 }
284 return rv;
285 }
286
ReadIfReady(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)287 int SocketPosix::ReadIfReady(IOBuffer* buf,
288 int buf_len,
289 CompletionOnceCallback callback) {
290 DCHECK(thread_checker_.CalledOnValidThread());
291 DCHECK_NE(kInvalidSocket, socket_fd_);
292 DCHECK(!waiting_connect_);
293 CHECK(read_if_ready_callback_.is_null());
294 DCHECK(!callback.is_null());
295 DCHECK_LT(0, buf_len);
296
297 int rv = DoRead(buf, buf_len);
298 if (rv != ERR_IO_PENDING)
299 return rv;
300
301 if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
302 socket_fd_, true, base::MessagePumpForIO::WATCH_READ,
303 &read_socket_watcher_, this)) {
304 PLOG(ERROR) << "WatchFileDescriptor failed on read";
305 return MapSystemError(errno);
306 }
307
308 read_if_ready_callback_ = std::move(callback);
309 return ERR_IO_PENDING;
310 }
311
CancelReadIfReady()312 int SocketPosix::CancelReadIfReady() {
313 DCHECK(read_if_ready_callback_);
314
315 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
316 DCHECK(ok);
317
318 read_if_ready_callback_.Reset();
319 return net::OK;
320 }
321
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag &)322 int SocketPosix::Write(
323 IOBuffer* buf,
324 int buf_len,
325 CompletionOnceCallback callback,
326 const NetworkTrafficAnnotationTag& /* traffic_annotation */) {
327 DCHECK(thread_checker_.CalledOnValidThread());
328 CHECK_NE(kInvalidSocket, socket_fd_);
329 CHECK(!waiting_connect_);
330 CHECK(write_callback_.is_null());
331 // Synchronous operation not supported
332 CHECK(!callback.is_null());
333 CHECK_LT(0, buf_len);
334
335 int rv = DoWrite(buf, buf_len);
336 if (rv == ERR_IO_PENDING)
337 rv = WaitForWrite(buf, buf_len, std::move(callback));
338 return rv;
339 }
340
WaitForWrite(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)341 int SocketPosix::WaitForWrite(IOBuffer* buf,
342 int buf_len,
343 CompletionOnceCallback callback) {
344 DCHECK(thread_checker_.CalledOnValidThread());
345 DCHECK_NE(kInvalidSocket, socket_fd_);
346 DCHECK(write_callback_.is_null());
347 // Synchronous operation not supported
348 DCHECK(!callback.is_null());
349 DCHECK_LT(0, buf_len);
350
351 if (!base::CurrentIOThread::Get()->WatchFileDescriptor(
352 socket_fd_, true, base::MessagePumpForIO::WATCH_WRITE,
353 &write_socket_watcher_, this)) {
354 PLOG(ERROR) << "WatchFileDescriptor failed on write";
355 return MapSystemError(errno);
356 }
357
358 write_buf_ = buf;
359 write_buf_len_ = buf_len;
360 write_callback_ = std::move(callback);
361 return ERR_IO_PENDING;
362 }
363
GetLocalAddress(SockaddrStorage * address) const364 int SocketPosix::GetLocalAddress(SockaddrStorage* address) const {
365 DCHECK(thread_checker_.CalledOnValidThread());
366 DCHECK(address);
367
368 if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
369 return MapSystemError(errno);
370 return OK;
371 }
372
GetPeerAddress(SockaddrStorage * address) const373 int SocketPosix::GetPeerAddress(SockaddrStorage* address) const {
374 DCHECK(thread_checker_.CalledOnValidThread());
375 DCHECK(address);
376
377 if (!HasPeerAddress())
378 return ERR_SOCKET_NOT_CONNECTED;
379
380 *address = *peer_address_;
381 return OK;
382 }
383
SetPeerAddress(const SockaddrStorage & address)384 void SocketPosix::SetPeerAddress(const SockaddrStorage& address) {
385 DCHECK(thread_checker_.CalledOnValidThread());
386 // |peer_address_| will be non-nullptr if Connect() has been called. Unless
387 // Close() is called to reset the internal state, a second call to Connect()
388 // is not allowed.
389 // Please note that we don't allow a second Connect() even if the previous
390 // Connect() has failed. Connecting the same |socket_| again after a
391 // connection attempt failed results in unspecified behavior according to
392 // POSIX.
393 DCHECK(!peer_address_);
394 peer_address_ = std::make_unique<SockaddrStorage>(address);
395 }
396
HasPeerAddress() const397 bool SocketPosix::HasPeerAddress() const {
398 DCHECK(thread_checker_.CalledOnValidThread());
399 return peer_address_ != nullptr;
400 }
401
Close()402 void SocketPosix::Close() {
403 DCHECK(thread_checker_.CalledOnValidThread());
404
405 StopWatchingAndCleanUp(true /* close_socket */);
406 }
407
DetachFromThread()408 void SocketPosix::DetachFromThread() {
409 thread_checker_.DetachFromThread();
410 }
411
OnFileCanReadWithoutBlocking(int fd)412 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
413 TRACE_EVENT0(NetTracingCategory(),
414 "SocketPosix::OnFileCanReadWithoutBlocking");
415 if (!accept_callback_.is_null()) {
416 AcceptCompleted();
417 } else {
418 DCHECK(!read_if_ready_callback_.is_null());
419 ReadCompleted();
420 }
421 }
422
OnFileCanWriteWithoutBlocking(int fd)423 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
424 DCHECK(!write_callback_.is_null());
425 if (waiting_connect_) {
426 ConnectCompleted();
427 } else {
428 WriteCompleted();
429 }
430 }
431
DoAccept(std::unique_ptr<SocketPosix> * socket)432 int SocketPosix::DoAccept(std::unique_ptr<SocketPosix>* socket) {
433 SockaddrStorage new_peer_address;
434 int new_socket = HANDLE_EINTR(accept(socket_fd_,
435 new_peer_address.addr,
436 &new_peer_address.addr_len));
437 if (new_socket < 0)
438 return MapAcceptError(errno);
439
440 auto accepted_socket = std::make_unique<SocketPosix>();
441 int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
442 if (rv != OK)
443 return rv;
444
445 *socket = std::move(accepted_socket);
446 return OK;
447 }
448
AcceptCompleted()449 void SocketPosix::AcceptCompleted() {
450 DCHECK(accept_socket_);
451 int rv = DoAccept(accept_socket_);
452 if (rv == ERR_IO_PENDING)
453 return;
454
455 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
456 DCHECK(ok);
457 accept_socket_ = nullptr;
458 std::move(accept_callback_).Run(rv);
459 }
460
DoConnect()461 int SocketPosix::DoConnect() {
462 int rv = HANDLE_EINTR(connect(socket_fd_,
463 peer_address_->addr,
464 peer_address_->addr_len));
465 DCHECK_GE(0, rv);
466 return rv == 0 ? OK : MapConnectError(errno);
467 }
468
ConnectCompleted()469 void SocketPosix::ConnectCompleted() {
470 // Get the error that connect() completed with.
471 int os_error = 0;
472 socklen_t len = sizeof(os_error);
473 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
474 // TCPSocketPosix expects errno to be set.
475 errno = os_error;
476 }
477
478 int rv = MapConnectError(errno);
479 if (rv == ERR_IO_PENDING)
480 return;
481
482 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
483 DCHECK(ok);
484 waiting_connect_ = false;
485 std::move(write_callback_).Run(rv);
486 }
487
DoRead(IOBuffer * buf,int buf_len)488 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
489 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
490 return rv >= 0 ? rv : MapSystemError(errno);
491 }
492
RetryRead(int rv)493 void SocketPosix::RetryRead(int rv) {
494 DCHECK(read_callback_);
495 DCHECK(read_buf_);
496 DCHECK_LT(0, read_buf_len_);
497
498 if (rv == OK) {
499 rv = ReadIfReady(
500 read_buf_.get(), read_buf_len_,
501 base::BindOnce(&SocketPosix::RetryRead, base::Unretained(this)));
502 if (rv == ERR_IO_PENDING)
503 return;
504 }
505 read_buf_ = nullptr;
506 read_buf_len_ = 0;
507 std::move(read_callback_).Run(rv);
508 }
509
ReadCompleted()510 void SocketPosix::ReadCompleted() {
511 DCHECK(read_if_ready_callback_);
512
513 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
514 DCHECK(ok);
515 std::move(read_if_ready_callback_).Run(OK);
516 }
517
DoWrite(IOBuffer * buf,int buf_len)518 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
519 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
520 // Disable SIGPIPE for this write. Although Chromium globally disables
521 // SIGPIPE, the net stack may be used in other consumers which do not do
522 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on
523 // socket creation.
524 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL));
525 #else
526 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
527 #endif
528 if (rv >= 0) {
529 CHECK_LE(rv, buf_len);
530 }
531 return rv >= 0 ? rv : MapSystemError(errno);
532 }
533
WriteCompleted()534 void SocketPosix::WriteCompleted() {
535 int rv = DoWrite(write_buf_.get(), write_buf_len_);
536 if (rv == ERR_IO_PENDING)
537 return;
538
539 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
540 DCHECK(ok);
541 write_buf_.reset();
542 write_buf_len_ = 0;
543 std::move(write_callback_).Run(rv);
544 }
545
StopWatchingAndCleanUp(bool close_socket)546 void SocketPosix::StopWatchingAndCleanUp(bool close_socket) {
547 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
548 DCHECK(ok);
549 ok = read_socket_watcher_.StopWatchingFileDescriptor();
550 DCHECK(ok);
551 ok = write_socket_watcher_.StopWatchingFileDescriptor();
552 DCHECK(ok);
553
554 // These needs to be done after the StopWatchingFileDescriptor() calls, but
555 // before deleting the write buffer.
556 if (close_socket) {
557 if (socket_fd_ != kInvalidSocket) {
558 if (IGNORE_EINTR(close(socket_fd_)) < 0)
559 DPLOG(ERROR) << "close() failed";
560 socket_fd_ = kInvalidSocket;
561 }
562 }
563
564 if (!accept_callback_.is_null()) {
565 accept_socket_ = nullptr;
566 accept_callback_.Reset();
567 }
568
569 if (!read_callback_.is_null()) {
570 read_buf_.reset();
571 read_buf_len_ = 0;
572 read_callback_.Reset();
573 }
574
575 read_if_ready_callback_.Reset();
576
577 if (!write_callback_.is_null()) {
578 write_buf_.reset();
579 write_buf_len_ = 0;
580 write_callback_.Reset();
581 }
582
583 waiting_connect_ = false;
584 peer_address_.reset();
585 }
586
587 } // namespace net
588