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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/*
tcpserverdevice.cpp
This file is part of GammaRay, the Qt application inspection and manipulation tool.
SPDX-FileCopyrightText: 2014 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Volker Krause <volker.krause@kdab.com>
SPDX-License-Identifier: GPL-2.0-or-later
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
#include "tcpserverdevice.h"
#include "server.h"
#include <QHostAddress>
#include <QNetworkInterface>
#include <QUdpSocket>
using namespace GammaRay;
TcpServerDevice::TcpServerDevice(QObject *parent)
: ServerDeviceImpl<QTcpServer>(parent)
, m_broadcastSocket(new QUdpSocket(this))
{
m_server = new QTcpServer(this);
connect(m_server, &QTcpServer::newConnection, this, &ServerDevice::newConnection);
}
TcpServerDevice::~TcpServerDevice() = default;
bool TcpServerDevice::listen()
{
const QHostAddress address(m_address.host());
// try the requested port first, and fall back to a random port otherwise
auto result = m_server->listen(address, m_address.port());
if (!result) {
result = m_server->listen(address, 0);
}
emit externalAddressChanged();
return result;
}
bool TcpServerDevice::isListening() const
{
return m_server->isListening();
}
QString TcpServerDevice::bestAvailableIP(const QHostAddress &address) const
{
QString firstHostFound;
foreach (const QNetworkInterface &inter, QNetworkInterface::allInterfaces()) {
if (!(inter.flags() & QNetworkInterface::IsUp)
|| !(inter.flags() & QNetworkInterface::IsRunning)
|| (inter.flags() & QNetworkInterface::IsLoopBack))
continue;
foreach (const QNetworkAddressEntry &addrEntry, inter.addressEntries()) {
const QHostAddress addr = addrEntry.ip();
// Return the ip according to the listening server protocol.
if (addr.protocol() != m_server->serverAddress().protocol()
|| !addr.scopeId().isEmpty())
continue;
// If its our desired IP (e.g. from --listen) return early
if (addr == address)
return addr.toString();
if (firstHostFound.isEmpty())
firstHostFound = addr.toString();
}
}
return firstHostFound;
}
QUrl TcpServerDevice::externalAddress() const
{
const QHostAddress address(m_server->serverAddress());
QString myHost;
if (address.isLoopback()) {
myHost = address.toString();
} else {
// scan Interfaces for available IPs, use requested address if we can find it.
myHost = bestAvailableIP(address);
}
// if localhost is all we got, use that rather than nothing
if (myHost.isEmpty()) {
switch (m_server->serverAddress().protocol()) {
case QAbstractSocket::IPv4Protocol:
case QAbstractSocket::AnyIPProtocol:
myHost = QHostAddress(QHostAddress::LocalHost).toString();
break;
case QAbstractSocket::IPv6Protocol:
myHost = QHostAddress(QHostAddress::LocalHostIPv6).toString();
break;
case QAbstractSocket::UnknownNetworkLayerProtocol:
qWarning() << "TcpServerDevice::externalAddress - unknown TCP protocol";
return m_address;
}
}
QUrl url;
url.setScheme(QStringLiteral("tcp"));
url.setHost(myHost);
url.setPort(m_server->serverPort());
return url;
}
void TcpServerDevice::broadcast(const QByteArray &data)
{
const QHostAddress address = m_server->serverAddress();
// broadcast announcement only if we are actually listinging to remote connections
if (address.isLoopback())
return;
m_broadcastSocket->writeDatagram(data.data(),
data.size(), QHostAddress::Broadcast, Server::broadcastPort());
}
|