/**************************************************************************** * Copyright (C) 2014-2023 Savoir-faire Linux Inc. * * Author : Emmanuel Lepage Vallee * * Author : Hugo Lefeuvre * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #pragma once #include "typedefs.h" #include #include class URIPimpl; class QDataStream; /** * @class URI A specialized string with multiple attributes * * Most of LibRingClient handle uri as strings, but more * advanced algorithms need to access the various sections. * This class implement a centralized and progressive URI * parser to avoid having custom implementation peppered * everywhere. This class doesn't attempt to produce perfect * output. It has multiple tradeoff to be faster when * accuracy has little value in the context of LibRingClient. * * Here is some example of common numbers/URIs: * * 123 * * 123@192.168.123.123 * * 123@asterisk-server * * * * * * * * ;tag=hyh8 * * 1 800 123-4567 * * 18001234567 * * @ref http://tools.ietf.org/html/rfc5456#page-8 * @ref http://tools.ietf.org/html/rfc3986 * @ref http://tools.ietf.org/html/rfc3261 * @ref http://tools.ietf.org/html/rfc5630 * * * From the RFC: * foo://example.com:8042/over/there?name=ferret#nose * \_/ \______________/\_________/ \_________/ \__/ * | | | | | * scheme authority path query fragment * | _____________________|__ * / \ / \ * urn:example:animal:ferret:nose * * authority = [ userinfo "@" ] host [ ":" port ] * * * "For example, the semicolon (";") and equals ("=") reserved characters are * often used to delimit parameters and parameter values applicable to * that segment. The comma (",") reserved character is often used for * similar purposes. For example, one URI producer might use a segment * such as "name;v=1.1" to indicate a reference to version 1.1 of * "name", whereas another might use a segment such as "name,1.1" to * indicate the same. " */ class LIB_EXPORT URI : public QString { public: URI(); URI(const URI& other); URI(const QString& other); virtual ~URI(); // @enum SchemeType The very first part of the URI followed by a ':' enum class SchemeType { SIP, SIPS, RING, NONE, COUNT__, UNRECOGNIZED }; Q_ENUMS(URI::SchemeType) /** * @enum Transport each known valid transport types * Defined at http://tools.ietf.org/html/rfc3261#page-222 */ enum class Transport { NOT_SET, /*!< The transport have not been set directly in the URI */ TLS, /*!< Encrypted calls (capital) */ tls, /*!< Encrypted calls */ TCP, /*!< TCP (the default) (capital) */ tcp, /*!< TCP (the default) */ UDP, /*!< Without a connection (capital) */ udp, /*!< Without a connection */ SCTP, /*!< */ sctp, /*!< */ DTLS, /*!< */ dtls, /*!< */ COUNT__ }; Q_ENUMS(URI::Transport) /** * @enum Section flags associated with each logical sections of the URI * * Those sections can be packed into a block to be used to define the * expected URI syntax * */ enum class Section { CHEVRONS = 0x1 << 0, /*!< \_/ \_/ |_________________Chevrons_______________________| */ SCHEME = 0x1 << 1, /*!< \___/ |______Scheme| */ USER_INFO = 0x1 << 2, /*!< \___/ |_________Userinfo */ HOSTNAME = 0x1 << 3, /*!< \______________/ |_________Hostname */ PORT = 0x1 << 4, /*!< \____/ |_____Port */ TRANSPORT = 0x1 << 5, /*!< \_____________/ Transport________| */ TAG = 0x1 << 6, /*!< \_____________/ Tag_________| */ }; /** * @enum ProtocolHint Expanded version of Account::Protocol * * This is used to make better choice when it come to choose an account or * guess if the URI can be used with the current set et configured accounts. * * @warning This is an approximation. Those values are guessed using partial * parsing (for performance) and are not definitive. */ enum class ProtocolHint { RING, /* Start with "ring:" and 45 ASCII chars OR 40 ASCII chars */ IP, /* Match an IPv4 address */ SIP_HOST, /* Start with "sip:", has an @ and no "ring:" prefix */ SIP_OTHER, /* Start with "sip:" and doesn't fit in other categories */ RING_USERNAME, /* Anything that starts with "ring:" and isn't followed by 40 ASCII chars */ UNRECOGNIZED /* Anything that doesn't fit in other categories */ }; Q_ENUMS(URI::ProtocolHint) // Getter QString hostname() const; QString userinfo() const; bool hasHostname() const; bool hasPort() const; int port() const; SchemeType schemeType() const; ProtocolHint protocolHint() const; // Setter void setUserinfo(const QString& userinfo); void setHostname(const QString& hostname); void setPort(const QString& port); void setSchemeType(SchemeType t); // Converter QString format(FlagPack sections) const; /** * Helper function which returns a QString containing a uri formatted to include at minimum the * SCHEME and USER_INFO, and also the HOSTNAME and PORT, if available. */ QString full() const; URI& operator=(const URI&); private: std::unique_ptr pimpl_; }; Q_DECLARE_METATYPE(URI) Q_DECLARE_METATYPE(URI::ProtocolHint) DECLARE_ENUM_FLAGS(URI::Section) QDataStream& operator<<(QDataStream& stream, const URI::ProtocolHint& ph);