File: NetworkServerLookup.cpp

package info (click to toggle)
js8call 2.5.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 24,724 kB
  • sloc: cpp: 562,639; sh: 898; python: 132; ansic: 102; makefile: 4
file content (76 lines) | stat: -rw-r--r-- 2,545 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "NetworkServerLookup.h"

#include <stdexcept>

#include <QHostInfo>
#include <QString>

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);
}