// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/lib/inet/socket_address.h"

#include <endian.h>

#include <sstream>

namespace inet {

// static
const SocketAddress SocketAddress::kInvalid;

SocketAddress::SocketAddress() { std::memset(&v6_, 0, sizeof(v6_)); }

SocketAddress::SocketAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, IpPort port) {
  std::memset(&v4_, 0, sizeof(v4_));
  v4_.sin_family = AF_INET;
  v4_.sin_port = port.as_in_port_t();
  uint8_t* bytes = reinterpret_cast<uint8_t*>(&v4_.sin_addr);
  bytes[0] = b0;
  bytes[1] = b1;
  bytes[2] = b2;
  bytes[3] = b3;
}

SocketAddress::SocketAddress(in_addr_t addr, IpPort port) {
  std::memset(&v4_, 0, sizeof(v4_));
  v4_.sin_family = AF_INET;
  v4_.sin_port = port.as_in_port_t();
  v4_.sin_addr.s_addr = addr;
}

SocketAddress::SocketAddress(const sockaddr_in& addr) {
  FXL_DCHECK(addr.sin_family == AF_INET);
  v4_ = addr;
}

SocketAddress::SocketAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3, uint16_t w4,
                             uint16_t w5, uint16_t w6, uint16_t w7, IpPort port) {
  std::memset(&v6_, 0, sizeof(v6_));
  v6_.sin6_family = AF_INET6;
  v6_.sin6_port = port.as_in_port_t();
  uint16_t* words = v6_.sin6_addr.s6_addr16;
  words[0] = htobe16(w0);
  words[1] = htobe16(w1);
  words[2] = htobe16(w2);
  words[3] = htobe16(w3);
  words[4] = htobe16(w4);
  words[5] = htobe16(w5);
  words[6] = htobe16(w6);
  words[7] = htobe16(w7);
}

SocketAddress::SocketAddress(uint16_t w0, uint16_t w7, IpPort port) {
  std::memset(&v6_, 0, sizeof(v6_));
  v6_.sin6_family = AF_INET6;
  v6_.sin6_port = port.as_in_port_t();
  uint16_t* words = v6_.sin6_addr.s6_addr16;
  words[0] = htobe16(w0);
  words[7] = htobe16(w7);
}

SocketAddress::SocketAddress(const in6_addr& addr, IpPort port) {
  std::memset(&v6_, 0, sizeof(v6_));
  v6_.sin6_family = AF_INET6;
  v6_.sin6_port = port.as_in_port_t();
  v6_.sin6_addr = addr;
}

SocketAddress::SocketAddress(const sockaddr_in6& addr) {
  FXL_DCHECK(addr.sin6_family == AF_INET6);
  v6_ = addr;
}

SocketAddress::SocketAddress(const IpAddress& addr, IpPort port) {
  if (!addr.is_valid()) {
    std::memset(&v6_, 0, sizeof(v6_));
    return;
  }

  if (addr.is_v4()) {
    std::memset(&v4_, 0, sizeof(v4_));
    v4_.sin_family = AF_INET;
    v4_.sin_port = port.as_in_port_t();
    v4_.sin_addr = addr.as_in_addr();
  } else {
    std::memset(&v6_, 0, sizeof(v6_));
    v6_.sin6_family = AF_INET6;
    v6_.sin6_port = port.as_in_port_t();
    v6_.sin6_addr = addr.as_in6_addr();
  }
}

SocketAddress::SocketAddress(const sockaddr_storage& addr) {
  FXL_DCHECK(addr.ss_family == AF_INET || addr.ss_family == AF_INET6);
  if (addr.ss_family == AF_INET) {
    v4_ = *reinterpret_cast<const sockaddr_in*>(&addr);
  } else {
    v6_ = *reinterpret_cast<const sockaddr_in6*>(&addr);
  }
}

SocketAddress::SocketAddress(const fuchsia::netstack::SocketAddress* addr)
    : SocketAddress(IpAddress(&addr->addr), IpPort::From_uint16_t(addr->port)) {
  FXL_DCHECK(addr != nullptr);
}

SocketAddress::SocketAddress(const fuchsia::net::Endpoint* endpoint)
    : SocketAddress(IpAddress(&endpoint->addr), IpPort::From_uint16_t(endpoint->port)) {
  FXL_DCHECK(endpoint != nullptr);
}

std::string SocketAddress::ToString() const {
  std::ostringstream os;
  os << *this;
  return os.str();
}

std::ostream& operator<<(std::ostream& os, const SocketAddress& value) {
  if (!value.is_valid()) {
    return os << "<invalid>";
  }

  return os << value.address() << ":" << value.port();
}

}  // namespace inet
