blob: 9661928f1aebb848925788ef5a551b1a9c2258ed [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"
15#include "base/posix/eintr_wrapper.h"
ssid6d6b40102016-04-05 18:59:5616#include "base/trace_event/trace_event.h"
davidben28150272016-06-06 21:03:1217#include "build/build_config.h"
[email protected]2ef2b0e2014-07-09 21:12:3418#include "net/base/io_buffer.h"
19#include "net/base/ip_endpoint.h"
20#include "net/base/net_errors.h"
tfarina3d87d7cd2016-01-13 02:26:5921#include "net/base/sockaddr_storage.h"
xunjieli0b7f5b62016-12-06 20:43:4822#include "net/base/trace_constants.h"
[email protected]a2b2cfc2017-12-06 09:06:0823#include "net/traffic_annotation/network_traffic_annotation.h"
[email protected]2ef2b0e2014-07-09 21:12:3424
Sergey Ulanovbc1d87a2017-08-16 02:18:3925#if defined(OS_FUCHSIA)
26#include <poll.h>
27#include <sys/ioctl.h>
28#endif // OS_FUCHSIA
29
[email protected]2ef2b0e2014-07-09 21:12:3430namespace net {
31
32namespace {
33
34int MapAcceptError(int os_error) {
35 switch (os_error) {
36 // If the client aborts the connection before the server calls accept,
37 // POSIX specifies accept should fail with ECONNABORTED. The server can
38 // ignore the error and just call accept again, so we map the error to
39 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
40 // 5.11, "Connection Abort before accept Returns".
41 case ECONNABORTED:
42 return ERR_IO_PENDING;
43 default:
44 return MapSystemError(os_error);
45 }
46}
47
48int MapConnectError(int os_error) {
49 switch (os_error) {
50 case EINPROGRESS:
51 return ERR_IO_PENDING;
52 case EACCES:
53 return ERR_NETWORK_ACCESS_DENIED;
54 case ETIMEDOUT:
55 return ERR_CONNECTION_TIMED_OUT;
56 default: {
57 int net_error = MapSystemError(os_error);
58 if (net_error == ERR_FAILED)
59 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
60 return net_error;
61 }
62 }
63}
64
65} // namespace
66
tfarina4eb7aad82015-09-14 17:10:3467SocketPosix::SocketPosix()
[email protected]2ef2b0e2014-07-09 21:12:3468 : socket_fd_(kInvalidSocket),
ssid5dd4fb32017-02-16 23:57:1769 accept_socket_watcher_(FROM_HERE),
70 read_socket_watcher_(FROM_HERE),
[email protected]2ef2b0e2014-07-09 21:12:3471 read_buf_len_(0),
ssid5dd4fb32017-02-16 23:57:1772 write_socket_watcher_(FROM_HERE),
[email protected]2ef2b0e2014-07-09 21:12:3473 write_buf_len_(0),
tfarina4eb7aad82015-09-14 17:10:3474 waiting_connect_(false) {}
[email protected]2ef2b0e2014-07-09 21:12:3475
tfarina4eb7aad82015-09-14 17:10:3476SocketPosix::~SocketPosix() {
[email protected]2ef2b0e2014-07-09 21:12:3477 Close();
78}
79
tfarina4eb7aad82015-09-14 17:10:3480int SocketPosix::Open(int address_family) {
[email protected]2ef2b0e2014-07-09 21:12:3481 DCHECK(thread_checker_.CalledOnValidThread());
82 DCHECK_EQ(kInvalidSocket, socket_fd_);
83 DCHECK(address_family == AF_INET ||
84 address_family == AF_INET6 ||
85 address_family == AF_UNIX);
86
87 socket_fd_ = CreatePlatformSocket(
88 address_family,
89 SOCK_STREAM,
90 address_family == AF_UNIX ? 0 : IPPROTO_TCP);
91 if (socket_fd_ < 0) {
92 PLOG(ERROR) << "CreatePlatformSocket() returned an error, errno=" << errno;
93 return MapSystemError(errno);
94 }
95
tfarina060df7e2015-12-16 05:15:3296 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:3497 int rv = MapSystemError(errno);
98 Close();
99 return rv;
100 }
101
102 return OK;
103}
104
tfarina4eb7aad82015-09-14 17:10:34105int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
106 const SockaddrStorage& address) {
rvera26f0a1392017-05-02 22:25:44107 int rv = AdoptUnconnectedSocket(socket);
108 if (rv != OK)
109 return rv;
110
111 SetPeerAddress(address);
112 return OK;
113}
114
115int SocketPosix::AdoptUnconnectedSocket(SocketDescriptor socket) {
[email protected]2ef2b0e2014-07-09 21:12:34116 DCHECK(thread_checker_.CalledOnValidThread());
117 DCHECK_EQ(kInvalidSocket, socket_fd_);
118
119 socket_fd_ = socket;
120
tfarina060df7e2015-12-16 05:15:32121 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:34122 int rv = MapSystemError(errno);
123 Close();
124 return rv;
125 }
126
[email protected]2ef2b0e2014-07-09 21:12:34127 return OK;
128}
129
tfarina4eb7aad82015-09-14 17:10:34130SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
cmasoneca100d52014-09-03 18:11:11131 StopWatchingAndCleanUp();
132 SocketDescriptor socket_fd = socket_fd_;
133 socket_fd_ = kInvalidSocket;
134 return socket_fd;
135}
136
tfarina4eb7aad82015-09-14 17:10:34137int SocketPosix::Bind(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34138 DCHECK(thread_checker_.CalledOnValidThread());
139 DCHECK_NE(kInvalidSocket, socket_fd_);
140
141 int rv = bind(socket_fd_, address.addr, address.addr_len);
142 if (rv < 0) {
143 PLOG(ERROR) << "bind() returned an error, errno=" << errno;
144 return MapSystemError(errno);
145 }
146
147 return OK;
148}
149
tfarina4eb7aad82015-09-14 17:10:34150int SocketPosix::Listen(int backlog) {
[email protected]2ef2b0e2014-07-09 21:12:34151 DCHECK(thread_checker_.CalledOnValidThread());
152 DCHECK_NE(kInvalidSocket, socket_fd_);
153 DCHECK_LT(0, backlog);
154
155 int rv = listen(socket_fd_, backlog);
156 if (rv < 0) {
157 PLOG(ERROR) << "listen() returned an error, errno=" << errno;
158 return MapSystemError(errno);
159 }
160
161 return OK;
162}
163
danakj655b66c2016-04-16 00:51:38164int SocketPosix::Accept(std::unique_ptr<SocketPosix>* socket,
tfarina4eb7aad82015-09-14 17:10:34165 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34166 DCHECK(thread_checker_.CalledOnValidThread());
167 DCHECK_NE(kInvalidSocket, socket_fd_);
168 DCHECK(accept_callback_.is_null());
169 DCHECK(socket);
170 DCHECK(!callback.is_null());
171
172 int rv = DoAccept(socket);
173 if (rv != ERR_IO_PENDING)
174 return rv;
175
176 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
177 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
178 &accept_socket_watcher_, this)) {
179 PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
180 return MapSystemError(errno);
181 }
182
183 accept_socket_ = socket;
184 accept_callback_ = callback;
185 return ERR_IO_PENDING;
186}
187
tfarina4eb7aad82015-09-14 17:10:34188int SocketPosix::Connect(const SockaddrStorage& address,
189 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34190 DCHECK(thread_checker_.CalledOnValidThread());
191 DCHECK_NE(kInvalidSocket, socket_fd_);
192 DCHECK(!waiting_connect_);
193 DCHECK(!callback.is_null());
194
195 SetPeerAddress(address);
196
197 int rv = DoConnect();
198 if (rv != ERR_IO_PENDING)
199 return rv;
200
201 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
202 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
203 &write_socket_watcher_, this)) {
204 PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
205 return MapSystemError(errno);
206 }
207
sdefresne8df022f2016-09-20 13:54:26208 // There is a race-condition in the above code if the kernel receive a RST
209 // packet for the "connect" call before the registration of the socket file
210 // descriptor to the message loop pump. On most platform it is benign as the
211 // message loop pump is awakened for that socket in an error state, but on
212 // iOS this does not happens. Check the status of the socket at this point
213 // and if in error, consider the connection as failed.
214 int os_error = 0;
215 socklen_t len = sizeof(os_error);
216 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
217 // TCPSocketPosix expects errno to be set.
218 errno = os_error;
219 }
220
221 rv = MapConnectError(errno);
222 if (rv != OK && rv != ERR_IO_PENDING) {
223 write_socket_watcher_.StopWatchingFileDescriptor();
224 return rv;
225 }
226
[email protected]2ef2b0e2014-07-09 21:12:34227 write_callback_ = callback;
228 waiting_connect_ = true;
229 return ERR_IO_PENDING;
230}
231
tfarina4eb7aad82015-09-14 17:10:34232bool SocketPosix::IsConnected() const {
[email protected]2ef2b0e2014-07-09 21:12:34233 DCHECK(thread_checker_.CalledOnValidThread());
234
235 if (socket_fd_ == kInvalidSocket || waiting_connect_)
236 return false;
237
Sergey Ulanovbc1d87a2017-08-16 02:18:39238#if !defined(OS_FUCHSIA)
[email protected]2ef2b0e2014-07-09 21:12:34239 // Checks if connection is alive.
240 char c;
241 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
242 if (rv == 0)
243 return false;
244 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
245 return false;
246
247 return true;
Sergey Ulanovbc1d87a2017-08-16 02:18:39248
249#else // OS_FUCHSIA
250 // Fuchsia currently doesn't support MSG_PEEK flag in recv(), so the code
251 // above doesn't work on Fuchsia. IsConnected() must return true if the
252 // connection is alive or if it was terminated but there is still data pending
253 // in the incoming buffer.
254 // 1. Check if the connection is alive using poll(POLLRDHUP).
255 // 2. If closed, then use ioctl(FIONREAD) to check if there is data to be
256 // read.
257 // TODO(bug 738275): Remove once MSG_PEEK is implemented on Fuchsia.
258 struct pollfd pollfd;
259 pollfd.fd = socket_fd_;
260 pollfd.events = POLLRDHUP;
261 pollfd.revents = 0;
262 const int poll_result = HANDLE_EINTR(poll(&pollfd, 1, 0));
263
264 if (poll_result == 1) {
265 int bytes_available;
266 int ioctl_result =
267 HANDLE_EINTR(ioctl(socket_fd_, FIONREAD, &bytes_available));
268 return ioctl_result == 0 && bytes_available > 0;
269 }
270
271 return poll_result == 0;
272#endif // OS_FUCHSIA
[email protected]2ef2b0e2014-07-09 21:12:34273}
274
tfarina4eb7aad82015-09-14 17:10:34275bool SocketPosix::IsConnectedAndIdle() const {
[email protected]2ef2b0e2014-07-09 21:12:34276 DCHECK(thread_checker_.CalledOnValidThread());
277
278 if (socket_fd_ == kInvalidSocket || waiting_connect_)
279 return false;
280
Sergey Ulanovbc1d87a2017-08-16 02:18:39281#if !defined(OS_FUCHSIA)
[email protected]2ef2b0e2014-07-09 21:12:34282 // Check if connection is alive and we haven't received any data
283 // unexpectedly.
284 char c;
285 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
286 if (rv >= 0)
287 return false;
288 if (errno != EAGAIN && errno != EWOULDBLOCK)
289 return false;
290
291 return true;
Sergey Ulanovbc1d87a2017-08-16 02:18:39292
293#else // OS_FUCHSIA
294 // Fuchsia currently doesn't support MSG_PEEK flag in recv(), so the code
295 // above doesn't work on Fuchsia. Use poll(POLLIN) to check state of the
296 // socket. POLLIN is signaled if the socket is readable or if it was closed by
297 // the peer, i.e. the socket is connected and idle if and only if POLLIN is
298 // not signaled.
299 // TODO(bug 738275): Remove once MSG_PEEK is implemented.
300 struct pollfd pollfd;
301 pollfd.fd = socket_fd_;
302 pollfd.events = POLLIN;
303 pollfd.revents = 0;
304 const int poll_result = HANDLE_EINTR(poll(&pollfd, 1, 0));
305 return poll_result == 0;
306#endif // OS_FUCHSIA
[email protected]2ef2b0e2014-07-09 21:12:34307}
308
tfarina4eb7aad82015-09-14 17:10:34309int SocketPosix::Read(IOBuffer* buf,
310 int buf_len,
311 const CompletionCallback& callback) {
xunjieli321a96f32017-03-07 19:42:17312 // Use base::Unretained() is safe here because OnFileCanReadWithoutBlocking()
313 // won't be called if |this| is gone.
314 int rv =
315 ReadIfReady(buf, buf_len,
316 base::Bind(&SocketPosix::RetryRead, base::Unretained(this)));
317 if (rv == ERR_IO_PENDING) {
318 read_buf_ = buf;
319 read_buf_len_ = buf_len;
320 read_callback_ = callback;
321 }
322 return rv;
323}
324
325int SocketPosix::ReadIfReady(IOBuffer* buf,
326 int buf_len,
327 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34328 DCHECK(thread_checker_.CalledOnValidThread());
329 DCHECK_NE(kInvalidSocket, socket_fd_);
330 DCHECK(!waiting_connect_);
xunjieli321a96f32017-03-07 19:42:17331 CHECK(read_if_ready_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34332 DCHECK(!callback.is_null());
333 DCHECK_LT(0, buf_len);
334
335 int rv = DoRead(buf, buf_len);
336 if (rv != ERR_IO_PENDING)
337 return rv;
338
339 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
340 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
341 &read_socket_watcher_, this)) {
342 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
343 return MapSystemError(errno);
344 }
345
xunjieli321a96f32017-03-07 19:42:17346 read_if_ready_callback_ = callback;
[email protected]2ef2b0e2014-07-09 21:12:34347 return ERR_IO_PENDING;
348}
349
tfarina4eb7aad82015-09-14 17:10:34350int SocketPosix::Write(IOBuffer* buf,
351 int buf_len,
[email protected]a2b2cfc2017-12-06 09:06:08352 const CompletionCallback& callback,
353 const NetworkTrafficAnnotationTag& traffic_annotation) {
[email protected]2ef2b0e2014-07-09 21:12:34354 DCHECK(thread_checker_.CalledOnValidThread());
355 DCHECK_NE(kInvalidSocket, socket_fd_);
356 DCHECK(!waiting_connect_);
vitalybuka63b47542014-09-29 17:14:19357 CHECK(write_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34358 // Synchronous operation not supported
359 DCHECK(!callback.is_null());
360 DCHECK_LT(0, buf_len);
361
[email protected]a2b2cfc2017-12-06 09:06:08362 // TODO(crbug.com/656607): Handle traffic annotation.
363
[email protected]2ef2b0e2014-07-09 21:12:34364 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(
381 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
382 &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
svaldez58804c402015-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