This source file includes following definitions.
- ConvertFromNetEndian16
- ConvertToNetEndian16
- GetAddressSize
- ToNetAddress
- ToNetAddress
- InitNetAddress
- IsValid
- GetFamily
- GetPort
- GetAddress
- GetScopeID
- AreHostsEqual
- AreEqual
- ConvertIPv4AddressToString
- ConvertIPv6AddressToString
- Describe
- ReplacePort
- GetAnyAddress
- CreateFromIPv4Address
- CreateFromIPv6Address
- GetPPB_NetAddress_Private_0_1_Thunk
- GetPPB_NetAddress_Private_1_0_Thunk
- GetPPB_NetAddress_Private_1_1_Thunk
- ValidateNetAddress
- SockaddrToNetAddress
- IPEndPointToNetAddress
- NetAddressToIPEndPoint
- DescribeNetAddress
- CreateNetAddressPrivateFromIPv4Address
- CreateNetAddressPrivateFromIPv6Address
- GetFamilyFromNetAddressPrivate
- DescribeNetAddressPrivateAsIPv4Address
- DescribeNetAddressPrivateAsIPv6Address
#include "ppapi/shared_impl/private/net_address_private_impl.h"
#if defined(OS_WIN)
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#elif defined(OS_POSIX) && !defined(OS_NACL)
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#endif
#include <string.h>
#include <string>
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/thunk.h"
#if defined(OS_MACOSX)
#define s6_addr16 __u6_addr.__u6_addr16
#endif
#if defined(OS_WIN)
typedef ADDRESS_FAMILY sa_family_t;
#define s6_addr16 u.Word
#define ntohs(x) _byteswap_ushort(x)
#define htons(x) _byteswap_ushort(x)
#endif
namespace ppapi {
namespace {
uint16 ConvertFromNetEndian16(uint16 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return (x << 8) | (x >> 8);
#else
return x;
#endif
}
uint16 ConvertToNetEndian16(uint16 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return (x << 8) | (x >> 8);
#else
return x;
#endif
}
static const size_t kIPv4AddressSize = 4;
static const size_t kIPv6AddressSize = 16;
struct NetAddress {
bool is_valid;
bool is_ipv6;
uint16_t port;
int32_t flow_info;
int32_t scope_id;
uint8_t address[kIPv6AddressSize];
};
COMPILE_ASSERT(sizeof(NetAddress) == 28,
NetAddress_different_for_compiler);
COMPILE_ASSERT(sizeof(reinterpret_cast<PP_NetAddress_Private*>(0)->data) >=
sizeof(NetAddress),
PP_NetAddress_Private_data_too_small);
size_t GetAddressSize(const NetAddress* net_addr) {
return net_addr->is_ipv6 ? kIPv6AddressSize : kIPv4AddressSize;
}
NetAddress* ToNetAddress(PP_NetAddress_Private* addr) {
if (!addr || addr->size != sizeof(NetAddress))
return NULL;
return reinterpret_cast<NetAddress*>(addr->data);
}
const NetAddress* ToNetAddress(const PP_NetAddress_Private* addr) {
return ToNetAddress(const_cast<PP_NetAddress_Private*>(addr));
}
NetAddress* InitNetAddress(PP_NetAddress_Private* addr) {
addr->size = sizeof(NetAddress);
NetAddress* net_addr = ToNetAddress(addr);
DCHECK(net_addr);
memset(net_addr, 0, sizeof(NetAddress));
return net_addr;
}
bool IsValid(const NetAddress* net_addr) {
return net_addr && net_addr->is_valid;
}
PP_NetAddressFamily_Private GetFamily(const PP_NetAddress_Private* addr) {
const NetAddress* net_addr = ToNetAddress(addr);
if (!IsValid(net_addr))
return PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED;
return net_addr->is_ipv6 ?
PP_NETADDRESSFAMILY_PRIVATE_IPV6 : PP_NETADDRESSFAMILY_PRIVATE_IPV4;
}
uint16_t GetPort(const PP_NetAddress_Private* addr) {
const NetAddress* net_addr = ToNetAddress(addr);
if (!IsValid(net_addr))
return 0;
return net_addr->port;
}
PP_Bool GetAddress(const PP_NetAddress_Private* addr,
void* address,
uint16_t address_size) {
const NetAddress* net_addr = ToNetAddress(addr);
if (!IsValid(net_addr))
return PP_FALSE;
size_t net_addr_size = GetAddressSize(net_addr);
if (net_addr_size > address_size)
return PP_FALSE;
memcpy(address, net_addr->address, net_addr_size);
return PP_TRUE;
}
uint32_t GetScopeID(const PP_NetAddress_Private* addr) {
const NetAddress* net_addr = ToNetAddress(addr);
if (!IsValid(net_addr))
return 0;
return net_addr->scope_id;
}
PP_Bool AreHostsEqual(const PP_NetAddress_Private* addr1,
const PP_NetAddress_Private* addr2) {
const NetAddress* net_addr1 = ToNetAddress(addr1);
const NetAddress* net_addr2 = ToNetAddress(addr2);
if (!IsValid(net_addr1) || !IsValid(net_addr2))
return PP_FALSE;
if ((net_addr1->is_ipv6 != net_addr2->is_ipv6) ||
(net_addr1->flow_info != net_addr2->flow_info) ||
(net_addr1->scope_id != net_addr2->scope_id))
return PP_FALSE;
size_t net_addr_size = GetAddressSize(net_addr1);
for (size_t i = 0; i < net_addr_size; i++) {
if (net_addr1->address[i] != net_addr2->address[i])
return PP_FALSE;
}
return PP_TRUE;
}
PP_Bool AreEqual(const PP_NetAddress_Private* addr1,
const PP_NetAddress_Private* addr2) {
if (!AreHostsEqual(addr1, addr2))
return PP_FALSE;
const NetAddress* net_addr1 = ToNetAddress(addr1);
const NetAddress* net_addr2 = ToNetAddress(addr2);
return PP_FromBool(net_addr1->port == net_addr2->port);
}
std::string ConvertIPv4AddressToString(const NetAddress* net_addr,
bool include_port) {
std::string description = base::StringPrintf(
"%u.%u.%u.%u",
net_addr->address[0], net_addr->address[1],
net_addr->address[2], net_addr->address[3]);
if (include_port)
base::StringAppendF(&description, ":%u", net_addr->port);
return description;
}
std::string ConvertIPv6AddressToString(const NetAddress* net_addr,
bool include_port) {
std::string description(include_port ? "[" : "");
const uint16_t* address16 =
reinterpret_cast<const uint16_t*>(net_addr->address);
if (address16[0] == 0 && address16[1] == 0 &&
address16[2] == 0 && address16[3] == 0 &&
address16[4] == 0 &&
(address16[5] == 0 || address16[5] == 0xffff)) {
base::StringAppendF(
&description,
address16[5] == 0 ? "::%u.%u.%u.%u" : "::ffff:%u.%u.%u.%u",
net_addr->address[12],
net_addr->address[13],
net_addr->address[14],
net_addr->address[15]);
} else {
int longest_start = 0;
int longest_length = 0;
int curr_start = 0;
int curr_length = 0;
for (int i = 0; i < 8; i++) {
if (address16[i] != 0) {
curr_length = 0;
} else {
if (!curr_length)
curr_start = i;
curr_length++;
if (curr_length > longest_length) {
longest_start = curr_start;
longest_length = curr_length;
}
}
}
bool need_sep = false;
for (int i = 0; i < 8;) {
if (longest_length > 1 && i == longest_start) {
description.append("::");
need_sep = false;
i += longest_length;
} else {
uint16_t v = ConvertFromNetEndian16(address16[i]);
base::StringAppendF(&description, need_sep ? ":%x" : "%x", v);
need_sep = true;
i++;
}
}
}
if (net_addr->scope_id != 0)
base::StringAppendF(&description, "%%%u", net_addr->scope_id);
if (include_port)
base::StringAppendF(&description, "]:%u", net_addr->port);
return description;
}
PP_Var Describe(PP_Module ,
const struct PP_NetAddress_Private* addr,
PP_Bool include_port) {
std::string str = NetAddressPrivateImpl::DescribeNetAddress(
*addr, PP_ToBool(include_port));
if (str.empty())
return PP_MakeUndefined();
ProxyAutoLock lock;
return StringVar::StringToPPVar(str);
}
PP_Bool ReplacePort(const struct PP_NetAddress_Private* src_addr,
uint16_t port,
struct PP_NetAddress_Private* dest_addr) {
const NetAddress* src_net_addr = ToNetAddress(src_addr);
if (!IsValid(src_net_addr) || !dest_addr)
return PP_FALSE;
dest_addr->size = sizeof(NetAddress);
NetAddress* dest_net_addr = ToNetAddress(dest_addr);
*dest_net_addr = *src_net_addr;
dest_net_addr->port = port;
return PP_TRUE;
}
void GetAnyAddress(PP_Bool is_ipv6, PP_NetAddress_Private* addr) {
if (addr) {
NetAddress* net_addr = InitNetAddress(addr);
net_addr->is_valid = true;
net_addr->is_ipv6 = (is_ipv6 == PP_TRUE);
}
}
void CreateFromIPv4Address(const uint8_t ip[4],
uint16_t port,
struct PP_NetAddress_Private* addr) {
if (addr) {
NetAddress* net_addr = InitNetAddress(addr);
net_addr->is_valid = true;
net_addr->is_ipv6 = false;
net_addr->port = port;
memcpy(net_addr->address, ip, kIPv4AddressSize);
}
}
void CreateFromIPv6Address(const uint8_t ip[16],
uint32_t scope_id,
uint16_t port,
struct PP_NetAddress_Private* addr) {
if (addr) {
NetAddress* net_addr = InitNetAddress(addr);
net_addr->is_valid = true;
net_addr->is_ipv6 = true;
net_addr->port = port;
net_addr->scope_id = scope_id;
memcpy(net_addr->address, ip, kIPv6AddressSize);
}
}
const PPB_NetAddress_Private_0_1 net_address_private_interface_0_1 = {
&AreEqual,
&AreHostsEqual,
&Describe,
&ReplacePort,
&GetAnyAddress
};
const PPB_NetAddress_Private_1_0 net_address_private_interface_1_0 = {
&AreEqual,
&AreHostsEqual,
&Describe,
&ReplacePort,
&GetAnyAddress,
&GetFamily,
&GetPort,
&GetAddress
};
const PPB_NetAddress_Private_1_1 net_address_private_interface_1_1 = {
&AreEqual,
&AreHostsEqual,
&Describe,
&ReplacePort,
&GetAnyAddress,
&GetFamily,
&GetPort,
&GetAddress,
&GetScopeID,
&CreateFromIPv4Address,
&CreateFromIPv6Address
};
}
namespace thunk {
PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_0_1*
GetPPB_NetAddress_Private_0_1_Thunk() {
return &net_address_private_interface_0_1;
}
PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_0*
GetPPB_NetAddress_Private_1_0_Thunk() {
return &net_address_private_interface_1_0;
}
PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_1*
GetPPB_NetAddress_Private_1_1_Thunk() {
return &net_address_private_interface_1_1;
}
}
#if !defined(OS_NACL)
bool NetAddressPrivateImpl::ValidateNetAddress(
const PP_NetAddress_Private& addr) {
return IsValid(ToNetAddress(&addr));
}
bool NetAddressPrivateImpl::SockaddrToNetAddress(
const sockaddr* sa,
uint32_t sa_length,
PP_NetAddress_Private* addr) {
if (!sa || sa_length == 0 || !addr)
return false;
NetAddress* net_addr = InitNetAddress(addr);
switch (sa->sa_family) {
case AF_INET: {
const struct sockaddr_in* addr4 =
reinterpret_cast<const struct sockaddr_in*>(sa);
net_addr->is_valid = true;
net_addr->is_ipv6 = false;
net_addr->port = ConvertFromNetEndian16(addr4->sin_port);
memcpy(net_addr->address, &addr4->sin_addr.s_addr, kIPv4AddressSize);
break;
}
case AF_INET6: {
const struct sockaddr_in6* addr6 =
reinterpret_cast<const struct sockaddr_in6*>(sa);
net_addr->is_valid = true;
net_addr->is_ipv6 = true;
net_addr->port = ConvertFromNetEndian16(addr6->sin6_port);
net_addr->flow_info = addr6->sin6_flowinfo;
net_addr->scope_id = addr6->sin6_scope_id;
memcpy(net_addr->address, addr6->sin6_addr.s6_addr, kIPv6AddressSize);
break;
}
default:
return false;
}
return true;}
bool NetAddressPrivateImpl::IPEndPointToNetAddress(
const std::vector<unsigned char>& address,
int port,
PP_NetAddress_Private* addr) {
if (!addr)
return false;
NetAddress* net_addr = InitNetAddress(addr);
switch (address.size()) {
case kIPv4AddressSize: {
net_addr->is_valid = true;
net_addr->is_ipv6 = false;
net_addr->port = static_cast<uint16_t>(port);
std::copy(address.begin(), address.end(), net_addr->address);
break;
}
case kIPv6AddressSize: {
net_addr->is_valid = true;
net_addr->is_ipv6 = true;
net_addr->port = static_cast<uint16_t>(port);
std::copy(address.begin(), address.end(), net_addr->address);
break;
}
default:
return false;
}
return true;
}
bool NetAddressPrivateImpl::NetAddressToIPEndPoint(
const PP_NetAddress_Private& addr,
std::vector<unsigned char>* address,
int* port) {
if (!address || !port)
return false;
const NetAddress* net_addr = ToNetAddress(&addr);
if (!IsValid(net_addr))
return false;
*port = net_addr->port;
size_t address_size = GetAddressSize(net_addr);
address->assign(&net_addr->address[0], &net_addr->address[address_size]);
return true;
}
#endif
std::string NetAddressPrivateImpl::DescribeNetAddress(
const PP_NetAddress_Private& addr,
bool include_port) {
const NetAddress* net_addr = ToNetAddress(&addr);
if (!IsValid(net_addr))
return std::string();
if (net_addr->is_ipv6)
return ConvertIPv6AddressToString(net_addr, include_port);
return ConvertIPv4AddressToString(net_addr, include_port);
}
void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv4Address(
const PP_NetAddress_IPv4& ipv4_addr,
PP_NetAddress_Private* addr) {
CreateFromIPv4Address(ipv4_addr.addr, ConvertFromNetEndian16(ipv4_addr.port),
addr);
}
void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv6Address(
const PP_NetAddress_IPv6& ipv6_addr,
PP_NetAddress_Private* addr) {
CreateFromIPv6Address(ipv6_addr.addr, 0,
ConvertFromNetEndian16(ipv6_addr.port), addr);
}
PP_NetAddress_Family NetAddressPrivateImpl::GetFamilyFromNetAddressPrivate(
const PP_NetAddress_Private& addr) {
const NetAddress* net_addr = ToNetAddress(&addr);
if (!IsValid(net_addr))
return PP_NETADDRESS_FAMILY_UNSPECIFIED;
return net_addr->is_ipv6 ? PP_NETADDRESS_FAMILY_IPV6 :
PP_NETADDRESS_FAMILY_IPV4;
}
bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv4Address(
const PP_NetAddress_Private& addr,
PP_NetAddress_IPv4* ipv4_addr) {
if (!ipv4_addr)
return false;
const NetAddress* net_addr = ToNetAddress(&addr);
if (!IsValid(net_addr) || net_addr->is_ipv6)
return false;
ipv4_addr->port = ConvertToNetEndian16(net_addr->port);
COMPILE_ASSERT(sizeof(ipv4_addr->addr) == kIPv4AddressSize,
mismatched_IPv4_address_size);
memcpy(ipv4_addr->addr, net_addr->address, kIPv4AddressSize);
return true;
}
bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv6Address(
const PP_NetAddress_Private& addr,
PP_NetAddress_IPv6* ipv6_addr) {
if (!ipv6_addr)
return false;
const NetAddress* net_addr = ToNetAddress(&addr);
if (!IsValid(net_addr) || !net_addr->is_ipv6)
return false;
ipv6_addr->port = ConvertToNetEndian16(net_addr->port);
COMPILE_ASSERT(sizeof(ipv6_addr->addr) == kIPv6AddressSize,
mismatched_IPv6_address_size);
memcpy(ipv6_addr->addr, net_addr->address, kIPv6AddressSize);
return true;
}
}