Rework the listening IP/interface selection code

Closes #11561
This commit is contained in:
sledgehammer999
2019-12-06 02:24:49 +02:00
parent d051519eff
commit 8200ef6bd5
9 changed files with 198 additions and 163 deletions

View File

@@ -28,6 +28,7 @@
#include "net.h"
#include <QNetworkInterface>
#include <QSslCertificate>
#include <QSslKey>
#include <QString>
@@ -91,6 +92,37 @@ namespace Utils
return subnet.first.toString() + '/' + QString::number(subnet.second);
}
QHostAddress canonicalIPv6Addr(const QHostAddress &addr)
{
// Link-local IPv6 textual address always contains a scope id (or zone index)
// The scope id is appended to the IPv6 address using the '%' character
// The scope id can be either a interface name or an interface number
// Examples:
// fe80::1%ethernet_17
// fe80::1%13
// The interface number is the mandatory supported way
// Unfortunately for us QHostAddress::toString() outputs (at least on Windows)
// the interface name, and libtorrent/boost.asio only support an interface number
// as scope id. Furthermore, QHostAddress doesn't have any convenient method to
// affect this, so we jump through hoops here.
if (addr.protocol() != QAbstractSocket::IPv6Protocol)
return QHostAddress{addr.toIPv6Address()};
// QHostAddress::setScopeId(addr.scopeId()); // Even though the docs say that setScopeId
// will convert a name to a number, this doesn't happen. Probably a Qt bug.
const QString scopeIdTxt = addr.scopeId();
if (scopeIdTxt.isEmpty())
return addr;
const int id = QNetworkInterface::interfaceIndexFromName(scopeIdTxt);
if (id == 0) // This failure might mean that the scope id was already a number
return addr;
QHostAddress canonical(addr.toIPv6Address());
canonical.setScopeId(QString::number(id));
return canonical;
}
QList<QSslCertificate> loadSSLCertificate(const QByteArray &data)
{
const QList<QSslCertificate> certs {QSslCertificate::fromData(data)};