net_address_private_impl.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/private/net_address_private_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ws2tcpip.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) && !defined(OS_NACL)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <arpa/inet.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/private/ppb_net_address_private.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/thunk.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a bit evil, but it's standard operating procedure for |s6_addr|....
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define s6_addr16 __u6_addr.__u6_addr16
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The type of |sockaddr::sa_family|.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ADDRESS_FAMILY sa_family_t;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define s6_addr16 u.Word
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ntohs(x) _byteswap_ushort(x)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define htons(x) _byteswap_ushort(x)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_WIN)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The net address interface doesn't have a normal C -> C++ thunk since it
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// doesn't actually have any proxy wrapping or associated objects; it's just a
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// call into base. So we implement the entire interface here, using the thunk
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// namespace so it magically gets hooked up in the proper places.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define our own net-host-net conversion, rather than reuse the one in
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base/sys_byteorder.h, to simplify the NaCl port. NaCl has no byte swap
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// primitives.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint16 ConvertNetEndian16(uint16 x) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_LITTLE_ENDIAN)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (x << 8) | (x >> 8);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return x;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kIPv4AddressSize = 4;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kIPv6AddressSize = 16;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This structure is a platform-independent representation of a network address.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is a private format that we embed in PP_NetAddress_Private and is NOT part
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the stable Pepper API.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct NetAddress {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_valid;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_ipv6;  // if true, IPv6, otherwise IPv4.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16_t port;  // host order, not network order.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t flow_info;  // 0 for IPv4
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t scope_id;   // 0 for IPv4
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv4 addresses are 4 bytes. IPv6 are 16 bytes. Addresses are stored in net
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // order (big-endian), which only affects IPv6 addresses, which consist of 8
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 16-bit components. These will be byte-swapped on small-endian hosts.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t address[kIPv6AddressSize];
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure that sizeof(NetAddress) is the same for all compilers. This ensures
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the alignment is the same on both sides of the NaCl proxy, which is
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// important because we serialize and deserialize PP_NetAddress_Private by
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simply copying the raw bytes.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(NetAddress) == 28,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               NetAddress_different_for_compiler);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure the storage in |PP_NetAddress_Private| is big enough. (Do it here
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// since the data is opaque elsewhere.)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(reinterpret_cast<PP_NetAddress_Private*>(0)->data) >=
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sizeof(NetAddress),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               PP_NetAddress_Private_data_too_small);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t GetAddressSize(const NetAddress* net_addr) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->is_ipv6 ? kIPv6AddressSize : kIPv4AddressSize;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert to embedded struct if it has been initialized.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetAddress* ToNetAddress(PP_NetAddress_Private* addr) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!addr || addr->size != sizeof(NetAddress))
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<NetAddress*>(addr->data);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const NetAddress* ToNetAddress(const PP_NetAddress_Private* addr) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ToNetAddress(const_cast<PP_NetAddress_Private*>(addr));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initializes the NetAddress struct embedded in a PP_NetAddress_Private struct.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Zeroes the memory, so net_addr->is_valid == false.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetAddress* InitNetAddress(PP_NetAddress_Private* addr) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr->size = sizeof(NetAddress);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* net_addr = ToNetAddress(addr);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(net_addr);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(net_addr, 0, sizeof(NetAddress));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValid(const NetAddress* net_addr) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr && net_addr->is_valid;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_NetAddressFamily_Private GetFamily(const PP_NetAddress_Private* addr) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_NETADDRESSFAMILY_UNSPECIFIED;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->is_ipv6 ?
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         PP_NETADDRESSFAMILY_IPV6 : PP_NETADDRESSFAMILY_IPV4;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint16_t GetPort(const PP_NetAddress_Private* addr) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->port;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool GetAddress(const PP_NetAddress_Private* addr,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   void* address,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   uint16_t address_size) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t net_addr_size = GetAddressSize(net_addr);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // address_size must be big enough.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_addr_size > address_size)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(address, net_addr->address, net_addr_size);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t GetScopeID(const PP_NetAddress_Private* addr) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->scope_id;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool AreHostsEqual(const PP_NetAddress_Private* addr1,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const PP_NetAddress_Private* addr2) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr1 = ToNetAddress(addr1);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr2 = ToNetAddress(addr2);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr1) || !IsValid(net_addr2))
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((net_addr1->is_ipv6 != net_addr2->is_ipv6) ||
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (net_addr1->flow_info != net_addr2->flow_info) ||
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (net_addr1->scope_id != net_addr2->scope_id))
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t net_addr_size = GetAddressSize(net_addr1);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < net_addr_size; i++) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_addr1->address[i] != net_addr2->address[i])
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return PP_FALSE;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool AreEqual(const PP_NetAddress_Private* addr1,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const PP_NetAddress_Private* addr2) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |AreHostsEqual()| will also validate the addresses and return false if
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either is invalid.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AreHostsEqual(addr1, addr2))
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AreHostsEqual has validated these net addresses.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr1 = ToNetAddress(addr1);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr2 = ToNetAddress(addr2);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_FromBool(net_addr1->port == net_addr2->port);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ConvertIPv4AddressToString(const NetAddress* net_addr,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool include_port) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string description = base::StringPrintf(
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "%u.%u.%u.%u",
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->address[0], net_addr->address[1],
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->address[2], net_addr->address[3]);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (include_port)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(&description, ":%u", net_addr->port);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return description;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Format an IPv6 address for human consumption, basically according to RFC
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5952.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If the scope is nonzero, it is appended to the address as "%<scope>" (this
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    is not in RFC 5952, but consistent with |getnameinfo()| on Linux and
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    Windows).
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If |include_port| is true, the address (possibly including the scope) is
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    enclosed in square brackets and ":<port>" is appended, i.e., the overall
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    format is "[<address>]:<port>".
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If the address is an IPv4 address embedded IPv6 (per RFC 4291), then the
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    mixed format is used, e.g., "::ffff:192.168.1.2". This is optional per RFC
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    5952, but consistent with |getnameinfo()|.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ConvertIPv6AddressToString(const NetAddress* net_addr,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool include_port) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string description(include_port ? "[" : "");
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint16_t* address16 =
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const uint16_t*>(net_addr->address);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv4 address embedded in IPv6.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address16[0] == 0 && address16[1] == 0 &&
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      address16[2] == 0 && address16[3] == 0 &&
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      address16[4] == 0 &&
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (address16[5] == 0 || address16[5] == 0xffff)) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &description,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        address16[5] == 0 ? "::%u.%u.%u.%u" : "::ffff:%u.%u.%u.%u",
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[12],
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[13],
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[14],
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[15]);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "Real" IPv6 addresses.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find the first longest run of 0s (of length > 1), to collapse to "::".
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int longest_start = 0;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int longest_length = 0;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int curr_start = 0;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int curr_length = 0;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 8; i++) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (address16[i] != 0) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_length = 0;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!curr_length)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          curr_start = i;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_length++;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (curr_length > longest_length) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          longest_start = curr_start;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          longest_length = curr_length;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool need_sep = false;  // Whether the next item needs a ':' to separate.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 8;) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (longest_length > 1 && i == longest_start) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        description.append("::");
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        need_sep = false;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i += longest_length;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint16_t v = ConvertNetEndian16(address16[i]);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringAppendF(&description, need_sep ? ":%x" : "%x", v);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        need_sep = true;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i++;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nonzero scopes, e.g., 123, are indicated by appending, e.g., "%123".
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_addr->scope_id != 0)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(&description, "%%%u", net_addr->scope_id);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (include_port)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(&description, "]:%u", net_addr->port);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return description;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var Describe(PP_Module /*module*/,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const struct PP_NetAddress_Private* addr,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PP_Bool include_port) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str = NetAddressPrivateImpl::DescribeNetAddress(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *addr, PP_ToBool(include_port));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (str.empty())
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_MakeUndefined();
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We must acquire the lock while accessing the VarTracker, which is part of
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the critical section of the proxy which may be accessed by other threads.
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyAutoLock lock;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StringVar::StringToPPVar(str);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool ReplacePort(const struct PP_NetAddress_Private* src_addr,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    uint16_t port,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    struct PP_NetAddress_Private* dest_addr) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* src_net_addr = ToNetAddress(src_addr);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(src_net_addr) || !dest_addr)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dest_addr->size = sizeof(NetAddress);  // make sure 'size' is valid.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* dest_net_addr = ToNetAddress(dest_addr);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *dest_net_addr = *src_net_addr;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dest_net_addr->port = port;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetAnyAddress(PP_Bool is_ipv6, PP_NetAddress_Private* addr) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (addr) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetAddress* net_addr = InitNetAddress(addr);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_valid = true;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_ipv6 = (is_ipv6 == PP_TRUE);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateFromIPv4Address(const uint8_t ip[4],
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint16_t port,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           struct PP_NetAddress_Private* addr) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (addr) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetAddress* net_addr = InitNetAddress(addr);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_valid = true;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_ipv6 = false;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->port = port;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(net_addr->address, ip, kIPv4AddressSize);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateFromIPv6Address(const uint8_t ip[16],
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint32_t scope_id,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint16_t port,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           struct PP_NetAddress_Private* addr) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (addr) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetAddress* net_addr = InitNetAddress(addr);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_valid = true;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_ipv6 = true;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->port = port;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->scope_id = scope_id;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(net_addr->address, ip, kIPv6AddressSize);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PPB_NetAddress_Private_0_1 net_address_private_interface_0_1 = {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreEqual,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreHostsEqual,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Describe,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &ReplacePort,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAnyAddress
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PPB_NetAddress_Private_1_0 net_address_private_interface_1_0 = {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreEqual,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreHostsEqual,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Describe,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &ReplacePort,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAnyAddress,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetFamily,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetPort,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAddress
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PPB_NetAddress_Private_1_1 net_address_private_interface_1_1 = {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreEqual,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreHostsEqual,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Describe,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &ReplacePort,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAnyAddress,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetFamily,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetPort,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAddress,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetScopeID,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &CreateFromIPv4Address,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &CreateFromIPv6Address
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace thunk {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_0_1*
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetPPB_NetAddress_Private_0_1_Thunk() {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &net_address_private_interface_0_1;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_0*
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetPPB_NetAddress_Private_1_0_Thunk() {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &net_address_private_interface_1_0;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_1*
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetPPB_NetAddress_Private_1_1_Thunk() {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &net_address_private_interface_1_1;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace thunk
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For the NaCl target, all we need are the API functions and the thunk.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_NACL)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PP_NetAddress_Private NetAddressPrivateImpl::kInvalidNetAddress = { 0 };
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::ValidateNetAddress(
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_NetAddress_Private& addr) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsValid(ToNetAddress(&addr));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::SockaddrToNetAddress(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sockaddr* sa,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t sa_length,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_NetAddress_Private* addr) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!sa || sa_length == 0 || !addr)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our platform neutral format stores ports in host order, not net order,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so convert them here.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* net_addr = InitNetAddress(addr);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (sa->sa_family) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AF_INET: {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct sockaddr_in* addr4 =
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const struct sockaddr_in*>(sa);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = false;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->port = ConvertNetEndian16(addr4->sin_port);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(net_addr->address, &addr4->sin_addr.s_addr, kIPv4AddressSize);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AF_INET6: {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct sockaddr_in6* addr6 =
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const struct sockaddr_in6*>(sa);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = true;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->port = ConvertNetEndian16(addr6->sin6_port);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->flow_info = addr6->sin6_flowinfo;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->scope_id = addr6->sin6_scope_id;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(net_addr->address, addr6->sin6_addr.s6_addr, kIPv6AddressSize);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // InitNetAddress sets net_addr->is_valid to false.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::IPEndPointToNetAddress(
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<unsigned char>& address,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_NetAddress_Private* addr) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!addr)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* net_addr = InitNetAddress(addr);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (address.size()) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kIPv4AddressSize: {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = false;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->port = static_cast<uint16_t>(port);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::copy(address.begin(), address.end(), net_addr->address);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kIPv6AddressSize: {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = true;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->port = static_cast<uint16_t>(port);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::copy(address.begin(), address.end(), net_addr->address);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // InitNetAddress sets net_addr->is_valid to false.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::NetAddressToIPEndPoint(
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_NetAddress_Private& addr,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<unsigned char>* address,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* port) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!address || !port)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(&addr);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *port = net_addr->port;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t address_size = GetAddressSize(net_addr);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  address->assign(&net_addr->address[0], &net_addr->address[address_size]);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_NACL)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NetAddressPrivateImpl::DescribeNetAddress(
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_NetAddress_Private& addr,
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool include_port) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(&addr);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows, |NetAddressToString()| doesn't work in the sandbox. On Mac,
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the output isn't consistent with RFC 5952, at least on Mac OS 10.6:
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |getnameinfo()| collapses length-one runs of zeros (and also doesn't
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // display the scope).
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_addr->is_ipv6)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ConvertIPv6AddressToString(net_addr, include_port);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ConvertIPv4AddressToString(net_addr, include_port);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
515