2021-02-16 16:16:46 +00:00
# include "udpserver.h"
2021-02-23 21:21:22 +00:00
# include "logcategories.h"
2021-02-16 16:16:46 +00:00
2021-02-18 13:49:19 +00:00
# define STALE_CONNECTION 15
2021-11-10 20:45:59 +00:00
# define LOCK_PERIOD 10 // time to attempt to lock Mutex in ms
2022-01-12 20:01:17 +00:00
# define AUDIO_SEND_PERIOD 20 //
2022-01-27 19:11:16 +00:00
udpServer : : udpServer ( SERVERCONFIG & config , audioSetup outAudio , audioSetup inAudio ) :
config ( config ) ,
2021-06-04 13:25:07 +00:00
outAudio ( outAudio ) ,
inAudio ( inAudio )
2021-02-16 16:16:46 +00:00
{
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < " Starting udp server " ;
2021-02-16 16:16:46 +00:00
}
2022-01-16 18:47:13 +00:00
void udpServer : : init ( )
2021-02-16 16:16:46 +00:00
{
2022-01-04 21:26:03 +00:00
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * rig : config . rigs )
2022-01-26 09:49:52 +00:00
{
2022-01-27 19:11:16 +00:00
qDebug ( logUdpServer ( ) ) < < " CIV: " < < rig - > civAddr ;
qDebug ( logUdpServer ( ) ) < < " Model: " < < rig - > modelName ;
qDebug ( logUdpServer ( ) ) < < " Name: " < < rig - > rigName ;
qDebug ( logUdpServer ( ) ) < < " CIV: " < < rig - > civAddr ;
2022-01-26 09:49:52 +00:00
qDebug ( logUdpServer ( ) ) . noquote ( ) < < QString ( " GUID: {%1%2%3%4-%5%6-%7%8-%9%10-%11%12%13%14%15%16} " )
2022-01-27 19:11:16 +00:00
. arg ( rig - > guid [ 0 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 1 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 2 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 3 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 4 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 5 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 6 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 7 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 8 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 9 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 10 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 11 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 12 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 13 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 14 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
. arg ( rig - > guid [ 15 ] , 2 , 16 , QLatin1Char ( ' 0 ' ) )
2022-01-26 09:49:52 +00:00
;
}
2022-01-29 22:50:58 +00:00
srand ( time ( NULL ) ) ; // Generate random
2021-02-23 20:49:26 +00:00
timeStarted . start ( ) ;
2021-02-16 16:16:46 +00:00
// Convoluted way to find the external IP address, there must be a better way????
QString localhostname = QHostInfo : : localHostName ( ) ;
QList < QHostAddress > hostList = QHostInfo : : fromName ( localhostname ) . addresses ( ) ;
foreach ( const QHostAddress & address , hostList )
{
if ( address . protocol ( ) = = QAbstractSocket : : IPv4Protocol & & address . isLoopback ( ) = = false )
{
localIP = QHostAddress ( address . toString ( ) ) ;
}
}
2021-02-28 20:10:07 +00:00
foreach ( QNetworkInterface netInterface , QNetworkInterface : : allInterfaces ( ) )
{
// Return only the first non-loopback MAC Address
if ( ! ( netInterface . flags ( ) & QNetworkInterface : : IsLoopBack ) ) {
macAddress = netInterface . hardwareAddress ( ) ;
}
}
2021-02-16 16:16:46 +00:00
uint32_t addr = localIP . toIPv4Address ( ) ;
2022-01-13 11:17:13 +00:00
qInfo ( logUdpServer ( ) ) < < " My IP Address: " < < QHostAddress ( addr ) . toString ( ) < < " My MAC Address: " < < macAddress ;
2021-02-16 16:16:46 +00:00
controlId = ( addr > > 8 & 0xff ) < < 24 | ( addr & 0xff ) < < 16 | ( config . controlPort & 0xffff ) ;
civId = ( addr > > 8 & 0xff ) < < 24 | ( addr & 0xff ) < < 16 | ( config . civPort & 0xffff ) ;
audioId = ( addr > > 8 & 0xff ) < < 24 | ( addr & 0xff ) < < 16 | ( config . audioPort & 0xffff ) ;
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < " Server Binding Control to: " < < config . controlPort ;
2021-02-16 16:16:46 +00:00
udpControl = new QUdpSocket ( this ) ;
2021-06-01 16:49:48 +00:00
udpControl - > bind ( config . controlPort ) ;
2021-02-28 20:10:07 +00:00
QUdpSocket : : connect ( udpControl , & QUdpSocket : : readyRead , this , & udpServer : : controlReceived ) ;
2021-02-17 23:10:26 +00:00
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < " Server Binding CIV to: " < < config . civPort ;
2021-02-16 16:16:46 +00:00
udpCiv = new QUdpSocket ( this ) ;
2021-02-17 23:10:26 +00:00
udpCiv - > bind ( config . civPort ) ;
2021-02-28 20:10:07 +00:00
QUdpSocket : : connect ( udpCiv , & QUdpSocket : : readyRead , this , & udpServer : : civReceived ) ;
2021-02-16 16:16:46 +00:00
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < " Server Binding Audio to: " < < config . audioPort ;
2021-02-28 20:10:07 +00:00
udpAudio = new QUdpSocket ( this ) ;
udpAudio - > bind ( config . audioPort ) ;
2021-02-16 16:16:46 +00:00
QUdpSocket : : connect ( udpAudio , & QUdpSocket : : readyRead , this , & udpServer : : audioReceived ) ;
2021-06-11 09:20:09 +00:00
2021-06-11 11:53:00 +00:00
wdTimer = new QTimer ( ) ;
connect ( wdTimer , & QTimer : : timeout , this , & udpServer : : watchdog ) ;
wdTimer - > start ( 500 ) ;
2021-02-16 16:16:46 +00:00
}
udpServer : : ~ udpServer ( )
{
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < " Closing udpServer " ;
2021-02-16 16:16:46 +00:00
2021-02-17 23:10:26 +00:00
foreach ( CLIENT * client , controlClients )
2021-02-16 16:16:46 +00:00
{
2021-10-20 11:47:16 +00:00
deleteConnection ( & controlClients , client ) ;
2021-02-28 20:10:07 +00:00
2021-02-16 16:16:46 +00:00
}
2021-02-17 23:10:26 +00:00
foreach ( CLIENT * client , civClients )
2021-02-16 16:16:46 +00:00
{
2021-10-20 11:47:16 +00:00
deleteConnection ( & civClients , client ) ;
2021-02-16 16:16:46 +00:00
}
2021-10-20 11:47:16 +00:00
2021-02-17 23:10:26 +00:00
foreach ( CLIENT * client , audioClients )
2021-02-16 16:16:46 +00:00
{
2021-10-20 11:47:16 +00:00
deleteConnection ( & audioClients , client ) ;
2021-03-22 09:10:03 +00:00
}
2021-02-18 13:49:19 +00:00
2022-01-29 22:50:58 +00:00
// Now all connections are deleted, close and delete the sockets
2021-02-17 23:10:26 +00:00
if ( udpControl ! = Q_NULLPTR ) {
udpControl - > close ( ) ;
delete udpControl ;
}
if ( udpCiv ! = Q_NULLPTR ) {
udpCiv - > close ( ) ;
delete udpCiv ;
}
if ( udpAudio ! = Q_NULLPTR ) {
udpAudio - > close ( ) ;
delete udpAudio ;
}
2022-02-02 16:02:40 +00:00
status . message = QString ( " " ) ;
emit haveNetworkStatus ( status ) ;
2021-02-16 16:16:46 +00:00
}
2021-02-28 20:10:07 +00:00
void udpServer : : receiveRigCaps ( rigCapabilities caps )
{
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * rig : config . rigs ) {
2022-01-29 22:50:58 +00:00
if ( ! memcmp ( rig - > guid , caps . guid , GUIDLEN ) ) {
2022-01-26 09:49:52 +00:00
// Matching rig, fill-in missing details
2022-01-27 19:11:16 +00:00
rig - > rigAvailable = true ;
rig - > modelName = caps . modelName ;
rig - > civAddr = caps . civ ;
2022-01-29 22:50:58 +00:00
if ( rig - > rigName = = " <NONE> " ) {
2022-01-27 19:11:16 +00:00
rig - > rigName = caps . modelName ;
2022-01-26 09:49:52 +00:00
}
}
}
2021-02-28 20:10:07 +00:00
}
2022-01-29 22:50:58 +00:00
2021-02-16 16:16:46 +00:00
void udpServer : : controlReceived ( )
{
// Received data on control port.
while ( udpControl - > hasPendingDatagrams ( ) ) {
QNetworkDatagram datagram = udpControl - > receiveDatagram ( ) ;
QByteArray r = datagram . data ( ) ;
CLIENT * current = Q_NULLPTR ;
2021-02-18 13:49:19 +00:00
if ( datagram . senderAddress ( ) . isNull ( ) | | datagram . senderPort ( ) = = 65535 | | datagram . senderPort ( ) = = 0 )
2021-02-18 09:14:41 +00:00
return ;
2021-02-16 16:16:46 +00:00
foreach ( CLIENT * client , controlClients )
{
2021-02-18 13:49:19 +00:00
if ( client ! = Q_NULLPTR )
2021-02-16 16:16:46 +00:00
{
2021-02-18 13:49:19 +00:00
if ( client - > ipAddress = = datagram . senderAddress ( ) & & client - > port = = datagram . senderPort ( ) )
{
current = client ;
}
2021-02-16 16:16:46 +00:00
}
}
if ( current = = Q_NULLPTR )
{
current = new CLIENT ( ) ;
2021-05-14 08:55:02 +00:00
current - > type = " Control " ;
2021-02-16 16:16:46 +00:00
current - > connected = true ;
2021-06-10 09:57:39 +00:00
current - > isAuthenticated = false ;
2021-02-17 23:10:26 +00:00
current - > isStreaming = false ;
current - > timeConnected = QDateTime : : currentDateTime ( ) ;
2021-02-16 16:16:46 +00:00
current - > ipAddress = datagram . senderAddress ( ) ;
current - > port = datagram . senderPort ( ) ;
2021-02-17 23:10:26 +00:00
current - > civPort = config . civPort ;
current - > audioPort = config . audioPort ;
2021-02-16 16:16:46 +00:00
current - > myId = controlId ;
current - > remoteId = qFromLittleEndian < quint32 > ( r . mid ( 8 , 4 ) ) ;
current - > socket = udpControl ;
2021-02-17 23:10:26 +00:00
current - > pingSeq = ( quint8 ) rand ( ) < < 8 | ( quint8 ) rand ( ) ;
2021-02-28 20:10:07 +00:00
2021-02-16 16:16:46 +00:00
current - > pingTimer = new QTimer ( ) ;
2021-02-18 13:49:19 +00:00
connect ( current - > pingTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendPing , this , & controlClients , current , ( quint16 ) 0x00 , false ) ) ;
2021-02-16 16:16:46 +00:00
current - > pingTimer - > start ( 100 ) ;
2021-02-28 20:10:07 +00:00
current - > idleTimer = new QTimer ( ) ;
connect ( current - > idleTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendControl , this , current , ( quint8 ) 0x00 , ( quint16 ) 0x00 ) ) ;
2021-02-16 16:16:46 +00:00
current - > idleTimer - > start ( 100 ) ;
2021-02-28 20:10:07 +00:00
current - > retransmitTimer = new QTimer ( ) ;
connect ( current - > retransmitTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendRetransmitRequest , this , current ) ) ;
current - > retransmitTimer - > start ( RETRANSMIT_PERIOD ) ;
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : New Control connection created " ;
2021-05-14 08:55:02 +00:00
2021-11-15 19:28:44 +00:00
if ( connMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-11-10 20:45:59 +00:00
{
controlClients . append ( current ) ;
connMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock connMutex() " ;
}
2021-02-16 16:16:46 +00:00
}
2021-02-17 23:10:26 +00:00
current - > lastHeard = QDateTime : : currentDateTime ( ) ;
2021-02-16 16:16:46 +00:00
switch ( r . length ( ) )
{
2021-06-01 16:49:48 +00:00
case ( CONTROL_SIZE ) :
{
control_packet_t in = ( control_packet_t ) r . constData ( ) ;
if ( in - > type = = 0x05 )
2021-02-16 16:16:46 +00:00
{
2021-06-01 16:49:48 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Received 'disconnect' request " ;
sendControl ( current , 0x00 , in - > seq ) ;
2021-06-11 08:56:19 +00:00
if ( current - > audioClient ! = Q_NULLPTR ) {
deleteConnection ( & audioClients , current - > audioClient ) ;
}
if ( current - > civClient ! = Q_NULLPTR ) {
deleteConnection ( & civClients , current - > civClient ) ;
}
2021-06-01 16:49:48 +00:00
deleteConnection ( & controlClients , current ) ;
2021-06-11 09:20:09 +00:00
return ;
2021-02-21 21:05:58 +00:00
}
2021-06-01 16:49:48 +00:00
break ;
}
case ( PING_SIZE ) :
{
ping_packet_t in = ( ping_packet_t ) r . constData ( ) ;
if ( in - > type = = 0x07 )
2021-02-16 16:16:46 +00:00
{
2021-06-01 16:49:48 +00:00
// It is a ping request/response
2021-02-21 21:05:58 +00:00
2021-06-01 16:49:48 +00:00
if ( in - > reply = = 0x00 )
{
current - > rxPingTime = in - > time ;
sendPing ( & controlClients , current , in - > seq , true ) ;
}
else if ( in - > reply = = 0x01 ) {
2022-01-05 14:45:34 +00:00
// A Reply to our ping!
if ( in - > seq = = current - > pingSeq ) {
current - > pingSeq + + ;
2021-02-16 16:16:46 +00:00
}
}
}
2021-06-01 16:49:48 +00:00
break ;
}
case ( TOKEN_SIZE ) :
{
// Token request
token_packet_t in = ( token_packet_t ) r . constData ( ) ;
current - > rxSeq = in - > seq ;
current - > authInnerSeq = in - > innerseq ;
2022-01-21 19:23:32 +00:00
memcpy ( current - > macaddress , in - > macaddress , 6 ) ;
2021-06-01 16:49:48 +00:00
if ( in - > res = = 0x02 ) {
// Request for new token
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Received create token request " ;
sendCapabilities ( current ) ;
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * radio : config . rigs ) {
sendConnectionInfo ( current , radio - > guid ) ;
2022-01-26 09:49:52 +00:00
}
2021-02-16 16:16:46 +00:00
}
2021-06-01 16:49:48 +00:00
else if ( in - > res = = 0x01 ) {
// Token disconnect
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Received token disconnect request " ;
sendTokenResponse ( current , in - > res ) ;
}
else if ( in - > res = = 0x04 ) {
// Disconnect audio/civ
sendTokenResponse ( current , in - > res ) ;
current - > isStreaming = false ;
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * radio : config . rigs ) {
2022-01-29 22:50:58 +00:00
if ( ! memcmp ( radio - > guid , current - > guid , GUIDLEN ) )
2022-01-26 09:49:52 +00:00
{
2022-01-27 19:11:16 +00:00
sendConnectionInfo ( current , radio - > guid ) ;
2022-01-26 09:49:52 +00:00
}
}
2021-06-01 16:49:48 +00:00
}
else {
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Received token request " ;
sendTokenResponse ( current , in - > res ) ;
}
break ;
}
case ( LOGIN_SIZE ) :
{
login_packet_t in = ( login_packet_t ) r . constData ( ) ;
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Received 'login' " ;
foreach ( SERVERUSER user , config . users )
2021-02-16 16:16:46 +00:00
{
2021-06-01 16:49:48 +00:00
QByteArray usercomp ;
passcode ( user . username , usercomp ) ;
2021-06-10 19:32:55 +00:00
QByteArray passcomp ;
passcode ( user . password , passcomp ) ;
2021-07-26 09:27:39 +00:00
if ( ! user . username . trimmed ( ) . isEmpty ( ) & & ! user . password . trimmed ( ) . isEmpty ( ) & & ! strcmp ( in - > username , usercomp . constData ( ) ) & &
( ! strcmp ( in - > password , user . password . toUtf8 ( ) ) | | ! strcmp ( in - > password , passcomp . constData ( ) ) ) )
2021-02-16 16:16:46 +00:00
{
2021-06-10 09:57:39 +00:00
current - > isAuthenticated = true ;
2021-06-01 16:49:48 +00:00
current - > user = user ;
break ;
2021-02-23 20:49:26 +00:00
}
2021-02-21 21:05:58 +00:00
}
2021-06-01 16:49:48 +00:00
// Generate login response
current - > rxSeq = in - > seq ;
current - > clientName = in - > name ;
current - > authInnerSeq = in - > innerseq ;
current - > tokenRx = in - > tokrequest ;
current - > tokenTx = ( quint8 ) rand ( ) | ( quint8 ) rand ( ) < < 8 | ( quint8 ) rand ( ) < < 16 | ( quint8 ) rand ( ) < < 24 ;
2021-06-10 09:57:39 +00:00
if ( current - > isAuthenticated ) {
2021-06-01 16:49:48 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : User " < < current - > user . username < < " login OK " ;
}
else {
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Incorrect username/password " ;
}
2021-10-21 23:24:15 +00:00
sendLoginResponse ( current , current - > isAuthenticated ) ;
2021-06-01 16:49:48 +00:00
break ;
}
case ( CONNINFO_SIZE ) :
{
conninfo_packet_t in = ( conninfo_packet_t ) r . constData ( ) ;
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Received request for radio connection " ;
// Request to start audio and civ!
current - > isStreaming = true ;
current - > rxSeq = in - > seq ;
current - > rxCodec = in - > rxcodec ;
current - > txCodec = in - > txcodec ;
current - > rxSampleRate = qFromBigEndian < quint32 > ( in - > rxsample ) ;
current - > txSampleRate = qFromBigEndian < quint32 > ( in - > txsample ) ;
current - > txBufferLen = qFromBigEndian < quint32 > ( in - > txbuffer ) ;
current - > authInnerSeq = in - > innerseq ;
2022-01-21 19:23:32 +00:00
2022-01-29 22:50:58 +00:00
memcpy ( current - > guid , in - > guid , GUIDLEN ) ;
2021-06-01 16:49:48 +00:00
sendStatus ( current ) ;
current - > authInnerSeq = 0x00 ;
2022-01-26 09:49:52 +00:00
sendConnectionInfo ( current , in - > guid ) ;
2021-06-01 16:49:48 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : rxCodec: " < < current - > rxCodec < < " txCodec: " < < current - > txCodec < <
" rxSampleRate " < < current - > rxSampleRate < <
2021-08-14 18:02:04 +00:00
" txSampleRate " < < current - > txSampleRate < <
2021-06-01 16:49:48 +00:00
" txBufferLen " < < current - > txBufferLen ;
2021-06-04 07:24:26 +00:00
2022-01-27 19:11:16 +00:00
audioSetup setup ;
setup . resampleQuality = config . resampleQuality ;
for ( RIGCONFIG * radio : config . rigs ) {
2022-01-29 22:50:58 +00:00
if ( ! memcmp ( radio - > guid , current - > guid , GUIDLEN ) & & radio - > txaudio = = Q_NULLPTR )
2022-01-27 19:11:16 +00:00
{
radio - > txAudioSetup . codec = current - > txCodec ;
2022-04-03 19:16:52 +00:00
radio - > txAudioSetup . format . setSampleRate ( current - > txSampleRate ) ;
2022-01-27 19:11:16 +00:00
radio - > txAudioSetup . isinput = false ;
radio - > txAudioSetup . latency = current - > txBufferLen ;
2022-04-10 22:13:51 +00:00
2022-01-27 19:11:16 +00:00
outAudio . isinput = false ;
2021-06-04 07:24:26 +00:00
2022-01-27 19:11:16 +00:00
radio - > txaudio = new audioHandler ( ) ;
radio - > txAudioThread = new QThread ( this ) ;
2021-03-22 09:10:03 +00:00
2022-01-27 19:11:16 +00:00
radio - > txaudio - > moveToThread ( radio - > txAudioThread ) ;
2021-09-22 10:07:07 +00:00
2022-01-27 19:11:16 +00:00
radio - > txAudioThread - > start ( QThread : : TimeCriticalPriority ) ;
2021-03-22 09:10:03 +00:00
2022-01-30 10:29:23 +00:00
connect ( this , SIGNAL ( setupTxAudio ( audioSetup ) ) , radio - > txaudio , SLOT ( init ( audioSetup ) ) ) ;
2022-01-27 19:11:16 +00:00
connect ( radio - > txAudioThread , SIGNAL ( finished ( ) ) , radio - > txaudio , SLOT ( deleteLater ( ) ) ) ;
2021-03-22 09:10:03 +00:00
2022-01-27 22:51:28 +00:00
// Not sure how we make this work in QT5.9?
# if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
2022-01-27 19:11:16 +00:00
QMetaObject : : invokeMethod ( radio - > txaudio , [ = ] ( ) {
radio - > txaudio - > init ( radio - > txAudioSetup ) ;
} , Qt : : QueuedConnection ) ;
2022-01-27 22:51:28 +00:00
# else
2022-01-30 10:52:40 +00:00
emit setupTxAudio ( radio - > txAudioSetup ) ;
2022-01-30 10:29:23 +00:00
# warning "QT 5.9 is not fully supported multiple rigs will NOT work!"
2022-01-27 22:51:28 +00:00
# endif
2022-01-27 19:11:16 +00:00
hasTxAudio = datagram . senderAddress ( ) ;
2021-03-22 09:10:03 +00:00
2022-01-27 19:11:16 +00:00
connect ( this , SIGNAL ( haveAudioData ( audioPacket ) ) , radio - > txaudio , SLOT ( incomingAudio ( audioPacket ) ) ) ;
2021-03-22 09:10:03 +00:00
2022-01-27 19:11:16 +00:00
}
2022-01-29 22:50:58 +00:00
if ( ! memcmp ( radio - > guid , current - > guid , GUIDLEN ) & & radio - > rxaudio = = Q_NULLPTR )
2022-01-27 19:11:16 +00:00
{
# if !defined(PORTAUDIO) && !defined(RTAUDIO)
qInfo ( logUdpServer ( ) ) < < " Radio " < < radio - > rigName < < " audio input(RX) : " < < radio - > rxAudioSetup . port . deviceName ( ) ;
qInfo ( logUdpServer ( ) ) < < " Radio " < < radio - > rigName < < " audio output(TX) : " < < radio - > txAudioSetup . port . deviceName ( ) ;
# else
qInfo ( logUdpServer ( ) ) < < " Server audio input (RX): " < < inAudio . name ;
qInfo ( logUdpServer ( ) ) < < " Server audio output (TX): " < < outAudio . name ;
# endif
2021-06-04 13:25:07 +00:00
2022-01-27 19:11:16 +00:00
radio - > rxAudioSetup . codec = current - > rxCodec ;
2022-04-03 19:16:52 +00:00
radio - > rxAudioSetup . format . setSampleRate ( current - > rxSampleRate ) ;
2022-01-27 19:11:16 +00:00
radio - > rxAudioSetup . latency = current - > txBufferLen ;
radio - > rxAudioSetup . isinput = true ;
2022-04-10 22:13:51 +00:00
memcpy ( radio - > rxAudioSetup . guid , radio - > guid , GUIDLEN ) ;
2021-08-19 09:21:30 +00:00
2022-01-27 19:11:16 +00:00
radio - > rxaudio = new audioHandler ( ) ;
2021-08-23 22:59:40 +00:00
2022-01-27 19:11:16 +00:00
radio - > rxAudioThread = new QThread ( this ) ;
2021-08-27 16:18:12 +00:00
2022-01-27 19:11:16 +00:00
radio - > rxaudio - > moveToThread ( radio - > rxAudioThread ) ;
2021-03-22 09:10:03 +00:00
2022-01-27 19:11:16 +00:00
radio - > rxAudioThread - > start ( QThread : : TimeCriticalPriority ) ;
2021-03-22 09:10:03 +00:00
2022-01-30 10:29:23 +00:00
connect ( this , SIGNAL ( setupRxAudio ( audioSetup ) ) , radio - > rxaudio , SLOT ( init ( audioSetup ) ) ) ;
2022-01-27 19:11:16 +00:00
connect ( radio - > rxAudioThread , SIGNAL ( finished ( ) ) , radio - > rxaudio , SLOT ( deleteLater ( ) ) ) ;
2022-04-10 22:13:51 +00:00
connect ( radio - > rxaudio , SIGNAL ( haveAudioData ( audioPacket ) ) , this , SLOT ( receiveAudioData ( audioPacket ) ) ) ;
2021-03-22 09:10:03 +00:00
2022-01-27 22:51:28 +00:00
# if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
2022-01-27 19:11:16 +00:00
QMetaObject : : invokeMethod ( radio - > rxaudio , [ = ] ( ) {
radio - > rxaudio - > init ( radio - > rxAudioSetup ) ;
} , Qt : : QueuedConnection ) ;
2022-01-27 22:51:28 +00:00
# else
2022-01-30 10:29:23 +00:00
# warning "QT 5.9 is not fully supported multiple rigs will NOT work!"
setupRxAudio ( radio - > rxAudioSetup ) ;
2022-01-27 22:51:28 +00:00
# endif
2022-01-27 19:11:16 +00:00
2021-03-22 09:10:03 +00:00
}
2021-02-16 16:16:46 +00:00
}
2021-06-01 16:49:48 +00:00
break ;
}
default :
{
break ;
}
2021-02-16 16:16:46 +00:00
}
2021-06-10 08:09:11 +00:00
2021-06-11 09:16:13 +00:00
// Connection "may" have been deleted so check before calling common function.
if ( current ! = Q_NULLPTR ) {
commonReceived ( & controlClients , current , r ) ;
}
2021-02-16 16:16:46 +00:00
}
}
void udpServer : : civReceived ( )
{
while ( udpCiv - > hasPendingDatagrams ( ) ) {
QNetworkDatagram datagram = udpCiv - > receiveDatagram ( ) ;
QByteArray r = datagram . data ( ) ;
2021-02-16 20:55:30 +00:00
2021-02-17 23:10:26 +00:00
CLIENT * current = Q_NULLPTR ;
2021-02-18 13:49:19 +00:00
if ( datagram . senderAddress ( ) . isNull ( ) | | datagram . senderPort ( ) = = 65535 | | datagram . senderPort ( ) = = 0 )
2021-02-18 09:14:41 +00:00
return ;
2021-02-18 13:49:19 +00:00
QDateTime now = QDateTime : : currentDateTime ( ) ;
2021-02-17 23:10:26 +00:00
foreach ( CLIENT * client , civClients )
{
2021-02-18 13:49:19 +00:00
if ( client ! = Q_NULLPTR )
2021-02-17 23:10:26 +00:00
{
2021-02-18 13:49:19 +00:00
if ( client - > ipAddress = = datagram . senderAddress ( ) & & client - > port = = datagram . senderPort ( ) )
{
current = client ;
}
2021-02-17 23:10:26 +00:00
}
}
2021-06-10 09:57:39 +00:00
2021-02-17 23:10:26 +00:00
if ( current = = Q_NULLPTR )
{
current = new CLIENT ( ) ;
2021-06-11 08:56:19 +00:00
foreach ( CLIENT * client , controlClients )
{
if ( client ! = Q_NULLPTR )
{
if ( client - > ipAddress = = datagram . senderAddress ( ) & & client - > isAuthenticated & & client - > civClient = = Q_NULLPTR )
{
current - > controlClient = client ;
client - > civClient = current ;
2022-01-29 22:50:58 +00:00
memcpy ( current - > guid , client - > guid , GUIDLEN ) ;
2021-06-11 08:56:19 +00:00
}
}
}
2021-08-15 13:41:54 +00:00
if ( current - > controlClient = = Q_NULLPTR | | ! current - > controlClient - > isAuthenticated )
{
// There is no current controlClient that matches this civClient
delete current ;
return ;
}
2021-05-14 08:55:02 +00:00
current - > type = " CIV " ;
current - > civId = 0 ;
2021-02-17 23:10:26 +00:00
current - > connected = true ;
current - > timeConnected = QDateTime : : currentDateTime ( ) ;
current - > ipAddress = datagram . senderAddress ( ) ;
current - > port = datagram . senderPort ( ) ;
current - > myId = civId ;
current - > remoteId = qFromLittleEndian < quint32 > ( r . mid ( 8 , 4 ) ) ;
current - > socket = udpCiv ;
current - > pingSeq = ( quint8 ) rand ( ) < < 8 | ( quint8 ) rand ( ) ;
2021-02-28 20:10:07 +00:00
2021-02-17 23:10:26 +00:00
current - > pingTimer = new QTimer ( ) ;
2021-02-18 13:49:19 +00:00
connect ( current - > pingTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendPing , this , & civClients , current , ( quint16 ) 0x00 , false ) ) ;
2021-02-17 23:10:26 +00:00
current - > pingTimer - > start ( 100 ) ;
2021-02-28 20:10:07 +00:00
current - > idleTimer = new QTimer ( ) ;
connect ( current - > idleTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendControl , this , current , 0x00 , ( quint16 ) 0x00 ) ) ;
2021-05-14 08:55:02 +00:00
//current->idleTimer->start(100); // Start idleTimer after receiving iamready.
2021-02-28 20:10:07 +00:00
current - > retransmitTimer = new QTimer ( ) ;
connect ( current - > retransmitTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendRetransmitRequest , this , current ) ) ;
current - > retransmitTimer - > start ( RETRANSMIT_PERIOD ) ;
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): New connection created " ;
2021-11-10 20:45:59 +00:00
if ( connMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
civClients . append ( current ) ;
connMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock connMutex() " ;
}
2021-05-14 08:55:02 +00:00
2021-02-17 23:10:26 +00:00
}
2021-06-11 08:56:19 +00:00
2021-02-17 23:10:26 +00:00
switch ( r . length ( ) )
{
2021-05-14 08:55:02 +00:00
/* case (CONTROL_SIZE):
2021-02-17 23:10:26 +00:00
{
2021-02-23 20:49:26 +00:00
}
2021-05-14 08:55:02 +00:00
*/
2021-06-01 16:49:48 +00:00
case ( PING_SIZE ) :
{
ping_packet_t in = ( ping_packet_t ) r . constData ( ) ;
if ( in - > type = = 0x07 )
2021-02-23 20:49:26 +00:00
{
2021-06-01 16:49:48 +00:00
// It is a ping request/response
2021-02-23 20:49:26 +00:00
2021-06-01 16:49:48 +00:00
if ( in - > reply = = 0x00 )
{
current - > rxPingTime = in - > time ;
sendPing ( & civClients , current , in - > seq , true ) ;
}
else if ( in - > reply = = 0x01 ) {
2022-01-05 14:45:34 +00:00
// A Reply to our ping!
if ( in - > seq = = current - > pingSeq ) {
current - > pingSeq + + ;
2021-02-17 23:10:26 +00:00
}
}
}
2021-06-01 16:49:48 +00:00
break ;
}
default :
{
2021-02-28 20:10:07 +00:00
2021-06-01 16:49:48 +00:00
if ( r . length ( ) > 0x18 ) {
data_packet_t in = ( data_packet_t ) r . constData ( ) ;
if ( in - > type ! = 0x01 )
{
if ( quint16 ( in - > datalen + 0x15 ) = = ( quint16 ) in - > len )
2021-02-23 20:49:26 +00:00
{
2021-06-01 16:49:48 +00:00
// Strip all '0xFE' command preambles first:
int lastFE = r . lastIndexOf ( ( char ) 0xfe ) ;
//qInfo(logUdpServer()) << "Got:" << r.mid(lastFE);
2021-06-09 07:31:34 +00:00
if ( current - > civId = = 0 & & r . length ( ) > lastFE + 2 & & ( quint8 ) r [ lastFE + 2 ] ! = 0xE1 & & ( quint8 ) r [ lastFE + 2 ] > ( quint8 ) 0xdf & & ( quint8 ) r [ lastFE + 2 ] < ( quint8 ) 0xef ) {
2021-06-01 16:49:48 +00:00
// This is (should be) the remotes CIV id.
current - > civId = ( quint8 ) r [ lastFE + 2 ] ;
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Detected remote CI-V: " < < hex < < current - > civId ;
}
2021-06-09 07:31:34 +00:00
else if ( current - > civId ! = 0 & & r . length ( ) > lastFE + 2 & & ( quint8 ) r [ lastFE + 2 ] ! = 0xE1 & & ( quint8 ) r [ lastFE + 2 ] ! = current - > civId )
2021-02-28 20:10:07 +00:00
{
2021-06-01 16:49:48 +00:00
current - > civId = ( quint8 ) r [ lastFE + 2 ] ;
2021-06-07 11:26:29 +00:00
qDebug ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Detected different remote CI-V: " < < hex < < current - > civId ; qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Detected different remote CI-V: " < < hex < < current - > civId ;
2021-06-09 07:31:34 +00:00
} else if ( r . length ( ) > lastFE + 2 & & ( quint8 ) r [ lastFE + 2 ] ! = 0xE1 ) {
2021-06-07 11:26:29 +00:00
qDebug ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Detected invalid remote CI-V: " < < hex < < ( quint8 ) r [ lastFE + 2 ] ;
2022-01-26 09:49:52 +00:00
}
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * radio : config . rigs ) {
if ( ! memcmp ( radio - > guid , current - > guid , sizeof ( radio - > guid ) ) )
2022-01-26 09:49:52 +00:00
{
// Only send to the rig that it belongs to!
2022-01-27 22:51:28 +00:00
# if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
2022-01-27 19:11:16 +00:00
QMetaObject : : invokeMethod ( radio - > rig , [ = ] ( ) {
radio - > rig - > dataFromServer ( r . mid ( 0x15 ) ) ; ;
2022-01-26 09:49:52 +00:00
} , Qt : : DirectConnection ) ;
2022-01-27 22:51:28 +00:00
# else
2022-01-30 10:29:23 +00:00
# warning "QT 5.9 is not fully supported, multiple rigs will NOT work!"
emit haveDataFromServer ( r . mid ( 0x15 ) ) ;
2022-01-27 22:51:28 +00:00
# endif
2022-01-26 09:49:52 +00:00
}
}
2021-05-14 08:55:02 +00:00
2021-06-01 16:49:48 +00:00
}
else {
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Datalen mismatch " < < quint16 ( in - > datalen + 0x15 ) < < " : " < < ( quint16 ) in - > len ;
2021-02-23 20:49:26 +00:00
}
2021-02-18 09:14:41 +00:00
}
2021-02-23 20:49:26 +00:00
}
2021-06-01 16:49:48 +00:00
//break;
}
2021-02-17 23:10:26 +00:00
}
2021-05-14 08:55:02 +00:00
if ( current ! = Q_NULLPTR ) {
udpServer : : commonReceived ( & civClients , current , r ) ;
}
2021-02-28 20:10:07 +00:00
2021-02-16 16:16:46 +00:00
}
}
void udpServer : : audioReceived ( )
{
while ( udpAudio - > hasPendingDatagrams ( ) ) {
QNetworkDatagram datagram = udpAudio - > receiveDatagram ( ) ;
QByteArray r = datagram . data ( ) ;
2021-02-17 23:10:26 +00:00
CLIENT * current = Q_NULLPTR ;
2021-02-18 13:49:19 +00:00
if ( datagram . senderAddress ( ) . isNull ( ) | | datagram . senderPort ( ) = = 65535 | | datagram . senderPort ( ) = = 0 )
2021-02-18 09:14:41 +00:00
return ;
2021-02-18 13:49:19 +00:00
QDateTime now = QDateTime : : currentDateTime ( ) ;
2021-02-17 23:10:26 +00:00
foreach ( CLIENT * client , audioClients )
{
2021-02-18 13:49:19 +00:00
if ( client ! = Q_NULLPTR )
2021-02-17 23:10:26 +00:00
{
2021-02-18 13:49:19 +00:00
if ( client - > ipAddress = = datagram . senderAddress ( ) & & client - > port = = datagram . senderPort ( ) )
{
current = client ;
}
2021-02-17 23:10:26 +00:00
}
}
if ( current = = Q_NULLPTR )
{
current = new CLIENT ( ) ;
2021-06-11 08:56:19 +00:00
foreach ( CLIENT * client , controlClients )
{
if ( client ! = Q_NULLPTR )
{
if ( client - > ipAddress = = datagram . senderAddress ( ) & & client - > isAuthenticated & & client - > audioClient = = Q_NULLPTR )
{
current - > controlClient = client ;
client - > audioClient = current ;
2022-01-29 22:50:58 +00:00
memcpy ( current - > guid , client - > guid , GUIDLEN ) ;
2021-06-11 08:56:19 +00:00
}
}
}
2021-08-15 13:41:54 +00:00
if ( current - > controlClient = = Q_NULLPTR | | ! current - > controlClient - > isAuthenticated )
{
// There is no current controlClient that matches this audioClient
delete current ;
return ;
}
2021-05-14 08:55:02 +00:00
current - > type = " Audio " ;
2021-02-17 23:10:26 +00:00
current - > connected = true ;
current - > timeConnected = QDateTime : : currentDateTime ( ) ;
current - > ipAddress = datagram . senderAddress ( ) ;
current - > port = datagram . senderPort ( ) ;
current - > myId = audioId ;
current - > remoteId = qFromLittleEndian < quint32 > ( r . mid ( 8 , 4 ) ) ;
current - > socket = udpAudio ;
current - > pingSeq = ( quint8 ) rand ( ) < < 8 | ( quint8 ) rand ( ) ;
2021-06-01 16:49:48 +00:00
2021-02-17 23:10:26 +00:00
current - > pingTimer = new QTimer ( ) ;
2021-02-18 13:49:19 +00:00
connect ( current - > pingTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendPing , this , & audioClients , current , ( quint16 ) 0x00 , false ) ) ;
2022-01-04 19:04:36 +00:00
current - > pingTimer - > start ( PING_PERIOD ) ;
2021-02-28 20:10:07 +00:00
current - > retransmitTimer = new QTimer ( ) ;
connect ( current - > retransmitTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendRetransmitRequest , this , current ) ) ;
current - > retransmitTimer - > start ( RETRANSMIT_PERIOD ) ;
2021-03-22 09:10:03 +00:00
current - > seqPrefix = 0 ;
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): New connection created " ;
2021-11-10 20:45:59 +00:00
if ( connMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
audioClients . append ( current ) ;
connMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock connMutex() " ;
}
2021-05-14 08:55:02 +00:00
2021-02-17 23:10:26 +00:00
}
2021-05-14 08:55:02 +00:00
2021-02-17 23:10:26 +00:00
switch ( r . length ( ) )
{
2021-06-01 16:49:48 +00:00
case ( PING_SIZE ) :
{
ping_packet_t in = ( ping_packet_t ) r . constData ( ) ;
if ( in - > type = = 0x07 )
2021-02-17 23:10:26 +00:00
{
2021-06-01 16:49:48 +00:00
// It is a ping request/response
2021-02-23 20:49:26 +00:00
2021-06-01 16:49:48 +00:00
if ( in - > reply = = 0x00 )
{
current - > rxPingTime = in - > time ;
sendPing ( & audioClients , current , in - > seq , true ) ;
}
else if ( in - > reply = = 0x01 ) {
2022-01-05 14:45:34 +00:00
// A Reply to our ping!
if ( in - > seq = = current - > pingSeq ) {
2022-01-04 19:04:36 +00:00
current - > pingSeq + + ;
2021-02-17 23:10:26 +00:00
}
}
2021-02-23 20:49:26 +00:00
}
2021-06-01 16:49:48 +00:00
break ;
}
default :
{
/* Audio packets start as follows:
PCM 16 bit and PCM8 / uLAW stereo : 0x44 , 0x02 for first packet and 0x6c , 0x05 for second .
uLAW 8 bit / PCM 8 bit 0xd8 , 0x03 for all packets
PCM 16 bit stereo 0x6c , 0x05 first & second 0x70 , 0x04 third
2021-03-22 09:10:03 +00:00
2021-06-01 16:49:48 +00:00
*/
control_packet_t in = ( control_packet_t ) r . constData ( ) ;
2021-03-22 09:10:03 +00:00
2021-08-14 19:08:11 +00:00
if ( in - > type ! = 0x01 ) {
// Opus packets can be smaller than this! && in->len >= 0xAC) {
2021-06-01 16:49:48 +00:00
if ( in - > seq = = 0 )
{
// Seq number has rolled over.
current - > seqPrefix + + ;
}
2021-03-22 09:10:03 +00:00
2021-06-01 16:49:48 +00:00
if ( hasTxAudio = = current - > ipAddress )
{
// 0xac is the smallest possible audio packet.
audioPacket tempAudio ;
tempAudio . seq = ( quint32 ) current - > seqPrefix < < 16 | in - > seq ;
tempAudio . time = QTime : : currentTime ( ) ; ;
tempAudio . sent = 0 ;
tempAudio . data = r . mid ( 0x18 ) ;
//qInfo(logUdpServer()) << "sending tx audio " << in->seq;
2021-11-15 15:02:00 +00:00
emit haveAudioData ( tempAudio ) ;
//txaudio->incomingAudio(tempAudio);
2021-10-31 23:53:20 +00:00
2021-03-22 09:10:03 +00:00
}
2021-02-17 23:10:26 +00:00
}
2021-06-01 16:49:48 +00:00
break ;
}
2021-03-22 09:10:03 +00:00
2021-02-17 23:10:26 +00:00
}
2021-03-22 15:16:41 +00:00
if ( current ! = Q_NULLPTR ) {
2021-05-14 08:55:02 +00:00
udpServer : : commonReceived ( & audioClients , current , r ) ;
2021-03-22 15:16:41 +00:00
}
2021-02-16 16:16:46 +00:00
}
}
2021-06-01 16:49:48 +00:00
void udpServer : : commonReceived ( QList < CLIENT * > * l , CLIENT * current , QByteArray r )
2021-02-28 20:10:07 +00:00
{
Q_UNUSED ( l ) ; // We might need it later!
2021-05-21 23:52:01 +00:00
if ( current = = Q_NULLPTR | | r . isNull ( ) ) {
return ;
}
2021-02-28 20:10:07 +00:00
current - > lastHeard = QDateTime : : currentDateTime ( ) ;
if ( r . length ( ) < 0x10 )
{
// Invalid packet
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Invalid packet received, len: " < < r . length ( ) ;
2021-02-28 20:10:07 +00:00
return ;
}
2021-02-17 23:10:26 +00:00
2021-02-28 20:10:07 +00:00
switch ( r . length ( ) )
2021-02-17 23:10:26 +00:00
{
2021-06-01 16:49:48 +00:00
case ( CONTROL_SIZE ) :
{
control_packet_t in = ( control_packet_t ) r . constData ( ) ;
if ( in - > type = = 0x03 ) {
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Received 'are you there' " ;
current - > remoteId = in - > sentid ;
sendControl ( current , 0x04 , in - > seq ) ;
} // This is This is "Are you ready" in response to "I am here".
else if ( in - > type = = 0x06 )
2021-02-28 20:10:07 +00:00
{
2021-06-01 16:49:48 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Received 'Are you ready' " ;
current - > remoteId = in - > sentid ;
sendControl ( current , 0x06 , in - > seq ) ;
if ( current - > idleTimer ! = Q_NULLPTR & & ! current - > idleTimer - > isActive ( ) ) {
current - > idleTimer - > start ( 100 ) ;
2021-02-28 20:10:07 +00:00
}
2021-06-01 16:49:48 +00:00
} // This is a retransmit request
else if ( in - > type = = 0x01 )
2021-02-28 20:10:07 +00:00
{
2021-06-01 16:49:48 +00:00
// Single packet request
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Received 'retransmit' request for " < < in - > seq ;
2021-06-01 22:32:39 +00:00
QMap < quint16 , SEQBUFENTRY > : : iterator match = current - > txSeqBuf . find ( in - > seq ) ;
2021-06-01 16:49:48 +00:00
if ( match ! = current - > txSeqBuf . end ( ) & & match - > retransmitCount < 5 ) {
// Found matching entry?
// Don't constantly retransmit the same packet, give-up eventually
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Sending retransmit of " < < hex < < match - > seqNum ;
match - > retransmitCount + + ;
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
current - > socket - > writeDatagram ( match - > data , current - > ipAddress , current - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-06-01 16:49:48 +00:00
}
else {
// Just send an idle!
sendControl ( current , 0x00 , in - > seq ) ;
}
2021-02-28 20:10:07 +00:00
}
2021-06-01 16:49:48 +00:00
break ;
}
default :
{
2022-01-26 09:49:52 +00:00
//break
2021-06-01 16:49:48 +00:00
}
2021-02-28 20:10:07 +00:00
}
// The packet is at least 0x10 in length so safe to cast it to control_packet for processing
control_packet_t in = ( control_packet_t ) r . constData ( ) ;
if ( in - > type = = 0x01 & & in - > len ! = 0x10 )
{
for ( quint16 i = 0x10 ; i < r . length ( ) ; i = i + 2 )
{
2022-01-28 09:43:53 +00:00
quint16 seq = ( quint8 ) r [ i ] | ( quint8 ) r [ i + 1 ] < < 8 ;
auto match = std : : find_if ( current - > txSeqBuf . begin ( ) , current - > txSeqBuf . end ( ) , [ & cs = seq ] ( SEQBUFENTRY & s ) {
2021-02-28 20:10:07 +00:00
return s . seqNum = = cs ;
} ) ;
if ( match = = current - > txSeqBuf . end ( ) ) {
2022-01-28 09:43:53 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Requested packet " < < hex < < seq < < " not found " ;
2021-02-28 20:10:07 +00:00
// Just send idle packet.
sendControl ( current , 0 , in - > seq ) ;
}
else if ( match - > seqNum ! = 0x00 )
{
// Found matching entry?
// Send "untracked" as it has already been sent once.
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Sending retransmit of " < < hex < < match - > seqNum ;
2021-02-28 20:10:07 +00:00
match - > retransmitCount + + ;
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
current - > socket - > writeDatagram ( match - > data , current - > ipAddress , current - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-02-28 20:10:07 +00:00
match + + ;
}
}
}
2021-05-14 08:55:02 +00:00
else if ( in - > type = = 0x00 & & in - > seq ! = 0x00 )
2021-02-28 20:10:07 +00:00
{
2021-05-14 08:55:02 +00:00
//if (current->type == "CIV") {
2021-05-15 17:53:16 +00:00
// qInfo(logUdpServer()) << "Got:" << in->seq;
2021-05-14 08:55:02 +00:00
//}
if ( current - > rxSeqBuf . isEmpty ( ) )
2021-02-28 20:10:07 +00:00
{
2021-11-10 20:45:59 +00:00
if ( current - > rxMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
current - > rxSeqBuf . insert ( in - > seq , QTime : : currentTime ( ) ) ;
current - > rxMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock rxMutex() " ;
}
2021-02-28 20:10:07 +00:00
}
else
{
2021-06-01 22:32:39 +00:00
if ( in - > seq < current - > rxSeqBuf . firstKey ( ) )
2021-02-28 20:10:07 +00:00
{
2021-06-01 22:32:39 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): ******* seq number may have rolled over ****** previous highest: " < < hex < < current - > rxSeqBuf . lastKey ( ) < < " current: " < < hex < < in - > seq ;
2021-02-28 20:10:07 +00:00
// Looks like it has rolled over so clear buffer and start again.
2021-11-10 20:45:59 +00:00
if ( current - > rxMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
current - > rxSeqBuf . clear ( ) ;
current - > rxMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock rxMutex() " ;
}
if ( current - > missMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
current - > rxMissing . clear ( ) ;
current - > missMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock missMutex() " ;
}
2021-02-28 20:10:07 +00:00
return ;
}
if ( ! current - > rxSeqBuf . contains ( in - > seq ) )
{
2021-11-10 20:45:59 +00:00
if ( current - > rxMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2022-01-27 19:11:16 +00:00
// Add incoming packet to the received buffer and if it is in the missing buffer, remove it.
2022-01-29 22:50:58 +00:00
//int missCounter = 0;
2022-01-27 19:11:16 +00:00
if ( in - > seq > current - > rxSeqBuf . lastKey ( ) + 1 ) {
// We are likely missing packets then!
if ( current - > missMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
2022-04-08 17:42:37 +00:00
for ( quint16 f = current - > rxSeqBuf . lastKey ( ) + 1 ; f < = in - > seq ; f + + )
2022-01-27 19:11:16 +00:00
{
if ( current - > rxSeqBuf . size ( ) > BUFSIZE )
{
current - > rxSeqBuf . remove ( current - > rxSeqBuf . firstKey ( ) ) ;
}
current - > rxSeqBuf . insert ( f , QTime : : currentTime ( ) ) ;
2022-04-08 17:42:37 +00:00
if ( f ! = in - > seq ) {
qInfo ( logUdpServer ( ) ) < < " Detected missing packet " < < f ;
if ( ! current - > rxMissing . contains ( f ) )
{
current - > rxMissing . insert ( f , 0 ) ;
}
2022-01-27 19:11:16 +00:00
}
}
current - > missMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock missMutex() " ;
}
}
else {
if ( current - > rxSeqBuf . size ( ) > BUFSIZE )
{
current - > rxSeqBuf . remove ( current - > rxSeqBuf . firstKey ( ) ) ;
}
current - > rxSeqBuf . insert ( in - > seq , QTime : : currentTime ( ) ) ;
2021-11-10 20:45:59 +00:00
}
current - > rxMutex . unlock ( ) ;
2021-06-01 22:32:39 +00:00
}
2021-11-10 20:45:59 +00:00
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock rxMutex() " ;
}
2021-06-01 22:32:39 +00:00
} else {
2021-02-28 20:10:07 +00:00
// Check whether this is one of our missing ones!
2021-11-10 20:45:59 +00:00
if ( current - > missMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-02-28 20:10:07 +00:00
{
2021-11-10 20:45:59 +00:00
QMap < quint16 , int > : : iterator s = current - > rxMissing . find ( in - > seq ) ;
if ( s ! = current - > rxMissing . end ( ) )
{
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Missing SEQ has been received! " < < hex < < in - > seq ;
s = current - > rxMissing . erase ( s ) ;
}
current - > missMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock missMutex() " ;
2021-02-28 20:10:07 +00:00
}
}
}
2021-02-17 23:10:26 +00:00
}
2021-02-28 20:10:07 +00:00
}
void udpServer : : sendControl ( CLIENT * c , quint8 type , quint16 seq )
{
2021-02-17 23:10:26 +00:00
2021-05-15 17:53:16 +00:00
//qInfo(logUdpServer()) << c->ipAddress.toString() << ": Sending control packet: " << type;
2021-02-28 20:10:07 +00:00
2021-02-23 20:49:26 +00:00
control_packet p ;
2021-02-28 20:10:07 +00:00
memset ( p . packet , 0x0 , CONTROL_SIZE ) ; // We can't be sure it is initialized with 0x00!
2021-02-23 20:49:26 +00:00
p . len = sizeof ( p ) ;
p . type = type ;
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
2021-02-17 23:10:26 +00:00
2021-02-28 20:10:07 +00:00
if ( seq = = 0x00 )
{
p . seq = c - > txSeq ;
2021-06-01 22:32:39 +00:00
SEQBUFENTRY s ;
s . seqNum = seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2021-11-10 20:45:59 +00:00
if ( c - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
2022-01-27 19:11:16 +00:00
if ( c - > txSeqBuf . size ( ) > BUFSIZE )
{
c - > txSeqBuf . remove ( c - > txSeqBuf . firstKey ( ) ) ;
}
2021-11-10 20:45:59 +00:00
c - > txSeqBuf . insert ( seq , s ) ;
c - > txSeq + + ;
c - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-06-02 09:43:52 +00:00
2021-02-28 20:10:07 +00:00
}
else {
p . seq = seq ;
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-02-28 20:10:07 +00:00
}
2021-02-16 16:16:46 +00:00
return ;
}
2021-02-17 23:10:26 +00:00
2021-06-01 16:49:48 +00:00
void udpServer : : sendPing ( QList < CLIENT * > * l , CLIENT * c , quint16 seq , bool reply )
2021-02-16 16:16:46 +00:00
{
2021-06-11 09:39:28 +00:00
Q_UNUSED ( l ) ;
2021-06-11 09:38:08 +00:00
/*
2021-02-18 13:49:19 +00:00
QDateTime now = QDateTime : : currentDateTime ( ) ;
if ( c - > lastHeard . secsTo ( now ) > STALE_CONNECTION )
{
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Deleting stale connection " ;
2021-02-18 13:49:19 +00:00
deleteConnection ( l , c ) ;
return ;
}
2021-06-11 09:38:08 +00:00
*/
2021-02-18 13:49:19 +00:00
2021-05-15 17:53:16 +00:00
//qInfo(logUdpServer()) << c->ipAddress.toString() << ": Sending Ping";
2021-02-16 16:16:46 +00:00
2021-02-23 20:49:26 +00:00
quint32 pingTime = 0 ;
2021-02-16 16:16:46 +00:00
if ( reply ) {
2021-02-23 20:49:26 +00:00
pingTime = c - > rxPingTime ;
2021-02-16 16:16:46 +00:00
}
else {
2021-02-23 20:49:26 +00:00
pingTime = ( quint32 ) timeStarted . msecsSinceStartOfDay ( ) ;
2021-02-16 20:55:30 +00:00
seq = c - > pingSeq ;
2021-02-28 20:10:07 +00:00
// Don't increment pingseq until we receive a reply.
2021-02-16 16:16:46 +00:00
}
2021-02-17 23:10:26 +00:00
// First byte of pings "from" server can be either 0x00 or packet length!
2021-02-23 20:49:26 +00:00
ping_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
2021-02-28 20:10:07 +00:00
if ( reply ) {
p . len = sizeof ( p ) ;
}
2021-02-23 20:49:26 +00:00
p . type = 0x07 ;
p . seq = seq ;
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
p . time = pingTime ;
2021-02-28 20:10:07 +00:00
p . reply = ( char ) reply ;
2021-02-16 16:16:46 +00:00
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-02-28 20:10:07 +00:00
2021-02-16 16:16:46 +00:00
return ;
}
2021-02-28 20:10:07 +00:00
void udpServer : : sendLoginResponse ( CLIENT * c , bool allowed )
2021-02-16 16:16:46 +00:00
{
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Sending Login response: " < < c - > txSeq ;
2021-02-17 23:10:26 +00:00
2021-02-23 20:49:26 +00:00
login_response_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
p . len = sizeof ( p ) ;
p . type = 0x00 ;
2021-02-28 20:10:07 +00:00
p . seq = c - > txSeq ;
2021-02-23 20:49:26 +00:00
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
p . innerseq = c - > authInnerSeq ;
p . tokrequest = c - > tokenRx ;
p . token = c - > tokenTx ;
p . code = 0x0250 ;
2021-02-16 16:16:46 +00:00
if ( ! allowed ) {
2021-02-23 20:49:26 +00:00
p . error = 0xFEFFFFFF ;
2021-02-28 20:10:07 +00:00
if ( c - > idleTimer ! = Q_NULLPTR )
c - > idleTimer - > stop ( ) ;
if ( c - > pingTimer ! = Q_NULLPTR )
c - > pingTimer - > stop ( ) ;
if ( c - > retransmitTimer ! = Q_NULLPTR )
c - > retransmitTimer - > stop ( ) ;
2021-02-16 16:16:46 +00:00
}
else {
2021-06-01 16:49:48 +00:00
strcpy ( p . connection , " WFVIEW " ) ;
2021-02-16 16:16:46 +00:00
}
2021-02-28 20:10:07 +00:00
2021-06-01 22:32:39 +00:00
SEQBUFENTRY s ;
s . seqNum = c - > txSeq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2021-11-10 20:45:59 +00:00
if ( c - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
2022-01-27 19:11:16 +00:00
if ( c - > txSeqBuf . size ( ) > BUFSIZE )
{
c - > txSeqBuf . remove ( c - > txSeqBuf . firstKey ( ) ) ;
}
2021-11-10 20:45:59 +00:00
c - > txSeqBuf . insert ( c - > txSeq , s ) ;
c - > txSeq + + ;
c - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-06-01 22:32:39 +00:00
2021-02-28 20:10:07 +00:00
if ( c - > idleTimer ! = Q_NULLPTR )
c - > idleTimer - > start ( 100 ) ;
2021-02-16 16:16:46 +00:00
return ;
}
void udpServer : : sendCapabilities ( CLIENT * c )
{
2021-02-23 20:49:26 +00:00
capabilities_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
p . type = 0x00 ;
p . seq = c - > txSeq ;
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
2021-03-22 09:10:03 +00:00
p . innerseq = c - > authInnerSeq ;
2021-02-23 20:49:26 +00:00
p . tokrequest = c - > tokenRx ;
p . token = c - > tokenTx ;
2022-01-21 19:23:32 +00:00
p . res = 0x0202 ;
2022-01-26 09:49:52 +00:00
p . numradios = config . rigs . count ( ) ;
2021-02-23 20:49:26 +00:00
2022-01-26 09:49:52 +00:00
SEQBUFENTRY s ;
s . seqNum = p . seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
2021-02-28 20:10:07 +00:00
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * rig : config . rigs ) {
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Sending Capabilities : " < < c - > txSeq < < " for " < < rig - > modelName ;
2022-01-26 09:49:52 +00:00
radio_cap_packet r ;
memset ( r . packet , 0x0 , sizeof ( r ) ) ; // We can't be sure it is initialized with 0x00!
2021-02-28 20:10:07 +00:00
2022-01-29 22:50:58 +00:00
memcpy ( r . guid , rig - > guid , GUIDLEN ) ;
2022-01-27 19:11:16 +00:00
memcpy ( r . name , rig - > rigName . toLocal8Bit ( ) , sizeof ( r . name ) ) ;
2022-01-26 09:49:52 +00:00
memcpy ( r . audio , QByteArrayLiteral ( " ICOM_VAUDIO " ) . constData ( ) , 11 ) ;
2022-01-27 19:11:16 +00:00
if ( rig - > hasWiFi & & ! rig - > hasEthernet ) {
r . conntype = 0x0707 ; // 0x0707 for wifi rig->
2022-01-26 09:49:52 +00:00
}
else {
2022-01-27 19:11:16 +00:00
r . conntype = 0x073f ; // 0x073f for ethernet rig->
2021-03-22 09:10:03 +00:00
}
2022-01-26 09:49:52 +00:00
2022-01-27 19:11:16 +00:00
r . civ = rig - > civAddr ;
r . baudrate = ( quint32 ) qToBigEndian ( rig - > baudRate ) ;
2022-01-26 09:49:52 +00:00
/*
0x80 = 12 K only
0x40 = 44.1 K only
0x20 = 22.05 K only
0x10 = 11.025 K only
0x08 = 48 K only
0x04 = 32 K only
0x02 = 16 K only
0x01 = 8 K only
*/
2022-01-27 19:11:16 +00:00
if ( rig - > rxaudio = = Q_NULLPTR ) {
2022-01-26 09:49:52 +00:00
r . rxsample = 0x8b01 ; // all rx sample frequencies supported
2021-03-22 09:10:03 +00:00
}
2022-01-26 09:49:52 +00:00
else {
if ( rxSampleRate = = 48000 ) {
r . rxsample = 0x0800 ; // fixed rx sample frequency
}
else if ( rxSampleRate = = 32000 ) {
r . rxsample = 0x0400 ;
}
else if ( rxSampleRate = = 24000 ) {
r . rxsample = 0x0001 ;
}
else if ( rxSampleRate = = 16000 ) {
r . rxsample = 0x0200 ;
}
else if ( rxSampleRate = = 12000 ) {
r . rxsample = 0x8000 ;
}
2021-03-22 09:10:03 +00:00
}
2022-01-26 09:49:52 +00:00
2022-01-27 19:11:16 +00:00
if ( rig - > txaudio = = Q_NULLPTR ) {
2022-01-26 09:49:52 +00:00
r . txsample = 0x8b01 ; // all tx sample frequencies supported
r . enablea = 0x01 ; // 0x01 enables TX 24K mode?
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Client will have TX audio " ;
2021-03-22 09:10:03 +00:00
}
2022-01-26 09:49:52 +00:00
else {
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Disable tx audio for client " ;
r . txsample = 0 ;
2021-03-22 09:10:03 +00:00
}
2022-01-26 09:49:52 +00:00
// I still don't know what these are?
r . enableb = 0x01 ; // 0x01 doesn't seem to do anything?
r . enablec = 0x01 ; // 0x01 doesn't seem to do anything?
r . capf = 0x5001 ;
r . capg = 0x0190 ;
s . data . append ( QByteArray : : fromRawData ( ( const char * ) r . packet , sizeof ( r ) ) ) ;
2021-03-22 09:10:03 +00:00
}
2021-02-28 20:10:07 +00:00
2022-01-26 09:49:52 +00:00
p . len = sizeof ( p ) + s . data . length ( ) ;
p . payloadsize = sizeof ( p ) + s . data . length ( ) - 0x0f ;
s . data . insert ( 0 , QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ) ;
2021-05-14 08:55:02 +00:00
2021-11-10 20:45:59 +00:00
if ( c - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2022-01-13 21:50:43 +00:00
if ( c - > txSeqBuf . size ( ) > BUFSIZE )
2021-11-10 20:45:59 +00:00
{
2022-01-13 21:12:27 +00:00
c - > txSeqBuf . remove ( c - > txSeqBuf . firstKey ( ) ) ;
2021-11-10 20:45:59 +00:00
}
c - > txSeqBuf . insert ( p . seq , s ) ;
c - > txSeq + + ;
c - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
2022-01-21 19:23:32 +00:00
c - > socket - > writeDatagram ( ( const char * ) s . data , s . data . length ( ) , c - > ipAddress , c - > port ) ;
2021-11-10 20:45:59 +00:00
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
2021-06-01 22:32:39 +00:00
}
2021-06-02 09:43:52 +00:00
2021-02-28 20:10:07 +00:00
if ( c - > idleTimer ! = Q_NULLPTR )
c - > idleTimer - > start ( 100 ) ;
2021-02-16 16:16:46 +00:00
return ;
}
2021-02-17 23:10:26 +00:00
// When client has requested civ/audio connection, this will contain their details
// Also used to display currently connected used information.
2022-01-29 22:50:58 +00:00
void udpServer : : sendConnectionInfo ( CLIENT * c , quint8 guid [ GUIDLEN ] )
2021-02-16 16:16:46 +00:00
{
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * radio : config . rigs ) {
2022-01-29 22:50:58 +00:00
if ( ! memcmp ( guid , radio - > guid , GUIDLEN ) )
2022-01-26 09:49:52 +00:00
{
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Sending ConnectionInfo : " < < c - > txSeq ;
conninfo_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ;
p . len = sizeof ( p ) ;
p . type = 0x00 ;
p . seq = c - > txSeq ;
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
//p.innerseq = c->authInnerSeq; // Innerseq not used in user packet
p . tokrequest = c - > tokenRx ;
p . token = c - > tokenTx ;
p . code = 0x0380 ;
2022-01-29 22:50:58 +00:00
memcpy ( p . guid , radio - > guid , GUIDLEN ) ;
2022-01-27 19:11:16 +00:00
memcpy ( p . name , radio - > rigName . toLocal8Bit ( ) , sizeof ( p . name ) ) ;
2022-01-26 09:49:52 +00:00
2022-01-27 19:11:16 +00:00
if ( radio - > rigAvailable ) {
2022-01-26 09:49:52 +00:00
if ( c - > isStreaming ) {
p . busy = 0x01 ;
}
else {
p . busy = 0x00 ;
}
}
else
{
p . busy = 0x02 ;
}
// This is the current streaming client (should we support multiple clients?)
if ( c - > isStreaming ) {
memcpy ( p . computer , c - > clientName . constData ( ) , c - > clientName . length ( ) ) ;
p . ipaddress = qToBigEndian ( c - > ipAddress . toIPv4Address ( ) ) ;
}
2021-02-16 16:16:46 +00:00
2021-02-17 23:10:26 +00:00
2022-01-26 09:49:52 +00:00
SEQBUFENTRY s ;
s . seqNum = p . seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2021-02-28 20:10:07 +00:00
2022-01-26 09:49:52 +00:00
if ( c - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
if ( c - > txSeqBuf . size ( ) > BUFSIZE )
{
c - > txSeqBuf . remove ( c - > txSeqBuf . firstKey ( ) ) ;
}
c - > txSeqBuf . insert ( p . seq , s ) ;
c - > txSeq + + ;
c - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
2021-02-28 20:10:07 +00:00
2021-11-10 20:45:59 +00:00
2022-01-26 09:49:52 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-11-10 20:45:59 +00:00
2022-01-26 09:49:52 +00:00
}
2021-06-01 22:32:39 +00:00
}
2021-02-28 20:10:07 +00:00
if ( c - > idleTimer ! = Q_NULLPTR )
c - > idleTimer - > start ( 100 ) ;
2021-02-16 16:16:46 +00:00
return ;
}
2021-02-17 23:10:26 +00:00
void udpServer : : sendTokenResponse ( CLIENT * c , quint8 type )
2021-02-16 16:16:46 +00:00
{
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Sending Token response for type: " < < type ;
2021-02-17 23:10:26 +00:00
2021-02-23 20:49:26 +00:00
token_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
p . len = sizeof ( p ) ;
p . type = 0x00 ;
p . seq = c - > txSeq ;
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
p . innerseq = c - > authInnerSeq ;
p . tokrequest = c - > tokenRx ;
p . token = c - > tokenTx ;
p . code = 0x0230 ;
2022-01-21 19:23:32 +00:00
memcpy ( p . macaddress , c - > macaddress , 6 ) ;
2021-03-22 09:10:03 +00:00
p . commoncap = c - > commonCap ;
2021-02-23 20:49:26 +00:00
p . res = type ;
2021-02-28 20:10:07 +00:00
2021-06-01 22:32:39 +00:00
SEQBUFENTRY s ;
s . seqNum = p . seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( c - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2022-01-13 21:50:43 +00:00
if ( c - > txSeqBuf . size ( ) > BUFSIZE )
2021-11-10 20:45:59 +00:00
{
2022-01-13 21:12:27 +00:00
c - > txSeqBuf . remove ( c - > txSeqBuf . firstKey ( ) ) ;
2021-11-10 20:45:59 +00:00
}
c - > txSeqBuf . insert ( p . seq , s ) ;
c - > txSeq + + ;
c - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
2021-06-01 22:32:39 +00:00
}
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-02-28 20:10:07 +00:00
2021-06-01 22:32:39 +00:00
2021-02-28 20:10:07 +00:00
if ( c - > idleTimer ! = Q_NULLPTR )
c - > idleTimer - > start ( 100 ) ;
2021-02-17 23:10:26 +00:00
return ;
}
2021-06-11 11:53:00 +00:00
void udpServer : : watchdog ( )
2021-02-28 20:10:07 +00:00
{
2021-06-11 09:38:08 +00:00
QDateTime now = QDateTime : : currentDateTime ( ) ;
2021-06-11 11:53:00 +00:00
foreach ( CLIENT * client , audioClients )
2021-06-11 09:38:08 +00:00
{
2021-06-11 11:53:00 +00:00
if ( client ! = Q_NULLPTR )
{
if ( client - > lastHeard . secsTo ( now ) > STALE_CONNECTION )
{
qInfo ( logUdpServer ( ) ) < < client - > ipAddress . toString ( ) < < " ( " < < client - > type < < " ): Deleting stale connection " ;
deleteConnection ( & audioClients , client ) ;
}
}
else {
qInfo ( logUdpServer ( ) ) < < " Current client is NULL! " ;
}
}
foreach ( CLIENT * client , civClients )
{
if ( client ! = Q_NULLPTR )
{
if ( client - > lastHeard . secsTo ( now ) > STALE_CONNECTION )
{
qInfo ( logUdpServer ( ) ) < < client - > ipAddress . toString ( ) < < " ( " < < client - > type < < " ): Deleting stale connection " ;
deleteConnection ( & civClients , client ) ;
}
}
else {
qInfo ( logUdpServer ( ) ) < < " Current client is NULL! " ;
}
}
foreach ( CLIENT * client , controlClients )
{
if ( client ! = Q_NULLPTR )
{
if ( client - > lastHeard . secsTo ( now ) > STALE_CONNECTION )
{
qInfo ( logUdpServer ( ) ) < < client - > ipAddress . toString ( ) < < " ( " < < client - > type < < " ): Deleting stale connection " ;
deleteConnection ( & controlClients , client ) ;
}
}
else {
qInfo ( logUdpServer ( ) ) < < " Current client is NULL! " ;
}
2021-06-11 09:38:08 +00:00
}
2021-02-17 23:10:26 +00:00
2022-02-02 16:02:40 +00:00
status . message = QString ( " <pre>Server connections: Control:%1 CI-V:%2 Audio:%3</pre> " ) . arg ( controlClients . size ( ) ) . arg ( civClients . size ( ) ) . arg ( audioClients . size ( ) ) ;
emit haveNetworkStatus ( status ) ;
2021-02-16 16:16:46 +00:00
}
2021-02-17 23:10:26 +00:00
void udpServer : : sendStatus ( CLIENT * c )
{
2021-02-18 13:49:19 +00:00
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Sending Status " ;
2021-02-17 23:10:26 +00:00
2021-02-23 20:49:26 +00:00
status_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
p . len = sizeof ( p ) ;
p . type = 0x00 ;
p . seq = c - > txSeq ;
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
p . innerseq = c - > authInnerSeq ;
p . tokrequest = c - > tokenRx ;
p . token = c - > tokenTx ;
p . code = 0x0240 ;
p . res = 0x03 ;
p . unknown = 0x1000 ;
p . unusede = ( char ) 0x80 ;
2022-01-21 19:23:32 +00:00
memcpy ( p . macaddress , c - > macaddress , 6 ) ;
2021-02-23 20:49:26 +00:00
2021-06-01 16:49:48 +00:00
p . civport = qToBigEndian ( c - > civPort ) ;
p . audioport = qToBigEndian ( c - > audioPort ) ;
2021-02-17 23:10:26 +00:00
// Send this to reject the request to tx/rx audio/civ
//memcpy(p + 0x30, QByteArrayLiteral("\xff\xff\xff\xfe").constData(), 4);
2021-06-01 22:32:39 +00:00
SEQBUFENTRY s ;
s . seqNum = p . seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2021-11-10 20:45:59 +00:00
if ( c - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2022-01-13 21:50:43 +00:00
if ( c - > txSeqBuf . size ( ) > BUFSIZE )
2021-11-10 20:45:59 +00:00
{
2022-01-13 21:12:27 +00:00
c - > txSeqBuf . remove ( c - > txSeqBuf . firstKey ( ) ) ;
2021-11-10 20:45:59 +00:00
}
c - > txSeq + + ;
c - > txSeqBuf . insert ( p . seq , s ) ;
c - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
2021-06-01 22:32:39 +00:00
}
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-02-16 16:16:46 +00:00
2021-02-17 23:10:26 +00:00
}
2021-02-18 09:14:41 +00:00
void udpServer : : dataForServer ( QByteArray d )
{
2022-01-26 09:49:52 +00:00
rigCommander * sender = qobject_cast < rigCommander * > ( QObject : : sender ( ) ) ;
if ( sender = = Q_NULLPTR )
2021-02-18 09:14:41 +00:00
{
2022-01-26 09:49:52 +00:00
return ;
}
2021-06-01 22:32:39 +00:00
2022-01-26 09:49:52 +00:00
for ( CLIENT * client : civClients )
{
if ( client = = Q_NULLPTR | | ! client - > connected )
{
continue ;
}
2022-01-27 19:11:16 +00:00
// Use the GUID to determine which radio the response is from
2022-01-29 22:50:58 +00:00
if ( memcmp ( sender - > getGUID ( ) , client - > guid , GUIDLEN ) )
2022-01-26 09:49:52 +00:00
{
2022-01-27 19:11:16 +00:00
continue ; // Rig guid doesn't match the one requested by the client.
}
int lastFE = d . lastIndexOf ( ( quint8 ) 0xfe ) ;
//qInfo(logUdpServer()) << "Server got CIV data from" << radio->rigName << "length" << d.length();
if ( client - > connected & & d . length ( ) > lastFE + 2 & &
( ( quint8 ) d [ lastFE + 1 ] = = client - > civId | | ( quint8 ) d [ lastFE + 2 ] = = client - > civId | |
( quint8 ) d [ lastFE + 1 ] = = 0x00 | | ( quint8 ) d [ lastFE + 2 ] = = 0x00 | | ( quint8 ) d [ lastFE + 1 ] = = 0xE1 | | ( quint8 ) d [ lastFE + 2 ] = = 0xE1 ) )
{
data_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
p . len = ( quint16 ) d . length ( ) + sizeof ( p ) ;
p . seq = client - > txSeq ;
p . sentid = client - > myId ;
p . rcvdid = client - > remoteId ;
p . reply = ( char ) 0xc1 ;
p . datalen = ( quint16 ) d . length ( ) ;
p . sendseq = client - > innerSeq ;
QByteArray t = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
t . append ( d ) ;
SEQBUFENTRY s ;
s . seqNum = p . seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = t ;
2021-06-02 09:43:52 +00:00
2022-01-27 19:11:16 +00:00
if ( client - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2022-01-27 19:11:16 +00:00
if ( client - > txSeqBuf . size ( ) > BUFSIZE )
2021-11-10 20:45:59 +00:00
{
2022-01-27 19:11:16 +00:00
client - > txSeqBuf . remove ( client - > txSeqBuf . firstKey ( ) ) ;
2021-11-10 20:45:59 +00:00
}
2022-01-27 19:11:16 +00:00
client - > txSeqBuf . insert ( p . seq , s ) ;
client - > txSeq + + ;
client - > innerSeq + + ;
client - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
2021-11-10 20:45:59 +00:00
2022-01-27 19:11:16 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
client - > socket - > writeDatagram ( t , client - > ipAddress , client - > port ) ;
udpMutex . unlock ( ) ;
2021-11-10 20:45:59 +00:00
}
else {
2022-01-27 19:11:16 +00:00
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
2021-06-01 22:32:39 +00:00
}
2022-01-26 09:49:52 +00:00
}
2022-01-27 19:11:16 +00:00
else {
qInfo ( logUdpServer ( ) ) < < " Got data for different ID " < < hex < < ( quint8 ) d [ lastFE + 1 ] < < " : " < < hex < < ( quint8 ) d [ lastFE + 2 ] ;
}
2021-02-28 20:10:07 +00:00
}
return ;
}
2021-03-22 09:10:03 +00:00
2021-06-01 16:49:48 +00:00
void udpServer : : receiveAudioData ( const audioPacket & d )
2021-02-28 20:10:07 +00:00
{
2022-01-29 22:50:58 +00:00
rigCommander * sender = qobject_cast < rigCommander * > ( QObject : : sender ( ) ) ;
quint8 guid [ GUIDLEN ] ;
if ( sender ! = Q_NULLPTR )
{
memcpy ( guid , sender - > getGUID ( ) , GUIDLEN ) ;
}
else {
memcpy ( guid , d . guid , GUIDLEN ) ;
}
2022-04-10 22:13:51 +00:00
//qInfo(logUdpServer()) << "Server got:" << d.data.length();
2021-02-28 20:10:07 +00:00
foreach ( CLIENT * client , audioClients )
{
2022-04-10 22:13:51 +00:00
int len = 0 ;
while ( len < d . data . length ( ) ) {
QByteArray partial ;
partial = d . data . mid ( len , 1364 ) ;
len = len + partial . length ( ) ;
if ( client ! = Q_NULLPTR & & client - > connected & & ! memcmp ( client - > guid , guid , GUIDLEN ) ) {
audio_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
p . len = sizeof ( p ) + partial . length ( ) ;
p . sentid = client - > myId ;
p . rcvdid = client - > remoteId ;
p . ident = 0x0080 ; // audio is always this?
p . datalen = ( quint16 ) qToBigEndian ( ( quint16 ) partial . length ( ) ) ;
p . sendseq = ( quint16 ) qToBigEndian ( ( quint16 ) client - > sendAudioSeq ) ; // THIS IS BIG ENDIAN!
p . seq = client - > txSeq ;
QByteArray t = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2022-04-11 10:26:52 +00:00
t . append ( partial ) ;
2022-04-10 22:13:51 +00:00
SEQBUFENTRY s ;
s . seqNum = p . seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = t ;
if ( client - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-11-10 20:45:59 +00:00
{
2022-04-10 22:13:51 +00:00
if ( client - > txSeqBuf . size ( ) > BUFSIZE )
{
client - > txSeqBuf . remove ( client - > txSeqBuf . firstKey ( ) ) ;
}
client - > txSeqBuf . insert ( p . seq , s ) ;
client - > txSeq + + ;
client - > sendAudioSeq + + ;
client - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
2021-11-10 20:45:59 +00:00
}
2022-04-10 22:13:51 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
client - > socket - > writeDatagram ( t , client - > ipAddress , client - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-06-02 09:43:52 +00:00
2022-04-10 22:13:51 +00:00
}
2021-02-18 13:49:19 +00:00
}
2021-02-18 09:14:41 +00:00
}
2021-02-28 20:10:07 +00:00
2021-02-18 09:14:41 +00:00
return ;
}
2021-03-13 09:50:43 +00:00
/// <summary>
/// Find all gaps in received packets and then send requests for them.
/// This will run every 100ms so out-of-sequence packets will not trigger a retransmit request.
/// </summary>
/// <param name="c"></param>
2021-06-01 16:49:48 +00:00
void udpServer : : sendRetransmitRequest ( CLIENT * c )
2021-02-28 20:10:07 +00:00
{
2021-06-01 22:32:39 +00:00
// Find all gaps in received packets and then send requests for them.
// This will run every 100ms so out-of-sequence packets will not trigger a retransmit request.
2021-02-28 20:10:07 +00:00
2022-01-27 23:12:07 +00:00
if ( c - > rxMissing . isEmpty ( ) ) {
return ;
}
2022-01-28 09:43:53 +00:00
else if ( c - > rxMissing . size ( ) > MAX_MISSING ) {
2022-01-27 23:24:54 +00:00
qDebug ( logUdp ( ) ) < < " Too many missing packets, " < < c - > rxMissing . size ( ) < < " flushing all buffers " ;
c - > rxMutex . lock ( ) ;
c - > rxSeqBuf . clear ( ) ;
2022-01-27 23:28:34 +00:00
c - > rxMutex . unlock ( ) ;
c - > missMutex . lock ( ) ;
2022-01-27 23:24:54 +00:00
c - > rxMissing . clear ( ) ;
c - > missMutex . unlock ( ) ;
return ;
}
2022-01-27 23:12:07 +00:00
2021-02-28 20:10:07 +00:00
QByteArray missingSeqs ;
2022-01-27 23:12:07 +00:00
2022-01-30 10:29:23 +00:00
//QTime missingTime = QTime::currentTime();
2021-06-01 22:32:39 +00:00
2021-11-10 20:45:59 +00:00
if ( c - > missMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-02-28 20:10:07 +00:00
{
2021-11-10 20:45:59 +00:00
for ( auto it = c - > rxMissing . begin ( ) ; it ! = c - > rxMissing . end ( ) ; + + it )
2021-02-28 20:10:07 +00:00
{
2022-01-30 10:29:23 +00:00
if ( & it . key ( ) ! = Q_NULLPTR & & it . value ( ) < 4 )
2021-11-10 20:45:59 +00:00
{
missingSeqs . append ( it . key ( ) & 0xff ) ;
missingSeqs . append ( it . key ( ) > > 8 & 0xff ) ;
missingSeqs . append ( it . key ( ) & 0xff ) ;
missingSeqs . append ( it . key ( ) > > 8 & 0xff ) ;
it . value ( ) + + ;
2022-01-27 19:11:16 +00:00
}
else {
// We have tried 4 times to request this packet, time to give up!
qDebug ( logUdp ( ) ) < < this - > metaObject ( ) - > className ( ) < < " : No response for missing packet " < < it . key ( ) < < " deleting " ;
it = c - > rxMissing . erase ( it ) ;
2021-11-10 20:45:59 +00:00
}
2021-02-28 20:10:07 +00:00
}
2021-06-01 22:32:39 +00:00
2021-11-10 20:45:59 +00:00
if ( missingSeqs . length ( ) ! = 0 )
2021-02-28 20:10:07 +00:00
{
2021-11-10 20:45:59 +00:00
control_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
p . type = 0x01 ;
p . seq = 0x0000 ;
p . sentid = c - > myId ;
p . rcvdid = c - > remoteId ;
if ( missingSeqs . length ( ) = = 4 ) // This is just a single missing packet so send using a control.
{
p . seq = ( missingSeqs [ 0 ] & 0xff ) | ( quint16 ) ( missingSeqs [ 1 ] < < 8 ) ;
qDebug ( logUdp ( ) ) < < this - > metaObject ( ) - > className ( ) < < " : sending request for missing packet : " < < hex < < p . seq ;
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
}
else
{
qDebug ( logUdp ( ) ) < < this - > metaObject ( ) - > className ( ) < < " : sending request for multiple missing packets : " < < missingSeqs . toHex ( ) ;
2022-01-07 14:42:32 +00:00
missingSeqs . insert ( 0 , p . packet , sizeof ( p . packet ) ) ;
2021-11-10 20:45:59 +00:00
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > socket - > writeDatagram ( missingSeqs , c - > ipAddress , c - > port ) ;
udpMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock udpMutex() " ;
}
}
2021-02-28 20:10:07 +00:00
}
2021-11-10 20:45:59 +00:00
c - > missMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock missMutex() " ;
2021-02-28 20:10:07 +00:00
}
}
2021-03-13 09:50:43 +00:00
/// <summary>
/// This function is passed a pointer to the list of connection objects and a pointer to the object itself
/// Needs to stop and delete all timers, remove the connection from the list and delete the connection.
/// </summary>
/// <param name="l"></param>
/// <param name="c"></param>
2021-06-01 16:49:48 +00:00
void udpServer : : deleteConnection ( QList < CLIENT * > * l , CLIENT * c )
2021-02-18 13:49:19 +00:00
{
2021-05-14 08:55:02 +00:00
2022-01-29 22:50:58 +00:00
quint8 guid [ GUIDLEN ] ;
memcpy ( guid , c - > guid , GUIDLEN ) ;
2022-01-26 09:49:52 +00:00
int len = l - > length ( ) ;
2021-06-11 09:08:04 +00:00
qInfo ( logUdpServer ( ) ) < < " Deleting " < < c - > type < < " connection to: " < < c - > ipAddress . toString ( ) < < " : " < < QString : : number ( c - > port ) ;
2021-02-18 14:15:03 +00:00
if ( c - > idleTimer ! = Q_NULLPTR ) {
c - > idleTimer - > stop ( ) ;
delete c - > idleTimer ;
}
if ( c - > pingTimer ! = Q_NULLPTR ) {
c - > pingTimer - > stop ( ) ;
delete c - > pingTimer ;
}
2021-02-28 20:10:07 +00:00
if ( c - > retransmitTimer ! = Q_NULLPTR ) {
c - > retransmitTimer - > stop ( ) ;
delete c - > retransmitTimer ;
}
2021-11-10 20:45:59 +00:00
if ( c - > rxMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > rxSeqBuf . clear ( ) ;
c - > rxMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock rxMutex() " ;
}
2021-06-01 22:32:39 +00:00
2021-11-10 20:45:59 +00:00
if ( c - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > txSeqBuf . clear ( ) ;
c - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
2021-06-01 22:32:39 +00:00
2021-11-10 20:45:59 +00:00
if ( c - > missMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > rxMissing . clear ( ) ;
c - > missMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock missMutex() " ;
}
if ( connMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
QList < CLIENT * > : : iterator it = l - > begin ( ) ;
while ( it ! = l - > end ( ) ) {
CLIENT * client = * it ;
if ( client ! = Q_NULLPTR & & client = = c ) {
qInfo ( logUdpServer ( ) ) < < " Found " < < client - > type < < " connection to: " < < client - > ipAddress . toString ( ) < < " : " < < QString : : number ( client - > port ) ;
it = l - > erase ( it ) ;
2022-01-26 09:49:52 +00:00
len - - ;
2021-11-10 20:45:59 +00:00
}
else {
+ + it ;
}
2021-02-18 13:49:19 +00:00
}
2021-11-10 20:45:59 +00:00
delete c ; // Is this needed or will the erase have done it?
c = Q_NULLPTR ;
qInfo ( logUdpServer ( ) ) < < " Current Number of clients connected: " < < l - > length ( ) ;
connMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock connMutex() " ;
2021-02-18 13:49:19 +00:00
}
2021-03-22 09:10:03 +00:00
2022-01-26 09:49:52 +00:00
if ( len = = 0 ) {
2022-01-27 19:11:16 +00:00
for ( RIGCONFIG * radio : config . rigs ) {
2022-01-29 22:50:58 +00:00
if ( ! memcmp ( radio - > guid , guid , GUIDLEN ) )
2022-01-26 09:49:52 +00:00
{
2021-03-22 09:10:03 +00:00
2022-01-27 19:11:16 +00:00
if ( radio - > rxAudioThread ! = Q_NULLPTR ) {
radio - > rxAudioThread - > quit ( ) ;
radio - > rxAudioThread - > wait ( ) ;
radio - > rxaudio = Q_NULLPTR ;
radio - > rxAudioThread = Q_NULLPTR ;
2022-01-26 09:49:52 +00:00
}
2021-03-22 09:10:03 +00:00
2022-01-27 19:11:16 +00:00
if ( radio - > txAudioThread ! = Q_NULLPTR ) {
radio - > txAudioThread - > quit ( ) ;
radio - > txAudioThread - > wait ( ) ;
radio - > txaudio = Q_NULLPTR ;
radio - > txAudioThread = Q_NULLPTR ;
2022-01-26 09:49:52 +00:00
}
}
2021-03-22 09:10:03 +00:00
}
}
2021-02-18 13:49:19 +00:00
}