blob: 81fa49a6cad578b796a57d05fb5d24fa17d2be9d [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 Charette39ddaf12018-04-10 13:42:5515#include "base/message_loop/message_loop.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,
tfarina4eb7aad82015-09-14 17:10:34166 const CompletionCallback& 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
177 if (!base::MessageLoopForIO::current()->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;
185 accept_callback_ = callback;
186 return ERR_IO_PENDING;
187}
188
tfarina4eb7aad82015-09-14 17:10:34189int SocketPosix::Connect(const SockaddrStorage& address,
190 const CompletionCallback& 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
202 if (!base::MessageLoopForIO::current()->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
[email protected]2ef2b0e2014-07-09 21:12:34228 write_callback_ = callback;
229 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,
312 const CompletionCallback& 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;
321 read_callback_ = callback;
322 }
323 return rv;
324}
325
326int SocketPosix::ReadIfReady(IOBuffer* buf,
327 int buf_len,
328 const CompletionCallback& 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
340 if (!base::MessageLoopForIO::current()->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
xunjieli321a96f32017-03-07 19:42:17347 read_if_ready_callback_ = callback;
[email protected]2ef2b0e2014-07-09 21:12:34348 return ERR_IO_PENDING;
349}
350
[email protected]578968d42017-12-13 15:39:32351int SocketPosix::Write(
352 IOBuffer* buf,
353 int buf_len,
354 const CompletionCallback& callback,
355 const NetworkTrafficAnnotationTag& /* traffic_annotation */) {
[email protected]2ef2b0e2014-07-09 21:12:34356 DCHECK(thread_checker_.CalledOnValidThread());
357 DCHECK_NE(kInvalidSocket, socket_fd_);
358 DCHECK(!waiting_connect_);
vitalybuka63b47542014-09-29 17:14:19359 CHECK(write_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34360 // Synchronous operation not supported
361 DCHECK(!callback.is_null());
362 DCHECK_LT(0, buf_len);
363
364 int rv = DoWrite(buf, buf_len);
365 if (rv == ERR_IO_PENDING)
366 rv = WaitForWrite(buf, buf_len, callback);
367 return rv;
368}
369
tfarina4eb7aad82015-09-14 17:10:34370int SocketPosix::WaitForWrite(IOBuffer* buf,
371 int buf_len,
372 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34373 DCHECK(thread_checker_.CalledOnValidThread());
374 DCHECK_NE(kInvalidSocket, socket_fd_);
375 DCHECK(write_callback_.is_null());
376 // Synchronous operation not supported
377 DCHECK(!callback.is_null());
378 DCHECK_LT(0, buf_len);
379
380 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
Gabriel Charette19d2ae62018-04-10 14:10:58381 socket_fd_, true, base::MessagePumpForIO::WATCH_WRITE,
[email protected]2ef2b0e2014-07-09 21:12:34382 &write_socket_watcher_, this)) {
383 PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
384 return MapSystemError(errno);
385 }
386
387 write_buf_ = buf;
388 write_buf_len_ = buf_len;
389 write_callback_ = callback;
390 return ERR_IO_PENDING;
391}
392
tfarina4eb7aad82015-09-14 17:10:34393int SocketPosix::GetLocalAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34394 DCHECK(thread_checker_.CalledOnValidThread());
395 DCHECK(address);
396
397 if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
398 return MapSystemError(errno);
399 return OK;
400}
401
tfarina4eb7aad82015-09-14 17:10:34402int SocketPosix::GetPeerAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34403 DCHECK(thread_checker_.CalledOnValidThread());
404 DCHECK(address);
405
406 if (!HasPeerAddress())
407 return ERR_SOCKET_NOT_CONNECTED;
408
409 *address = *peer_address_;
410 return OK;
411}
412
tfarina4eb7aad82015-09-14 17:10:34413void SocketPosix::SetPeerAddress(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34414 DCHECK(thread_checker_.CalledOnValidThread());
415 // |peer_address_| will be non-NULL if Connect() has been called. Unless
416 // Close() is called to reset the internal state, a second call to Connect()
417 // is not allowed.
418 // Please note that we don't allow a second Connect() even if the previous
419 // Connect() has failed. Connecting the same |socket_| again after a
420 // connection attempt failed results in unspecified behavior according to
421 // POSIX.
422 DCHECK(!peer_address_);
423 peer_address_.reset(new SockaddrStorage(address));
424}
425
tfarina4eb7aad82015-09-14 17:10:34426bool SocketPosix::HasPeerAddress() const {
[email protected]2ef2b0e2014-07-09 21:12:34427 DCHECK(thread_checker_.CalledOnValidThread());
428 return peer_address_ != NULL;
429}
430
tfarina4eb7aad82015-09-14 17:10:34431void SocketPosix::Close() {
[email protected]2ef2b0e2014-07-09 21:12:34432 DCHECK(thread_checker_.CalledOnValidThread());
433
cmasoneca100d52014-09-03 18:11:11434 StopWatchingAndCleanUp();
[email protected]2ef2b0e2014-07-09 21:12:34435
436 if (socket_fd_ != kInvalidSocket) {
437 if (IGNORE_EINTR(close(socket_fd_)) < 0)
438 PLOG(ERROR) << "close() returned an error, errno=" << errno;
439 socket_fd_ = kInvalidSocket;
440 }
[email protected]2ef2b0e2014-07-09 21:12:34441}
442
svaldez58804c42015-10-06 00:13:47443void SocketPosix::DetachFromThread() {
444 thread_checker_.DetachFromThread();
445}
446
tfarina4eb7aad82015-09-14 17:10:34447void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
xunjieli0b7f5b62016-12-06 20:43:48448 TRACE_EVENT0(kNetTracingCategory,
449 "SocketPosix::OnFileCanReadWithoutBlocking");
[email protected]2ef2b0e2014-07-09 21:12:34450 if (!accept_callback_.is_null()) {
451 AcceptCompleted();
xunjieli321a96f32017-03-07 19:42:17452 } else {
453 DCHECK(!read_if_ready_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34454 ReadCompleted();
455 }
456}
457
tfarina4eb7aad82015-09-14 17:10:34458void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
[email protected]2ef2b0e2014-07-09 21:12:34459 DCHECK(!write_callback_.is_null());
460 if (waiting_connect_) {
461 ConnectCompleted();
462 } else {
463 WriteCompleted();
464 }
465}
466
danakj655b66c2016-04-16 00:51:38467int SocketPosix::DoAccept(std::unique_ptr<SocketPosix>* socket) {
[email protected]2ef2b0e2014-07-09 21:12:34468 SockaddrStorage new_peer_address;
469 int new_socket = HANDLE_EINTR(accept(socket_fd_,
470 new_peer_address.addr,
471 &new_peer_address.addr_len));
472 if (new_socket < 0)
473 return MapAcceptError(errno);
474
danakj655b66c2016-04-16 00:51:38475 std::unique_ptr<SocketPosix> accepted_socket(new SocketPosix);
[email protected]2ef2b0e2014-07-09 21:12:34476 int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
477 if (rv != OK)
478 return rv;
479
dchengc7eeda422015-12-26 03:56:48480 *socket = std::move(accepted_socket);
[email protected]2ef2b0e2014-07-09 21:12:34481 return OK;
482}
483
tfarina4eb7aad82015-09-14 17:10:34484void SocketPosix::AcceptCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34485 DCHECK(accept_socket_);
486 int rv = DoAccept(accept_socket_);
487 if (rv == ERR_IO_PENDING)
488 return;
489
490 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
491 DCHECK(ok);
492 accept_socket_ = NULL;
493 base::ResetAndReturn(&accept_callback_).Run(rv);
494}
495
tfarina4eb7aad82015-09-14 17:10:34496int SocketPosix::DoConnect() {
[email protected]2ef2b0e2014-07-09 21:12:34497 int rv = HANDLE_EINTR(connect(socket_fd_,
498 peer_address_->addr,
499 peer_address_->addr_len));
500 DCHECK_GE(0, rv);
501 return rv == 0 ? OK : MapConnectError(errno);
502}
503
tfarina4eb7aad82015-09-14 17:10:34504void SocketPosix::ConnectCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34505 // Get the error that connect() completed with.
506 int os_error = 0;
507 socklen_t len = sizeof(os_error);
508 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
tfarina4eb7aad82015-09-14 17:10:34509 // TCPSocketPosix expects errno to be set.
[email protected]2ef2b0e2014-07-09 21:12:34510 errno = os_error;
511 }
512
513 int rv = MapConnectError(errno);
514 if (rv == ERR_IO_PENDING)
515 return;
516
517 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
518 DCHECK(ok);
519 waiting_connect_ = false;
520 base::ResetAndReturn(&write_callback_).Run(rv);
521}
522
tfarina4eb7aad82015-09-14 17:10:34523int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
[email protected]2ef2b0e2014-07-09 21:12:34524 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
525 return rv >= 0 ? rv : MapSystemError(errno);
526}
527
xunjieli321a96f32017-03-07 19:42:17528void SocketPosix::RetryRead(int rv) {
529 DCHECK(read_callback_);
530 DCHECK(read_buf_);
531 DCHECK_LT(0, read_buf_len_);
532
533 if (rv == OK) {
534 rv = ReadIfReady(
535 read_buf_.get(), read_buf_len_,
536 base::Bind(&SocketPosix::RetryRead, base::Unretained(this)));
537 if (rv == ERR_IO_PENDING)
538 return;
539 }
540 read_buf_ = nullptr;
541 read_buf_len_ = 0;
542 base::ResetAndReturn(&read_callback_).Run(rv);
543}
544
tfarina4eb7aad82015-09-14 17:10:34545void SocketPosix::ReadCompleted() {
xunjieli321a96f32017-03-07 19:42:17546 DCHECK(read_if_ready_callback_);
[email protected]2ef2b0e2014-07-09 21:12:34547
548 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
549 DCHECK(ok);
xunjieli321a96f32017-03-07 19:42:17550 base::ResetAndReturn(&read_if_ready_callback_).Run(OK);
[email protected]2ef2b0e2014-07-09 21:12:34551}
552
tfarina4eb7aad82015-09-14 17:10:34553int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
davidben28150272016-06-06 21:03:12554#if defined(OS_LINUX) || defined(OS_ANDROID)
555 // Disable SIGPIPE for this write. Although Chromium globally disables
556 // SIGPIPE, the net stack may be used in other consumers which do not do
557 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on
558 // socket creation.
559 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL));
560#else
[email protected]2ef2b0e2014-07-09 21:12:34561 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
davidben28150272016-06-06 21:03:12562#endif
[email protected]2ef2b0e2014-07-09 21:12:34563 return rv >= 0 ? rv : MapSystemError(errno);
564}
565
tfarina4eb7aad82015-09-14 17:10:34566void SocketPosix::WriteCompleted() {
dcheng08ea2af02014-08-25 23:38:09567 int rv = DoWrite(write_buf_.get(), write_buf_len_);
[email protected]2ef2b0e2014-07-09 21:12:34568 if (rv == ERR_IO_PENDING)
569 return;
570
571 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
572 DCHECK(ok);
573 write_buf_ = NULL;
574 write_buf_len_ = 0;
575 base::ResetAndReturn(&write_callback_).Run(rv);
576}
577
tfarina4eb7aad82015-09-14 17:10:34578void SocketPosix::StopWatchingAndCleanUp() {
cmasoneca100d52014-09-03 18:11:11579 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
580 DCHECK(ok);
581 ok = read_socket_watcher_.StopWatchingFileDescriptor();
582 DCHECK(ok);
583 ok = write_socket_watcher_.StopWatchingFileDescriptor();
584 DCHECK(ok);
585
586 if (!accept_callback_.is_null()) {
587 accept_socket_ = NULL;
588 accept_callback_.Reset();
589 }
590
591 if (!read_callback_.is_null()) {
592 read_buf_ = NULL;
593 read_buf_len_ = 0;
594 read_callback_.Reset();
595 }
596
xunjieli321a96f32017-03-07 19:42:17597 read_if_ready_callback_.Reset();
598
cmasoneca100d52014-09-03 18:11:11599 if (!write_callback_.is_null()) {
600 write_buf_ = NULL;
601 write_buf_len_ = 0;
602 write_callback_.Reset();
603 }
604
605 waiting_connect_ = false;
606 peer_address_.reset();
607}
608
[email protected]2ef2b0e2014-07-09 21:12:34609} // namespace net