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"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/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.
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)uint16 ConvertFromNetEndian16(uint16 x) {
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(ARCH_CPU_LITTLE_ENDIAN)
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return (x << 8) | (x >> 8);
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return x;
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)uint16 ConvertToNetEndian16(uint16 x) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_LITTLE_ENDIAN)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (x << 8) | (x >> 8);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return x;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kIPv4AddressSize = 4;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kIPv6AddressSize = 16;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This structure is a platform-independent representation of a network address.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is a private format that we embed in PP_NetAddress_Private and is NOT part
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the stable Pepper API.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct NetAddress {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_valid;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_ipv6;  // if true, IPv6, otherwise IPv4.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16_t port;  // host order, not network order.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t flow_info;  // 0 for IPv4
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t scope_id;   // 0 for IPv4
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv4 addresses are 4 bytes. IPv6 are 16 bytes. Addresses are stored in net
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // order (big-endian), which only affects IPv6 addresses, which consist of 8
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 16-bit components. These will be byte-swapped on small-endian hosts.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t address[kIPv6AddressSize];
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure that sizeof(NetAddress) is the same for all compilers. This ensures
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the alignment is the same on both sides of the NaCl proxy, which is
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// important because we serialize and deserialize PP_NetAddress_Private by
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simply copying the raw bytes.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(NetAddress) == 28,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               NetAddress_different_for_compiler);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make sure the storage in |PP_NetAddress_Private| is big enough. (Do it here
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// since the data is opaque elsewhere.)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(reinterpret_cast<PP_NetAddress_Private*>(0)->data) >=
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sizeof(NetAddress),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               PP_NetAddress_Private_data_too_small);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t GetAddressSize(const NetAddress* net_addr) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->is_ipv6 ? kIPv6AddressSize : kIPv4AddressSize;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert to embedded struct if it has been initialized.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetAddress* ToNetAddress(PP_NetAddress_Private* addr) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!addr || addr->size != sizeof(NetAddress))
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<NetAddress*>(addr->data);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const NetAddress* ToNetAddress(const PP_NetAddress_Private* addr) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ToNetAddress(const_cast<PP_NetAddress_Private*>(addr));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initializes the NetAddress struct embedded in a PP_NetAddress_Private struct.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Zeroes the memory, so net_addr->is_valid == false.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetAddress* InitNetAddress(PP_NetAddress_Private* addr) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr->size = sizeof(NetAddress);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* net_addr = ToNetAddress(addr);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(net_addr);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(net_addr, 0, sizeof(NetAddress));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValid(const NetAddress* net_addr) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr && net_addr->is_valid;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_NetAddressFamily_Private GetFamily(const PP_NetAddress_Private* addr) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->is_ipv6 ?
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         PP_NETADDRESSFAMILY_PRIVATE_IPV6 : PP_NETADDRESSFAMILY_PRIVATE_IPV4;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint16_t GetPort(const PP_NetAddress_Private* addr) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->port;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool GetAddress(const PP_NetAddress_Private* addr,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   void* address,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   uint16_t address_size) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t net_addr_size = GetAddressSize(net_addr);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // address_size must be big enough.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_addr_size > address_size)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(address, net_addr->address, net_addr_size);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t GetScopeID(const PP_NetAddress_Private* addr) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(addr);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_addr->scope_id;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool AreHostsEqual(const PP_NetAddress_Private* addr1,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const PP_NetAddress_Private* addr2) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr1 = ToNetAddress(addr1);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr2 = ToNetAddress(addr2);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr1) || !IsValid(net_addr2))
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((net_addr1->is_ipv6 != net_addr2->is_ipv6) ||
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (net_addr1->flow_info != net_addr2->flow_info) ||
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (net_addr1->scope_id != net_addr2->scope_id))
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t net_addr_size = GetAddressSize(net_addr1);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < net_addr_size; i++) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_addr1->address[i] != net_addr2->address[i])
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return PP_FALSE;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool AreEqual(const PP_NetAddress_Private* addr1,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const PP_NetAddress_Private* addr2) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |AreHostsEqual()| will also validate the addresses and return false if
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either is invalid.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AreHostsEqual(addr1, addr2))
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AreHostsEqual has validated these net addresses.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr1 = ToNetAddress(addr1);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr2 = ToNetAddress(addr2);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_FromBool(net_addr1->port == net_addr2->port);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ConvertIPv4AddressToString(const NetAddress* net_addr,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool include_port) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string description = base::StringPrintf(
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "%u.%u.%u.%u",
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->address[0], net_addr->address[1],
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->address[2], net_addr->address[3]);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (include_port)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(&description, ":%u", net_addr->port);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return description;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Format an IPv6 address for human consumption, basically according to RFC
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5952.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If the scope is nonzero, it is appended to the address as "%<scope>" (this
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    is not in RFC 5952, but consistent with |getnameinfo()| on Linux and
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    Windows).
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If |include_port| is true, the address (possibly including the scope) is
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    enclosed in square brackets and ":<port>" is appended, i.e., the overall
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    format is "[<address>]:<port>".
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If the address is an IPv4 address embedded IPv6 (per RFC 4291), then the
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    mixed format is used, e.g., "::ffff:192.168.1.2". This is optional per RFC
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    5952, but consistent with |getnameinfo()|.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ConvertIPv6AddressToString(const NetAddress* net_addr,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool include_port) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string description(include_port ? "[" : "");
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint16_t* address16 =
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const uint16_t*>(net_addr->address);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv4 address embedded in IPv6.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address16[0] == 0 && address16[1] == 0 &&
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      address16[2] == 0 && address16[3] == 0 &&
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      address16[4] == 0 &&
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (address16[5] == 0 || address16[5] == 0xffff)) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &description,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        address16[5] == 0 ? "::%u.%u.%u.%u" : "::ffff:%u.%u.%u.%u",
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[12],
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[13],
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[14],
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_addr->address[15]);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "Real" IPv6 addresses.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find the first longest run of 0s (of length > 1), to collapse to "::".
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int longest_start = 0;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int longest_length = 0;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int curr_start = 0;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int curr_length = 0;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 8; i++) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (address16[i] != 0) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_length = 0;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!curr_length)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          curr_start = i;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        curr_length++;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (curr_length > longest_length) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          longest_start = curr_start;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          longest_length = curr_length;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool need_sep = false;  // Whether the next item needs a ':' to separate.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 8;) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (longest_length > 1 && i == longest_start) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        description.append("::");
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        need_sep = false;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i += longest_length;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        uint16_t v = ConvertFromNetEndian16(address16[i]);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringAppendF(&description, need_sep ? ":%x" : "%x", v);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        need_sep = true;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i++;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nonzero scopes, e.g., 123, are indicated by appending, e.g., "%123".
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_addr->scope_id != 0)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(&description, "%%%u", net_addr->scope_id);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (include_port)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringAppendF(&description, "]:%u", net_addr->port);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return description;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var Describe(PP_Module /*module*/,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const struct PP_NetAddress_Private* addr,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PP_Bool include_port) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str = NetAddressPrivateImpl::DescribeNetAddress(
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *addr, PP_ToBool(include_port));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (str.empty())
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_MakeUndefined();
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We must acquire the lock while accessing the VarTracker, which is part of
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the critical section of the proxy which may be accessed by other threads.
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyAutoLock lock;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StringVar::StringToPPVar(str);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool ReplacePort(const struct PP_NetAddress_Private* src_addr,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    uint16_t port,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    struct PP_NetAddress_Private* dest_addr) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* src_net_addr = ToNetAddress(src_addr);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(src_net_addr) || !dest_addr)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dest_addr->size = sizeof(NetAddress);  // make sure 'size' is valid.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* dest_net_addr = ToNetAddress(dest_addr);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *dest_net_addr = *src_net_addr;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dest_net_addr->port = port;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetAnyAddress(PP_Bool is_ipv6, PP_NetAddress_Private* addr) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (addr) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetAddress* net_addr = InitNetAddress(addr);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_valid = true;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_ipv6 = (is_ipv6 == PP_TRUE);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateFromIPv4Address(const uint8_t ip[4],
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint16_t port,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           struct PP_NetAddress_Private* addr) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (addr) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetAddress* net_addr = InitNetAddress(addr);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_valid = true;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_ipv6 = false;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->port = port;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(net_addr->address, ip, kIPv4AddressSize);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateFromIPv6Address(const uint8_t ip[16],
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint32_t scope_id,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           uint16_t port,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           struct PP_NetAddress_Private* addr) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (addr) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetAddress* net_addr = InitNetAddress(addr);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_valid = true;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->is_ipv6 = true;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->port = port;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_addr->scope_id = scope_id;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(net_addr->address, ip, kIPv6AddressSize);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PPB_NetAddress_Private_0_1 net_address_private_interface_0_1 = {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreEqual,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreHostsEqual,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Describe,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &ReplacePort,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAnyAddress
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PPB_NetAddress_Private_1_0 net_address_private_interface_1_0 = {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreEqual,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreHostsEqual,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Describe,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &ReplacePort,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAnyAddress,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetFamily,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetPort,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAddress
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PPB_NetAddress_Private_1_1 net_address_private_interface_1_1 = {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreEqual,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AreHostsEqual,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Describe,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &ReplacePort,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAnyAddress,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetFamily,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetPort,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetAddress,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetScopeID,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &CreateFromIPv4Address,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &CreateFromIPv6Address
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace thunk {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_0_1*
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetPPB_NetAddress_Private_0_1_Thunk() {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &net_address_private_interface_0_1;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_0*
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetPPB_NetAddress_Private_1_0_Thunk() {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &net_address_private_interface_1_0;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_1*
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetPPB_NetAddress_Private_1_1_Thunk() {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &net_address_private_interface_1_1;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace thunk
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For the NaCl target, all we need are the API functions and the thunk.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_NACL)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::ValidateNetAddress(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_NetAddress_Private& addr) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsValid(ToNetAddress(&addr));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::SockaddrToNetAddress(
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sockaddr* sa,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t sa_length,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_NetAddress_Private* addr) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!sa || sa_length == 0 || !addr)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our platform neutral format stores ports in host order, not net order,
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so convert them here.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* net_addr = InitNetAddress(addr);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (sa->sa_family) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AF_INET: {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct sockaddr_in* addr4 =
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const struct sockaddr_in*>(sa);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = false;
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      net_addr->port = ConvertFromNetEndian16(addr4->sin_port);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(net_addr->address, &addr4->sin_addr.s_addr, kIPv4AddressSize);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case AF_INET6: {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct sockaddr_in6* addr6 =
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const struct sockaddr_in6*>(sa);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = true;
439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      net_addr->port = ConvertFromNetEndian16(addr6->sin6_port);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->flow_info = addr6->sin6_flowinfo;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->scope_id = addr6->sin6_scope_id;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(net_addr->address, addr6->sin6_addr.s6_addr, kIPv6AddressSize);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // InitNetAddress sets net_addr->is_valid to false.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::IPEndPointToNetAddress(
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<unsigned char>& address,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_NetAddress_Private* addr) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!addr)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetAddress* net_addr = InitNetAddress(addr);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (address.size()) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kIPv4AddressSize: {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = false;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->port = static_cast<uint16_t>(port);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::copy(address.begin(), address.end(), net_addr->address);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case kIPv6AddressSize: {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_valid = true;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->is_ipv6 = true;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_addr->port = static_cast<uint16_t>(port);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::copy(address.begin(), address.end(), net_addr->address);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // InitNetAddress sets net_addr->is_valid to false.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetAddressPrivateImpl::NetAddressToIPEndPoint(
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_NetAddress_Private& addr,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<unsigned char>* address,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* port) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!address || !port)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(&addr);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *port = net_addr->port;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t address_size = GetAddressSize(net_addr);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  address->assign(&net_addr->address[0], &net_addr->address[address_size]);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_NACL)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NetAddressPrivateImpl::DescribeNetAddress(
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_NetAddress_Private& addr,
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool include_port) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(&addr);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsValid(net_addr))
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows, |NetAddressToString()| doesn't work in the sandbox. On Mac,
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the output isn't consistent with RFC 5952, at least on Mac OS 10.6:
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |getnameinfo()| collapses length-one runs of zeros (and also doesn't
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // display the scope).
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_addr->is_ipv6)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ConvertIPv6AddressToString(net_addr, include_port);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ConvertIPv4AddressToString(net_addr, include_port);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv4Address(
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const PP_NetAddress_IPv4& ipv4_addr,
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PP_NetAddress_Private* addr) {
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateFromIPv4Address(ipv4_addr.addr, ConvertFromNetEndian16(ipv4_addr.port),
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        addr);
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv6Address(
530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const PP_NetAddress_IPv6& ipv6_addr,
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PP_NetAddress_Private* addr) {
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CreateFromIPv6Address(ipv6_addr.addr, 0,
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        ConvertFromNetEndian16(ipv6_addr.port), addr);
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochPP_NetAddress_Family NetAddressPrivateImpl::GetFamilyFromNetAddressPrivate(
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const PP_NetAddress_Private& addr) {
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(&addr);
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsValid(net_addr))
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PP_NETADDRESS_FAMILY_UNSPECIFIED;
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return net_addr->is_ipv6 ? PP_NETADDRESS_FAMILY_IPV6 :
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             PP_NETADDRESS_FAMILY_IPV4;
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv4Address(
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   const PP_NetAddress_Private& addr,
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch   PP_NetAddress_IPv4* ipv4_addr) {
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ipv4_addr)
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(&addr);
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsValid(net_addr) || net_addr->is_ipv6)
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ipv4_addr->port = ConvertToNetEndian16(net_addr->port);
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  COMPILE_ASSERT(sizeof(ipv4_addr->addr) == kIPv4AddressSize,
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 mismatched_IPv4_address_size);
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  memcpy(ipv4_addr->addr, net_addr->address, kIPv4AddressSize);
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv6Address(
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const PP_NetAddress_Private& addr,
569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    PP_NetAddress_IPv6* ipv6_addr) {
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ipv6_addr)
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const NetAddress* net_addr = ToNetAddress(&addr);
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsValid(net_addr) || !net_addr->is_ipv6)
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ipv6_addr->port = ConvertToNetEndian16(net_addr->port);
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  COMPILE_ASSERT(sizeof(ipv6_addr->addr) == kIPv6AddressSize,
580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 mismatched_IPv6_address_size);
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  memcpy(ipv6_addr->addr, net_addr->address, kIPv6AddressSize);
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
587