mirror of
https://github.com/JS8Call-improved/JS8Call-improved
synced 2026-08-13 17:47:36 -04:00
89 lines
2.8 KiB
C++
89 lines
2.8 KiB
C++
/**
|
|
* @file NetworkServerLookup.cpp
|
|
* @brief Implementation of network server lookup function
|
|
*/
|
|
#include "NetworkServerLookup.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <QHostInfo>
|
|
#include <QString>
|
|
|
|
/**
|
|
* @brief Looks up the network server address and port.
|
|
*
|
|
* @param query
|
|
* @param default_service_port
|
|
* @param default_host_address
|
|
* @param required_protocol
|
|
* @return std::tuple<QHostAddress, quint16>
|
|
*/
|
|
std::tuple<QHostAddress, quint16>
|
|
network_server_lookup(QString query, quint16 default_service_port,
|
|
QHostAddress default_host_address,
|
|
QAbstractSocket::NetworkLayerProtocol required_protocol) {
|
|
query = query.trimmed();
|
|
|
|
QHostAddress host_address{default_host_address};
|
|
quint16 service_port{default_service_port};
|
|
|
|
QString host_name;
|
|
if (!query.isEmpty()) {
|
|
qsizetype port_colon_index = -1;
|
|
|
|
if ('[' == query[0]) {
|
|
// assume IPv6 combined address/port syntax [<address>]:<port>
|
|
auto close_bracket_index = query.lastIndexOf(']');
|
|
host_name = query.mid(1, close_bracket_index - 1);
|
|
port_colon_index = query.indexOf(':', close_bracket_index);
|
|
} else {
|
|
port_colon_index = query.lastIndexOf(':');
|
|
host_name = query.left(port_colon_index);
|
|
}
|
|
host_name = host_name.trimmed();
|
|
|
|
if (port_colon_index >= 0) {
|
|
bool ok;
|
|
service_port =
|
|
query.mid(port_colon_index + 1).trimmed().toUShort(&ok);
|
|
if (!ok) {
|
|
throw std::runtime_error{
|
|
"network server lookup error: invalid port"};
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!host_name.isEmpty()) {
|
|
auto host_info = QHostInfo::fromName(host_name);
|
|
if (host_info.addresses().isEmpty()) {
|
|
throw std::runtime_error{
|
|
"network server lookup error: host name lookup failed"};
|
|
}
|
|
|
|
bool found{false};
|
|
for (int i{0}; i < host_info.addresses().size() && !found; ++i) {
|
|
host_address = host_info.addresses().at(i);
|
|
switch (required_protocol) {
|
|
case QAbstractSocket::IPv4Protocol:
|
|
case QAbstractSocket::IPv6Protocol:
|
|
if (required_protocol != host_address.protocol()) {
|
|
break;
|
|
}
|
|
[[fallthrough]];
|
|
case QAbstractSocket::AnyIPProtocol:
|
|
found = true;
|
|
break;
|
|
|
|
default:
|
|
throw std::runtime_error{
|
|
"network server lookup error: invalid required protocol"};
|
|
}
|
|
}
|
|
if (!found) {
|
|
throw std::runtime_error{
|
|
"network server lookup error: no suitable host address found"};
|
|
}
|
|
}
|
|
|
|
return std::make_tuple(host_address, service_port);
|
|
}
|