Home | History | Annotate | Download | only in nacl_io
      1 // Copyright (c) 2013 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 "nacl_io/ossocket.h"
      6 #ifdef PROVIDES_SOCKET_API
      7 
      8 #include <errno.h>
      9 #include <string.h>
     10 
     11 #include "nacl_io/kernel_handle.h"
     12 #include "nacl_io/mount.h"
     13 #include "nacl_io/mount_node_socket.h"
     14 #include "nacl_io/pepper_interface.h"
     15 
     16 #include "ppapi/c/pp_resource.h"
     17 #include "ppapi/c/ppb_net_address.h"
     18 
     19 namespace nacl_io {
     20 
     21 MountNodeSocket::MountNodeSocket(Mount* mount)
     22     : MountNodeStream(mount),
     23       socket_resource_(0),
     24       local_addr_(0),
     25       remote_addr_(0),
     26       socket_flags_(0),
     27       last_errno_(0),
     28       keep_alive_(false) {
     29   memset(&linger_, 0, sizeof(linger_));
     30   SetType(S_IFSOCK);
     31 }
     32 
     33 MountNodeSocket::MountNodeSocket(Mount* mount, PP_Resource socket)
     34     : MountNodeStream(mount),
     35       socket_resource_(socket),
     36       local_addr_(0),
     37       remote_addr_(0),
     38       socket_flags_(0),
     39       last_errno_(0),
     40       keep_alive_(false) {
     41   memset(&linger_, 0, sizeof(linger_));
     42   SetType(S_IFSOCK);
     43   mount_->ppapi()->AddRefResource(socket_resource_);
     44 }
     45 
     46 void MountNodeSocket::Destroy() {
     47   if (socket_resource_)
     48     mount_->ppapi()->ReleaseResource(socket_resource_);
     49   if (local_addr_)
     50     mount_->ppapi()->ReleaseResource(local_addr_);
     51   if (remote_addr_)
     52     mount_->ppapi()->ReleaseResource(remote_addr_);
     53 
     54   socket_resource_ = 0;
     55   local_addr_ = 0;
     56   remote_addr_ = 0;
     57 }
     58 
     59 // Assume that |addr| and |out_addr| are non-NULL.
     60 Error MountNodeSocket::MMap(void* addr,
     61                             size_t length,
     62                             int prot,
     63                             int flags,
     64                             size_t offset,
     65                             void** out_addr) {
     66   return EACCES;
     67 }
     68 
     69 // Normal read/write operations on a Socket are equivalent to
     70 // send/recv with a flag value of 0.
     71 Error MountNodeSocket::Read(const HandleAttr& attr,
     72                             void* buf,
     73                             size_t count,
     74                             int* out_bytes) {
     75   return Recv(attr, buf, count, 0, out_bytes);
     76 }
     77 
     78 Error MountNodeSocket::Write(const HandleAttr& attr,
     79                              const void* buf,
     80                              size_t count,
     81                              int* out_bytes) {
     82   return Send(attr, buf, count, 0, out_bytes);
     83 }
     84 
     85 
     86 NetAddressInterface* MountNodeSocket::NetInterface() {
     87   if (mount_->ppapi() == NULL)
     88     return NULL;
     89 
     90   return mount_->ppapi()->GetNetAddressInterface();
     91 }
     92 
     93 TCPSocketInterface* MountNodeSocket::TCPInterface() {
     94   if (mount_->ppapi() == NULL)
     95     return NULL;
     96 
     97   return mount_->ppapi()->GetTCPSocketInterface();
     98 }
     99 
    100 UDPSocketInterface* MountNodeSocket::UDPInterface() {
    101   if (mount_->ppapi() == NULL)
    102     return NULL;
    103 
    104   return mount_->ppapi()->GetUDPSocketInterface();
    105 }
    106 
    107 PP_Resource MountNodeSocket::SockAddrToResource(const struct sockaddr* addr,
    108                                                 socklen_t len) {
    109   if (NULL == addr)
    110     return 0;
    111 
    112   if (AF_INET == addr->sa_family) {
    113     PP_NetAddress_IPv4 addr4;
    114     const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(addr);
    115 
    116     if (len != sizeof(sockaddr_in))
    117       return 0;
    118 
    119     memset(&addr4, 0, sizeof(addr4));
    120 
    121     addr4.port = sin->sin_port;
    122     memcpy(addr4.addr, &sin->sin_addr, sizeof(addr4.addr));
    123     return mount_->ppapi()->GetNetAddressInterface()->CreateFromIPv4Address(
    124         mount_->ppapi()->GetInstance(), &addr4);
    125   }
    126 
    127   if (AF_INET6 == addr->sa_family) {
    128     PP_NetAddress_IPv6 addr6;
    129     const sockaddr_in6* sin = reinterpret_cast<const sockaddr_in6*>(addr);
    130 
    131     if (len != sizeof(sockaddr_in6))
    132       return 0;
    133 
    134     memset(&addr6, 0, sizeof(addr6));
    135 
    136     addr6.port = sin->sin6_port;
    137     memcpy(addr6.addr, &sin->sin6_addr, sizeof(addr6.addr));
    138     return mount_->ppapi()->GetNetAddressInterface()->CreateFromIPv6Address(
    139         mount_->ppapi()->GetInstance(), &addr6);
    140   }
    141   return 0;
    142 }
    143 
    144 
    145 socklen_t MountNodeSocket::ResourceToSockAddr(PP_Resource addr,
    146                                               socklen_t len,
    147                                               struct sockaddr* out_addr) {
    148   if (0 == addr)
    149     return 0;
    150 
    151   PP_NetAddress_IPv4 ipv4;
    152   PP_NetAddress_IPv6 ipv6;
    153 
    154   if (PP_TRUE == NetInterface()->DescribeAsIPv4Address(addr, &ipv4)) {
    155     sockaddr_in addr4;
    156     addr4.sin_family = AF_INET;
    157     addr4.sin_port = ipv4.port;
    158     memcpy(&addr4.sin_addr, ipv4.addr, sizeof(ipv4.addr));
    159     memcpy(out_addr, &addr4, len);
    160 
    161     // Returns required size not copied size like getpeername/getsockname.
    162     return sizeof(sockaddr_in);
    163   }
    164 
    165   if (PP_TRUE == NetInterface()->DescribeAsIPv6Address(addr, &ipv6)) {
    166     sockaddr_in6 addr6;
    167     addr6.sin6_family = AF_INET6;
    168     addr6.sin6_port = ipv6.port;
    169     memcpy(&addr6.sin6_addr, ipv6.addr, sizeof(ipv6.addr));
    170     memcpy(out_addr, &addr6, len);
    171 
    172     // Returns required size not copied size like getpeername/getsockname.
    173     return sizeof(sockaddr_in6);
    174   }
    175 
    176   return 0;
    177 }
    178 
    179 bool MountNodeSocket::IsEquivalentAddress(PP_Resource addr1,
    180                                           PP_Resource addr2) {
    181   if (addr1 == addr2)
    182     return true;
    183 
    184   char data1[sizeof(sockaddr_in6)];
    185   char data2[sizeof(sockaddr_in6)];
    186 
    187   sockaddr* saddr1 = reinterpret_cast<sockaddr*>(data1);
    188   sockaddr* saddr2 = reinterpret_cast<sockaddr*>(data2);
    189 
    190   socklen_t len1 = ResourceToSockAddr(addr1, sizeof(data1), saddr1);
    191   socklen_t len2 = ResourceToSockAddr(addr2, sizeof(data2), saddr2);
    192 
    193   if (len1 != len2)
    194     return false;
    195 
    196   return memcmp(saddr1, saddr2, len1) == 0;
    197 }
    198 
    199 Error MountNodeSocket::Accept(const HandleAttr& attr,
    200                               PP_Resource* new_sock,
    201                               struct sockaddr* addr,
    202                               socklen_t* len) {
    203   return ENOSYS;
    204 }
    205 
    206 Error MountNodeSocket::Connect(const HandleAttr& attr,
    207                                const struct sockaddr* addr,
    208                                socklen_t len) {
    209   if (len < 1)
    210     return EINVAL;
    211 
    212   if (NULL == addr)
    213     return EFAULT;
    214 
    215   return EOPNOTSUPP;
    216 }
    217 
    218 Error MountNodeSocket::Listen(int backlog) {
    219   return EOPNOTSUPP;
    220 }
    221 
    222 Error MountNodeSocket::GetSockOpt(int lvl,
    223                                   int optname,
    224                                   void* optval,
    225                                   socklen_t* len) {
    226   if (lvl != SOL_SOCKET)
    227     return ENOPROTOOPT;
    228 
    229   AUTO_LOCK(node_lock_);
    230 
    231   int value = 0;
    232   socklen_t value_len = 0;
    233   void* value_ptr = NULL;
    234 
    235   switch (optname) {
    236     case SO_REUSEADDR:
    237       // SO_REUSEADDR is effectively always on since we can't
    238       // disable it with PPAPI sockets.
    239       value = 1;
    240       value_ptr = &value;
    241       value_len = sizeof(value);
    242       break;
    243     case SO_LINGER:
    244       value_ptr = &linger_;
    245       value_len = sizeof(linger_);
    246       break;
    247     case SO_KEEPALIVE:
    248       value = keep_alive_;
    249       value_ptr = &value;
    250       value_len = sizeof(value);
    251       break;
    252     case SO_ERROR:
    253       value_ptr = &last_errno_;
    254       value_len = sizeof(last_errno_);
    255       last_errno_ = 0;
    256       break;
    257     default:
    258       return ENOPROTOOPT;
    259   }
    260 
    261 
    262   int copy_bytes = std::min(value_len, *len);
    263   memcpy(optval, value_ptr, copy_bytes);
    264   *len = value_len;
    265   return 0;
    266 }
    267 
    268 Error MountNodeSocket::SetSockOpt(int lvl,
    269                                   int optname,
    270                                   const void* optval,
    271                                   socklen_t len) {
    272   if (lvl != SOL_SOCKET)
    273     return ENOPROTOOPT;
    274 
    275   AUTO_LOCK(node_lock_);
    276 
    277   switch (optname) {
    278     case SO_REUSEADDR: {
    279       // SO_REUSEADDR is effectivly always on since we can't
    280       // disable it with PPAPI sockets. Just return success
    281       // here regardless.
    282       if (len < sizeof(int))
    283         return EINVAL;
    284       return 0;
    285     }
    286     case SO_LINGER: {
    287       // Not supported by the PPAPI interface but we preserve
    288       // the settings and pretend to support it.
    289       if (len < sizeof(struct linger))
    290         return EINVAL;
    291       struct linger new_linger = *static_cast<const linger*>(optval);
    292       // Don't allow setting linger to be enabled until we
    293       // implement the required synchronous shutdown()/close().
    294       // TODO(sbc): remove this after http://crbug.com/312401
    295       // gets fixed.
    296       if (new_linger.l_onoff != 0)
    297         return EINVAL;
    298       linger_ = new_linger;
    299       return 0;
    300     }
    301     case SO_KEEPALIVE: {
    302       // Not supported by the PPAPI interface but we preserve
    303       // the flag and pretend to support it.
    304       if (len < sizeof(int))
    305         return EINVAL;
    306       int value = *static_cast<const int*>(optval);
    307       keep_alive_ = value != 0;
    308       return 0;
    309     }
    310   }
    311 
    312   return ENOPROTOOPT;
    313 }
    314 
    315 Error MountNodeSocket::Bind(const struct sockaddr* addr, socklen_t len) {
    316   return EINVAL;
    317 }
    318 
    319 Error MountNodeSocket::Recv(const HandleAttr& attr,
    320                             void* buf,
    321                             size_t len,
    322                             int flags,
    323                             int* out_len) {
    324   return RecvFrom(attr, buf, len, flags, NULL, 0, out_len);
    325 }
    326 
    327 Error MountNodeSocket::RecvFrom(const HandleAttr& attr,
    328                                 void* buf,
    329                                 size_t len,
    330                                 int flags,
    331                                 struct sockaddr* src_addr,
    332                                 socklen_t* addrlen,
    333                                 int* out_len) {
    334   PP_Resource addr = 0;
    335   Error err = RecvHelper(attr, buf, len, flags, &addr, out_len);
    336   if (0 == err && 0 != addr) {
    337     if (src_addr)
    338       *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr);
    339 
    340     mount_->ppapi()->ReleaseResource(addr);
    341   }
    342 
    343   return err;
    344 }
    345 
    346 Error MountNodeSocket::RecvHelper(const HandleAttr& attr,
    347                                   void* buf,
    348                                   size_t len,
    349                                   int flags,
    350                                   PP_Resource* addr,
    351                                   int* out_len) {
    352   if (0 == socket_resource_)
    353     return EBADF;
    354 
    355   int ms = read_timeout_;
    356   if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
    357     ms = 0;
    358 
    359   //TODO(noelallen) BUG=295177
    360   //For UDP we should support filtering packets when using connect
    361   EventListenerLock wait(GetEventEmitter());
    362   Error err = wait.WaitOnEvent(POLLIN, ms);
    363 
    364   // Timeout is treated as a would block for sockets.
    365   if (ETIMEDOUT == err)
    366     return EWOULDBLOCK;
    367 
    368   if (err)
    369     return err;
    370 
    371   err = Recv_Locked(buf, len, addr, out_len);
    372 
    373   // We must have read from then inputbuffer, so Q up some receive work.
    374   if ((err == 0) && *out_len)
    375     QueueInput();
    376   return err;
    377 }
    378 
    379 Error MountNodeSocket::Send(const HandleAttr& attr,
    380                             const void* buf,
    381                             size_t len,
    382                             int flags,
    383                             int* out_len) {
    384   return SendHelper(attr, buf, len, flags, remote_addr_, out_len);
    385 }
    386 
    387 Error MountNodeSocket::SendTo(const HandleAttr& attr,
    388                               const void* buf,
    389                               size_t len,
    390                               int flags,
    391                               const struct sockaddr* dest_addr,
    392                               socklen_t addrlen,
    393                               int* out_len) {
    394   if ((NULL == dest_addr) && (0 == remote_addr_))
    395     return EDESTADDRREQ;
    396 
    397   PP_Resource addr = SockAddrToResource(dest_addr, addrlen);
    398   if (0 == addr)
    399     return EINVAL;
    400 
    401   Error err = SendHelper(attr, buf, len, flags, addr, out_len);
    402   mount_->ppapi()->ReleaseResource(addr);
    403   return err;
    404 }
    405 
    406 Error MountNodeSocket::SendHelper(const HandleAttr& attr,
    407                                   const void* buf,
    408                                   size_t len,
    409                                   int flags,
    410                                   PP_Resource addr,
    411                                   int* out_len) {
    412   if (0 == socket_resource_)
    413     return EBADF;
    414 
    415   if (0 == addr)
    416     return ENOTCONN;
    417 
    418   int ms = write_timeout_;
    419   if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
    420     ms = 0;
    421 
    422   EventListenerLock wait(GetEventEmitter());
    423   Error err = wait.WaitOnEvent(POLLOUT, ms);
    424 
    425   // Timeout is treated as a would block for sockets.
    426   if (ETIMEDOUT == err)
    427     return EWOULDBLOCK;
    428 
    429   if (err)
    430     return err;
    431 
    432   err = Send_Locked(buf, len, addr, out_len);
    433 
    434   // We must have added to the output buffer, so Q up some transmit work.
    435   if ((err == 0) && *out_len)
    436     QueueOutput();
    437   return err;
    438 }
    439 
    440 void MountNodeSocket::SetError_Locked(int pp_error_num) {
    441   SetStreamFlags(SSF_ERROR | SSF_CLOSED);
    442   ClearStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
    443   last_errno_ = PPErrorToErrno(pp_error_num);
    444 }
    445 
    446 Error MountNodeSocket::Shutdown(int how) {
    447   return EOPNOTSUPP;
    448 }
    449 
    450 
    451 Error MountNodeSocket::GetPeerName(struct sockaddr* addr, socklen_t* len) {
    452   if (NULL == addr || NULL == len)
    453     return EFAULT;
    454 
    455   AUTO_LOCK(node_lock_);
    456   if (remote_addr_ != 0) {
    457     *len = ResourceToSockAddr(remote_addr_, *len, addr);
    458     return 0;
    459   }
    460 
    461   return ENOTCONN;
    462 }
    463 
    464 Error MountNodeSocket::GetSockName(struct sockaddr* addr, socklen_t* len) {
    465   if (NULL == addr || NULL == len)
    466     return EFAULT;
    467 
    468   AUTO_LOCK(node_lock_);
    469   if (local_addr_ == 0) {
    470     // getsockname succeeds even if the socket is not bound. In this case,
    471     // just return address 0, port 0.
    472     memset(addr, 0, *len);
    473     return 0;
    474   }
    475 
    476   *len = ResourceToSockAddr(local_addr_, *len, addr);
    477   return 0;
    478 }
    479 
    480 }  // namespace nacl_io
    481 
    482 #endif  // PROVIDES_SOCKET_API
    483