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

#ifndef GARNET_LIB_INET_SOCKET_ADDRESS_H_
#define GARNET_LIB_INET_SOCKET_ADDRESS_H_

#include <arpa/inet.h>
#include <fuchsia/net/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <sys/socket.h>

#include <ostream>

#include "garnet/lib/inet/ip_address.h"
#include "garnet/lib/inet/ip_port.h"
#include "src/lib/fxl/logging.h"

namespace inet {

// Represents a V4 or V6 socket address.
class SocketAddress {
 public:
  static const SocketAddress kInvalid;

  // Creates an invalid socket.
  SocketAddress();

  // Creates an IPV4 socket address from four address bytes and an IpPort.
  SocketAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, IpPort port);

  // Creates an IPV4 socket address from an in_addr_t and an IpPort.
  SocketAddress(in_addr_t addr, IpPort port);

  // Creates an IPV4 socket address from an sockaddr_in struct.
  explicit SocketAddress(const sockaddr_in& addr);

  // Creates an IPV6 socket address from eight address words and an IpPort.
  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);

  // Creates an IPV6 socket address from two address words and an IpPort.
  SocketAddress(uint16_t w0, uint16_t w7, IpPort port);

  // Creates an IPV6 socket address from an in6_addr struct and an IpPort.
  SocketAddress(const in6_addr& addr, IpPort port);

  // Creates an IPV6 socket address from an sockaddr_in6 struct.
  explicit SocketAddress(const sockaddr_in6& addr);

  // Creates a socket address from a IpAddress and an IpPort.
  SocketAddress(const IpAddress& addr, IpPort port);

  // Creates a socket address from an sockaddr_storage struct.
  explicit SocketAddress(const sockaddr_storage& addr);

  // Creates a socket address from a fuchsia.netstack SocketAddress struct.
  explicit SocketAddress(const fuchsia::netstack::SocketAddress* addr);

  // Creates a socket address from a fuchsia.net Endpoint struct.
  explicit SocketAddress(const fuchsia::net::Endpoint* endpoint);

  bool is_valid() const { return family() != AF_UNSPEC; }

  sa_family_t family() const { return v4_.sin_family; }

  bool is_v4() const { return family() == AF_INET; }

  bool is_v6() const { return family() == AF_INET6; }

  IpAddress address() const {
    return is_v4() ? IpAddress(v4_.sin_addr) : IpAddress(v6_.sin6_addr);
  }

  IpPort port() const { return IpPort::From_in_port_t(v4_.sin_port); }

  const sockaddr_in& as_sockaddr_in() const {
    FXL_DCHECK(is_v4());
    return v4_;
  }

  const sockaddr_in6& as_sockaddr_in6() const {
    FXL_DCHECK(is_v6());
    return v6_;
  }

  const sockaddr* as_sockaddr() const {
    return reinterpret_cast<const sockaddr*>(&v4_);
  }

  socklen_t socklen() const { return is_v4() ? sizeof(v4_) : sizeof(v6_); }

  std::string ToString() const;

  explicit operator bool() const { return is_valid(); }

  bool operator==(const SocketAddress& other) const {
    return is_v4() == other.is_v4() &&
           std::memcmp(as_sockaddr(), other.as_sockaddr(), socklen()) == 0;
  }

  bool operator!=(const SocketAddress& other) const {
    return !(*this == other);
  }

 private:
  union {
    sockaddr_in v4_;
    sockaddr_in6 v6_;
  };
};

std::ostream& operator<<(std::ostream& os, const SocketAddress& value);

}  // namespace inet

template <>
struct std::hash<inet::SocketAddress> {
  std::size_t operator()(const inet::SocketAddress& address) const noexcept {
    return std::hash<inet::IpAddress>{}(address.address()) ^
           (std::hash<uint16_t>{}(address.port().as_uint16_t()) << 1);
  }
};

#endif  // GARNET_LIB_INET_SOCKET_ADDRESS_H_
