2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								///////////////////////////////////////////////////////////////////////////////////
  
						 
					
						
							
								
									
										
										
										
											2023-11-18 13:12:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Copyright (C) 2021-2022 Jon Beniston, M7RCE <jon@beniston.com>                //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Copyright (C) 2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com>               //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai>                      //
  
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								//                                                                               //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This program is free software; you can redistribute it and/or modify          //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it under the terms of the GNU General Public License as published by          //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the Free Software Foundation as version 3 of the License, or                  //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (at your option) any later version.                                           //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//                                                                               //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This program is distributed in the hope that it will be useful,               //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// but WITHOUT ANY WARRANTY; without even the implied warranty of                //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GNU General Public License V3 for more details.                               //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//                                                                               //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// You should have received a copy of the GNU General Public License             //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// along with this program. If not, see <http://www.gnu.org/licenses/>.          //
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								///////////////////////////////////////////////////////////////////////////////////
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <algorithm> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <random> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QDebug> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QTcpServer> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QTcpSocket> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QNetworkDatagram> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QEventLoop> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <QTimer> 
  
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <QRegularExpression> 
  
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "util/ax25.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "pertester.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "pertesterworker.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "pertesterreport.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MESSAGE_CLASS_DEFINITION ( PERTesterWorker : : MsgConfigurePERTesterWorker ,  Message )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MESSAGE_CLASS_DEFINITION ( PERTesterReport : : MsgReportStats ,  Message )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								PERTesterWorker : : PERTesterWorker ( )  :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_msgQueueToFeature ( nullptr ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_msgQueueToGUI ( nullptr ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_rxUDPSocket ( nullptr ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-25 09:28:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    m_txUDPSocket ( this ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_txTimer ( this ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    m_tx ( 0 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_rxMatched ( 0 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_rxUnmatched ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    connect ( & m_inputMessageQueue ,  SIGNAL ( messageEnqueued ( ) ) ,  this ,  SLOT ( handleInputMessages ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								PERTesterWorker : : ~ PERTesterWorker ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-09-20 21:13:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    stopWork ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    closeUDP ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    disconnect ( & m_inputMessageQueue ,  SIGNAL ( messageEnqueued ( ) ) ,  this ,  SLOT ( handleInputMessages ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_inputMessageQueue . clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-20 11:48:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  PERTesterWorker : : startWork ( )  
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    qDebug ( )  < <  " PERTesterWorker::startWork " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QMutexLocker  mutexLocker ( & m_mutex ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    openUDP ( m_settings ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Automatically restart if previous run had finished, otherwise continue
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_tx  > =  m_settings . m_packetCount ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        resetStats ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    connect ( & m_txTimer ,  SIGNAL ( timeout ( ) ) ,  this ,  SLOT ( tx ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_txTimer . start ( m_settings . m_interval  *  1000.0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-20 11:48:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // Handle any messages already on the queue
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    handleInputMessages ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : stopWork ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2021-11-25 09:28:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    qDebug ( )  < <  " PERTesterWorker::stopWork " ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    m_txTimer . stop ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    closeUDP ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    disconnect ( & m_txTimer ,  SIGNAL ( timeout ( ) ) ,  this ,  SLOT ( tx ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : handleInputMessages ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Message *  message ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( ( message  =  m_inputMessageQueue . pop ( ) )  ! =  nullptr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( handleMessage ( * message ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            delete  message ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : resetStats ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_tx  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_rxMatched  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_rxUnmatched  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( getMessageQueueToGUI ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        getMessageQueueToGUI ( ) - > push ( PERTesterReport : : MsgReportStats : : create ( m_tx ,  m_rxMatched ,  m_rxUnmatched ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  PERTesterWorker : : handleMessage ( const  Message &  cmd )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( MsgConfigurePERTesterWorker : : match ( cmd ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        QMutexLocker  mutexLocker ( & m_mutex ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        MsgConfigurePERTesterWorker &  cfg  =  ( MsgConfigurePERTesterWorker & )  cmd ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-26 12:35:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        applySettings ( cfg . getSettings ( ) ,  cfg . getSettingsKeys ( ) ,  cfg . getForce ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else  if  ( PERTester : : MsgResetStats : : match ( cmd ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        resetStats ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-26 12:35:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  PERTesterWorker : : applySettings ( const  PERTesterSettings &  settings ,  const  QList < QString > &  settingsKeys ,  bool  force )  
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-11-26 12:35:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    qDebug ( )  < <  " PERTesterWorker::applySettings: "  < <  settings . getDebugString ( settingsKeys ,  force ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            < <  "  force:  "  < <  force ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-26 12:35:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // if (   (settings.m_rxUDPAddress != m_settings.m_rxUDPAddress)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //     || (settings.m_rxUDPPort != m_settings.m_rxUDPPort)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //     || force)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( settingsKeys . contains ( " rxUDPAddress " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     | |  settingsKeys . contains ( " rxUDPPort " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     | |  force ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        openUDP ( settings ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-26 12:35:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( settingsKeys . contains ( " interval " )  | |  force )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        m_txTimer . setInterval ( settings . m_interval  *  1000.0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-26 12:35:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-26 12:35:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( force )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_settings  =  settings ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_settings . applySettings ( settingsKeys ,  settings ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : openUDP ( const  PERTesterSettings &  settings )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    closeUDP ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_rxUDPSocket  =  new  QUdpSocket ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! m_rxUDPSocket - > bind ( QHostAddress ( settings . m_rxUDPAddress ) ,  settings . m_rxUDPPort ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        qCritical ( )  < <  " PERTesterWorker::openUDP: Failed to bind to port  "  < <  settings . m_rxUDPAddress  < <  " : "  < <  settings . m_rxUDPPort  < <  " . Error:  "  < <  m_rxUDPSocket - > error ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( m_msgQueueToFeature ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            m_msgQueueToFeature - > push ( PERTester : : MsgReportWorker : : create ( QString ( " Failed to bind to port %1:%2 - %3 " ) . arg ( settings . m_rxUDPAddress ) . arg ( settings . m_rxUDPPort ) . arg ( m_rxUDPSocket - > error ( ) ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        qDebug ( )  < <  " PERTesterWorker::openUDP: Listening on port  "  < <  settings . m_rxUDPAddress  < <  " : "  < <  settings . m_rxUDPPort  < <  " . " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    connect ( m_rxUDPSocket ,  & QUdpSocket : : readyRead ,  this ,  & PERTesterWorker : : rx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : closeUDP ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_rxUDPSocket  ! =  nullptr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        qDebug ( )  < <  " PERTesterWorker::closeUDP: Closing port  "  < <  m_settings . m_rxUDPAddress  < <  " : "  < <  m_settings . m_rxUDPPort  < <  " . " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        disconnect ( m_rxUDPSocket ,  & QUdpSocket : : readyRead ,  this ,  & PERTesterWorker : : rx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        delete  m_rxUDPSocket ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_rxUDPSocket  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : rx ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( m_rxUDPSocket - > hasPendingDatagrams ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        QNetworkDatagram  datagram  =  m_rxUDPSocket - > receiveDatagram ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        QByteArray  packet  =  datagram . data ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Ignore header and CRC, if requested
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        packet  =  packet . mid ( m_settings . m_ignoreLeadingBytes ,  packet . size ( )  -  m_settings . m_ignoreLeadingBytes  -  m_settings . m_ignoreTrailingBytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Remove from list of transmitted packets
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( i  =  0 ;  i  <  m_txPackets . size ( ) ;  i + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( packet  = =  m_txPackets [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                m_rxMatched + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                m_txPackets . removeAt ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( i  = =  m_txPackets . size ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            qDebug ( )  < <  " PERTesterWorker::rx: Received packet that was not transmitted:  "  < <  packet . toHex ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            m_rxUnmatched + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( getMessageQueueToGUI ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        getMessageQueueToGUI ( ) - > push ( PERTesterReport : : MsgReportStats : : create ( m_tx ,  m_rxMatched ,  m_rxUnmatched ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : tx ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    QRegularExpression  ax25Dst ( " ^% \\ {ax25 \\ .dst=([A-Za-z0-9-]+) \ \ } " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QRegularExpression  ax25Src ( " ^% \\ {ax25 \\ .src=([A-Za-z0-9-]+) \ \ } " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QRegularExpression  num ( " ^% \\ {num \\ } " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QRegularExpression  data ( " ^% \\ {data=([0-9]+) , ( [ 0 - 9 ] + ) \ \ } " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QRegularExpression  hex ( " ^(0x) ? ( [ 0 - 9 a - fA - F ] ? [ 0 - 9 a - fA - F ] ) " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    QRegularExpressionMatch  match ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    QByteArray  bytes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  pos  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( pos  <  m_settings . m_packet . size ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( m_settings . m_packet [ pos ]  = =  ' % ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( ( match  =  ax25Dst . match ( m_settings . m_packet ,  pos ,  QRegularExpression : : NormalMatch ,  QRegularExpression : : AnchoredMatchOption ) ) . hasMatch ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                // AX.25 destination callsign & SSID
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                QString  address  =  match . captured ( 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                bytes . append ( AX25Packet : : encodeAddress ( address ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                pos  + =  match . capturedLength ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            else  if  ( ( match  =  ax25Src . match ( m_settings . m_packet ,  pos ,  QRegularExpression : : NormalMatch ,  QRegularExpression : : AnchoredMatchOption ) ) . hasMatch ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                // AX.25 source callsign & SSID
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                QString  address  =  match . captured ( 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                bytes . append ( AX25Packet : : encodeAddress ( address ,  1 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                pos  + =  match . capturedLength ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            else  if  ( ( match  =  num . match ( m_settings . m_packet ,  pos ,  QRegularExpression : : NormalMatch ,  QRegularExpression : : AnchoredMatchOption ) ) . hasMatch ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                // Big endian packet number
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                bytes . append ( ( m_tx  > >  24 )  &  0xff ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                bytes . append ( ( m_tx  > >  16 )  &  0xff ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                bytes . append ( ( m_tx  > >  8 )  &  0xff ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                bytes . append ( m_tx  &  0xff ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                pos  + =  match . capturedLength ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            else  if  ( ( match  =  data . match ( m_settings . m_packet ,  pos ,  QRegularExpression : : NormalMatch ,  QRegularExpression : : AnchoredMatchOption ) ) . hasMatch ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                // Constrained random number of random bytes
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                int  minBytes  =  match . captured ( 1 ) . toInt ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                int  maxBytes  =  match . captured ( 2 ) . toInt ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                std : : random_device  rd ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                std : : mt19937  gen ( rd ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                std : : uniform_int_distribution < >  distr0 ( minBytes ,  maxBytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                std : : uniform_int_distribution < >  distr1 ( 0 ,  255 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                int  count  =  distr0 ( gen ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  ( int  i  =  0 ;  i  <  count ;  i + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    bytes . append ( distr1 ( gen ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                pos  + =  match . capturedLength ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                qWarning ( )  < <  " PERTester: Unsupported substitution in packet: pos= "  < <  pos  < <  "  in  "  < <  m_settings . m_packet ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( m_settings . m_packet [ pos ]  = =  ' \" ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // ASCII string in double quotes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            int  startIdx  =  pos  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            int  endQuoteIdx  =  m_settings . m_packet . indexOf ( ' \" ' ,  startIdx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( endQuoteIdx  ! =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                int  len  =  endQuoteIdx  -  startIdx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                QString  string  =  m_settings . m_packet . mid ( startIdx ,  len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                bytes . append ( string . toLocal8Bit ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                pos  =  endQuoteIdx  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                qWarning ( )  < <  " PERTester: Unterminated string: pos= "  < <  pos  < <  "  in  "  < <  m_settings . m_packet ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else  if  ( ( match  =  hex . match ( m_settings . m_packet ,  pos ,  QRegularExpression : : NormalMatch ,  QRegularExpression : : AnchoredMatchOption ) ) . hasMatch ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // Hex byte
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            int  value  =  match . captured ( 2 ) . toInt ( nullptr ,  16 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            bytes . append ( value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-21 17:08:41 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            pos  + =  match . capturedLength ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-07 20:25:12 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( ( m_settings . m_packet [ pos ]  = =  '   ' )  | |  ( m_settings . m_packet [ pos ]  = =  ' , ' )  | |  ( m_settings . m_packet [ pos ]  = =  ' : ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            pos + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            qWarning ( )  < <  " PERTester: Unexpected character in packet: pos= "  < <  pos  < <  "  in  "  < <  m_settings . m_packet ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( pos  > =  m_settings . m_packet . size ( ) )  & &  ( m_tx  <  m_settings . m_packetCount ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Send packet via UDP
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_txUDPSocket . writeDatagram ( bytes . data ( ) ,  bytes . size ( ) ,  QHostAddress ( m_settings . m_txUDPAddress ) ,  m_settings . m_txUDPPort ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_tx + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_txPackets . append ( bytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( getMessageQueueToGUI ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            getMessageQueueToGUI ( ) - > push ( PERTesterReport : : MsgReportStats : : create ( m_tx ,  m_rxMatched ,  m_rxUnmatched ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_tx  > =  m_settings . m_packetCount ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Test complete
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_txTimer . stop ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Wait for a couple of seconds for the last packet to be received
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        QTimer : : singleShot ( 2000 ,  this ,  & PERTesterWorker : : testComplete ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  PERTesterWorker : : testComplete ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_msgQueueToFeature  ! =  nullptr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_msgQueueToFeature - > push ( PERTester : : MsgReportWorker : : create ( " Complete " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    qDebug ( )  < <  " PERTesterWorker::tx: Test complete " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}