Commit 50f7674b authored by Gus Grubba's avatar Gus Grubba

Fixed wrong logic when testing _socket for wrtites. It was never writing (sending anything).

Work around a new Windows issue where the call to list the local network interfaces takes for freaking ever to return, blocking the UDP thread altogether.
parent 83030ca6
...@@ -68,27 +68,6 @@ static QString get_ip_address(const QString& address) ...@@ -68,27 +68,6 @@ static QString get_ip_address(const QString& address)
return QString(""); 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) static bool contains_target(const QList<UDPCLient*> list, const QHostAddress& address, quint16 port)
{ {
foreach(UDPCLient* target, list) { foreach(UDPCLient* target, list) {
...@@ -112,6 +91,9 @@ UDPLink::UDPLink(SharedLinkConfigurationPointer& config) ...@@ -112,6 +91,9 @@ UDPLink::UDPLink(SharedLinkConfigurationPointer& config)
if (!_udpConfig) { if (!_udpConfig) {
qWarning() << "Internal error"; qWarning() << "Internal error";
} }
foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) {
_localAddress.append(QHostAddress(address));
}
moveToThread(this); moveToThread(this);
} }
...@@ -158,10 +140,36 @@ QString UDPLink::getName() const ...@@ -158,10 +140,36 @@ QString UDPLink::getName() const
return _udpConfig->name(); 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) void UDPLink::_writeBytes(const QByteArray data)
{ {
if (!_socket) if (!_socket) {
return; return;
}
// Send to all manually targeted systems // Send to all manually targeted systems
foreach(UDPCLient* target, _udpConfig->targetHosts()) { foreach(UDPCLient* target, _udpConfig->targetHosts()) {
// Skip it if it's part of the session clients below // Skip it if it's part of the session clients below
...@@ -177,6 +185,7 @@ void UDPLink::_writeBytes(const QByteArray data) ...@@ -177,6 +185,7 @@ void UDPLink::_writeBytes(const QByteArray data)
void UDPLink::_writeDataGram(const QByteArray data, const UDPCLient* target) 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) { if(_socket->writeDatagram(data, target->address, target->port) < 0) {
qWarning() << "Error writing to" << target->address << target->port; qWarning() << "Error writing to" << target->address << target->port;
} else { } else {
...@@ -193,10 +202,9 @@ void UDPLink::_writeDataGram(const QByteArray data, const UDPCLient* target) ...@@ -193,10 +202,9 @@ void UDPLink::_writeDataGram(const QByteArray data, const UDPCLient* target)
**/ **/
void UDPLink::readBytes() void UDPLink::readBytes()
{ {
if (_socket) { if (!_socket) {
return; return;
} }
QByteArray databuffer; QByteArray databuffer;
while (_socket->hasPendingDatagrams()) while (_socket->hasPendingDatagrams())
{ {
...@@ -204,6 +212,7 @@ void UDPLink::readBytes() ...@@ -204,6 +212,7 @@ void UDPLink::readBytes()
datagram.resize(_socket->pendingDatagramSize()); datagram.resize(_socket->pendingDatagramSize());
QHostAddress sender; QHostAddress sender;
quint16 senderPort; 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); _socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
databuffer.append(datagram); databuffer.append(datagram);
//-- Wait a bit before sending it over //-- Wait a bit before sending it over
...@@ -217,7 +226,7 @@ void UDPLink::readBytes() ...@@ -217,7 +226,7 @@ void UDPLink::readBytes()
// would trigger this. // would trigger this.
// Add host to broadcast list if not yet present, or update its port // Add host to broadcast list if not yet present, or update its port
QHostAddress asender = sender; QHostAddress asender = sender;
if(is_ip_local(sender)) { if(_isIpLocal(sender)) {
asender = QHostAddress(QString("127.0.0.1")); asender = QHostAddress(QString("127.0.0.1"));
} }
if(!contains_target(_sessionTargets, asender, senderPort)) { if(!contains_target(_sessionTargets, asender, senderPort)) {
......
...@@ -184,6 +184,7 @@ private: ...@@ -184,6 +184,7 @@ private:
bool _connect (void) override; bool _connect (void) override;
void _disconnect (void) override; void _disconnect (void) override;
bool _isIpLocal (const QHostAddress& add);
bool _hardwareConnect (); bool _hardwareConnect ();
void _restartConnection (); void _restartConnection ();
void _registerZeroconf (uint16_t port, const std::string& regType); void _registerZeroconf (uint16_t port, const std::string& regType);
...@@ -194,11 +195,12 @@ private: ...@@ -194,11 +195,12 @@ private:
DNSServiceRef _dnssServiceRef; DNSServiceRef _dnssServiceRef;
#endif #endif
bool _running; bool _running;
QUdpSocket* _socket; QUdpSocket* _socket;
UDPConfiguration* _udpConfig; UDPConfiguration* _udpConfig;
bool _connectState; bool _connectState;
QList<UDPCLient*> _sessionTargets; 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