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