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