|
|
@ -7,14 +7,6 @@ |
|
|
|
* |
|
|
|
* |
|
|
|
****************************************************************************/ |
|
|
|
****************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @file |
|
|
|
|
|
|
|
* @brief Definition of UDP connection (server) for unmanned vehicles |
|
|
|
|
|
|
|
* @author Lorenz Meier <mavteam@student.ethz.ch> |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <QtGlobal> |
|
|
|
#include <QtGlobal> |
|
|
|
#include <QTimer> |
|
|
|
#include <QTimer> |
|
|
|
#include <QList> |
|
|
|
#include <QList> |
|
|
@ -31,15 +23,12 @@ |
|
|
|
#include "SettingsManager.h" |
|
|
|
#include "SettingsManager.h" |
|
|
|
#include "AutoConnectSettings.h" |
|
|
|
#include "AutoConnectSettings.h" |
|
|
|
|
|
|
|
|
|
|
|
#define REMOVE_GONE_HOSTS 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char* kZeroconfRegistration = "_qgroundcontrol._udp"; |
|
|
|
static const char* kZeroconfRegistration = "_qgroundcontrol._udp"; |
|
|
|
|
|
|
|
|
|
|
|
static bool is_ip(const QString& address) |
|
|
|
static bool is_ip(const QString& address) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int a,b,c,d; |
|
|
|
int a,b,c,d; |
|
|
|
if (sscanf(address.toStdString().c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4 |
|
|
|
if (sscanf(address.toStdString().c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4 && strcmp("::1", address.toStdString().c_str())) { |
|
|
|
&& strcmp("::1", address.toStdString().c_str())) { |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -48,28 +37,27 @@ static bool is_ip(const QString& address) |
|
|
|
|
|
|
|
|
|
|
|
static QString get_ip_address(const QString& address) |
|
|
|
static QString get_ip_address(const QString& address) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(is_ip(address)) |
|
|
|
if (is_ip(address)) { |
|
|
|
return address; |
|
|
|
return address; |
|
|
|
|
|
|
|
} |
|
|
|
// Need to look it up
|
|
|
|
// Need to look it up
|
|
|
|
QHostInfo info = QHostInfo::fromName(address); |
|
|
|
QHostInfo info = QHostInfo::fromName(address); |
|
|
|
if (info.error() == QHostInfo::NoError) |
|
|
|
if (info.error() == QHostInfo::NoError) { |
|
|
|
{ |
|
|
|
|
|
|
|
QList<QHostAddress> hostAddresses = info.addresses(); |
|
|
|
QList<QHostAddress> hostAddresses = info.addresses(); |
|
|
|
for (int i = 0; i < hostAddresses.size(); i++) |
|
|
|
for (int i=0; i<hostAddresses.size(); i++) { |
|
|
|
{ |
|
|
|
|
|
|
|
// Exclude all IPv6 addresses
|
|
|
|
// Exclude all IPv6 addresses
|
|
|
|
if (!hostAddresses.at(i).toString().contains(":")) |
|
|
|
if (!hostAddresses.at(i).toString().contains(":")) { |
|
|
|
{ |
|
|
|
|
|
|
|
return hostAddresses.at(i).toString(); |
|
|
|
return hostAddresses.at(i).toString(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return {}; |
|
|
|
return QString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool contains_target(const QList<UDPCLient*> list, const QHostAddress& address, quint16 port) |
|
|
|
static bool contains_target(const QList<UDPCLient*> list, const QHostAddress& address, quint16 port) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for(UDPCLient* target: list) { |
|
|
|
for (int i=0; i<list.count(); i++) { |
|
|
|
|
|
|
|
UDPCLient* target = list[i]; |
|
|
|
if (target->address == address && target->port == port) { |
|
|
|
if (target->address == address && target->port == port) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
@ -90,8 +78,10 @@ UDPLink::UDPLink(SharedLinkConfigurationPointer& config) |
|
|
|
if (!_udpConfig) { |
|
|
|
if (!_udpConfig) { |
|
|
|
qWarning() << "Internal error"; |
|
|
|
qWarning() << "Internal error"; |
|
|
|
} |
|
|
|
} |
|
|
|
for (const QHostAddress &address: QNetworkInterface::allAddresses()) { |
|
|
|
auto allAddresses = QNetworkInterface::allAddresses(); |
|
|
|
_localAddress.append(QHostAddress(address)); |
|
|
|
for (int i=0; i<allAddresses.count(); i++) { |
|
|
|
|
|
|
|
QHostAddress &address = allAddresses[i]; |
|
|
|
|
|
|
|
_localAddresses.append(QHostAddress(address)); |
|
|
|
} |
|
|
|
} |
|
|
|
moveToThread(this); |
|
|
|
moveToThread(this); |
|
|
|
} |
|
|
|
} |
|
|
@ -127,8 +117,7 @@ void UDPLink::run() |
|
|
|
|
|
|
|
|
|
|
|
void UDPLink::_restartConnection() |
|
|
|
void UDPLink::_restartConnection() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(this->isConnected()) |
|
|
|
if (this->isConnected()) { |
|
|
|
{ |
|
|
|
|
|
|
|
_disconnect(); |
|
|
|
_disconnect(); |
|
|
|
_connect(); |
|
|
|
_connect(); |
|
|
|
} |
|
|
|
} |
|
|
@ -155,7 +144,8 @@ bool UDPLink::_isIpLocal(const QHostAddress& add) |
|
|
|
// On Windows, this is a very expensive call only Redmond would know
|
|
|
|
// On Windows, this is a very expensive call only Redmond would know
|
|
|
|
// why. As such, we make it once and keep the list locally. If a new
|
|
|
|
// why. As such, we make it once and keep the list locally. If a new
|
|
|
|
// interface shows up after we start, it won't be on this list.
|
|
|
|
// interface shows up after we start, it won't be on this list.
|
|
|
|
for (const QHostAddress &address: _localAddress) { |
|
|
|
for (int i=0; i<_localAddresses.count(); i++) { |
|
|
|
|
|
|
|
QHostAddress &address = _localAddresses[i]; |
|
|
|
if (address == add) { |
|
|
|
if (address == add) { |
|
|
|
// This is a local address of the same host
|
|
|
|
// This is a local address of the same host
|
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -267,8 +257,7 @@ void UDPLink::_disconnect(void) |
|
|
|
**/ |
|
|
|
**/ |
|
|
|
bool UDPLink::_connect(void) |
|
|
|
bool UDPLink::_connect(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(this->isRunning() || _running) |
|
|
|
if (this->isRunning() || _running) { |
|
|
|
{ |
|
|
|
|
|
|
|
_running = false; |
|
|
|
_running = false; |
|
|
|
quit(); |
|
|
|
quit(); |
|
|
|
wait(); |
|
|
|
wait(); |
|
|
@ -408,7 +397,8 @@ void UDPConfiguration::_copyFrom(LinkConfiguration *source) |
|
|
|
if (usource) { |
|
|
|
if (usource) { |
|
|
|
_localPort = usource->localPort(); |
|
|
|
_localPort = usource->localPort(); |
|
|
|
_clearTargetHosts(); |
|
|
|
_clearTargetHosts(); |
|
|
|
for(UDPCLient* target: usource->targetHosts()) { |
|
|
|
for (int i=0; i<usource->targetHosts().count(); i++) { |
|
|
|
|
|
|
|
UDPCLient* target = usource->targetHosts()[i]; |
|
|
|
if(!contains_target(_targetHosts, target->address, target->port)) { |
|
|
|
if(!contains_target(_targetHosts, target->address, target->port)) { |
|
|
|
UDPCLient* newTarget = new UDPCLient(target); |
|
|
|
UDPCLient* newTarget = new UDPCLient(target); |
|
|
|
_targetHosts.append(newTarget); |
|
|
|
_targetHosts.append(newTarget); |
|
|
@ -432,13 +422,10 @@ void UDPConfiguration::_clearTargetHosts() |
|
|
|
void UDPConfiguration::addHost(const QString host) |
|
|
|
void UDPConfiguration::addHost(const QString host) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Handle x.x.x.x:p
|
|
|
|
// Handle x.x.x.x:p
|
|
|
|
if (host.contains(":")) |
|
|
|
if (host.contains(":")) { |
|
|
|
{ |
|
|
|
|
|
|
|
addHost(host.split(":").first(), host.split(":").last().toUInt()); |
|
|
|
addHost(host.split(":").first(), host.split(":").last().toUInt()); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// If no port, use default
|
|
|
|
// If no port, use default
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
addHost(host, _localPort); |
|
|
|
addHost(host, _localPort); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -460,8 +447,7 @@ void UDPConfiguration::addHost(const QString& host, quint16 port) |
|
|
|
|
|
|
|
|
|
|
|
void UDPConfiguration::removeHost(const QString host) |
|
|
|
void UDPConfiguration::removeHost(const QString host) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (host.contains(":")) |
|
|
|
if (host.contains(":")) { |
|
|
|
{ |
|
|
|
|
|
|
|
QHostAddress address = QHostAddress(get_ip_address(host.split(":").first())); |
|
|
|
QHostAddress address = QHostAddress(get_ip_address(host.split(":").first())); |
|
|
|
quint16 port = host.split(":").last().toUInt(); |
|
|
|
quint16 port = host.split(":").last().toUInt(); |
|
|
|
for (int i=0; i<_targetHosts.size(); i++) { |
|
|
|
for (int i=0; i<_targetHosts.size(); i++) { |
|
|
|