// 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.";
      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;
}
