/*
 * 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;
}

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 size_t 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);
    return sizeof(sockaddr_in6);
  } else if (addr->ss_family == AF_INET) {
    sockaddr_in* saddr = reinterpret_cast<sockaddr_in*>(addr);
    saddr->sin_addr = ip.ipv4_address();
    saddr->sin_port = HostToNetwork16(port);
    return sizeof(sockaddr_in);
  }
  return 0;
}

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

size_t SocketAddress::ToSockAddrStorage(sockaddr_storage* addr) const {
  return 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<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
