Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / net / socket / socket_posix.cc
blob657774a0b718f7d5e1b50786db6f182120b81267
1 // 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.
5 #include "net/socket/socket_posix.h"
7 #include <errno.h>
8 #include <netinet/in.h>
9 #include <sys/socket.h>
11 #include "base/callback_helpers.h"
12 #include "base/logging.h"
13 #include "base/posix/eintr_wrapper.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/ip_endpoint.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_util.h"
19 namespace net {
21 namespace {
23 int MapAcceptError(int os_error) {
24 switch (os_error) {
25 // If the client aborts the connection before the server calls accept,
26 // POSIX specifies accept should fail with ECONNABORTED. The server can
27 // ignore the error and just call accept again, so we map the error to
28 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
29 // 5.11, "Connection Abort before accept Returns".
30 case ECONNABORTED:
31 return ERR_IO_PENDING;
32 default:
33 return MapSystemError(os_error);
37 int MapConnectError(int os_error) {
38 switch (os_error) {
39 case EINPROGRESS:
40 return ERR_IO_PENDING;
41 case EACCES:
42 return ERR_NETWORK_ACCESS_DENIED;
43 case ETIMEDOUT:
44 return ERR_CONNECTION_TIMED_OUT;
45 default: {
46 int net_error = MapSystemError(os_error);
47 if (net_error == ERR_FAILED)
48 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
49 return net_error;
54 } // namespace
56 SocketPosix::SocketPosix()
57 : socket_fd_(kInvalidSocket),
58 read_buf_len_(0),
59 write_buf_len_(0),
60 waiting_connect_(false) {}
62 SocketPosix::~SocketPosix() {
63 Close();
66 int SocketPosix::Open(int address_family) {
67 DCHECK(thread_checker_.CalledOnValidThread());
68 DCHECK_EQ(kInvalidSocket, socket_fd_);
69 DCHECK(address_family == AF_INET ||
70 address_family == AF_INET6 ||
71 address_family == AF_UNIX);
73 socket_fd_ = CreatePlatformSocket(
74 address_family,
75 SOCK_STREAM,
76 address_family == AF_UNIX ? 0 : IPPROTO_TCP);
77 if (socket_fd_ < 0) {
78 PLOG(ERROR) << "CreatePlatformSocket() returned an error, errno=" << errno;
79 return MapSystemError(errno);
82 if (SetNonBlocking(socket_fd_)) {
83 int rv = MapSystemError(errno);
84 Close();
85 return rv;
88 return OK;
91 int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
92 const SockaddrStorage& address) {
93 DCHECK(thread_checker_.CalledOnValidThread());
94 DCHECK_EQ(kInvalidSocket, socket_fd_);
96 socket_fd_ = socket;
98 if (SetNonBlocking(socket_fd_)) {
99 int rv = MapSystemError(errno);
100 Close();
101 return rv;
104 SetPeerAddress(address);
105 return OK;
108 SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
109 StopWatchingAndCleanUp();
110 SocketDescriptor socket_fd = socket_fd_;
111 socket_fd_ = kInvalidSocket;
112 return socket_fd;
115 int SocketPosix::Bind(const SockaddrStorage& address) {
116 DCHECK(thread_checker_.CalledOnValidThread());
117 DCHECK_NE(kInvalidSocket, socket_fd_);
119 int rv = bind(socket_fd_, address.addr, address.addr_len);
120 if (rv < 0) {
121 PLOG(ERROR) << "bind() returned an error, errno=" << errno;
122 return MapSystemError(errno);
125 return OK;
128 int SocketPosix::Listen(int backlog) {
129 DCHECK(thread_checker_.CalledOnValidThread());
130 DCHECK_NE(kInvalidSocket, socket_fd_);
131 DCHECK_LT(0, backlog);
133 int rv = listen(socket_fd_, backlog);
134 if (rv < 0) {
135 PLOG(ERROR) << "listen() returned an error, errno=" << errno;
136 return MapSystemError(errno);
139 return OK;
142 int SocketPosix::Accept(scoped_ptr<SocketPosix>* socket,
143 const CompletionCallback& callback) {
144 DCHECK(thread_checker_.CalledOnValidThread());
145 DCHECK_NE(kInvalidSocket, socket_fd_);
146 DCHECK(accept_callback_.is_null());
147 DCHECK(socket);
148 DCHECK(!callback.is_null());
150 int rv = DoAccept(socket);
151 if (rv != ERR_IO_PENDING)
152 return rv;
154 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
155 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
156 &accept_socket_watcher_, this)) {
157 PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
158 return MapSystemError(errno);
161 accept_socket_ = socket;
162 accept_callback_ = callback;
163 return ERR_IO_PENDING;
166 int SocketPosix::Connect(const SockaddrStorage& address,
167 const CompletionCallback& callback) {
168 DCHECK(thread_checker_.CalledOnValidThread());
169 DCHECK_NE(kInvalidSocket, socket_fd_);
170 DCHECK(!waiting_connect_);
171 DCHECK(!callback.is_null());
173 SetPeerAddress(address);
175 int rv = DoConnect();
176 if (rv != ERR_IO_PENDING)
177 return rv;
179 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
180 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
181 &write_socket_watcher_, this)) {
182 PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
183 return MapSystemError(errno);
186 write_callback_ = callback;
187 waiting_connect_ = true;
188 return ERR_IO_PENDING;
191 bool SocketPosix::IsConnected() const {
192 DCHECK(thread_checker_.CalledOnValidThread());
194 if (socket_fd_ == kInvalidSocket || waiting_connect_)
195 return false;
197 // Checks if connection is alive.
198 char c;
199 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
200 if (rv == 0)
201 return false;
202 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
203 return false;
205 return true;
208 bool SocketPosix::IsConnectedAndIdle() const {
209 DCHECK(thread_checker_.CalledOnValidThread());
211 if (socket_fd_ == kInvalidSocket || waiting_connect_)
212 return false;
214 // Check if connection is alive and we haven't received any data
215 // unexpectedly.
216 char c;
217 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
218 if (rv >= 0)
219 return false;
220 if (errno != EAGAIN && errno != EWOULDBLOCK)
221 return false;
223 return true;
226 int SocketPosix::Read(IOBuffer* buf,
227 int buf_len,
228 const CompletionCallback& callback) {
229 DCHECK(thread_checker_.CalledOnValidThread());
230 DCHECK_NE(kInvalidSocket, socket_fd_);
231 DCHECK(!waiting_connect_);
232 CHECK(read_callback_.is_null());
233 // Synchronous operation not supported
234 DCHECK(!callback.is_null());
235 DCHECK_LT(0, buf_len);
237 int rv = DoRead(buf, buf_len);
238 if (rv != ERR_IO_PENDING)
239 return rv;
241 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
242 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
243 &read_socket_watcher_, this)) {
244 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
245 return MapSystemError(errno);
248 read_buf_ = buf;
249 read_buf_len_ = buf_len;
250 read_callback_ = callback;
251 return ERR_IO_PENDING;
254 int SocketPosix::Write(IOBuffer* buf,
255 int buf_len,
256 const CompletionCallback& callback) {
257 DCHECK(thread_checker_.CalledOnValidThread());
258 DCHECK_NE(kInvalidSocket, socket_fd_);
259 DCHECK(!waiting_connect_);
260 CHECK(write_callback_.is_null());
261 // Synchronous operation not supported
262 DCHECK(!callback.is_null());
263 DCHECK_LT(0, buf_len);
265 int rv = DoWrite(buf, buf_len);
266 if (rv == ERR_IO_PENDING)
267 rv = WaitForWrite(buf, buf_len, callback);
268 return rv;
271 int SocketPosix::WaitForWrite(IOBuffer* buf,
272 int buf_len,
273 const CompletionCallback& callback) {
274 DCHECK(thread_checker_.CalledOnValidThread());
275 DCHECK_NE(kInvalidSocket, socket_fd_);
276 DCHECK(write_callback_.is_null());
277 // Synchronous operation not supported
278 DCHECK(!callback.is_null());
279 DCHECK_LT(0, buf_len);
281 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
282 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
283 &write_socket_watcher_, this)) {
284 PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
285 return MapSystemError(errno);
288 write_buf_ = buf;
289 write_buf_len_ = buf_len;
290 write_callback_ = callback;
291 return ERR_IO_PENDING;
294 int SocketPosix::GetLocalAddress(SockaddrStorage* address) const {
295 DCHECK(thread_checker_.CalledOnValidThread());
296 DCHECK(address);
298 if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
299 return MapSystemError(errno);
300 return OK;
303 int SocketPosix::GetPeerAddress(SockaddrStorage* address) const {
304 DCHECK(thread_checker_.CalledOnValidThread());
305 DCHECK(address);
307 if (!HasPeerAddress())
308 return ERR_SOCKET_NOT_CONNECTED;
310 *address = *peer_address_;
311 return OK;
314 void SocketPosix::SetPeerAddress(const SockaddrStorage& address) {
315 DCHECK(thread_checker_.CalledOnValidThread());
316 // |peer_address_| will be non-NULL if Connect() has been called. Unless
317 // Close() is called to reset the internal state, a second call to Connect()
318 // is not allowed.
319 // Please note that we don't allow a second Connect() even if the previous
320 // Connect() has failed. Connecting the same |socket_| again after a
321 // connection attempt failed results in unspecified behavior according to
322 // POSIX.
323 DCHECK(!peer_address_);
324 peer_address_.reset(new SockaddrStorage(address));
327 bool SocketPosix::HasPeerAddress() const {
328 DCHECK(thread_checker_.CalledOnValidThread());
329 return peer_address_ != NULL;
332 void SocketPosix::Close() {
333 DCHECK(thread_checker_.CalledOnValidThread());
335 StopWatchingAndCleanUp();
337 if (socket_fd_ != kInvalidSocket) {
338 if (IGNORE_EINTR(close(socket_fd_)) < 0)
339 PLOG(ERROR) << "close() returned an error, errno=" << errno;
340 socket_fd_ = kInvalidSocket;
344 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
345 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
346 if (!accept_callback_.is_null()) {
347 AcceptCompleted();
348 } else { // !read_callback_.is_null()
349 ReadCompleted();
353 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
354 DCHECK(!write_callback_.is_null());
355 if (waiting_connect_) {
356 ConnectCompleted();
357 } else {
358 WriteCompleted();
362 int SocketPosix::DoAccept(scoped_ptr<SocketPosix>* socket) {
363 SockaddrStorage new_peer_address;
364 int new_socket = HANDLE_EINTR(accept(socket_fd_,
365 new_peer_address.addr,
366 &new_peer_address.addr_len));
367 if (new_socket < 0)
368 return MapAcceptError(errno);
370 scoped_ptr<SocketPosix> accepted_socket(new SocketPosix);
371 int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
372 if (rv != OK)
373 return rv;
375 *socket = accepted_socket.Pass();
376 return OK;
379 void SocketPosix::AcceptCompleted() {
380 DCHECK(accept_socket_);
381 int rv = DoAccept(accept_socket_);
382 if (rv == ERR_IO_PENDING)
383 return;
385 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
386 DCHECK(ok);
387 accept_socket_ = NULL;
388 base::ResetAndReturn(&accept_callback_).Run(rv);
391 int SocketPosix::DoConnect() {
392 int rv = HANDLE_EINTR(connect(socket_fd_,
393 peer_address_->addr,
394 peer_address_->addr_len));
395 DCHECK_GE(0, rv);
396 return rv == 0 ? OK : MapConnectError(errno);
399 void SocketPosix::ConnectCompleted() {
400 // Get the error that connect() completed with.
401 int os_error = 0;
402 socklen_t len = sizeof(os_error);
403 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
404 // TCPSocketPosix expects errno to be set.
405 errno = os_error;
408 int rv = MapConnectError(errno);
409 if (rv == ERR_IO_PENDING)
410 return;
412 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
413 DCHECK(ok);
414 waiting_connect_ = false;
415 base::ResetAndReturn(&write_callback_).Run(rv);
418 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
419 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
420 return rv >= 0 ? rv : MapSystemError(errno);
423 void SocketPosix::ReadCompleted() {
424 int rv = DoRead(read_buf_.get(), read_buf_len_);
425 if (rv == ERR_IO_PENDING)
426 return;
428 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
429 DCHECK(ok);
430 read_buf_ = NULL;
431 read_buf_len_ = 0;
432 base::ResetAndReturn(&read_callback_).Run(rv);
435 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
436 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
437 return rv >= 0 ? rv : MapSystemError(errno);
440 void SocketPosix::WriteCompleted() {
441 int rv = DoWrite(write_buf_.get(), write_buf_len_);
442 if (rv == ERR_IO_PENDING)
443 return;
445 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
446 DCHECK(ok);
447 write_buf_ = NULL;
448 write_buf_len_ = 0;
449 base::ResetAndReturn(&write_callback_).Run(rv);
452 void SocketPosix::StopWatchingAndCleanUp() {
453 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
454 DCHECK(ok);
455 ok = read_socket_watcher_.StopWatchingFileDescriptor();
456 DCHECK(ok);
457 ok = write_socket_watcher_.StopWatchingFileDescriptor();
458 DCHECK(ok);
460 if (!accept_callback_.is_null()) {
461 accept_socket_ = NULL;
462 accept_callback_.Reset();
465 if (!read_callback_.is_null()) {
466 read_buf_ = NULL;
467 read_buf_len_ = 0;
468 read_callback_.Reset();
471 if (!write_callback_.is_null()) {
472 write_buf_ = NULL;
473 write_buf_len_ = 0;
474 write_callback_.Reset();
477 waiting_connect_ = false;
478 peer_address_.reset();
481 } // namespace net