blob: ca8b04f09a4741282f7d441711d87ba315332ce3 [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"
[email protected]2ef2b0e2014-07-09 21:12:3417#include "net/base/io_buffer.h"
18#include "net/base/ip_endpoint.h"
19#include "net/base/net_errors.h"
tfarina3d87d7cd2016-01-13 02:26:5920#include "net/base/sockaddr_storage.h"
[email protected]2ef2b0e2014-07-09 21:12:3421
22namespace net {
23
24namespace {
25
26int MapAcceptError(int os_error) {
27 switch (os_error) {
28 // If the client aborts the connection before the server calls accept,
29 // POSIX specifies accept should fail with ECONNABORTED. The server can
30 // ignore the error and just call accept again, so we map the error to
31 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
32 // 5.11, "Connection Abort before accept Returns".
33 case ECONNABORTED:
34 return ERR_IO_PENDING;
35 default:
36 return MapSystemError(os_error);
37 }
38}
39
40int MapConnectError(int os_error) {
41 switch (os_error) {
42 case EINPROGRESS:
43 return ERR_IO_PENDING;
44 case EACCES:
45 return ERR_NETWORK_ACCESS_DENIED;
46 case ETIMEDOUT:
47 return ERR_CONNECTION_TIMED_OUT;
48 default: {
49 int net_error = MapSystemError(os_error);
50 if (net_error == ERR_FAILED)
51 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
52 return net_error;
53 }
54 }
55}
56
57} // namespace
58
tfarina4eb7aad82015-09-14 17:10:3459SocketPosix::SocketPosix()
[email protected]2ef2b0e2014-07-09 21:12:3460 : socket_fd_(kInvalidSocket),
61 read_buf_len_(0),
62 write_buf_len_(0),
tfarina4eb7aad82015-09-14 17:10:3463 waiting_connect_(false) {}
[email protected]2ef2b0e2014-07-09 21:12:3464
tfarina4eb7aad82015-09-14 17:10:3465SocketPosix::~SocketPosix() {
[email protected]2ef2b0e2014-07-09 21:12:3466 Close();
67}
68
tfarina4eb7aad82015-09-14 17:10:3469int SocketPosix::Open(int address_family) {
[email protected]2ef2b0e2014-07-09 21:12:3470 DCHECK(thread_checker_.CalledOnValidThread());
71 DCHECK_EQ(kInvalidSocket, socket_fd_);
72 DCHECK(address_family == AF_INET ||
73 address_family == AF_INET6 ||
74 address_family == AF_UNIX);
75
76 socket_fd_ = CreatePlatformSocket(
77 address_family,
78 SOCK_STREAM,
79 address_family == AF_UNIX ? 0 : IPPROTO_TCP);
80 if (socket_fd_ < 0) {
81 PLOG(ERROR) << "CreatePlatformSocket() returned an error, errno=" << errno;
82 return MapSystemError(errno);
83 }
84
tfarina060df7e2015-12-16 05:15:3285 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:3486 int rv = MapSystemError(errno);
87 Close();
88 return rv;
89 }
90
91 return OK;
92}
93
tfarina4eb7aad82015-09-14 17:10:3494int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
95 const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:3496 DCHECK(thread_checker_.CalledOnValidThread());
97 DCHECK_EQ(kInvalidSocket, socket_fd_);
98
99 socket_fd_ = socket;
100
tfarina060df7e2015-12-16 05:15:32101 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:34102 int rv = MapSystemError(errno);
103 Close();
104 return rv;
105 }
106
107 SetPeerAddress(address);
108 return OK;
109}
110
tfarina4eb7aad82015-09-14 17:10:34111SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
cmasoneca100d52014-09-03 18:11:11112 StopWatchingAndCleanUp();
113 SocketDescriptor socket_fd = socket_fd_;
114 socket_fd_ = kInvalidSocket;
115 return socket_fd;
116}
117
tfarina4eb7aad82015-09-14 17:10:34118int SocketPosix::Bind(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34119 DCHECK(thread_checker_.CalledOnValidThread());
120 DCHECK_NE(kInvalidSocket, socket_fd_);
121
122 int rv = bind(socket_fd_, address.addr, address.addr_len);
123 if (rv < 0) {
124 PLOG(ERROR) << "bind() returned an error, errno=" << errno;
125 return MapSystemError(errno);
126 }
127
128 return OK;
129}
130
tfarina4eb7aad82015-09-14 17:10:34131int SocketPosix::Listen(int backlog) {
[email protected]2ef2b0e2014-07-09 21:12:34132 DCHECK(thread_checker_.CalledOnValidThread());
133 DCHECK_NE(kInvalidSocket, socket_fd_);
134 DCHECK_LT(0, backlog);
135
136 int rv = listen(socket_fd_, backlog);
137 if (rv < 0) {
138 PLOG(ERROR) << "listen() returned an error, errno=" << errno;
139 return MapSystemError(errno);
140 }
141
142 return OK;
143}
144
tfarina4eb7aad82015-09-14 17:10:34145int SocketPosix::Accept(scoped_ptr<SocketPosix>* socket,
146 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34147 DCHECK(thread_checker_.CalledOnValidThread());
148 DCHECK_NE(kInvalidSocket, socket_fd_);
149 DCHECK(accept_callback_.is_null());
150 DCHECK(socket);
151 DCHECK(!callback.is_null());
152
153 int rv = DoAccept(socket);
154 if (rv != ERR_IO_PENDING)
155 return rv;
156
157 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
158 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
159 &accept_socket_watcher_, this)) {
160 PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
161 return MapSystemError(errno);
162 }
163
164 accept_socket_ = socket;
165 accept_callback_ = callback;
166 return ERR_IO_PENDING;
167}
168
tfarina4eb7aad82015-09-14 17:10:34169int SocketPosix::Connect(const SockaddrStorage& address,
170 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34171 DCHECK(thread_checker_.CalledOnValidThread());
172 DCHECK_NE(kInvalidSocket, socket_fd_);
173 DCHECK(!waiting_connect_);
174 DCHECK(!callback.is_null());
175
176 SetPeerAddress(address);
177
178 int rv = DoConnect();
179 if (rv != ERR_IO_PENDING)
180 return rv;
181
182 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
183 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
184 &write_socket_watcher_, this)) {
185 PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
186 return MapSystemError(errno);
187 }
188
189 write_callback_ = callback;
190 waiting_connect_ = true;
191 return ERR_IO_PENDING;
192}
193
tfarina4eb7aad82015-09-14 17:10:34194bool SocketPosix::IsConnected() const {
[email protected]2ef2b0e2014-07-09 21:12:34195 DCHECK(thread_checker_.CalledOnValidThread());
196
197 if (socket_fd_ == kInvalidSocket || waiting_connect_)
198 return false;
199
200 // Checks if connection is alive.
201 char c;
202 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
203 if (rv == 0)
204 return false;
205 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
206 return false;
207
208 return true;
209}
210
tfarina4eb7aad82015-09-14 17:10:34211bool SocketPosix::IsConnectedAndIdle() const {
[email protected]2ef2b0e2014-07-09 21:12:34212 DCHECK(thread_checker_.CalledOnValidThread());
213
214 if (socket_fd_ == kInvalidSocket || waiting_connect_)
215 return false;
216
217 // Check if connection is alive and we haven't received any data
218 // unexpectedly.
219 char c;
220 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
221 if (rv >= 0)
222 return false;
223 if (errno != EAGAIN && errno != EWOULDBLOCK)
224 return false;
225
226 return true;
227}
228
tfarina4eb7aad82015-09-14 17:10:34229int SocketPosix::Read(IOBuffer* buf,
230 int buf_len,
231 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34232 DCHECK(thread_checker_.CalledOnValidThread());
233 DCHECK_NE(kInvalidSocket, socket_fd_);
234 DCHECK(!waiting_connect_);
vitalybuka63b47542014-09-29 17:14:19235 CHECK(read_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34236 // Synchronous operation not supported
237 DCHECK(!callback.is_null());
238 DCHECK_LT(0, buf_len);
239
240 int rv = DoRead(buf, buf_len);
241 if (rv != ERR_IO_PENDING)
242 return rv;
243
244 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
245 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
246 &read_socket_watcher_, this)) {
247 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
248 return MapSystemError(errno);
249 }
250
251 read_buf_ = buf;
252 read_buf_len_ = buf_len;
253 read_callback_ = callback;
254 return ERR_IO_PENDING;
255}
256
tfarina4eb7aad82015-09-14 17:10:34257int SocketPosix::Write(IOBuffer* buf,
258 int buf_len,
259 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34260 DCHECK(thread_checker_.CalledOnValidThread());
261 DCHECK_NE(kInvalidSocket, socket_fd_);
262 DCHECK(!waiting_connect_);
vitalybuka63b47542014-09-29 17:14:19263 CHECK(write_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34264 // Synchronous operation not supported
265 DCHECK(!callback.is_null());
266 DCHECK_LT(0, buf_len);
267
268 int rv = DoWrite(buf, buf_len);
269 if (rv == ERR_IO_PENDING)
270 rv = WaitForWrite(buf, buf_len, callback);
271 return rv;
272}
273
tfarina4eb7aad82015-09-14 17:10:34274int SocketPosix::WaitForWrite(IOBuffer* buf,
275 int buf_len,
276 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34277 DCHECK(thread_checker_.CalledOnValidThread());
278 DCHECK_NE(kInvalidSocket, socket_fd_);
279 DCHECK(write_callback_.is_null());
280 // Synchronous operation not supported
281 DCHECK(!callback.is_null());
282 DCHECK_LT(0, buf_len);
283
284 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
285 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
286 &write_socket_watcher_, this)) {
287 PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
288 return MapSystemError(errno);
289 }
290
291 write_buf_ = buf;
292 write_buf_len_ = buf_len;
293 write_callback_ = callback;
294 return ERR_IO_PENDING;
295}
296
tfarina4eb7aad82015-09-14 17:10:34297int SocketPosix::GetLocalAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34298 DCHECK(thread_checker_.CalledOnValidThread());
299 DCHECK(address);
300
301 if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
302 return MapSystemError(errno);
303 return OK;
304}
305
tfarina4eb7aad82015-09-14 17:10:34306int SocketPosix::GetPeerAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34307 DCHECK(thread_checker_.CalledOnValidThread());
308 DCHECK(address);
309
310 if (!HasPeerAddress())
311 return ERR_SOCKET_NOT_CONNECTED;
312
313 *address = *peer_address_;
314 return OK;
315}
316
tfarina4eb7aad82015-09-14 17:10:34317void SocketPosix::SetPeerAddress(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34318 DCHECK(thread_checker_.CalledOnValidThread());
319 // |peer_address_| will be non-NULL if Connect() has been called. Unless
320 // Close() is called to reset the internal state, a second call to Connect()
321 // is not allowed.
322 // Please note that we don't allow a second Connect() even if the previous
323 // Connect() has failed. Connecting the same |socket_| again after a
324 // connection attempt failed results in unspecified behavior according to
325 // POSIX.
326 DCHECK(!peer_address_);
327 peer_address_.reset(new SockaddrStorage(address));
328}
329
tfarina4eb7aad82015-09-14 17:10:34330bool SocketPosix::HasPeerAddress() const {
[email protected]2ef2b0e2014-07-09 21:12:34331 DCHECK(thread_checker_.CalledOnValidThread());
332 return peer_address_ != NULL;
333}
334
tfarina4eb7aad82015-09-14 17:10:34335void SocketPosix::Close() {
[email protected]2ef2b0e2014-07-09 21:12:34336 DCHECK(thread_checker_.CalledOnValidThread());
337
cmasoneca100d52014-09-03 18:11:11338 StopWatchingAndCleanUp();
[email protected]2ef2b0e2014-07-09 21:12:34339
340 if (socket_fd_ != kInvalidSocket) {
341 if (IGNORE_EINTR(close(socket_fd_)) < 0)
342 PLOG(ERROR) << "close() returned an error, errno=" << errno;
343 socket_fd_ = kInvalidSocket;
344 }
[email protected]2ef2b0e2014-07-09 21:12:34345}
346
svaldez58804c42015-10-06 00:13:47347void SocketPosix::DetachFromThread() {
348 thread_checker_.DetachFromThread();
349}
350
tfarina4eb7aad82015-09-14 17:10:34351void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
ssid6d6b40102016-04-05 18:59:56352 TRACE_EVENT0("net", "SocketPosix::OnFileCanReadWithoutBlocking");
[email protected]2ef2b0e2014-07-09 21:12:34353 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
354 if (!accept_callback_.is_null()) {
355 AcceptCompleted();
356 } else { // !read_callback_.is_null()
357 ReadCompleted();
358 }
359}
360
tfarina4eb7aad82015-09-14 17:10:34361void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
[email protected]2ef2b0e2014-07-09 21:12:34362 DCHECK(!write_callback_.is_null());
363 if (waiting_connect_) {
364 ConnectCompleted();
365 } else {
366 WriteCompleted();
367 }
368}
369
tfarina4eb7aad82015-09-14 17:10:34370int SocketPosix::DoAccept(scoped_ptr<SocketPosix>* socket) {
[email protected]2ef2b0e2014-07-09 21:12:34371 SockaddrStorage new_peer_address;
372 int new_socket = HANDLE_EINTR(accept(socket_fd_,
373 new_peer_address.addr,
374 &new_peer_address.addr_len));
375 if (new_socket < 0)
376 return MapAcceptError(errno);
377
tfarina4eb7aad82015-09-14 17:10:34378 scoped_ptr<SocketPosix> accepted_socket(new SocketPosix);
[email protected]2ef2b0e2014-07-09 21:12:34379 int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
380 if (rv != OK)
381 return rv;
382
dchengc7eeda422015-12-26 03:56:48383 *socket = std::move(accepted_socket);
[email protected]2ef2b0e2014-07-09 21:12:34384 return OK;
385}
386
tfarina4eb7aad82015-09-14 17:10:34387void SocketPosix::AcceptCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34388 DCHECK(accept_socket_);
389 int rv = DoAccept(accept_socket_);
390 if (rv == ERR_IO_PENDING)
391 return;
392
393 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
394 DCHECK(ok);
395 accept_socket_ = NULL;
396 base::ResetAndReturn(&accept_callback_).Run(rv);
397}
398
tfarina4eb7aad82015-09-14 17:10:34399int SocketPosix::DoConnect() {
[email protected]2ef2b0e2014-07-09 21:12:34400 int rv = HANDLE_EINTR(connect(socket_fd_,
401 peer_address_->addr,
402 peer_address_->addr_len));
403 DCHECK_GE(0, rv);
404 return rv == 0 ? OK : MapConnectError(errno);
405}
406
tfarina4eb7aad82015-09-14 17:10:34407void SocketPosix::ConnectCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34408 // Get the error that connect() completed with.
409 int os_error = 0;
410 socklen_t len = sizeof(os_error);
411 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
tfarina4eb7aad82015-09-14 17:10:34412 // TCPSocketPosix expects errno to be set.
[email protected]2ef2b0e2014-07-09 21:12:34413 errno = os_error;
414 }
415
416 int rv = MapConnectError(errno);
417 if (rv == ERR_IO_PENDING)
418 return;
419
420 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
421 DCHECK(ok);
422 waiting_connect_ = false;
423 base::ResetAndReturn(&write_callback_).Run(rv);
424}
425
tfarina4eb7aad82015-09-14 17:10:34426int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
[email protected]2ef2b0e2014-07-09 21:12:34427 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
428 return rv >= 0 ? rv : MapSystemError(errno);
429}
430
tfarina4eb7aad82015-09-14 17:10:34431void SocketPosix::ReadCompleted() {
dcheng08ea2af02014-08-25 23:38:09432 int rv = DoRead(read_buf_.get(), read_buf_len_);
[email protected]2ef2b0e2014-07-09 21:12:34433 if (rv == ERR_IO_PENDING)
434 return;
435
436 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
437 DCHECK(ok);
438 read_buf_ = NULL;
439 read_buf_len_ = 0;
440 base::ResetAndReturn(&read_callback_).Run(rv);
441}
442
tfarina4eb7aad82015-09-14 17:10:34443int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
[email protected]2ef2b0e2014-07-09 21:12:34444 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
445 return rv >= 0 ? rv : MapSystemError(errno);
446}
447
tfarina4eb7aad82015-09-14 17:10:34448void SocketPosix::WriteCompleted() {
dcheng08ea2af02014-08-25 23:38:09449 int rv = DoWrite(write_buf_.get(), write_buf_len_);
[email protected]2ef2b0e2014-07-09 21:12:34450 if (rv == ERR_IO_PENDING)
451 return;
452
453 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
454 DCHECK(ok);
455 write_buf_ = NULL;
456 write_buf_len_ = 0;
457 base::ResetAndReturn(&write_callback_).Run(rv);
458}
459
tfarina4eb7aad82015-09-14 17:10:34460void SocketPosix::StopWatchingAndCleanUp() {
cmasoneca100d52014-09-03 18:11:11461 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
462 DCHECK(ok);
463 ok = read_socket_watcher_.StopWatchingFileDescriptor();
464 DCHECK(ok);
465 ok = write_socket_watcher_.StopWatchingFileDescriptor();
466 DCHECK(ok);
467
468 if (!accept_callback_.is_null()) {
469 accept_socket_ = NULL;
470 accept_callback_.Reset();
471 }
472
473 if (!read_callback_.is_null()) {
474 read_buf_ = NULL;
475 read_buf_len_ = 0;
476 read_callback_.Reset();
477 }
478
479 if (!write_callback_.is_null()) {
480 write_buf_ = NULL;
481 write_buf_len_ = 0;
482 write_callback_.Reset();
483 }
484
485 waiting_connect_ = false;
486 peer_address_.reset();
487}
488
[email protected]2ef2b0e2014-07-09 21:12:34489} // namespace net