// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/socket.h"

#if SB_API_VERSION >= 4

#include <arpa/inet.h>
#include <ifaddrs.h>
#include <linux/if.h>
#include <linux/if_addr.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

#include "starboard/byte_swap.h"
#include "starboard/log.h"
#include "starboard/memory.h"
#include "starboard/shared/posix/socket_internal.h"

namespace sbposix = starboard::shared::posix;

namespace {

// TODO: Move this constant to socket.h.
const int kIPv6AddressSize = 16;

bool IsAnyAddress(const SbSocketAddress& address) {
  switch (address.type) {
    case kSbSocketAddressTypeIpv4:
      return (address.address[0] == 0 && address.address[1] == 0 &&
              address.address[2] == 0 && address.address[3] == 0);
#if SB_HAS(IPV6)
    case kSbSocketAddressTypeIpv6: {
      bool found_nonzero = false;
      for (std::size_t i = 0; i != kIPv6AddressSize; ++i) {
        found_nonzero |= (address.address[i] != 0);
      }
      return !found_nonzero;
    }
#endif
    default:
      SB_NOTREACHED() << "Invalid address type " << address.type;
      break;
  }

  return false;
}

template <typename T, int source_size>
void CopyIntoObjectFromArray(T* out_destination,
                             const unsigned char(&source)[source_size]) {
  SB_COMPILE_ASSERT(sizeof(T) <= source_size, destination_is_too_small);
  SbMemoryCopy(out_destination, source, sizeof(T));
}

bool GetPotentialMatch(const sockaddr* input_addr,
                       const in_addr** out_interface_addr) {
  if (!input_addr || input_addr->sa_family != AF_INET) {
    *out_interface_addr = NULL;
    return false;
  }

  const sockaddr_in* v4input_addr =
      reinterpret_cast<const sockaddr_in*>(input_addr);
  *out_interface_addr = &(v4input_addr->sin_addr);
  return true;
}

bool GetPotentialMatch(const sockaddr* input_addr,
                       const in6_addr** out_interface_addr) {
  if (!input_addr || input_addr->sa_family != AF_INET6) {
    *out_interface_addr = NULL;
    return false;
  }

  const sockaddr_in6* v6input_addr =
      reinterpret_cast<const sockaddr_in6*>(input_addr);
  *out_interface_addr = &(v6input_addr->sin6_addr);
  return true;
}

template <typename in_addr_type>
bool GetNetmaskForInterfaceAddress(const SbSocketAddress& interface_address,
                                   SbSocketAddress* out_netmask) {
  SB_DCHECK((interface_address.type == kSbSocketAddressTypeIpv4) ||
            (interface_address.type == kSbSocketAddressTypeIpv6));
  struct ifaddrs* interface_addrs = NULL;

  int retval = getifaddrs(&interface_addrs);
  if (retval != 0) {
    return false;
  }

  in_addr_type to_match;
  CopyIntoObjectFromArray(&to_match, interface_address.address);

  bool found_netmask = false;
  for (struct ifaddrs* interface = interface_addrs; interface != NULL;
       interface = interface->ifa_next) {
    if (!(IFF_UP & interface->ifa_flags) ||
        (IFF_LOOPBACK & interface->ifa_flags)) {
      continue;
    }

    const in_addr_type* potential_match;
    if (!GetPotentialMatch(interface->ifa_addr, &potential_match))
      continue;

    if (SbMemoryCompare(&to_match, potential_match, sizeof(in_addr_type)) !=
        0) {
      continue;
    }

    sbposix::SockAddr sock_addr;
    sock_addr.FromSockaddr(interface->ifa_netmask);
    if (sock_addr.ToSbSocketAddress(out_netmask)) {
      found_netmask = true;
      break;
    }
  }

  freeifaddrs(interface_addrs);

  return found_netmask;
}

bool GetNetMaskForInterfaceAddress(const SbSocketAddress& interface_address,
                                   SbSocketAddress* out_netmask) {
  SB_DCHECK(out_netmask);

  switch (interface_address.type) {
    case kSbSocketAddressTypeIpv4:
      return GetNetmaskForInterfaceAddress<in_addr>(interface_address,
                                                    out_netmask);
#if SB_HAS(IPV6)
    case kSbSocketAddressTypeIpv6:
      return GetNetmaskForInterfaceAddress<in6_addr>(interface_address,
                                                     out_netmask);
#endif
    default:
      SB_NOTREACHED() << "Invalid address type " << interface_address.type;
      break;
  }

  return false;
}

bool FindIPv4InterfaceIP(SbSocketAddress* out_interface_ip,
                         SbSocketAddress* out_netmask) {
  if (out_interface_ip == NULL) {
    SB_NOTREACHED() << "out_interface_ip must be specified";
    return false;
  }
  struct ifaddrs* interface_addrs = NULL;

  int retval = getifaddrs(&interface_addrs);
  if (retval != 0) {
    return false;
  }

  bool success = false;
  for (struct ifaddrs* interface = interface_addrs; interface != NULL;
       interface = interface->ifa_next) {
    if (!(IFF_UP & interface->ifa_flags) ||
        (IFF_LOOPBACK & interface->ifa_flags)) {
      continue;
    }

    const struct sockaddr* addr = interface->ifa_addr;
    const struct sockaddr* netmask = interface->ifa_netmask;
    if (!addr || !netmask || (addr->sa_family != AF_INET)) {
      // IPv4 addresses only.
      continue;
    }

    sbposix::SockAddr sock_addr;
    sock_addr.FromSockaddr(addr);
    if (sock_addr.ToSbSocketAddress(out_interface_ip)) {
      if (out_netmask) {
        sbposix::SockAddr netmask_addr;
        netmask_addr.FromSockaddr(netmask);
        if (!netmask_addr.ToSbSocketAddress(out_netmask)) {
          continue;
        }
      }

      success = true;
      break;
    }
  }

  freeifaddrs(interface_addrs);

  return success;
}

#if SB_HAS(IPV6)
bool IsUniqueLocalAddress(const unsigned char ip[16]) {
  // Unique Local Addresses are in fd08::/8.
  return ip[0] == 0xfd && ip[1] == 0x08;
}

bool FindIPv6InterfaceIP(SbSocketAddress* out_interface_ip,
                         SbSocketAddress* out_netmask) {
  if (!out_interface_ip) {
    SB_NOTREACHED() << "out_interface_ip must be specified";
    return false;
  }
  struct ifaddrs* interface_addrs = NULL;

  int retval = getifaddrs(&interface_addrs);
  if (retval != 0) {
    return false;
  }

  int max_scope_interface_value = -1;

  bool ip_found = false;
  SbSocketAddress temp_interface_ip;
  SbSocketAddress temp_netmask;

  for (struct ifaddrs* interface = interface_addrs; interface != NULL;
       interface = interface->ifa_next) {
    if (!(IFF_UP & interface->ifa_flags) ||
        (IFF_LOOPBACK & interface->ifa_flags)) {
      continue;
    }

    const struct sockaddr* addr = interface->ifa_addr;
    const struct sockaddr* netmask = interface->ifa_netmask;
    if (!addr || !netmask || addr->sa_family != AF_INET6) {
      // IPv6 addresses only.
      continue;
    }

    const in6_addr* potential_match;
    if (!GetPotentialMatch(interface->ifa_addr, &potential_match))
      continue;

    // Check the IP for loopback again, just in case flags were incorrect.
    if (IN6_IS_ADDR_LOOPBACK(potential_match) ||
        IN6_IS_ADDR_LINKLOCAL(potential_match)) {
      continue;
    }

    const sockaddr_in6* v6addr =
        reinterpret_cast<const sockaddr_in6*>(interface->ifa_addr);
    if (!v6addr) {
      continue;
    }

    int current_interface_scope = v6addr->sin6_scope_id;

    if (IsUniqueLocalAddress(v6addr->sin6_addr.s6_addr)) {
      // ULAs have global scope, but not globally routable.  So prefer
      // non ULA addresses with global scope by adjusting their "scope"
      current_interface_scope -= 1;
    }

    if (current_interface_scope <= max_scope_interface_value) {
      continue;
    }
    max_scope_interface_value = current_interface_scope;

    sbposix::SockAddr sock_addr;
    sock_addr.FromSockaddr(addr);
    if (sock_addr.ToSbSocketAddress(&temp_interface_ip)) {
      if (netmask) {
        sbposix::SockAddr netmask_addr;
        netmask_addr.FromSockaddr(netmask);
        if (!netmask_addr.ToSbSocketAddress(&temp_netmask)) {
          continue;
        }
      }

      ip_found = true;
    }
  }

  freeifaddrs(interface_addrs);

  if (!ip_found) {
    return false;
  }

  SbMemoryCopy(out_interface_ip, &temp_interface_ip, sizeof(SbSocketAddress));
  if (out_netmask != NULL) {
    SbMemoryCopy(out_netmask, &temp_netmask, sizeof(SbSocketAddress));
  }

  return true;
}
#endif

bool FindInterfaceIP(const SbSocketAddressType type,
                     SbSocketAddress* out_interface_ip,
                     SbSocketAddress* out_netmask) {
  switch (type) {
    case kSbSocketAddressTypeIpv4:
      return FindIPv4InterfaceIP(out_interface_ip, out_netmask);
#if SB_HAS(IPV6)
    case kSbSocketAddressTypeIpv6:
      return FindIPv6InterfaceIP(out_interface_ip, out_netmask);
#endif
    default:
      SB_NOTREACHED() << "Invalid socket address type " << type;
  }

  return false;
}

bool FindSourceAddressForDestination(const SbSocketAddress& destination,
                                     SbSocketAddress* out_source_address) {
  SbSocket socket = SbSocketCreate(destination.type, kSbSocketProtocolUdp);
  if (!SbSocketIsValid(socket)) {
    return false;
  }

  SbSocketError connect_retval = SbSocketConnect(socket, &destination);
  if (connect_retval != kSbSocketOk) {
    bool socket_destroyed = SbSocketDestroy(socket);
    SB_DCHECK(socket_destroyed);
    return false;
  }

  bool success = SbSocketGetLocalAddress(socket, out_source_address);
  bool socket_destroyed = SbSocketDestroy(socket);
  SB_DCHECK(socket_destroyed);
  return success;
}

}  // namespace

bool SbSocketGetInterfaceAddress(const SbSocketAddress* const destination,
                                 SbSocketAddress* out_source_address,
                                 SbSocketAddress* out_netmask) {
  if (!out_source_address) {
    return false;
  }

  if (destination == NULL) {
#if SB_HAS(IPV6)
    // Return either a v4 or a v6 address.  Per spec.
    return (FindIPv4InterfaceIP(out_source_address, out_netmask) ||
            FindIPv6InterfaceIP(out_source_address, out_netmask));
#else
    return FindIPv4InterfaceIP(out_source_address, out_netmask);
#endif

  } else if (IsAnyAddress(*destination)) {
    return FindInterfaceIP(destination->type, out_source_address, out_netmask);
  } else {
    return (FindSourceAddressForDestination(*destination, out_source_address) &&
            GetNetMaskForInterfaceAddress(*out_source_address, out_netmask));
  }

  return false;
}

#endif  // SB_API_VERSION >= 4
