blob: cabd3b8ed19cfbdd810e0bbdd481b8e1f2e16620 [file] [log] [blame]
[email protected]2ef2b0e2014-07-09 21:12:341// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
tfarina4eb7aad82015-09-14 17:10:345#include "net/socket/socket_posix.h"
[email protected]2ef2b0e2014-07-09 21:12:346
7#include <errno.h>
8#include <netinet/in.h>
9#include <sys/socket.h>
dchengc7eeda422015-12-26 03:56:4810#include <utility>
[email protected]2ef2b0e2014-07-09 21:12:3411
12#include "base/callback_helpers.h"
tfarina060df7e2015-12-16 05:15:3213#include "base/files/file_util.h"
[email protected]2ef2b0e2014-07-09 21:12:3414#include "base/logging.h"
Gabriel Charette1e5bed442018-04-24 23:25:4915#include "base/message_loop/message_loop_current.h"
[email protected]2ef2b0e2014-07-09 21:12:3416#include "base/posix/eintr_wrapper.h"
ssid6d6b40102016-04-05 18:59:5617#include "base/trace_event/trace_event.h"
davidben28150272016-06-06 21:03:1218#include "build/build_config.h"
[email protected]2ef2b0e2014-07-09 21:12:3419#include "net/base/io_buffer.h"
20#include "net/base/ip_endpoint.h"
21#include "net/base/net_errors.h"
tfarina3d87d7cd2016-01-13 02:26:5922#include "net/base/sockaddr_storage.h"
xunjieli0b7f5b62016-12-06 20:43:4823#include "net/base/trace_constants.h"
[email protected]a2b2cfc2017-12-06 09:06:0824#include "net/traffic_annotation/network_traffic_annotation.h"
[email protected]2ef2b0e2014-07-09 21:12:3425
Sergey Ulanovbc1d87a2017-08-16 02:18:3926#if defined(OS_FUCHSIA)
27#include <poll.h>
28#include <sys/ioctl.h>
29#endif // OS_FUCHSIA
30
[email protected]2ef2b0e2014-07-09 21:12:3431namespace net {
32
33namespace {
34
35int MapAcceptError(int os_error) {
36 switch (os_error) {
37 // If the client aborts the connection before the server calls accept,
38 // POSIX specifies accept should fail with ECONNABORTED. The server can
39 // ignore the error and just call accept again, so we map the error to
40 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
41 // 5.11, "Connection Abort before accept Returns".
42 case ECONNABORTED:
43 return ERR_IO_PENDING;
44 default:
45 return MapSystemError(os_error);
46 }
47}
48
49int MapConnectError(int os_error) {
50 switch (os_error) {
51 case EINPROGRESS:
52 return ERR_IO_PENDING;
53 case EACCES:
54 return ERR_NETWORK_ACCESS_DENIED;
55 case ETIMEDOUT:
56 return ERR_CONNECTION_TIMED_OUT;
57 default: {
58 int net_error = MapSystemError(os_error);
59 if (net_error == ERR_FAILED)
60 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
61 return net_error;
62 }
63 }
64}
65
66} // namespace
67
tfarina4eb7aad82015-09-14 17:10:3468SocketPosix::SocketPosix()
[email protected]2ef2b0e2014-07-09 21:12:3469 : socket_fd_(kInvalidSocket),
ssid5dd4fb32017-02-16 23:57:1770 accept_socket_watcher_(FROM_HERE),
71 read_socket_watcher_(FROM_HERE),
[email protected]2ef2b0e2014-07-09 21:12:3472 read_buf_len_(0),
ssid5dd4fb32017-02-16 23:57:1773 write_socket_watcher_(FROM_HERE),
[email protected]2ef2b0e2014-07-09 21:12:3474 write_buf_len_(0),
tfarina4eb7aad82015-09-14 17:10:3475 waiting_connect_(false) {}
[email protected]2ef2b0e2014-07-09 21:12:3476
tfarina4eb7aad82015-09-14 17:10:3477SocketPosix::~SocketPosix() {
[email protected]2ef2b0e2014-07-09 21:12:3478 Close();
79}
80
tfarina4eb7aad82015-09-14 17:10:3481int SocketPosix::Open(int address_family) {
[email protected]2ef2b0e2014-07-09 21:12:3482 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() returned an error, errno=" << errno;
94 return MapSystemError(errno);
95 }
96
tfarina060df7e2015-12-16 05:15:3297 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:3498 int rv = MapSystemError(errno);
99 Close();
100 return rv;
101 }
102
103 return OK;
104}
105
tfarina4eb7aad82015-09-14 17:10:34106int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
107 const SockaddrStorage& address) {
rvera26f0a1392017-05-02 22:25:44108 int rv = AdoptUnconnectedSocket(socket);
109 if (rv != OK)
110 return rv;
111
112 SetPeerAddress(address);
113 return OK;
114}
115
116int SocketPosix::AdoptUnconnectedSocket(SocketDescriptor socket) {
[email protected]2ef2b0e2014-07-09 21:12:34117 DCHECK(thread_checker_.CalledOnValidThread());
118 DCHECK_EQ(kInvalidSocket, socket_fd_);
119
120 socket_fd_ = socket;
121
tfarina060df7e2015-12-16 05:15:32122 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:34123 int rv = MapSystemError(errno);
124 Close();
125 return rv;
126 }
127
[email protected]2ef2b0e2014-07-09 21:12:34128 return OK;
129}
130
tfarina4eb7aad82015-09-14 17:10:34131SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
cmasoneca100d52014-09-03 18:11:11132 StopWatchingAndCleanUp();
133 SocketDescriptor socket_fd = socket_fd_;
134 socket_fd_ = kInvalidSocket;
135 return socket_fd;
136}
137
tfarina4eb7aad82015-09-14 17:10:34138int SocketPosix::Bind(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34139 DCHECK(thread_checker_.CalledOnValidThread());
140 DCHECK_NE(kInvalidSocket, socket_fd_);
141
142 int rv = bind(socket_fd_, address.addr, address.addr_len);
143 if (rv < 0) {
144 PLOG(ERROR) << "bind() returned an error, errno=" << errno;
145 return MapSystemError(errno);
146 }
147
148 return OK;
149}
150
tfarina4eb7aad82015-09-14 17:10:34151int SocketPosix::Listen(int backlog) {
[email protected]2ef2b0e2014-07-09 21:12:34152 DCHECK(thread_checker_.CalledOnValidThread());
153 DCHECK_NE(kInvalidSocket, socket_fd_);
154 DCHECK_LT(0, backlog);
155
156 int rv = listen(socket_fd_, backlog);
157 if (rv < 0) {
158 PLOG(ERROR) << "listen() returned an error, errno=" << errno;
159 return MapSystemError(errno);
160 }
161
162 return OK;
163}
164
danakj655b66c2016-04-16 00:51:38165int SocketPosix::Accept(std::unique_ptr<SocketPosix>* socket,
Brad Lassey3a814172018-04-26 03:30:21166 CompletionOnceCallback callback) {
[email protected]2ef2b0e2014-07-09 21:12:34167 DCHECK(thread_checker_.CalledOnValidThread());
168 DCHECK_NE(kInvalidSocket, socket_fd_);
169 DCHECK(accept_callback_.is_null());
170 DCHECK(socket);
171 DCHECK(!callback.is_null());
172
173 int rv = DoAccept(socket);
174 if (rv != ERR_IO_PENDING)
175 return rv;
176
Gabriel Charette1e5bed442018-04-24 23:25:49177 if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
Gabriel Charette19d2ae62018-04-10 14:10:58178 socket_fd_, true, base::MessagePumpForIO::WATCH_READ,
[email protected]2ef2b0e2014-07-09 21:12:34179 &accept_socket_watcher_, this)) {
180 PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
181 return MapSystemError(errno);
182 }
183
184 accept_socket_ = socket;
Brad Lassey3a814172018-04-26 03:30:21185 accept_callback_ = std::move(callback);
[email protected]2ef2b0e2014-07-09 21:12:34186 return ERR_IO_PENDING;
187}
188
tfarina4eb7aad82015-09-14 17:10:34189int SocketPosix::Connect(const SockaddrStorage& address,
Brad Lassey3a814172018-04-26 03:30:21190 CompletionOnceCallback callback) {
[email protected]2ef2b0e2014-07-09 21:12:34191 DCHECK(thread_checker_.CalledOnValidThread());
192 DCHECK_NE(kInvalidSocket, socket_fd_);
193 DCHECK(!waiting_connect_);
194 DCHECK(!callback.is_null());
195
196 SetPeerAddress(address);
197
198 int rv = DoConnect();
199 if (rv != ERR_IO_PENDING)
200 return rv;
201
Gabriel Charette1e5bed442018-04-24 23:25:49202 if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
Gabriel Charette19d2ae62018-04-10 14:10:58203 socket_fd_, true, base::MessagePumpForIO::WATCH_WRITE,
[email protected]2ef2b0e2014-07-09 21:12:34204 &write_socket_watcher_, this)) {
205 PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
206 return MapSystemError(errno);
207 }
208
sdefresne8df022f2016-09-20 13:54:26209 // There is a race-condition in the above code if the kernel receive a RST
210 // packet for the "connect" call before the registration of the socket file
211 // descriptor to the message loop pump. On most platform it is benign as the
212 // message loop pump is awakened for that socket in an error state, but on
213 // iOS this does not happens. Check the status of the socket at this point
214 // and if in error, consider the connection as failed.
215 int os_error = 0;
216 socklen_t len = sizeof(os_error);
217 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
218 // TCPSocketPosix expects errno to be set.
219 errno = os_error;
220 }
221
222 rv = MapConnectError(errno);
223 if (rv != OK && rv != ERR_IO_PENDING) {
224 write_socket_watcher_.StopWatchingFileDescriptor();
225 return rv;
226 }
227
Brad Lassey3a814172018-04-26 03:30:21228 write_callback_ = std::move(callback);
[email protected]2ef2b0e2014-07-09 21:12:34229 waiting_connect_ = true;
230 return ERR_IO_PENDING;
231}
232
tfarina4eb7aad82015-09-14 17:10:34233bool SocketPosix::IsConnected() const {
[email protected]2ef2b0e2014-07-09 21:12:34234 DCHECK(thread_checker_.CalledOnValidThread());
235
236 if (socket_fd_ == kInvalidSocket || waiting_connect_)
237 return false;
238
Sergey Ulanovbc1d87a2017-08-16 02:18:39239#if !defined(OS_FUCHSIA)
[email protected]2ef2b0e2014-07-09 21:12:34240 // Checks if connection is alive.
241 char c;
242 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
243 if (rv == 0)
244 return false;
245 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
246 return false;
247
248 return true;
Sergey Ulanovbc1d87a2017-08-16 02:18:39249
250#else // OS_FUCHSIA
251 // Fuchsia currently doesn't support MSG_PEEK flag in recv(), so the code
252 // above doesn't work on Fuchsia. IsConnected() must return true if the
253 // connection is alive or if it was terminated but there is still data pending
254 // in the incoming buffer.
255 // 1. Check if the connection is alive using poll(POLLRDHUP).
256 // 2. If closed, then use ioctl(FIONREAD) to check if there is data to be
257 // read.
258 // TODO(bug 738275): Remove once MSG_PEEK is implemented on Fuchsia.
259 struct pollfd pollfd;
260 pollfd.fd = socket_fd_;
261 pollfd.events = POLLRDHUP;
262 pollfd.revents = 0;
263 const int poll_result = HANDLE_EINTR(poll(&pollfd, 1, 0));
264
265 if (poll_result == 1) {
266 int bytes_available;
267 int ioctl_result =
268 HANDLE_EINTR(ioctl(socket_fd_, FIONREAD, &bytes_available));
269 return ioctl_result == 0 && bytes_available > 0;
270 }
271
272 return poll_result == 0;
273#endif // OS_FUCHSIA
[email protected]2ef2b0e2014-07-09 21:12:34274}
275
tfarina4eb7aad82015-09-14 17:10:34276bool SocketPosix::IsConnectedAndIdle() const {
[email protected]2ef2b0e2014-07-09 21:12:34277 DCHECK(thread_checker_.CalledOnValidThread());
278
279 if (socket_fd_ == kInvalidSocket || waiting_connect_)
280 return false;
281
Sergey Ulanovbc1d87a2017-08-16 02:18:39282#if !defined(OS_FUCHSIA)
[email protected]2ef2b0e2014-07-09 21:12:34283 // Check if connection is alive and we haven't received any data
284 // unexpectedly.
285 char c;
286 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
287 if (rv >= 0)
288 return false;
289 if (errno != EAGAIN && errno != EWOULDBLOCK)
290 return false;
291
292 return true;
Sergey Ulanovbc1d87a2017-08-16 02:18:39293
294#else // OS_FUCHSIA
295 // Fuchsia currently doesn't support MSG_PEEK flag in recv(), so the code
296 // above doesn't work on Fuchsia. Use poll(POLLIN) to check state of the
297 // socket. POLLIN is signaled if the socket is readable or if it was closed by
298 // the peer, i.e. the socket is connected and idle if and only if POLLIN is
299 // not signaled.
300 // TODO(bug 738275): Remove once MSG_PEEK is implemented.
301 struct pollfd pollfd;
302 pollfd.fd = socket_fd_;
303 pollfd.events = POLLIN;
304 pollfd.revents = 0;
305 const int poll_result = HANDLE_EINTR(poll(&pollfd, 1, 0));
306 return poll_result == 0;
307#endif // OS_FUCHSIA
[email protected]2ef2b0e2014-07-09 21:12:34308}
309
tfarina4eb7aad82015-09-14 17:10:34310int SocketPosix::Read(IOBuffer* buf,
311 int buf_len,
Brad Lassey3a814172018-04-26 03:30:21312 CompletionOnceCallback callback) {
xunjieli321a96f32017-03-07 19:42:17313 // Use base::Unretained() is safe here because OnFileCanReadWithoutBlocking()
314 // won't be called if |this| is gone.
315 int rv =
316 ReadIfReady(buf, buf_len,
317 base::Bind(&SocketPosix::RetryRead, base::Unretained(this)));
318 if (rv == ERR_IO_PENDING) {
319 read_buf_ = buf;
320 read_buf_len_ = buf_len;
Brad Lassey3a814172018-04-26 03:30:21321 read_callback_ = std::move(callback);
xunjieli321a96f32017-03-07 19:42:17322 }
323 return rv;
324}
325
326int SocketPosix::ReadIfReady(IOBuffer* buf,
327 int buf_len,
Brad Lassey3a814172018-04-26 03:30:21328 CompletionOnceCallback callback) {
[email protected]2ef2b0e2014-07-09 21:12:34329 DCHECK(thread_checker_.CalledOnValidThread());
330 DCHECK_NE(kInvalidSocket, socket_fd_);
331 DCHECK(!waiting_connect_);
xunjieli321a96f32017-03-07 19:42:17332 CHECK(read_if_ready_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34333 DCHECK(!callback.is_null());
334 DCHECK_LT(0, buf_len);
335
336 int rv = DoRead(buf, buf_len);
337 if (rv != ERR_IO_PENDING)
338 return rv;
339
Gabriel Charette1e5bed442018-04-24 23:25:49340 if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
Gabriel Charette19d2ae62018-04-10 14:10:58341 socket_fd_, true, base::MessagePumpForIO::WATCH_READ,
[email protected]2ef2b0e2014-07-09 21:12:34342 &read_socket_watcher_, this)) {
343 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
344 return MapSystemError(errno);
345 }
346
Brad Lassey3a814172018-04-26 03:30:21347 read_if_ready_callback_ = std::move(callback);
[email protected]2ef2b0e2014-07-09 21:12:34348 return ERR_IO_PENDING;
349}
350
Helen Lia6d3b2c2018-05-08 16:09:07351int SocketPosix::CancelReadIfReady() {
352 DCHECK(read_if_ready_callback_);
353
354 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
355 DCHECK(ok);
356
357 read_if_ready_callback_.Reset();
358 return net::OK;
359}
360
[email protected]578968d42017-12-13 15:39:32361int SocketPosix::Write(
362 IOBuffer* buf,
363 int buf_len,
Brad Lassey3a814172018-04-26 03:30:21364 CompletionOnceCallback callback,
[email protected]578968d42017-12-13 15:39:32365 const NetworkTrafficAnnotationTag& /* traffic_annotation */) {
[email protected]2ef2b0e2014-07-09 21:12:34366 DCHECK(thread_checker_.CalledOnValidThread());
367 DCHECK_NE(kInvalidSocket, socket_fd_);
368 DCHECK(!waiting_connect_);
vitalybuka63b47542014-09-29 17:14:19369 CHECK(write_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34370 // Synchronous operation not supported
371 DCHECK(!callback.is_null());
372 DCHECK_LT(0, buf_len);
373
374 int rv = DoWrite(buf, buf_len);
375 if (rv == ERR_IO_PENDING)
Brad Lassey3a814172018-04-26 03:30:21376 rv = WaitForWrite(buf, buf_len, std::move(callback));
[email protected]2ef2b0e2014-07-09 21:12:34377 return rv;
378}
379
tfarina4eb7aad82015-09-14 17:10:34380int SocketPosix::WaitForWrite(IOBuffer* buf,
381 int buf_len,
Brad Lassey3a814172018-04-26 03:30:21382 CompletionOnceCallback callback) {
[email protected]2ef2b0e2014-07-09 21:12:34383 DCHECK(thread_checker_.CalledOnValidThread());
384 DCHECK_NE(kInvalidSocket, socket_fd_);
385 DCHECK(write_callback_.is_null());
386 // Synchronous operation not supported
387 DCHECK(!callback.is_null());
388 DCHECK_LT(0, buf_len);
389
Gabriel Charette1e5bed442018-04-24 23:25:49390 if (!base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
Gabriel Charette19d2ae62018-04-10 14:10:58391 socket_fd_, true, base::MessagePumpForIO::WATCH_WRITE,
[email protected]2ef2b0e2014-07-09 21:12:34392 &write_socket_watcher_, this)) {
393 PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
394 return MapSystemError(errno);
395 }
396
397 write_buf_ = buf;
398 write_buf_len_ = buf_len;
Brad Lassey3a814172018-04-26 03:30:21399 write_callback_ = std::move(callback);
[email protected]2ef2b0e2014-07-09 21:12:34400 return ERR_IO_PENDING;
401}
402
tfarina4eb7aad82015-09-14 17:10:34403int SocketPosix::GetLocalAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34404 DCHECK(thread_checker_.CalledOnValidThread());
405 DCHECK(address);
406
407 if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
408 return MapSystemError(errno);
409 return OK;
410}
411
tfarina4eb7aad82015-09-14 17:10:34412int SocketPosix::GetPeerAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34413 DCHECK(thread_checker_.CalledOnValidThread());
414 DCHECK(address);
415
416 if (!HasPeerAddress())
417 return ERR_SOCKET_NOT_CONNECTED;
418
419 *address = *peer_address_;
420 return OK;
421}
422
tfarina4eb7aad82015-09-14 17:10:34423void SocketPosix::SetPeerAddress(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34424 DCHECK(thread_checker_.CalledOnValidThread());
425 // |peer_address_| will be non-NULL if Connect() has been called. Unless
426 // Close() is called to reset the internal state, a second call to Connect()
427 // is not allowed.
428 // Please note that we don't allow a second Connect() even if the previous
429 // Connect() has failed. Connecting the same |socket_| again after a
430 // connection attempt failed results in unspecified behavior according to
431 // POSIX.
432 DCHECK(!peer_address_);
433 peer_address_.reset(new SockaddrStorage(address));
434}
435
tfarina4eb7aad82015-09-14 17:10:34436bool SocketPosix::HasPeerAddress() const {
[email protected]2ef2b0e2014-07-09 21:12:34437 DCHECK(thread_checker_.CalledOnValidThread());
438 return peer_address_ != NULL;
439}
440
tfarina4eb7aad82015-09-14 17:10:34441void SocketPosix::Close() {
[email protected]2ef2b0e2014-07-09 21:12:34442 DCHECK(thread_checker_.CalledOnValidThread());
443
cmasoneca100d52014-09-03 18:11:11444 StopWatchingAndCleanUp();
[email protected]2ef2b0e2014-07-09 21:12:34445
446 if (socket_fd_ != kInvalidSocket) {
447 if (IGNORE_EINTR(close(socket_fd_)) < 0)
448 PLOG(ERROR) << "close() returned an error, errno=" << errno;
449 socket_fd_ = kInvalidSocket;
450 }
[email protected]2ef2b0e2014-07-09 21:12:34451}
452
svaldez58804c42015-10-06 00:13:47453void SocketPosix::DetachFromThread() {
454 thread_checker_.DetachFromThread();
455}
456
tfarina4eb7aad82015-09-14 17:10:34457void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
xunjieli0b7f5b62016-12-06 20:43:48458 TRACE_EVENT0(kNetTracingCategory,
459 "SocketPosix::OnFileCanReadWithoutBlocking");
[email protected]2ef2b0e2014-07-09 21:12:34460 if (!accept_callback_.is_null()) {
461 AcceptCompleted();
xunjieli321a96f32017-03-07 19:42:17462 } else {
463 DCHECK(!read_if_ready_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34464 ReadCompleted();
465 }
466}
467
tfarina4eb7aad82015-09-14 17:10:34468void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
[email protected]2ef2b0e2014-07-09 21:12:34469 DCHECK(!write_callback_.is_null());
470 if (waiting_connect_) {
471 ConnectCompleted();
472 } else {
473 WriteCompleted();
474 }
475}
476
danakj655b66c2016-04-16 00:51:38477int SocketPosix::DoAccept(std::unique_ptr<SocketPosix>* socket) {
[email protected]2ef2b0e2014-07-09 21:12:34478 SockaddrStorage new_peer_address;
479 int new_socket = HANDLE_EINTR(accept(socket_fd_,
480 new_peer_address.addr,
481 &new_peer_address.addr_len));
482 if (new_socket < 0)
483 return MapAcceptError(errno);
484
danakj655b66c2016-04-16 00:51:38485 std::unique_ptr<SocketPosix> accepted_socket(new SocketPosix);
[email protected]2ef2b0e2014-07-09 21:12:34486 int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
487 if (rv != OK)
488 return rv;
489
dchengc7eeda422015-12-26 03:56:48490 *socket = std::move(accepted_socket);
[email protected]2ef2b0e2014-07-09 21:12:34491 return OK;
492}
493
tfarina4eb7aad82015-09-14 17:10:34494void SocketPosix::AcceptCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34495 DCHECK(accept_socket_);
496 int rv = DoAccept(accept_socket_);
497 if (rv == ERR_IO_PENDING)
498 return;
499
500 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
501 DCHECK(ok);
502 accept_socket_ = NULL;
Brad Lassey3a814172018-04-26 03:30:21503 std::move(accept_callback_).Run(rv);
[email protected]2ef2b0e2014-07-09 21:12:34504}
505
tfarina4eb7aad82015-09-14 17:10:34506int SocketPosix::DoConnect() {
[email protected]2ef2b0e2014-07-09 21:12:34507 int rv = HANDLE_EINTR(connect(socket_fd_,
508 peer_address_->addr,
509 peer_address_->addr_len));
510 DCHECK_GE(0, rv);
511 return rv == 0 ? OK : MapConnectError(errno);
512}
513
tfarina4eb7aad82015-09-14 17:10:34514void SocketPosix::ConnectCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34515 // Get the error that connect() completed with.
516 int os_error = 0;
517 socklen_t len = sizeof(os_error);
518 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
tfarina4eb7aad82015-09-14 17:10:34519 // TCPSocketPosix expects errno to be set.
[email protected]2ef2b0e2014-07-09 21:12:34520 errno = os_error;
521 }
522
523 int rv = MapConnectError(errno);
524 if (rv == ERR_IO_PENDING)
525 return;
526
527 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
528 DCHECK(ok);
529 waiting_connect_ = false;
Brad Lassey3a814172018-04-26 03:30:21530 std::move(write_callback_).Run(rv);
[email protected]2ef2b0e2014-07-09 21:12:34531}
532
tfarina4eb7aad82015-09-14 17:10:34533int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
[email protected]2ef2b0e2014-07-09 21:12:34534 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
535 return rv >= 0 ? rv : MapSystemError(errno);
536}
537
xunjieli321a96f32017-03-07 19:42:17538void SocketPosix::RetryRead(int rv) {
539 DCHECK(read_callback_);
540 DCHECK(read_buf_);
541 DCHECK_LT(0, read_buf_len_);
542
543 if (rv == OK) {
544 rv = ReadIfReady(
545 read_buf_.get(), read_buf_len_,
546 base::Bind(&SocketPosix::RetryRead, base::Unretained(this)));
547 if (rv == ERR_IO_PENDING)
548 return;
549 }
550 read_buf_ = nullptr;
551 read_buf_len_ = 0;
Brad Lassey3a814172018-04-26 03:30:21552 std::move(read_callback_).Run(rv);
xunjieli321a96f32017-03-07 19:42:17553}
554
tfarina4eb7aad82015-09-14 17:10:34555void SocketPosix::ReadCompleted() {
xunjieli321a96f32017-03-07 19:42:17556 DCHECK(read_if_ready_callback_);
[email protected]2ef2b0e2014-07-09 21:12:34557
558 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
559 DCHECK(ok);
Brad Lassey3a814172018-04-26 03:30:21560 std::move(read_if_ready_callback_).Run(OK);
[email protected]2ef2b0e2014-07-09 21:12:34561}
562
tfarina4eb7aad82015-09-14 17:10:34563int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
davidben28150272016-06-06 21:03:12564#if defined(OS_LINUX) || defined(OS_ANDROID)
565 // Disable SIGPIPE for this write. Although Chromium globally disables
566 // SIGPIPE, the net stack may be used in other consumers which do not do
567 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on
568 // socket creation.
569 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL));
570#else
[email protected]2ef2b0e2014-07-09 21:12:34571 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
davidben28150272016-06-06 21:03:12572#endif
[email protected]2ef2b0e2014-07-09 21:12:34573 return rv >= 0 ? rv : MapSystemError(errno);
574}
575
tfarina4eb7aad82015-09-14 17:10:34576void SocketPosix::WriteCompleted() {
dcheng08ea2af02014-08-25 23:38:09577 int rv = DoWrite(write_buf_.get(), write_buf_len_);
[email protected]2ef2b0e2014-07-09 21:12:34578 if (rv == ERR_IO_PENDING)
579 return;
580
581 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
582 DCHECK(ok);
583 write_buf_ = NULL;
584 write_buf_len_ = 0;
Brad Lassey3a814172018-04-26 03:30:21585 std::move(write_callback_).Run(rv);
[email protected]2ef2b0e2014-07-09 21:12:34586}
587
tfarina4eb7aad82015-09-14 17:10:34588void SocketPosix::StopWatchingAndCleanUp() {
cmasoneca100d52014-09-03 18:11:11589 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
590 DCHECK(ok);
591 ok = read_socket_watcher_.StopWatchingFileDescriptor();
592 DCHECK(ok);
593 ok = write_socket_watcher_.StopWatchingFileDescriptor();
594 DCHECK(ok);
595
596 if (!accept_callback_.is_null()) {
597 accept_socket_ = NULL;
598 accept_callback_.Reset();
599 }
600
601 if (!read_callback_.is_null()) {
602 read_buf_ = NULL;
603 read_buf_len_ = 0;
604 read_callback_.Reset();
605 }
606
xunjieli321a96f32017-03-07 19:42:17607 read_if_ready_callback_.Reset();
608
cmasoneca100d52014-09-03 18:11:11609 if (!write_callback_.is_null()) {
610 write_buf_ = NULL;
611 write_buf_len_ = 0;
612 write_callback_.Reset();
613 }
614
615 waiting_connect_ = false;
616 peer_address_.reset();
617}
618
[email protected]2ef2b0e2014-07-09 21:12:34619} // namespace net