// 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"

#include <winsock2.h>

#include <ifdef.h>
#include <iphlpapi.h>

#include <algorithm>
#include <memory>

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

namespace sbwin32 = starboard::shared::win32;

namespace {
const ULONG kDefaultAdapterInfoBufferSizeInBytes = 16 * 1024;

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);
    case kSbSocketAddressTypeIpv6: {
      bool found_nonzero = false;
      for (std::size_t i = 0; i != sbwin32::kAddressLengthIpv6; ++i) {
        found_nonzero |= (address.address[i] != 0);
      }
      return !found_nonzero;
    }
    default:
      SB_NOTREACHED() << "Invalid address type " << address.type;
      break;
  }

  return false;
}

void GenerateNetMaskFromPrefixLength(UINT8 prefix_length,
                                     UINT32* const address_begin,
                                     UINT32* const address_end) {
  SB_DCHECK(address_end >= address_begin);
  SB_DCHECK((reinterpret_cast<char*>(address_end) -
             reinterpret_cast<char*>(address_begin)) %
                4 ==
            0);
  UINT8 ones_left = prefix_length;
  const int kBitsInOneDWORD = sizeof(UINT32) * 8;
  for (UINT32* iterator = address_begin; iterator != address_end; ++iterator) {
    UINT8 ones_in_this_dword = std::min<UINT8>(kBitsInOneDWORD, ones_left);
    UINT64 mask_value =
        kSbUInt64Max - ((1ULL << (kBitsInOneDWORD - ones_in_this_dword)) - 1);
    *iterator =
        SB_HOST_TO_NET_U32(static_cast<UINT32>(mask_value & kSbUInt64Max));
    ones_left -= ones_in_this_dword;
  }
}

bool PopulateInterfaceAddress(const IP_ADAPTER_UNICAST_ADDRESS& unicast_address,
                              SbSocketAddress* out_interface_ip) {
  if (!out_interface_ip) {
    return true;
  }

  const SOCKET_ADDRESS& address = unicast_address.Address;
  sbwin32::SockAddr addr;
  return addr.FromSockaddr(address.lpSockaddr) &&
         addr.ToSbSocketAddress(out_interface_ip);
}

bool PopulateNetmask(const IP_ADAPTER_UNICAST_ADDRESS& unicast_address,
                     SbSocketAddress* out_netmask) {
  if (!out_netmask) {
    return true;
  }

  const SOCKET_ADDRESS& address = unicast_address.Address;
  if (address.lpSockaddr == nullptr) {
    return false;
  }
  const ADDRESS_FAMILY& family = address.lpSockaddr->sa_family;

  switch (family) {
    case AF_INET:
      out_netmask->type = kSbSocketAddressTypeIpv4;
      break;
    case AF_INET6:
      out_netmask->type = kSbSocketAddressTypeIpv6;
      break;
    default:
      SB_NOTREACHED() << "Invalid family " << family;
      return false;
  }

  UINT32* const begin_netmask =
      reinterpret_cast<UINT32*>(&(out_netmask->address[0]));
  UINT32* const end_netmask =
      begin_netmask + SB_ARRAY_SIZE(out_netmask->address) / sizeof(UINT32);

  GenerateNetMaskFromPrefixLength(unicast_address.OnLinkPrefixLength,
                                  begin_netmask, end_netmask);
  return true;
}

bool GetAdapters(const SbSocketAddressType address_type,
                 std::unique_ptr<char[]>* adapter_info) {
  SB_DCHECK(adapter_info);

  ULONG family = 0;
  int address_length_bytes = 0;

  switch (address_type) {
    case kSbSocketAddressTypeIpv4:
      family = AF_INET;
      address_length_bytes = sbwin32::kAddressLengthIpv4;
      break;
    case kSbSocketAddressTypeIpv6:
      family = AF_INET6;
      address_length_bytes = sbwin32::kAddressLengthIpv6;
      break;
    default:
      SB_NOTREACHED() << "Invalid address type: " << address_type;
      return false;
  }

  ULONG adapter_addresses_number_bytes = kDefaultAdapterInfoBufferSizeInBytes;

  for (int try_count = 0; try_count != 2; ++try_count) {
    // Using auto for return value here, since different versions of windows use
    // slightly different datatypes.  These differences do not matter to us, but
    // the compiler might warn on them.
    adapter_info->reset(new char[adapter_addresses_number_bytes]);
    PIP_ADAPTER_ADDRESSES adapter_addresses =
        reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_info->get());

    // Note: If |GetAdapterAddresses| deems that buffer supplied is not enough,
    // it will return the recommended number of bytes in
    // |adapter_addresses_number_bytes|.
    auto retval = GetAdaptersAddresses(
        family, GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_DNS_SERVER, nullptr,
        adapter_addresses, &adapter_addresses_number_bytes);

    if (retval == ERROR_SUCCESS) {
      return true;
    }
    if (retval != ERROR_BUFFER_OVERFLOW) {
      // Only retry with more memory if the error says so.
      break;
    }
    SB_LOG(ERROR) << "GetAdapterAddresses() failed with error code " << retval;
  }

  return false;
}

