/*
 * 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.
 */

#ifdef POSIX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif

#include <sstream>

#include "bruno/byteorder.h"
#include "bruno/common.h"
#include "bruno/logging.h"
#include "bruno/nethelpers.h"
#include "bruno/socketaddress.h"

#ifdef WIN32
// Win32 doesn't provide inet_aton, so we add our own version here.
// Since inet_addr returns 0xFFFFFFFF on error, if we get this value
// we need to test the input to see if the address really was 255.255.255.255.
// This is slightly fragile, but better than doing nothing.
int inet_aton(const char* cp, struct in_addr* inp) {
  inp->s_addr = inet_addr(cp);
  return (inp->s_addr == INADDR_NONE &&
          strcmp(cp, "255.255.255.255") != 0) ? 0 : 1;
}
#endif  // WIN32

namespace bruno_base {

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

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

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

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

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

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

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

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

void SocketAddress::SetIP(uint32 ip) {
  hostname_.clear();
  ip_ = ip;
}

void SocketAddress::SetIP(const std::string& hostname) {
  hostname_ = hostname;
  ip_ = StringToIP(hostname);
}

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

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

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

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

std::string SocketAddress::IPAsString() const {
  if (!hostname_.empty())
    return hostname_;
  return IPToString(ip_);
}

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) {
  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 (ip_ == 0);
}

bool SocketAddress::IsLoopbackIP() const {
  if (0 == ip_) {
    return (0 == stricmp(hostname_.c_str(), "localhost"));
  } else {
    return ((ip_ >> 24) == 127);
  }
}

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

  std::vector<uint32> ips;
  if (0 == 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 ((ip_ >> 24) == 127) ||
         ((ip_ >> 24) == 10) ||
         ((ip_ >> 20) == ((172 << 4) | 1)) ||
         ((ip_ >> 16) == ((192 << 8) | 168)) ||
         ((ip_ >> 16) == ((169 << 8) | 254));
}

bool SocketAddress::IsUnresolvedIP() const {
  return IsAny() && !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)) {
      ip_ = NetworkToHost32(*reinterpret_cast<uint32*>(pHost->h_addr_list[0]));
      LOG_F(LS_VERBOSE) << "(" << hostname_ << ") resolved to: "
                        << IPToString(ip_);
      FreeHostEnt(pHost);
    } else {
      LOG_F(LS_ERROR) << "(" << hostname_ << ") err: " << errcode;
    }
    if (error) {
      *error = errcode;
    }
  }
  return (ip_ != 0);
}

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.ip_ == 0) {
    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_) && ((ip_ != 0) || (hostname_ == addr.hostname_));
}

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

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

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

bool SocketAddress::Write_(char* buf, int len) const {
  if (len < static_cast<int>(Size_()))
    return false;
  buf[0] = 0;
  buf[1] = AF_INET;
  SetBE16(buf + 2, port_);
  SetBE32(buf + 4, ip_);
  return true;
}

bool SocketAddress::Read_(const char* buf, int len) {
  if (len < static_cast<int>(Size_()) || buf[1] != AF_INET)
    return false;
  port_ = GetBE16(buf + 2);
  ip_ = GetBE32(buf + 4);
  return true;
}

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

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));
  return true;
}

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

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

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

}  // namespace bruno_base
