/*
 * libjingle
 * Copyright 2004--2005, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/base/socketaddress.h"

#ifdef POSIX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#if defined(OPENBSD)
#include <netinet/in_systm.h>
#endif
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif

#include <sstream>

#include "talk/base/byteorder.h"
#include "talk/base/common.h"
#include "talk/base/logging.h"
#include "talk/base/nethelpers.h"

#ifdef WIN32
#include "talk/base/win32.h"
#endif

namespace talk_base {

// Address family constants for STUN (see RFC 5389).
static const int kStunFamilyIPv4 = 1;
static const int kStunFamilyIPv6 = 2;

SocketAddress::SocketAddress() {
  Clear();
}

SocketAddress::SocketAddress(const std::string& hostname, int port) {
  SetIP(hostname);
  SetPort(port);
}

SocketAddress::SocketAddress(uint32 ip_as_host_order_integer, int port) {
  SetIP(IPAddress(ip_as_host_order_integer));
  SetPort(port);
}

SocketAddress::SocketAddress(const IPAddress& ip, int port) {
  SetIP(ip);
  SetPort(port);
}

SocketAddress::SocketAddress(const SocketAddress& addr) {
  this->operator=(addr);
}

void SocketAddress::Clear() {
  hostname_.clear();
  literal_ = false;
  ip_ = IPAddress(INADDR_ANY);
  port_ = 0;
}

bool SocketAddress::IsNil() const {
  return hostname_.empty() && IPIsAny(ip_) && 0 == port_;
}

bool SocketAddress::IsComplete() const {
  return (!IPIsAny(ip_)) && (0 != port_);
}

SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
  hostname_ = addr.hostname_;
  ip_ = addr.ip_;
  port_ = addr.port_;
  literal_ = addr.literal_;
  return *this;
}

void SocketAddress::SetIP(uint32 ip_as_host_order_integer) {
  hostname_.clear();
  literal_ = false;
  ip_ = IPAddress(ip_as_host_order_integer);
}

void SocketAddress::SetIP(const IPAddress& ip) {
  hostname_.clear();
  literal_ = false;
  ip_ = ip;
}

void SocketAddress::SetIP(const std::string& hostname) {
  hostname_ = hostname;
  literal_ = IPFromString(hostname, &ip_);
  if (!literal_) {
    ip_ = IPAddress(INADDR_ANY);
  }
}

void SocketAddress::SetResolvedIP(uint32 ip_as_host_order_integer) {
  ip_ = IPAddress(ip_as_host_order_integer);
}

void SocketAddress::SetResolvedIP(const IPAddress& ip) {
  ip_ = ip;
}

void SocketAddress::SetPort(int port) {
  ASSERT((0 <= port) && (port < 65536));
  port_ = port;
}

uint32 SocketAddress::ip() const {
  return ip_.v4AddressAsHostOrderInteger();
}

IPAddress SocketAddress::ipaddr() const {
  return ip_;
}

uint16 SocketAddress::port() const {
  return port_;
}

std::string SocketAddress::IPAsString() const {
  // If the hostname was a literal IP string, it may need to have square
  // brackets added (for SocketAddress::ToString()).
  if (!literal_ && !hostname_.empty())
    return hostname_;
  if (ip_.family() == AF_INET6) {
    return "[" + ip_.ToString() + "]";
  } else {
    return ip_.ToString();
  }
}

std::string SocketAddress::PortAsString() const {
  std::ostringstream ost;
  ost << port_;
  return ost.str();
}

std::string SocketAddress::ToString() const {
  std::ostringstream ost;
  ost << IPAsString();
  ost << ":";
  ost << port();
  return ost.str();
}

bool SocketAddress::FromString(const std::string& str) {
  if (str.at(0) == '[') {
    std::string::size_type closebracket = str.rfind(']');
    if (closebracket != std::string::npos) {
      std::string::size_type colon = str.find(':', closebracket);
      if (colon != std::string::npos && colon > closebracket) {
        SetPort(strtoul(str.substr(colon + 1).c_str(), NULL, 10));
        SetIP(str.substr(1, closebracket - 1));
      } else {
        return false;
      }
    }
  } else {
    std::string::size_type pos = str.find(':');
    if (std::string::npos == pos)
      return false;
    SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10));
    SetIP(str.substr(0, pos));
  }
  return true;
}

std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
  os << addr.IPAsString() << ":" << addr.port();
  return os;
}

bool SocketAddress::IsAnyIP() const {
  return IPIsAny(ip_);
}

bool SocketAddress::IsLoopbackIP() const {
  return IPIsLoopback(ip_) || (IPIsAny(ip_) &&
                               0 == strcmp(hostname_.c_str(), "localhost"));
}

bool SocketAddress::IsLocalIP() const {
  if (IsLoopbackIP())
    return true;

  std::vector<IPAddress> ips;
  if (IPIsAny(ip_)) {
    if (!hostname_.empty()
        && (0 == stricmp(hostname_.c_str(), GetHostname().c_str()))) {
      return true;
    }
  } else if (GetLocalIPs(&ips)) {
    for (size_t i = 0; i < ips.size(); ++i) {
      if (ips[i] == ip_) {
        return true;
      }
    }
  }
  return false;
}

bool SocketAddress::IsPrivateIP() const {
  return IPIsPrivate(ip_);
}

bool SocketAddress::IsUnresolvedIP() const {
  return IsAny() && !literal_ && !hostname_.empty();
}

bool SocketAddress::ResolveIP(bool force, int* error) {
  if (hostname_.empty()) {
    // nothing to resolve
  } else if (!force && !IsAny()) {
    // already resolved
  } else {
    LOG_F(LS_VERBOSE) << "(" << hostname_ << ")";
    int errcode = 0;
    if (hostent* pHost = SafeGetHostByName(hostname_.c_str(), &errcode)) {
      if (IPFromHostEnt(pHost, &ip_)) {
        LOG_F(LS_VERBOSE) << "(" << hostname_ << ") resolved to: "
                          << ip_.ToString();
      }
      FreeHostEnt(pHost);
    } else {
      LOG_F(LS_ERROR) << "(" << hostname_ << ") err: " << errcode;
    }
    if (error) {
      *error = errcode;
    }
  }
  return (!IPIsAny(ip_));
}

bool SocketAddress::operator==(const SocketAddress& addr) const {
  return EqualIPs(addr) && EqualPorts(addr);
}

bool SocketAddress::operator<(const SocketAddress& addr) const {
  if (ip_ < addr.ip_)
    return true;
  else if (addr.ip_ < ip_)
    return false;

  // We only check hostnames if both IPs are zero.  This matches EqualIPs()
  if (addr.IsAnyIP()) {
    if (hostname_ < addr.hostname_)
      return true;
    else if (addr.hostname_ < hostname_)
      return false;
  }

  return port_ < addr.port_;
}

bool SocketAddress::EqualIPs(const SocketAddress& addr) const {
  return (ip_ == addr.ip_) &&
      ((!IPIsAny(ip_)) || (hostname_ == addr.hostname_));
}

bool SocketAddress::EqualPorts(const SocketAddress& addr) const {
  return (port_ == addr.port_);
}

size_t SocketAddress::Hash() const {
  size_t h = 0;
  h ^= HashIP(ip_);
  h ^= port_ | (port_ << 16);
  return h;
}

size_t SocketAddress::Size_() const {
  return ip_.Size() + sizeof(port_) + 2;
}

bool SocketAddress::Write_(char* buf, int len) const {
  if (len < static_cast<int>(Size_()))
    return false;
  int family = ip_.family();
  if (family != AF_INET && family != AF_INET6) {
    return false;
  }
  buf[0] = 0;
  SetBE16(buf + 2, port_);
  if (family == AF_INET) {
    buf[1] = kStunFamilyIPv4;
    SetBE32(buf + 4, ip_.v4AddressAsHostOrderInteger());
  } else if (family == AF_INET6) {
    buf[1] = kStunFamilyIPv6;
    in6_addr addr = ip_.ipv6_address();
    memcpy((buf + 4), &addr.s6_addr, sizeof(addr.s6_addr));
  }
  return true;
}

bool SocketAddress::Read_(const char* buf, int len) {
  if (len < static_cast<int>(Size_()) ||
      (buf[1] != kStunFamilyIPv4 && buf[1] != kStunFamilyIPv6))
    return false;
  port_ = GetBE16(buf + 2);
  if (buf[1] == kStunFamilyIPv4) {
    ip_ = IPAddress(GetBE32(buf + 4));
  } else if (buf[1] == kStunFamilyIPv6) {
    in6_addr addr;
    memcpy(&addr.s6_addr, (buf + 4), sizeof(addr.s6_addr));
    ip_ = IPAddress(addr);
  }
  return true;
}

void SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
  memset(saddr, 0, sizeof(*saddr));
  if (ip_.family() != AF_INET) {
    saddr->sin_family = AF_UNSPEC;
    return;
  }
  saddr->sin_family = AF_INET;
  saddr->sin_port = HostToNetwork16(port_);
  if (IPIsAny(ip_)) {
    saddr->sin_addr.s_addr = INADDR_ANY;
  } else {
    saddr->sin_addr = ip_.ipv4_address();
  }
}

bool SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
  if (saddr.sin_family != AF_INET)
    return false;
  SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
  SetPort(NetworkToHost16(saddr.sin_port));
  literal_ = false;
  return true;
}

static void ToSockAddrStorageHelper(sockaddr_storage* addr,
                                    IPAddress ip, int port) {
  memset(addr, 0, sizeof(sockaddr_storage));
  addr->ss_family = ip.family();
  if (addr->ss_family == AF_INET6) {
    sockaddr_in6* saddr = reinterpret_cast<sockaddr_in6*>(addr);
    saddr->sin6_addr = ip.ipv6_address();
    saddr->sin6_port = HostToNetwork16(port);
  } else {
    sockaddr_in* saddr = reinterpret_cast<sockaddr_in*>(addr);
    saddr->sin_addr = ip.ipv4_address();
    saddr->sin_port = HostToNetwork16(port);
  }
}

void SocketAddress::ToDualStackSockAddrStorage(sockaddr_storage *addr) const {
  ToSockAddrStorageHelper(addr, ip_.AsIPv6Address(), port_);
}

void SocketAddress::ToSockAddrStorage(sockaddr_storage* addr) const {
  ToSockAddrStorageHelper(addr, ip_, port_);
}

std::string SocketAddress::IPToString(uint32 ip_as_host_order_integer) {
  std::ostringstream ost;
  ost << ((ip_as_host_order_integer >> 24) & 0xff);
  ost << '.';
  ost << ((ip_as_host_order_integer >> 16) & 0xff);
  ost << '.';
  ost << ((ip_as_host_order_integer >> 8) & 0xff);
  ost << '.';
  ost << ((ip_as_host_order_integer >> 0) & 0xff);
  return ost.str();
}

bool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) {
  in_addr addr;
  if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr) == 0)
    return false;
  *ip = NetworkToHost32(addr.s_addr);
  return true;
}

bool SocketAddress::StringToIP(const std::string& hostname, IPAddress* ip) {
  in_addr addr4;
  if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr4) > 0) {
    if (ip) {
      *ip = IPAddress(addr4);
    }
    return true;
  }

  in6_addr addr6;
  if (talk_base::inet_pton(AF_INET6, hostname.c_str(), &addr6) > 0) {
    if (ip) {
      *ip = IPAddress(addr6);
    }
    return true;
  }
  return false;
}

uint32 SocketAddress::StringToIP(const std::string& hostname) {
  uint32 ip = 0;
  StringToIP(hostname, &ip);
  return ip;
}

std::string SocketAddress::GetHostname() {
  char hostname[256];
  if (gethostname(hostname, ARRAY_SIZE(hostname)) == 0)
    return hostname;
  return "";
}

bool SocketAddress::GetLocalIPs(std::vector<uint32>& ips) {
  ips.clear();

  const std::string hostname = GetHostname();
  if (hostname.empty())
    return false;

  int errcode;
  if (hostent* pHost = SafeGetHostByName(hostname.c_str(), &errcode)) {
    for (size_t i = 0; pHost->h_addr_list[i]; ++i) {
      uint32 ip =
        NetworkToHost32(*reinterpret_cast<uint32 *>(pHost->h_addr_list[i]));
      ips.push_back(ip);
    }
    FreeHostEnt(pHost);
    return !ips.empty();
  }
  LOG(LS_ERROR) << "gethostbyname err: " << errcode;
  return false;
}

bool SocketAddress::GetLocalIPs(std::vector<IPAddress>* ips) {
  if (!ips) {
    return false;
  }
  ips->clear();

  const std::string hostname = SocketAddress::GetHostname();
  if (hostname.empty())
    return false;

  int errcode;
  if (hostent* pHost = SafeGetHostByName(hostname.c_str(), &errcode)) {
    for (size_t i = 0; pHost->h_addr_list[i]; ++i) {
      IPAddress ip;
      if (IPFromHostEnt(pHost, i, &ip)) {
        ips->push_back(ip);
      }
    }
    FreeHostEnt(pHost);
    return !ips->empty();
  }
  LOG(LS_ERROR) << "gethostbyname err: " << errcode;
  return false;
}

bool SocketAddressFromSockAddrStorage(const sockaddr_storage& addr,
                                      SocketAddress* out) {
  if (!out) {
    return false;
  }
  if (addr.ss_family == AF_INET) {
    const sockaddr_in* saddr = reinterpret_cast<const sockaddr_in*>(&addr);
    *out = SocketAddress(IPAddress(saddr->sin_addr),
                         NetworkToHost16(saddr->sin_port));
    return true;
  } else if (addr.ss_family == AF_INET6) {
    const sockaddr_in6* saddr = reinterpret_cast<const sockaddr_in6*>(&addr);
    *out = SocketAddress(IPAddress(saddr->sin6_addr),
                         NetworkToHost16(saddr->sin6_port));
    return true;
  }
  return false;
}
}  // namespace talk_base
