CS144Lab/libsponge/util/address.hh
2021-09-21 17:11:37 -07:00

86 lines
2.8 KiB
C++

#ifndef SPONGE_LIBSPONGE_ADDRESS_HH
#define SPONGE_LIBSPONGE_ADDRESS_HH
#include <cstddef>
#include <cstdint>
#include <netdb.h>
#include <netinet/in.h>
#include <string>
#include <sys/socket.h>
#include <utility>
//! Wrapper around [IPv4 addresses](@ref man7::ip) and DNS operations.
class Address {
public:
//! \brief Wrapper around [sockaddr_storage](@ref man7::socket).
//! \details A `sockaddr_storage` is enough space to store any socket address (IPv4 or IPv6).
class Raw {
public:
sockaddr_storage storage{}; //!< The wrapped struct itself.
operator sockaddr *();
operator const sockaddr *() const;
};
private:
socklen_t _size; //!< Size of the wrapped address.
Raw _address{}; //!< A wrapped [sockaddr_storage](@ref man7::socket) containing the address.
//! Constructor from ip/host, service/port, and hints to the resolver.
Address(const std::string &node, const std::string &service, const addrinfo &hints);
public:
//! Construct by resolving a hostname and servicename.
Address(const std::string &hostname, const std::string &service);
//! Construct from dotted-quad string ("18.243.0.1") and numeric port.
Address(const std::string &ip, const std::uint16_t port = 0);
//! Construct from a [sockaddr *](@ref man7::socket).
Address(const sockaddr *addr, const std::size_t size);
//! Equality comparison.
bool operator==(const Address &other) const;
bool operator!=(const Address &other) const { return not operator==(other); }
//! \name Conversions
//!@{
//! Dotted-quad IP address string ("18.243.0.1") and numeric port.
std::pair<std::string, uint16_t> ip_port() const;
//! Dotted-quad IP address string ("18.243.0.1").
std::string ip() const { return ip_port().first; }
//! Numeric port (host byte order).
uint16_t port() const { return ip_port().second; }
//! Numeric IP address as an integer (i.e., in [host byte order](\ref man3::byteorder)).
uint32_t ipv4_numeric() const;
//! Create an Address from a 32-bit raw numeric IP address
static Address from_ipv4_numeric(const uint32_t ip_address);
//! Human-readable string, e.g., "8.8.8.8:53".
std::string to_string() const;
//!@}
//! \name Low-level operations
//!@{
//! Size of the underlying address storage.
socklen_t size() const { return _size; }
//! Const pointer to the underlying socket address storage.
operator const sockaddr *() const { return _address; }
//!@}
};
//! \class Address
//! For example, you can do DNS lookups:
//!
//! \include address_example_1.cc
//!
//! or you can specify an IP address and port number:
//!
//! \include address_example_2.cc
//!
//! Once you have an address, you can convert it to other useful representations, e.g.,
//!
//! \include address_example_3.cc
#endif // SPONGE_LIBSPONGE_ADDRESS_HH