blob: cd7aff12d34559cf2ede0fe6144a849c10018f97 [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>
10
11#include "base/callback_helpers.h"
tfarina060df7e2015-12-16 05:15:3212#include "base/files/file_util.h"
[email protected]2ef2b0e2014-07-09 21:12:3413#include "base/logging.h"
14#include "base/posix/eintr_wrapper.h"
15#include "net/base/io_buffer.h"
16#include "net/base/ip_endpoint.h"
17#include "net/base/net_errors.h"
18#include "net/base/net_util.h"
19
20namespace net {
21
22namespace {
23
24int MapAcceptError(int os_error) {
25 switch (os_error) {
26 // If the client aborts the connection before the server calls accept,
27 // POSIX specifies accept should fail with ECONNABORTED. The server can
28 // ignore the error and just call accept again, so we map the error to
29 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
30 // 5.11, "Connection Abort before accept Returns".
31 case ECONNABORTED:
32 return ERR_IO_PENDING;
33 default:
34 return MapSystemError(os_error);
35 }
36}
37
38int MapConnectError(int os_error) {
39 switch (os_error) {
40 case EINPROGRESS:
41 return ERR_IO_PENDING;
42 case EACCES:
43 return ERR_NETWORK_ACCESS_DENIED;
44 case ETIMEDOUT:
45 return ERR_CONNECTION_TIMED_OUT;
46 default: {
47 int net_error = MapSystemError(os_error);
48 if (net_error == ERR_FAILED)
49 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
50 return net_error;
51 }
52 }
53}
54
55} // namespace
56
tfarina4eb7aad82015-09-14 17:10:3457SocketPosix::SocketPosix()
[email protected]2ef2b0e2014-07-09 21:12:3458 : socket_fd_(kInvalidSocket),
59 read_buf_len_(0),
60 write_buf_len_(0),
tfarina4eb7aad82015-09-14 17:10:3461 waiting_connect_(false) {}
[email protected]2ef2b0e2014-07-09 21:12:3462
tfarina4eb7aad82015-09-14 17:10:3463SocketPosix::~SocketPosix() {
[email protected]2ef2b0e2014-07-09 21:12:3464 Close();
65}
66
tfarina4eb7aad82015-09-14 17:10:3467int SocketPosix::Open(int address_family) {
[email protected]2ef2b0e2014-07-09 21:12:3468 DCHECK(thread_checker_.CalledOnValidThread());
69 DCHECK_EQ(kInvalidSocket, socket_fd_);
70 DCHECK(address_family == AF_INET ||
71 address_family == AF_INET6 ||
72 address_family == AF_UNIX);
73
74 socket_fd_ = CreatePlatformSocket(
75 address_family,
76 SOCK_STREAM,
77 address_family == AF_UNIX ? 0 : IPPROTO_TCP);
78 if (socket_fd_ < 0) {
79 PLOG(ERROR) << "CreatePlatformSocket() returned an error, errno=" << errno;
80 return MapSystemError(errno);
81 }
82
tfarina060df7e2015-12-16 05:15:3283 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:3484 int rv = MapSystemError(errno);
85 Close();
86 return rv;
87 }
88
89 return OK;
90}
91
tfarina4eb7aad82015-09-14 17:10:3492int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
93 const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:3494 DCHECK(thread_checker_.CalledOnValidThread());
95 DCHECK_EQ(kInvalidSocket, socket_fd_);
96
97 socket_fd_ = socket;
98
tfarina060df7e2015-12-16 05:15:3299 if (!base::SetNonBlocking(socket_fd_)) {
[email protected]2ef2b0e2014-07-09 21:12:34100 int rv = MapSystemError(errno);
101 Close();
102 return rv;
103 }
104
105 SetPeerAddress(address);
106 return OK;
107}
108
tfarina4eb7aad82015-09-14 17:10:34109SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
cmasoneca100d52014-09-03 18:11:11110 StopWatchingAndCleanUp();
111 SocketDescriptor socket_fd = socket_fd_;
112 socket_fd_ = kInvalidSocket;
113 return socket_fd;
114}
115
tfarina4eb7aad82015-09-14 17:10:34116int SocketPosix::Bind(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34117 DCHECK(thread_checker_.CalledOnValidThread());
118 DCHECK_NE(kInvalidSocket, socket_fd_);
119
120 int rv = bind(socket_fd_, address.addr, address.addr_len);
121 if (rv < 0) {
122 PLOG(ERROR) << "bind() returned an error, errno=" << errno;
123 return MapSystemError(errno);
124 }
125
126 return OK;
127}
128
tfarina4eb7aad82015-09-14 17:10:34129int SocketPosix::Listen(int backlog) {
[email protected]2ef2b0e2014-07-09 21:12:34130 DCHECK(thread_checker_.CalledOnValidThread());
131 DCHECK_NE(kInvalidSocket, socket_fd_);
132 DCHECK_LT(0, backlog);
133
134 int rv = listen(socket_fd_, backlog);
135 if (rv < 0) {
136 PLOG(ERROR) << "listen() returned an error, errno=" << errno;
137 return MapSystemError(errno);
138 }
139
140 return OK;
141}
142
tfarina4eb7aad82015-09-14 17:10:34143int SocketPosix::Accept(scoped_ptr<SocketPosix>* socket,
144 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34145 DCHECK(thread_checker_.CalledOnValidThread());
146 DCHECK_NE(kInvalidSocket, socket_fd_);
147 DCHECK(accept_callback_.is_null());
148 DCHECK(socket);
149 DCHECK(!callback.is_null());
150
151 int rv = DoAccept(socket);
152 if (rv != ERR_IO_PENDING)
153 return rv;
154
155 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
156 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
157 &accept_socket_watcher_, this)) {
158 PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
159 return MapSystemError(errno);
160 }
161
162 accept_socket_ = socket;
163 accept_callback_ = callback;
164 return ERR_IO_PENDING;
165}
166
tfarina4eb7aad82015-09-14 17:10:34167int SocketPosix::Connect(const SockaddrStorage& address,
168 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34169 DCHECK(thread_checker_.CalledOnValidThread());
170 DCHECK_NE(kInvalidSocket, socket_fd_);
171 DCHECK(!waiting_connect_);
172 DCHECK(!callback.is_null());
173
174 SetPeerAddress(address);
175
176 int rv = DoConnect();
177 if (rv != ERR_IO_PENDING)
178 return rv;
179
180 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
181 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
182 &write_socket_watcher_, this)) {
183 PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
184 return MapSystemError(errno);
185 }
186
187 write_callback_ = callback;
188 waiting_connect_ = true;
189 return ERR_IO_PENDING;
190}
191
tfarina4eb7aad82015-09-14 17:10:34192bool SocketPosix::IsConnected() const {
[email protected]2ef2b0e2014-07-09 21:12:34193 DCHECK(thread_checker_.CalledOnValidThread());
194
195 if (socket_fd_ == kInvalidSocket || waiting_connect_)
196 return false;
197
198 // Checks if connection is alive.
199 char c;
200 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
201 if (rv == 0)
202 return false;
203 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
204 return false;
205
206 return true;
207}
208
tfarina4eb7aad82015-09-14 17:10:34209bool SocketPosix::IsConnectedAndIdle() const {
[email protected]2ef2b0e2014-07-09 21:12:34210 DCHECK(thread_checker_.CalledOnValidThread());
211
212 if (socket_fd_ == kInvalidSocket || waiting_connect_)
213 return false;
214
215 // Check if connection is alive and we haven't received any data
216 // unexpectedly.
217 char c;
218 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
219 if (rv >= 0)
220 return false;
221 if (errno != EAGAIN && errno != EWOULDBLOCK)
222 return false;
223
224 return true;
225}
226
tfarina4eb7aad82015-09-14 17:10:34227int SocketPosix::Read(IOBuffer* buf,
228 int buf_len,
229 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34230 DCHECK(thread_checker_.CalledOnValidThread());
231 DCHECK_NE(kInvalidSocket, socket_fd_);
232 DCHECK(!waiting_connect_);
vitalybuka63b47542014-09-29 17:14:19233 CHECK(read_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34234 // Synchronous operation not supported
235 DCHECK(!callback.is_null());
236 DCHECK_LT(0, buf_len);
237
238 int rv = DoRead(buf, buf_len);
239 if (rv != ERR_IO_PENDING)
240 return rv;
241
242 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
243 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
244 &read_socket_watcher_, this)) {
245 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
246 return MapSystemError(errno);
247 }
248
249 read_buf_ = buf;
250 read_buf_len_ = buf_len;
251 read_callback_ = callback;
252 return ERR_IO_PENDING;
253}
254
tfarina4eb7aad82015-09-14 17:10:34255int SocketPosix::Write(IOBuffer* buf,
256 int buf_len,
257 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34258 DCHECK(thread_checker_.CalledOnValidThread());
259 DCHECK_NE(kInvalidSocket, socket_fd_);
260 DCHECK(!waiting_connect_);
vitalybuka63b47542014-09-29 17:14:19261 CHECK(write_callback_.is_null());
[email protected]2ef2b0e2014-07-09 21:12:34262 // Synchronous operation not supported
263 DCHECK(!callback.is_null());
264 DCHECK_LT(0, buf_len);
265
266 int rv = DoWrite(buf, buf_len);
267 if (rv == ERR_IO_PENDING)
268 rv = WaitForWrite(buf, buf_len, callback);
269 return rv;
270}
271
tfarina4eb7aad82015-09-14 17:10:34272int SocketPosix::WaitForWrite(IOBuffer* buf,
273 int buf_len,
274 const CompletionCallback& callback) {
[email protected]2ef2b0e2014-07-09 21:12:34275 DCHECK(thread_checker_.CalledOnValidThread());
276 DCHECK_NE(kInvalidSocket, socket_fd_);
277 DCHECK(write_callback_.is_null());
278 // Synchronous operation not supported
279 DCHECK(!callback.is_null());
280 DCHECK_LT(0, buf_len);
281
282 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
283 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
284 &write_socket_watcher_, this)) {
285 PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
286 return MapSystemError(errno);
287 }
288
289 write_buf_ = buf;
290 write_buf_len_ = buf_len;
291 write_callback_ = callback;
292 return ERR_IO_PENDING;
293}
294
tfarina4eb7aad82015-09-14 17:10:34295int SocketPosix::GetLocalAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34296 DCHECK(thread_checker_.CalledOnValidThread());
297 DCHECK(address);
298
299 if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
300 return MapSystemError(errno);
301 return OK;
302}
303
tfarina4eb7aad82015-09-14 17:10:34304int SocketPosix::GetPeerAddress(SockaddrStorage* address) const {
[email protected]2ef2b0e2014-07-09 21:12:34305 DCHECK(thread_checker_.CalledOnValidThread());
306 DCHECK(address);
307
308 if (!HasPeerAddress())
309 return ERR_SOCKET_NOT_CONNECTED;
310
311 *address = *peer_address_;
312 return OK;
313}
314
tfarina4eb7aad82015-09-14 17:10:34315void SocketPosix::SetPeerAddress(const SockaddrStorage& address) {
[email protected]2ef2b0e2014-07-09 21:12:34316 DCHECK(thread_checker_.CalledOnValidThread());
317 // |peer_address_| will be non-NULL if Connect() has been called. Unless
318 // Close() is called to reset the internal state, a second call to Connect()
319 // is not allowed.
320 // Please note that we don't allow a second Connect() even if the previous
321 // Connect() has failed. Connecting the same |socket_| again after a
322 // connection attempt failed results in unspecified behavior according to
323 // POSIX.
324 DCHECK(!peer_address_);
325 peer_address_.reset(new SockaddrStorage(address));
326}
327
tfarina4eb7aad82015-09-14 17:10:34328bool SocketPosix::HasPeerAddress() const {
[email protected]2ef2b0e2014-07-09 21:12:34329 DCHECK(thread_checker_.CalledOnValidThread());
330 return peer_address_ != NULL;
331}
332
tfarina4eb7aad82015-09-14 17:10:34333void SocketPosix::Close() {
[email protected]2ef2b0e2014-07-09 21:12:34334 DCHECK(thread_checker_.CalledOnValidThread());
335
cmasoneca100d52014-09-03 18:11:11336 StopWatchingAndCleanUp();
[email protected]2ef2b0e2014-07-09 21:12:34337
338 if (socket_fd_ != kInvalidSocket) {
339 if (IGNORE_EINTR(close(socket_fd_)) < 0)
340 PLOG(ERROR) << "close() returned an error, errno=" << errno;
341 socket_fd_ = kInvalidSocket;
342 }
[email protected]2ef2b0e2014-07-09 21:12:34343}
344
svaldez58804c42015-10-06 00:13:47345void SocketPosix::DetachFromThread() {
346 thread_checker_.DetachFromThread();
347}
348
tfarina4eb7aad82015-09-14 17:10:34349void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
[email protected]2ef2b0e2014-07-09 21:12:34350 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
351 if (!accept_callback_.is_null()) {
352 AcceptCompleted();
353 } else { // !read_callback_.is_null()
354 ReadCompleted();
355 }
356}
357
tfarina4eb7aad82015-09-14 17:10:34358void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
[email protected]2ef2b0e2014-07-09 21:12:34359 DCHECK(!write_callback_.is_null());
360 if (waiting_connect_) {
361 ConnectCompleted();
362 } else {
363 WriteCompleted();
364 }
365}
366
tfarina4eb7aad82015-09-14 17:10:34367int SocketPosix::DoAccept(scoped_ptr<SocketPosix>* socket) {
[email protected]2ef2b0e2014-07-09 21:12:34368 SockaddrStorage new_peer_address;
369 int new_socket = HANDLE_EINTR(accept(socket_fd_,
370 new_peer_address.addr,
371 &new_peer_address.addr_len));
372 if (new_socket < 0)
373 return MapAcceptError(errno);
374
tfarina4eb7aad82015-09-14 17:10:34375 scoped_ptr<SocketPosix> accepted_socket(new SocketPosix);
[email protected]2ef2b0e2014-07-09 21:12:34376 int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
377 if (rv != OK)
378 return rv;
379
380 *socket = accepted_socket.Pass();
381 return OK;
382}
383
tfarina4eb7aad82015-09-14 17:10:34384void SocketPosix::AcceptCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34385 DCHECK(accept_socket_);
386 int rv = DoAccept(accept_socket_);
387 if (rv == ERR_IO_PENDING)
388 return;
389
390 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
391 DCHECK(ok);
392 accept_socket_ = NULL;
393 base::ResetAndReturn(&accept_callback_).Run(rv);
394}
395
tfarina4eb7aad82015-09-14 17:10:34396int SocketPosix::DoConnect() {
[email protected]2ef2b0e2014-07-09 21:12:34397 int rv = HANDLE_EINTR(connect(socket_fd_,
398 peer_address_->addr,
399 peer_address_->addr_len));
400 DCHECK_GE(0, rv);
401 return rv == 0 ? OK : MapConnectError(errno);
402}
403
tfarina4eb7aad82015-09-14 17:10:34404void SocketPosix::ConnectCompleted() {
[email protected]2ef2b0e2014-07-09 21:12:34405 // Get the error that connect() completed with.
406 int os_error = 0;
407 socklen_t len = sizeof(os_error);
408 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
tfarina4eb7aad82015-09-14 17:10:34409 // TCPSocketPosix expects errno to be set.
[email protected]2ef2b0e2014-07-09 21:12:34410 errno = os_error;
411 }
412
413 int rv = MapConnectError(errno);
414 if (rv == ERR_IO_PENDING)
415 return;
416
417 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
418 DCHECK(ok);
419 waiting_connect_ = false;
420 base::ResetAndReturn(&write_callback_).Run(rv);
421}
422
tfarina4eb7aad82015-09-14 17:10:34423int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
[email protected]2ef2b0e2014-07-09 21:12:34424 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
425 return rv >= 0 ? rv : MapSystemError(errno);
426}
427
tfarina4eb7aad82015-09-14 17:10:34428void SocketPosix::ReadCompleted() {
dcheng08ea2af02014-08-25 23:38:09429 int rv = DoRead(read_buf_.get(), read_buf_len_);
[email protected]2ef2b0e2014-07-09 21:12:34430 if (rv == ERR_IO_PENDING)
431 return;
432
433 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
434 DCHECK(ok);
435 read_buf_ = NULL;
436 read_buf_len_ = 0;
437 base::ResetAndReturn(&read_callback_).Run(rv);
438}
439
tfarina4eb7aad82015-09-14 17:10:34440int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
[email protected]2ef2b0e2014-07-09 21:12:34441 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
442 return rv >= 0 ? rv : MapSystemError(errno);
443}
444
tfarina4eb7aad82015-09-14 17:10:34445void SocketPosix::WriteCompleted() {
dcheng08ea2af02014-08-25 23:38:09446 int rv = DoWrite(write_buf_.get(), write_buf_len_);
[email protected]2ef2b0e2014-07-09 21:12:34447 if (rv == ERR_IO_PENDING)
448 return;
449
450 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
451 DCHECK(ok);
452 write_buf_ = NULL;
453 write_buf_len_ = 0;
454 base::ResetAndReturn(&write_callback_).Run(rv);
455}
456
tfarina4eb7aad82015-09-14 17:10:34457void SocketPosix::StopWatchingAndCleanUp() {
cmasoneca100d52014-09-03 18:11:11458 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
459 DCHECK(ok);
460 ok = read_socket_watcher_.StopWatchingFileDescriptor();
461 DCHECK(ok);
462 ok = write_socket_watcher_.StopWatchingFileDescriptor();
463 DCHECK(ok);
464
465 if (!accept_callback_.is_null()) {
466 accept_socket_ = NULL;
467 accept_callback_.Reset();
468 }
469
470 if (!read_callback_.is_null()) {
471 read_buf_ = NULL;
472 read_buf_len_ = 0;
473 read_callback_.Reset();
474 }
475
476 if (!write_callback_.is_null()) {
477 write_buf_ = NULL;
478 write_buf_len_ = 0;
479 write_callback_.Reset();
480 }
481
482 waiting_connect_ = false;
483 peer_address_.reset();
484}
485
[email protected]2ef2b0e2014-07-09 21:12:34486} // namespace net