/* * Copyright (C) 2017 Charybdis Development Team * Copyright (C) 2017 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. * * 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. */ #pragma once #define HAVE_IRCD_NET_REMOTE_H // Forward declarations for boost because it is not included here. namespace boost::asio::ip { struct address; }; namespace ircd::net { struct hostport; struct ipport; struct remote; 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 &); const auto &host(const hostport &); uint128_t &host6(ipport &); uint32_t &host4(ipport &); auto &host(hostport &); 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 hostport &); string_view string(const mutable_buffer &out, const ipport &); string_view string(const mutable_buffer &out, const remote &); } namespace ircd { using net::hostport; using net::ipport; using net::remote; using net::host; using net::port; } /// This structure holds a hostname and port usually fresh from user input /// intended for resolution. /// /// The host can be specified as a hostname or hostname:port string. If no /// port argument is specified and no port is present in the host string /// then 8448 is assumed. /// struct ircd::net::hostport { string_view host {"0.0.0.0"}; string_view port {"8448"}; uint16_t portnum {0}; hostport(const string_view &host, const string_view &port) :host{host} ,port{port} {} hostport(const string_view &host, const uint16_t &portnum) :host{host} ,port{} ,portnum{portnum} {} hostport(const string_view &amalgam) :host{rsplit(amalgam, ':').first} ,port{rsplit(amalgam, ':').second} {} hostport() = default; friend std::ostream &operator<<(std::ostream &, const hostport &); }; /// 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. /// /// Constructing this object with a hostname will yield an IP address /// resolution, the result being saved in the structure. The hostname argument /// is not saved in the structure; consider using net::remote instead. /// /// 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 hostport &); // DNS lookup! May yield ircd::ctx! ipport(const uint32_t &ip, const uint16_t &port); ipport(const uint128_t &ip, const uint16_t &port); ipport(const boost::asio::ip::address &, const uint16_t &port); ipport(); friend std::ostream &operator<<(std::ostream &, const ipport &); }; /// This structure combines features of hostport and ipport to hold a remote's /// resolved IP in bytes, a port number, and an optional hostname string which /// may have been used to resolve the IP, or may have been resolved from the /// IP, or may just be empty, but either way still has some use being carried /// along as part of this struct. struct ircd::net::remote :ircd::net::ipport { std::string hostname; explicit operator bool() const; bool operator!() const { return !static_cast(*this); } bool resolved() const; explicit remote(const ipport &ipp) :ipport{ipp} {} remote(const hostport &hp) :ipport{hp} ,hostname{std::string{hp.host}} {} remote() = default; friend std::ostream &operator<<(std::ostream &, const remote &); }; inline bool ircd::net::remote::resolved() const { return bool(static_cast(*this)); } inline ircd::net::remote::operator bool() const { return resolved() || !hostname.empty(); } 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; 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 auto & ircd::net::host(hostport &hp) { return hp.host; } inline const auto & ircd::net::host(const hostport &hp) { return hp.host; } 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); }