// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2018 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_NET_IPPORT_H // Forward declarations for boost because it is not included here. namespace boost::asio::ip { struct address; }; namespace ircd::net { struct ipport; const uint16_t &port(const ipport &); uint16_t &port(ipport &); bool is_v6(const ipport &); bool is_v4(const ipport &); const uint128_t &host6(const ipport &); const uint32_t &host4(const ipport &); uint128_t &host6(ipport &); uint32_t &host4(ipport &); string_view string(const mutable_buffer &out, const uint32_t &); string_view string(const mutable_buffer &out, const uint128_t &); string_view string(const mutable_buffer &out, const ipport &); } namespace ircd { using net::ipport; using net::host; using net::port; } /// This lightweight structure holds an IP address and port in native byte /// form. It is usually returned from the result of a resolution but may also /// serve as input to a reverse resolution. Either way, this allocation-free /// structure is useful for storing raw IP/port data, even in large sets. /// /// The TYPE field is only a boolean for now indicating IPv4 or IPv6; the /// official way to query this is to use net::is_v6(ipport) etc and not /// std::get the type directly. /// struct ircd::net::ipport :std::tuple, uint16_t, bool> { enum { IP, PORT, TYPE }; explicit operator bool() const; bool operator!() const { return !static_cast(*this); } ipport(const uint32_t &ip, const uint16_t &port); ipport(const uint128_t &ip, const uint16_t &port); ipport(const rfc1035::record::A &, const uint16_t &port); ipport(const rfc1035::record::AAAA &, const uint16_t &port); ipport(const boost::asio::ip::address &, const uint16_t &port); ipport(const string_view &ip, const uint16_t &port); ipport(const string_view &ip, const string_view &port); ipport(); friend std::ostream &operator<<(std::ostream &, const ipport &); }; inline ircd::net::ipport::ipport() { std::get(*this) = 0; std::get(*this) = 0; auto &ip(std::get(*this)); std::fill(begin(ip), end(ip), 0x0); } inline ircd::net::ipport::ipport(const uint32_t &ip, const uint16_t &p) { std::get(*this) = false; host6(*this) = 0; host4(*this) = ip; port(*this) = p; } inline ircd::net::ipport::ipport(const uint128_t &ip, const uint16_t &p) { std::get(*this) = true; host6(*this) = ip; port(*this) = p; } inline ircd::net::ipport::operator bool() const { return std::get(*this) != 0; } inline ircd::uint128_t & ircd::net::host6(ipport &ipp) { auto &bytes{std::get(ipp)}; return *reinterpret_cast(bytes.data()); } inline const ircd::uint128_t & ircd::net::host6(const ipport &ipp) { const auto &bytes{std::get(ipp)}; return *reinterpret_cast(bytes.data()); } inline bool ircd::net::is_v6(const ipport &ipp) { return std::get(ipp) == true; } inline uint32_t & ircd::net::host4(ipport &ipp) { auto &bytes{std::get(ipp)}; return *reinterpret_cast(bytes.data()); } inline const uint32_t & ircd::net::host4(const ipport &ipp) { const auto &bytes{std::get(ipp)}; return *reinterpret_cast(bytes.data()); } inline bool ircd::net::is_v4(const ipport &ipp) { return std::get(ipp) == false; } inline uint16_t & ircd::net::port(ipport &ipp) { return std::get(ipp); } inline const uint16_t & ircd::net::port(const ipport &ipp) { return std::get(ipp); }