@ -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)
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
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)
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)
* */
* */
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()
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()
// 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_l ocal( sender ) ) {
if ( _isIpL ocal( 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 ) ) {