Unverified Commit 6d13ae3a authored by Gus Grubba's avatar Gus Grubba Committed by GitHub

Merge pull request #6366 from mavlink/udpFixes

UDP Fixes
parents 83030ca6 50f7674b
......@@ -68,27 +68,6 @@ static QString get_ip_address(const QString& address)
return QString("");
}
static bool is_ip_local(const QHostAddress& add)
{
// In simulation and testing setups the vehicle and the GCS can be
// running on the same host. This leads to packets arriving through
// the local network or the loopback adapter, which makes it look
// like the vehicle is connected through two different links,
// complicating routing.
//
// We detect this case and force all traffic to a simulated instance
// onto the local loopback interface.
// Run through all IPv4 interfaces and check if their canonical
// IP address in string representation matches the source IP address
foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) {
if (address == add) {
// This is a local address of the same host
return true;
}
}
return false;
}
static bool contains_target(const QList<UDPCLient*> list, const QHostAddress& address, quint16 port)
{
foreach(UDPCLient* target, list) {
......@@ -112,6 +91,9 @@ UDPLink::UDPLink(SharedLinkConfigurationPointer& config)
if (!_udpConfig) {
qWarning() << "Internal error";
}
foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) {
_localAddress.append(QHostAddress(address));
}
moveToThread(this);
}
......@@ -158,10 +140,36 @@ QString UDPLink::getName() const
return _udpConfig->name();
}
bool UDPLink::_isIpLocal(const QHostAddress& add)
{
// In simulation and testing setups the vehicle and the GCS can be
// running on the same host. This leads to packets arriving through
// the local network or the loopback adapter, which makes it look
// like the vehicle is connected through two different links,
// complicating routing.
//
// We detect this case and force all traffic to a simulated instance
// onto the local loopback interface.
// Run through all IPv4 interfaces and check if their canonical
// IP address in string representation matches the source IP address
//
// 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
// interface shows up after we start, it won't be on this list.
foreach (const QHostAddress &address, _localAddress) {
if (address == add) {
// This is a local address of the same host
return true;
}
}
return false;
}
void UDPLink::_writeBytes(const QByteArray data)
{
if (!_socket)
if (!_socket) {
return;
}
// Send to all manually targeted systems
foreach(UDPCLient* target, _udpConfig->targetHosts()) {
// Skip it if it's part of the session clients below
......@@ -177,6 +185,7 @@ void UDPLink::_writeBytes(const QByteArray data)
void UDPLink::_writeDataGram(const QByteArray data, const UDPCLient* target)
{
//qDebug() << "UDP Out" << target->address << target->port;
if(_socket->writeDatagram(data, target->address, target->port) < 0) {
qWarning() << "Error writing to" << target->address << target->port;
} else {
......@@ -193,10 +202,9 @@ void UDPLink::_writeDataGram(const QByteArray data, const UDPCLient* target)
**/
void UDPLink::readBytes()
{
if (_socket) {
if (!_socket) {
return;
}
QByteArray databuffer;
while (_socket->hasPendingDatagrams())
{
......@@ -204,6 +212,7 @@ void UDPLink::readBytes()
datagram.resize(_socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
//-- Note: This call is broken in Qt 5.9.3 on Windows. It always returns a blank sender and 0 for the port.
_socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
databuffer.append(datagram);
//-- Wait a bit before sending it over
......@@ -217,7 +226,7 @@ void UDPLink::readBytes()
// would trigger this.
// Add host to broadcast list if not yet present, or update its port
QHostAddress asender = sender;
if(is_ip_local(sender)) {
if(_isIpLocal(sender)) {
asender = QHostAddress(QString("127.0.0.1"));
}
if(!contains_target(_sessionTargets, asender, senderPort)) {
......
......@@ -184,6 +184,7 @@ private:
bool _connect (void) override;
void _disconnect (void) override;
bool _isIpLocal (const QHostAddress& add);
bool _hardwareConnect ();
void _restartConnection ();
void _registerZeroconf (uint16_t port, const std::string& regType);
......@@ -194,11 +195,12 @@ private:
DNSServiceRef _dnssServiceRef;
#endif
bool _running;
QUdpSocket* _socket;
UDPConfiguration* _udpConfig;
bool _connectState;
QList<UDPCLient*> _sessionTargets;
bool _running;
QUdpSocket* _socket;
UDPConfiguration* _udpConfig;
bool _connectState;
QList<UDPCLient*> _sessionTargets;
QList<QHostAddress> _localAddress;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment