Home | History | Annotate | Download | only in socket
      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.
      4 
      5 #include "net/socket/socket_libevent.h"
      6 
      7 #include <errno.h>
      8 #include <netinet/in.h>
      9 #include <sys/socket.h>
     10 
     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"
     18 
     19 namespace net {
     20 
     21 namespace {
     22 
     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);
     34   }
     35 }
     36 
     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;
     50     }
     51   }
     52 }
     53 
     54 }  // namespace
     55 
     56 SocketLibevent::SocketLibevent()
     57     : socket_fd_(kInvalidSocket),
     58       read_buf_len_(0),
     59       write_buf_len_(0),
     60       waiting_connect_(false) {
     61 }
     62 
     63 SocketLibevent::~SocketLibevent() {
     64   Close();
     65 }
     66 
     67 int SocketLibevent::Open(int address_family) {
     68   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 
     83   if (SetNonBlocking(socket_fd_)) {
     84     int rv = MapSystemError(errno);
     85     Close();
     86     return rv;
     87   }
     88 
     89   return OK;
     90 }
     91 
     92 int SocketLibevent::AdoptConnectedSocket(SocketDescriptor socket,
     93                                          const SockaddrStorage& address) {
     94   DCHECK(thread_checker_.CalledOnValidThread());
     95   DCHECK_EQ(kInvalidSocket, socket_fd_);
     96 
     97   socket_fd_ = socket;
     98 
     99   if (SetNonBlocking(socket_fd_)) {
    100     int rv = MapSystemError(errno);
    101     Close();
    102     return rv;
    103   }
    104 
    105   SetPeerAddress(address);
    106   return OK;
    107 }
    108 
    109 SocketDescriptor SocketLibevent::ReleaseConnectedSocket() {
    110   StopWatchingAndCleanUp();
    111   SocketDescriptor socket_fd = socket_fd_;
    112   socket_fd_ = kInvalidSocket;
    113   return socket_fd;
    114 }
    115 
    116 int SocketLibevent::Bind(const SockaddrStorage& address) {
    117   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 
    129 int SocketLibevent::Listen(int backlog) {
    130   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 
    143 int SocketLibevent::Accept(scoped_ptr<SocketLibevent>* socket,
    144                            const CompletionCallback& callback) {
    145   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 
    167 int SocketLibevent::Connect(const SockaddrStorage& address,
    168                             const CompletionCallback& callback) {
    169   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 
    192 bool SocketLibevent::IsConnected() const {
    193   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 
    209 bool SocketLibevent::IsConnectedAndIdle() const {
    210   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 
    227 int SocketLibevent::Read(IOBuffer* buf,
    228                          int buf_len,
    229                          const CompletionCallback& callback) {
    230   DCHECK(thread_checker_.CalledOnValidThread());
    231   DCHECK_NE(kInvalidSocket, socket_fd_);
    232   DCHECK(!waiting_connect_);
    233   DCHECK(read_callback_.is_null());
    234   // 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 
    255 int SocketLibevent::Write(IOBuffer* buf,
    256                           int buf_len,
    257                           const CompletionCallback& callback) {
    258   DCHECK(thread_checker_.CalledOnValidThread());
    259   DCHECK_NE(kInvalidSocket, socket_fd_);
    260   DCHECK(!waiting_connect_);
    261   DCHECK(write_callback_.is_null());
    262   // 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 
    272 int SocketLibevent::WaitForWrite(IOBuffer* buf,
    273                                  int buf_len,
    274                                  const CompletionCallback& callback) {
    275   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 
    295 int SocketLibevent::GetLocalAddress(SockaddrStorage* address) const {
    296   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 
    304 int SocketLibevent::GetPeerAddress(SockaddrStorage* address) const {
    305   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 
    315 void SocketLibevent::SetPeerAddress(const SockaddrStorage& address) {
    316   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 
    328 bool SocketLibevent::HasPeerAddress() const {
    329   DCHECK(thread_checker_.CalledOnValidThread());
    330   return peer_address_ != NULL;
    331 }
    332 
    333 void SocketLibevent::Close() {
    334   DCHECK(thread_checker_.CalledOnValidThread());
    335 
    336   StopWatchingAndCleanUp();
    337 
    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   }
    343 }
    344 
    345 void SocketLibevent::OnFileCanReadWithoutBlocking(int fd) {
    346   DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
    347   if (!accept_callback_.is_null()) {
    348     AcceptCompleted();
    349   } else {  // !read_callback_.is_null()
    350     ReadCompleted();
    351   }
    352 }
    353 
    354 void SocketLibevent::OnFileCanWriteWithoutBlocking(int fd) {
    355   DCHECK(!write_callback_.is_null());
    356   if (waiting_connect_) {
    357     ConnectCompleted();
    358   } else {
    359     WriteCompleted();
    360   }
    361 }
    362 
    363 int SocketLibevent::DoAccept(scoped_ptr<SocketLibevent>* socket) {
    364   SockaddrStorage new_peer_address;
    365   int new_socket = HANDLE_EINTR(accept(socket_fd_,
    366                                        new_peer_address.addr,
    367                                        &new_peer_address.addr_len));
    368   if (new_socket < 0)
    369     return MapAcceptError(errno);
    370 
    371   scoped_ptr<SocketLibevent> accepted_socket(new SocketLibevent);
    372   int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
    373   if (rv != OK)
    374     return rv;
    375 
    376   *socket = accepted_socket.Pass();
    377   return OK;
    378 }
    379 
    380 void SocketLibevent::AcceptCompleted() {
    381   DCHECK(accept_socket_);
    382   int rv = DoAccept(accept_socket_);
    383   if (rv == ERR_IO_PENDING)
    384     return;
    385 
    386   bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
    387   DCHECK(ok);
    388   accept_socket_ = NULL;
    389   base::ResetAndReturn(&accept_callback_).Run(rv);
    390 }
    391 
    392 int SocketLibevent::DoConnect() {
    393   int rv = HANDLE_EINTR(connect(socket_fd_,
    394                                 peer_address_->addr,
    395                                 peer_address_->addr_len));
    396   DCHECK_GE(0, rv);
    397   return rv == 0 ? OK : MapConnectError(errno);
    398 }
    399 
    400 void SocketLibevent::ConnectCompleted() {
    401   // Get the error that connect() completed with.
    402   int os_error = 0;
    403   socklen_t len = sizeof(os_error);
    404   if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
    405     // TCPSocketLibevent expects errno to be set.
    406     errno = os_error;
    407   }
    408 
    409   int rv = MapConnectError(errno);
    410   if (rv == ERR_IO_PENDING)
    411     return;
    412 
    413   bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
    414   DCHECK(ok);
    415   waiting_connect_ = false;
    416   base::ResetAndReturn(&write_callback_).Run(rv);
    417 }
    418 
    419 int SocketLibevent::DoRead(IOBuffer* buf, int buf_len) {
    420   int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
    421   return rv >= 0 ? rv : MapSystemError(errno);
    422 }
    423 
    424 void SocketLibevent::ReadCompleted() {
    425   int rv = DoRead(read_buf_.get(), read_buf_len_);
    426   if (rv == ERR_IO_PENDING)
    427     return;
    428 
    429   bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
    430   DCHECK(ok);
    431   read_buf_ = NULL;
    432   read_buf_len_ = 0;
    433   base::ResetAndReturn(&read_callback_).Run(rv);
    434 }
    435 
    436 int SocketLibevent::DoWrite(IOBuffer* buf, int buf_len) {
    437   int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
    438   return rv >= 0 ? rv : MapSystemError(errno);
    439 }
    440 
    441 void SocketLibevent::WriteCompleted() {
    442   int rv = DoWrite(write_buf_.get(), write_buf_len_);
    443   if (rv == ERR_IO_PENDING)
    444     return;
    445 
    446   bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
    447   DCHECK(ok);
    448   write_buf_ = NULL;
    449   write_buf_len_ = 0;
    450   base::ResetAndReturn(&write_callback_).Run(rv);
    451 }
    452 
    453 void SocketLibevent::StopWatchingAndCleanUp() {
    454   bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
    455   DCHECK(ok);
    456   ok = read_socket_watcher_.StopWatchingFileDescriptor();
    457   DCHECK(ok);
    458   ok = write_socket_watcher_.StopWatchingFileDescriptor();
    459   DCHECK(ok);
    460 
    461   if (!accept_callback_.is_null()) {
    462     accept_socket_ = NULL;
    463     accept_callback_.Reset();
    464   }
    465 
    466   if (!read_callback_.is_null()) {
    467     read_buf_ = NULL;
    468     read_buf_len_ = 0;
    469     read_callback_.Reset();
    470   }
    471 
    472   if (!write_callback_.is_null()) {
    473     write_buf_ = NULL;
    474     write_buf_len_ = 0;
    475     write_callback_.Reset();
    476   }
    477 
    478   waiting_connect_ = false;
    479   peer_address_.reset();
    480 }
    481 
    482 }  // namespace net
    483