2018-12-28 18:12:45 +01:00
# pragma once
# include <utils/Logger.h>
# include <QTcpServer>
2021-11-17 21:30:43 +01:00
# include <QUrl>
# include <QHostAddress>
# include <QHostInfo>
2018-12-28 18:12:45 +01:00
namespace NetUtils {
2021-11-17 21:30:43 +01:00
const int MAX_PORT = 65535 ;
2018-12-28 18:12:45 +01:00
///
/// @brief Check if the port is available for listening
/// @param[in/out] port The port to test, will be incremented if port is in use
/// @param log The logger of the caller to print
/// @return True on success else false
///
2021-11-17 21:30:43 +01:00
inline bool portAvailable ( quint16 & port , Logger * log )
2018-12-28 18:12:45 +01:00
{
const quint16 prevPort = port ;
QTcpServer server ;
while ( ! server . listen ( QHostAddress : : Any , port ) )
{
Warning ( log , " Port '%d' is already in use, will increment " , port ) ;
port + + ;
}
server . close ( ) ;
2020-06-28 23:12:22 +02:00
if ( port ! = prevPort )
2018-12-28 18:12:45 +01:00
{
Warning ( log , " The requested Port '%d' was already in use, will use Port '%d' instead " , prevPort , port ) ;
return false ;
}
return true ;
}
2021-11-17 21:30:43 +01:00
///
/// @brief Check if the port is in the valid range
/// @param log The logger of the caller to print///
/// @param[in] port The port to be tested
/// @param[in] host A hostname/IP-address to make reference to during logging
/// @return True on success else false
///
inline bool isValidPort ( Logger * log , int port , const QString & host )
{
if ( port < = 0 | | port > MAX_PORT )
{
Error ( log , " Invalid port [%d] for host: %s! " , port , QSTRING_CSTR ( host ) ) ;
return false ;
}
return true ;
}
///
/// @brief Get host and port from an host address
/// @param[in] address Hostname or IP-address with or without port (e.g. 192.168.1.100:4711, 2003:e4:c73a:8e00:d5bb:dc3c:50cb:c76e, hyperion.fritz.box)
/// @param[in/out] host The resolved hostname or IP-address
/// @param[in/out] port The resolved port, if available.
/// @return True on success else false
///
inline bool resolveHostPort ( const QString & address , QString & host , quint16 & port )
{
2021-11-29 18:51:03 +01:00
if ( address . isEmpty ( ) )
{
return false ;
}
2021-11-17 21:30:43 +01:00
QString testUrl ;
if ( address . at ( 0 ) ! = ' [ ' & & address . count ( ' : ' ) > 1 )
{
testUrl = QString ( " http://[%1] " ) . arg ( address ) ;
}
else
{
testUrl = QString ( " http://%1 " ) . arg ( address ) ;
}
QUrl url ( testUrl ) ;
if ( ! url . isValid ( ) )
{
return false ;
}
host = url . host ( ) ;
if ( url . port ( ) ! = - 1 )
{
port = url . port ( ) ;
}
return true ;
}
///
/// @brief Check if the port is in the valid range
2021-11-29 18:51:03 +01:00
/// @param log The logger of the caller to print
/// @param[in] address The port to be tested
2021-11-17 21:30:43 +01:00
/// @param[out] hostAddress A hostname to make reference to during logging
2021-11-29 18:51:03 +01:00
/// @return True on success else false
2021-11-17 21:30:43 +01:00
///
inline bool resolveHostAddress ( Logger * log , const QString & address , QHostAddress & hostAddress )
{
bool isHostAddressOK { false } ;
if ( hostAddress . setAddress ( address ) )
{
Debug ( log , " Successfully parsed %s as an IP-address. " , QSTRING_CSTR ( hostAddress . toString ( ) ) ) ;
isHostAddressOK = true ;
}
else
{
QHostInfo hostInfo = QHostInfo : : fromName ( address ) ;
if ( hostInfo . error ( ) = = QHostInfo : : NoError )
{
hostAddress = hostInfo . addresses ( ) . first ( ) ;
Debug ( log , " Successfully resolved IP-address (%s) for hostname (%s). " , QSTRING_CSTR ( hostAddress . toString ( ) ) , QSTRING_CSTR ( address ) ) ;
isHostAddressOK = true ;
}
else
{
QString errortext = QString ( " Failed resolving IP-address for [%1], (%2) %3 " ) . arg ( address ) . arg ( hostInfo . error ( ) ) . arg ( hostInfo . errorString ( ) ) ;
Error ( log , " %s " , QSTRING_CSTR ( errortext ) ) ;
isHostAddressOK = false ;
}
}
return isHostAddressOK ;
}
2018-12-28 18:12:45 +01:00
}