bool GetNetmaskForInterfaceAddress(const SbSocketAddress& interface_address,
                                   SbSocketAddress* out_netmask) {
  std::unique_ptr<char[]> adapter_info_memory_block;
  if (!GetAdapters(interface_address.type, &adapter_info_memory_block)) {
    return false;
  }
  const void* const interface_address_buffer =
      reinterpret_cast<const void* const>(interface_address.address);
  for (PIP_ADAPTER_ADDRESSES adapter = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(
           adapter_info_memory_block.get());
       adapter != nullptr; adapter = adapter->Next) {
    if ((adapter->OperStatus != IfOperStatusUp) ||
        (adapter->IfType != IF_TYPE_ETHERNET_CSMACD)) {
      // Note: IfType == IF_TYPE_SOFTWARE_LOOPBACK is also skipped.
      continue;
    }

    for (PIP_ADAPTER_UNICAST_ADDRESS unicast_address =
             adapter->FirstUnicastAddress;
         unicast_address != nullptr; unicast_address = unicast_address->Next) {
      sbwin32::SockAddr addr;
      if (!addr.FromSockaddr(unicast_address->Address.lpSockaddr)) {
        continue;
      }

      const void* unicast_address_buffer = nullptr;
      int bytes_to_check = 0;

      switch (interface_address.type) {
        case kSbSocketAddressTypeIpv4:
          unicast_address_buffer =
              reinterpret_cast<void*>(&(addr.sockaddr_in()->sin_addr));
          bytes_to_check = sbwin32::kAddressLengthIpv4;
          break;
        case kSbSocketAddressTypeIpv6:
          unicast_address_buffer =
              reinterpret_cast<void*>(&(addr.sockaddr_in6()->sin6_addr));
          bytes_to_check = sbwin32::kAddressLengthIpv6;
          break;
        default:
          SB_DLOG(ERROR) << "Invalid interface address type "
                         << interface_address.type;
          return false;
      }

      if (SbMemoryCompare(unicast_address_buffer, interface_address_buffer,
                          bytes_to_check) != 0) {
        continue;
      }

      if (PopulateNetmask(*unicast_address, out_netmask)) {
        return true;
      }
    }
  }

  return false;
}

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

bool FindInterfaceIP(const SbSocketAddressType address_type,
                     SbSocketAddress* out_interface_ip,
                     SbSocketAddress* out_netmask) {
  if (out_interface_ip == nullptr) {
    SB_NOTREACHED() << "out_interface_ip must be specified";
    return false;
  }

  std::unique_ptr<char[]> adapter_info_memory_block;
  if (!GetAdapters(address_type, &adapter_info_memory_block)) {
    return false;
  }

  for (PIP_ADAPTER_ADDRESSES adapter = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(
           adapter_info_memory_block.get());
       adapter != nullptr; adapter = adapter->Next) {
    if ((adapter->OperStatus != IfOperStatusUp) ||
        (adapter->IfType != IF_TYPE_ETHERNET_CSMACD)) {
      // Note: IfType == IF_TYPE_SOFTWARE_LOOPBACK is also skipped.
      continue;
    }

    for (PIP_ADAPTER_UNICAST_ADDRESS unicast_address =
             adapter->FirstUnicastAddress;
         unicast_address != nullptr; unicast_address = unicast_address->Next) {
      if (unicast_address->Flags & (IP_ADAPTER_ADDRESS_TRANSIENT)) {
        continue;
      }
      if (!(unicast_address->Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE)) {
        continue;
      }

      // TODO: For IPv6, Prioritize interface with highest scope.
      // Skip ULAs for now.
      if (address_type == kSbSocketAddressTypeIpv6) {
        // Documentation on MSDN states:
        // "The SOCKADDR structure pointed to by the lpSockaddr member varies
        // depending on the protocol or address family selected. For example,
        // the sockaddr_in6 structure is used for an IPv6 socket address
        // while the sockaddr_in4 structure is used for an IPv4 socket address."
        // https://msdn.microsoft.com/en-us/library/windows/desktop/ms740507(v=vs.85).aspx

        sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(
            unicast_address->Address.lpSockaddr);
        SB_DCHECK(addr->sin6_family == AF_INET6);
        if (IsUniqueLocalAddress(addr->sin6_addr.u.Byte)) {
          continue;
        }
      }

      if (!PopulateInterfaceAddress(*unicast_address, out_interface_ip)) {
        continue;
      }
      if (!PopulateNetmask(*unicast_address, out_netmask)) {
        continue;
      }

      return true;
    }
  }
  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 == nullptr) {
    // Return either a v4 or a v6 address.  Per spec.
    return (FindInterfaceIP(kSbSocketAddressTypeIpv4, out_source_address,
                            out_netmask) ||
            FindInterfaceIP(kSbSocketAddressTypeIpv6, out_source_address,
                            out_netmask));
  } 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;
}
