diff --git a/include/ircd/net/hostport.h b/include/ircd/net/hostport.h index f14252294..dee6576ce 100644 --- a/include/ircd/net/hostport.h +++ b/include/ircd/net/hostport.h @@ -26,9 +26,13 @@ namespace ircd::net { struct hostport; - uint16_t port(const hostport &); + const uint16_t &port(const hostport &); const string_view &host(const hostport &); + const string_view &service(const hostport &); + + uint16_t &port(hostport &); string_view &host(hostport &); + string_view string(const mutable_buffer &out, const hostport &); } @@ -38,42 +42,63 @@ namespace ircd using net::host; } -/// This structure holds a hostname and port usually fresh from user input -/// intended for resolution. +/// This structure holds a hostname and service or 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. +/// The host can be passed to the constructor as a hostname or hostname:port +/// string. +/// +/// The service field is a string which will trigger an SRV query during +/// resolution and/or be used to figure out the port number. If it is omitted +/// then the numerical port should be specified directly. If it exists then +/// the numerical port will only be used as a fallback, and an SRV response +/// with an alternative port may even override both the host and given +/// numerical port here. /// struct ircd::net::hostport { string_view host {"0.0.0.0"}; - string_view port {"8448"}; - uint16_t portnum {0}; + string_view service {"matrix"}; + uint16_t port {8448}; bool operator!() const; - 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{amalgam != host? rsplit(amalgam, ':').second : "8448"} - {} - + hostport(const string_view &host, const string_view &service); + hostport(const string_view &host, const uint16_t &port); + hostport(const string_view &amalgam); hostport() = default; friend std::ostream &operator<<(std::ostream &, const hostport &); }; +inline +ircd::net::hostport::hostport(const string_view &host, + const string_view &service) +:host{host} +,service{service} +{} + +inline +ircd::net::hostport::hostport(const string_view &host, + const uint16_t &port) +:host{host} +,service{} +,port{port} +{} + +inline +ircd::net::hostport::hostport(const string_view &amalgam) +:host +{ + rsplit(amalgam, ':').first +} +,service{} +,port +{ + amalgam != host? lex_cast(rsplit(amalgam, ':').second) : uint16_t(0) +} +{} + inline bool ircd::net::hostport::operator!() const @@ -88,16 +113,26 @@ ircd::net::host(hostport &hp) return hp.host; } +inline uint16_t & +ircd::net::port(hostport &hp) +{ + return hp.port; +} + +inline const ircd::string_view & +ircd::net::service(const hostport &hp) +{ + return hp.service; +} + inline const ircd::string_view & ircd::net::host(const hostport &hp) { return hp.host; } -inline uint16_t +inline const uint16_t & ircd::net::port(const hostport &hp) { - return hp.portnum? hp.portnum: - hp.port? lex_cast(hp.port): - 0; + return hp.port; } diff --git a/ircd/net.cc b/ircd/net.cc index 72ac03b4a..e37eaae5a 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -2850,15 +2850,22 @@ ircd::string_view ircd::net::string(const mutable_buffer &buf, const hostport &hp) { - const auto len - { - fmt::sprintf + if(empty(service(hp))) + return fmt::sprintf { buf, "%s:%u", host(hp), port(hp) - } - }; + }; - return { data(buf), size_t(len) }; + if(port(hp) == 0) + return fmt::sprintf + { + buf, "%s (%s)", host(hp), service(hp) + }; + + return fmt::sprintf + { + buf, "%s:%u (%s)", host(hp), port(hp), service(hp) + }; } ///////////////////////////////////////////////////////////////////////////////