15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/socket_node.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/ossocket.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <errno.h>
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <string.h>
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/filesystem.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/pepper_interface.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ppapi/c/pp_resource.h"
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ppapi/c/ppb_net_address.h"
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace nacl_io {
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SocketNode::SocketNode(Filesystem* filesystem)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : StreamNode(filesystem),
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      socket_resource_(0),
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      local_addr_(0),
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      remote_addr_(0),
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      socket_flags_(0),
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      last_errno_(0),
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      keep_alive_(false) {
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  memset(&linger_, 0, sizeof(linger_));
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SetType(S_IFSOCK);
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SocketNode::SocketNode(Filesystem* filesystem, PP_Resource socket)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : StreamNode(filesystem),
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      socket_resource_(socket),
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      local_addr_(0),
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      remote_addr_(0),
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      socket_flags_(0),
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      last_errno_(0),
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      keep_alive_(false) {
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  memset(&linger_, 0, sizeof(linger_));
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SetType(S_IFSOCK);
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  filesystem_->ppapi()->AddRefResource(socket_resource_);
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SocketNode::Destroy() {
483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (socket_resource_)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    filesystem_->ppapi()->ReleaseResource(socket_resource_);
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (local_addr_)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    filesystem_->ppapi()->ReleaseResource(local_addr_);
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (remote_addr_)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    filesystem_->ppapi()->ReleaseResource(remote_addr_);
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  socket_resource_ = 0;
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  local_addr_ = 0;
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  remote_addr_ = 0;
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Assume that |addr| and |out_addr| are non-NULL.
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::MMap(void* addr,
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       size_t length,
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       int prot,
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       int flags,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       size_t offset,
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       void** out_addr) {
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return EACCES;
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Normal read/write operations on a Socket are equivalent to
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// send/recv with a flag value of 0.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::Read(const HandleAttr& attr,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       void* buf,
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       size_t count,
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       int* out_bytes) {
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return Recv(attr, buf, count, 0, out_bytes);
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::Write(const HandleAttr& attr,
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        const void* buf,
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        size_t count,
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        int* out_bytes) {
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return Send(attr, buf, count, 0, out_bytes);
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NetAddressInterface* SocketNode::NetInterface() {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (filesystem_->ppapi() == NULL)
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return filesystem_->ppapi()->GetNetAddressInterface();
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TCPSocketInterface* SocketNode::TCPInterface() {
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (filesystem_->ppapi() == NULL)
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return filesystem_->ppapi()->GetTCPSocketInterface();
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)UDPSocketInterface* SocketNode::UDPInterface() {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (filesystem_->ppapi() == NULL)
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return filesystem_->ppapi()->GetUDPSocketInterface();
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PP_Resource SocketNode::SockAddrToResource(const struct sockaddr* addr,
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           socklen_t len) {
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == addr)
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return 0;
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (AF_INET == addr->sa_family) {
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    PP_NetAddress_IPv4 addr4;
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(addr);
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (len != sizeof(sockaddr_in))
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return 0;
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    memset(&addr4, 0, sizeof(addr4));
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    addr4.port = sin->sin_port;
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    memcpy(addr4.addr, &sin->sin_addr, sizeof(addr4.addr));
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return filesystem_->ppapi()
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ->GetNetAddressInterface()
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ->CreateFromIPv4Address(filesystem_->ppapi()->GetInstance(), &addr4);
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (AF_INET6 == addr->sa_family) {
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    PP_NetAddress_IPv6 addr6;
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const sockaddr_in6* sin = reinterpret_cast<const sockaddr_in6*>(addr);
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (len != sizeof(sockaddr_in6))
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return 0;
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    memset(&addr6, 0, sizeof(addr6));
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    addr6.port = sin->sin6_port;
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    memcpy(addr6.addr, &sin->sin6_addr, sizeof(addr6.addr));
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return filesystem_->ppapi()
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ->GetNetAddressInterface()
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ->CreateFromIPv6Address(filesystem_->ppapi()->GetInstance(), &addr6);
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)socklen_t SocketNode::ResourceToSockAddr(PP_Resource addr,
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         socklen_t len,
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         struct sockaddr* out_addr) {
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (0 == addr)
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return 0;
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PP_NetAddress_IPv4 ipv4;
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PP_NetAddress_IPv6 ipv6;
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (PP_TRUE == NetInterface()->DescribeAsIPv4Address(addr, &ipv4)) {
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    sockaddr_in addr4;
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    addr4.sin_family = AF_INET;
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    addr4.sin_port = ipv4.port;
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    memcpy(&addr4.sin_addr, ipv4.addr, sizeof(ipv4.addr));
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(out_addr, &addr4,
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           std::min(len, static_cast<socklen_t>(sizeof(addr4))));
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Returns required size not copied size like getpeername/getsockname.
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return sizeof(addr4);
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (PP_TRUE == NetInterface()->DescribeAsIPv6Address(addr, &ipv6)) {
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    sockaddr_in6 addr6;
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    addr6.sin6_family = AF_INET6;
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    addr6.sin6_port = ipv6.port;
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    memcpy(&addr6.sin6_addr, ipv6.addr, sizeof(ipv6.addr));
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    memcpy(out_addr, &addr6,
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           std::min(len, static_cast<socklen_t>(sizeof(addr6))));
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Returns required size not copied size like getpeername/getsockname.
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return sizeof(addr6);
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SocketNode::IsEquivalentAddress(PP_Resource addr1, PP_Resource addr2) {
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (addr1 == addr2)
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return true;
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char data1[sizeof(sockaddr_in6)];
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char data2[sizeof(sockaddr_in6)];
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  sockaddr* saddr1 = reinterpret_cast<sockaddr*>(data1);
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  sockaddr* saddr2 = reinterpret_cast<sockaddr*>(data2);
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  socklen_t len1 = ResourceToSockAddr(addr1, sizeof(data1), saddr1);
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  socklen_t len2 = ResourceToSockAddr(addr2, sizeof(data2), saddr2);
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (len1 != len2)
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return memcmp(saddr1, saddr2, len1) == 0;
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::Accept(const HandleAttr& attr,
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         PP_Resource* new_sock,
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         struct sockaddr* addr,
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         socklen_t* len) {
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return ENOSYS;
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::Connect(const HandleAttr& attr,
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const struct sockaddr* addr,
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          socklen_t len) {
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (len < 1)
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EINVAL;
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (NULL == addr)
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EFAULT;
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return EOPNOTSUPP;
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Error SocketNode::Listen(int backlog) {
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return EOPNOTSUPP;
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::GetSockOpt(int lvl,
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             int optname,
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             void* optval,
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             socklen_t* len) {
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (lvl != SOL_SOCKET)
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOPROTOOPT;
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AUTO_LOCK(node_lock_);
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int value = 0;
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  socklen_t value_len = 0;
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void* value_ptr = NULL;
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch (optname) {
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case SO_REUSEADDR:
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // SO_REUSEADDR is effectively always on since we can't
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // disable it with PPAPI sockets.
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value = 1;
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_ptr = &value;
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_len = sizeof(value);
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case SO_LINGER:
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_ptr = &linger_;
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_len = sizeof(linger_);
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case SO_KEEPALIVE:
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value = keep_alive_;
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_ptr = &value;
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_len = sizeof(value);
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case SO_ERROR:
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_ptr = &last_errno_;
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_len = sizeof(last_errno_);
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      last_errno_ = 0;
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    default:
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return ENOPROTOOPT;
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int copy_bytes = std::min(value_len, *len);
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  memcpy(optval, value_ptr, copy_bytes);
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *len = value_len;
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return 0;
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::SetSockOpt(int lvl,
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             int optname,
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const void* optval,
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             socklen_t len) {
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  size_t buflen = static_cast<size_t>(len);
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (lvl != SOL_SOCKET)
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOPROTOOPT;
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AUTO_LOCK(node_lock_);
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch (optname) {
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case SO_REUSEADDR: {
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // SO_REUSEADDR is effectivly always on since we can't
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // disable it with PPAPI sockets. Just return success
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // here regardless.
285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (buflen < sizeof(int))
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return EINVAL;
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return 0;
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case SO_LINGER: {
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Not supported by the PPAPI interface but we preserve
2911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // the settings and pretend to support it.
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (buflen < sizeof(struct linger))
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return EINVAL;
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      struct linger new_linger = *static_cast<const linger*>(optval);
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Don't allow setting linger to be enabled until we
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // implement the required synchronous shutdown()/close().
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // TODO(sbc): remove this after http://crbug.com/312401
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // gets fixed.
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (new_linger.l_onoff != 0)
3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return EINVAL;
3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      linger_ = new_linger;
3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return 0;
3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case SO_KEEPALIVE: {
3051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Not supported by the PPAPI interface but we preserve
3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // the flag and pretend to support it.
307c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (buflen < sizeof(int))
3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return EINVAL;
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int value = *static_cast<const int*>(optval);
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      keep_alive_ = value != 0;
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return 0;
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return ENOPROTOOPT;
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::Bind(const struct sockaddr* addr, socklen_t len) {
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return EINVAL;
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::Recv(const HandleAttr& attr,
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       void* buf,
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       size_t len,
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       int flags,
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       int* out_len) {
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return RecvFrom(attr, buf, len, flags, NULL, 0, out_len);
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::RecvFrom(const HandleAttr& attr,
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           void* buf,
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           size_t len,
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           int flags,
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           struct sockaddr* src_addr,
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           socklen_t* addrlen,
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           int* out_len) {
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource addr = 0;
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = RecvHelper(attr, buf, len, flags, &addr, out_len);
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (0 == err && 0 != addr) {
34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (src_addr)
34168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr);
34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    filesystem_->ppapi()->ReleaseResource(addr);
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return err;
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::RecvHelper(const HandleAttr& attr,
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             void* buf,
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             size_t len,
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             int flags,
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             PP_Resource* addr,
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             int* out_len) {
35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (0 == socket_resource_)
35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return EBADF;
35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms = read_timeout_;
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
36068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms = 0;
36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(noelallen) BUG=295177
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // For UDP we should support filtering packets when using connect
36468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventListenerLock wait(GetEventEmitter());
36568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Error err = wait.WaitOnEvent(POLLIN, ms);
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Timeout is treated as a would block for sockets.
36868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (ETIMEDOUT == err)
36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return EWOULDBLOCK;
37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
37168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (err)
37268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return err;
37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
37468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  err = Recv_Locked(buf, len, addr, out_len);
37568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
37668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // We must have read from then inputbuffer, so Q up some receive work.
37768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if ((err == 0) && *out_len)
37868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    QueueInput();
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return err;
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::Send(const HandleAttr& attr,
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const void* buf,
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       size_t len,
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       int flags,
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       int* out_len) {
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return SendHelper(attr, buf, len, flags, remote_addr_, out_len);
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::SendTo(const HandleAttr& attr,
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const void* buf,
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         size_t len,
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         int flags,
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const struct sockaddr* dest_addr,
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         socklen_t addrlen,
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         int* out_len) {
39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if ((NULL == dest_addr) && (0 == remote_addr_))
39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return EDESTADDRREQ;
39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PP_Resource addr = SockAddrToResource(dest_addr, addrlen);
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (0 == addr)
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return EINVAL;
40368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = SendHelper(attr, buf, len, flags, addr, out_len);
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  filesystem_->ppapi()->ReleaseResource(addr);
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return err;
40768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::SendHelper(const HandleAttr& attr,
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const void* buf,
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             size_t len,
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             int flags,
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             PP_Resource addr,
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             int* out_len) {
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (0 == socket_resource_)
41668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return EBADF;
41768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (0 == addr)
41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return ENOTCONN;
42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms = write_timeout_;
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms = 0;
42468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventListenerLock wait(GetEventEmitter());
42668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Error err = wait.WaitOnEvent(POLLOUT, ms);
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Timeout is treated as a would block for sockets.
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (ETIMEDOUT == err)
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return EWOULDBLOCK;
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (err)
43368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return err;
43468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  err = Send_Locked(buf, len, addr, out_len);
43668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // We must have added to the output buffer, so Q up some transmit work.
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if ((err == 0) && *out_len)
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    QueueOutput();
44068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return err;
44168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SocketNode::SetError_Locked(int pp_error_num) {
44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetStreamFlags(SSF_ERROR | SSF_CLOSED);
44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ClearStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  last_errno_ = PPErrorToErrno(pp_error_num);
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
44946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Error SocketNode::Shutdown(int how) {
45046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return EOPNOTSUPP;
45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::GetPeerName(struct sockaddr* addr, socklen_t* len) {
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (NULL == addr || NULL == len)
4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EFAULT;
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AUTO_LOCK(node_lock_);
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (remote_addr_ != 0) {
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *len = ResourceToSockAddr(remote_addr_, *len, addr);
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return 0;
4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return ENOTCONN;
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error SocketNode::GetSockName(struct sockaddr* addr, socklen_t* len) {
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (NULL == addr || NULL == len)
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EFAULT;
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AUTO_LOCK(node_lock_);
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (local_addr_ == 0) {
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // getsockname succeeds even if the socket is not bound. In this case,
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // just return address 0, port 0.
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    memset(addr, 0, *len);
4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return 0;
4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *len = ResourceToSockAddr(local_addr_, *len, addr);
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 0;
4803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace nacl_io
4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif  // PROVIDES_SOCKET_API
485