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
2021-06-04 13:25:07 +00:00
udpServer : : udpServer ( SERVERCONFIG config , audioSetup outAudio , audioSetup inAudio ) :
config ( config ) ,
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
}
void udpServer : : init ( )
{
srand ( time ( NULL ) ) ; // Generate random key
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 ( ) ;
2021-05-15 17:53:16 +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
2021-10-20 11:47:16 +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 ;
}
2021-02-16 16:16:46 +00:00
}
2021-02-28 20:10:07 +00:00
void udpServer : : receiveRigCaps ( rigCapabilities caps )
{
this - > rigCaps = caps ;
}
# define RETRANSMIT_PERIOD 100
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-02-23 20:49:26 +00:00
current - > commonCap = 0x8010 ;
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 ) {
if ( in - > seq = = current - > pingSeq | | in - > seq = = current - > pingSeq - 1 )
2021-02-21 21:05:58 +00:00
{
2021-06-01 16:49:48 +00:00
// A Reply to our ping!
if ( in - > seq = = current - > pingSeq ) {
current - > pingSeq + + ;
}
else {
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : got out of sequence ping reply. Got: " < < in - > seq < < " expecting: " < < current - > pingSeq ;
2021-02-21 21:05:58 +00:00
}
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 ;
current - > identa = in - > identa ;
current - > identb = in - > identb ;
if ( in - > res = = 0x02 ) {
// Request for new token
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : Received create token request " ;
sendCapabilities ( current ) ;
sendConnectionInfo ( current ) ;
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 ;
sendConnectionInfo ( current ) ;
}
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 ;
current - > identa = in - > identa ;
current - > identb = in - > identb ;
sendStatus ( current ) ;
current - > authInnerSeq = 0x00 ;
sendConnectionInfo ( current ) ;
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 ;
if ( ! config . lan ) {
// Radio is connected by USB/Serial and we assume that audio is connected as well.
// Create audio TX/RX threads if they don't already exist (first client chooses samplerate/codec)
2021-06-04 07:24:26 +00:00
audioSetup setup ;
setup . resampleQuality = config . resampleQuality ;
2021-06-01 16:49:48 +00:00
if ( txaudio = = Q_NULLPTR )
{
2021-06-04 13:25:07 +00:00
outAudio . codec = current - > txCodec ;
outAudio . samplerate = current - > txSampleRate ;
outAudio . latency = current - > txBufferLen ;
2021-03-22 09:10:03 +00:00
2021-06-01 16:49:48 +00:00
txaudio = new audioHandler ( ) ;
txAudioThread = new QThread ( this ) ;
2021-09-22 10:07:07 +00:00
2021-06-01 16:49:48 +00:00
txaudio - > moveToThread ( txAudioThread ) ;
2021-03-22 09:10:03 +00:00
2021-08-23 22:59:40 +00:00
txAudioThread - > start ( QThread : : TimeCriticalPriority ) ;
2021-03-22 09:10:03 +00:00
2021-06-04 07:24:26 +00:00
connect ( this , SIGNAL ( setupTxAudio ( audioSetup ) ) , txaudio , SLOT ( init ( audioSetup ) ) ) ;
2021-06-01 16:49:48 +00:00
connect ( txAudioThread , SIGNAL ( finished ( ) ) , txaudio , SLOT ( deleteLater ( ) ) ) ;
2021-03-22 09:10:03 +00:00
2021-06-04 13:25:07 +00:00
emit setupTxAudio ( outAudio ) ;
2021-06-01 16:49:48 +00:00
hasTxAudio = datagram . senderAddress ( ) ;
2021-03-22 09:10:03 +00:00
2021-06-01 16:49:48 +00:00
connect ( this , SIGNAL ( haveAudioData ( audioPacket ) ) , txaudio , SLOT ( incomingAudio ( audioPacket ) ) ) ;
2021-03-22 09:10:03 +00:00
2021-06-01 16:49:48 +00:00
}
if ( rxaudio = = Q_NULLPTR )
{
2021-06-06 20:34:54 +00:00
inAudio . codec = current - > rxCodec ;
2021-06-04 13:25:07 +00:00
inAudio . samplerate = current - > rxSampleRate ;
2021-06-01 16:49:48 +00:00
rxaudio = new audioHandler ( ) ;
2021-08-19 09:21:30 +00:00
2021-06-01 16:49:48 +00:00
rxAudioThread = new QThread ( this ) ;
2021-08-23 22:59:40 +00:00
2021-08-23 22:59:40 +00:00
rxaudio - > moveToThread ( rxAudioThread ) ;
2021-08-27 16:18:12 +00:00
2021-08-23 22:59:40 +00:00
rxAudioThread - > start ( QThread : : TimeCriticalPriority ) ;
2021-03-22 09:10:03 +00:00
2021-06-04 07:24:26 +00:00
connect ( this , SIGNAL ( setupRxAudio ( audioSetup ) ) , rxaudio , SLOT ( init ( audioSetup ) ) ) ;
2021-06-02 07:37:26 +00:00
connect ( rxAudioThread , SIGNAL ( finished ( ) ) , rxaudio , SLOT ( deleteLater ( ) ) ) ;
2021-03-22 09:10:03 +00:00
2021-06-04 13:25:07 +00:00
emit setupRxAudio ( inAudio ) ;
2021-03-22 09:10:03 +00:00
2021-06-01 16:49:48 +00:00
rxAudioTimer = new QTimer ( ) ;
rxAudioTimer - > setTimerType ( Qt : : PreciseTimer ) ;
connect ( rxAudioTimer , & QTimer : : timeout , this , std : : bind ( & udpServer : : sendRxAudio , this ) ) ;
2021-06-01 19:37:12 +00:00
rxAudioTimer - > start ( 20 ) ;
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 ;
}
}
}
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 ) {
if ( in - > seq = = current - > pingSeq | | in - > seq = = current - > pingSeq - 1 )
2021-02-23 20:49:26 +00:00
{
2021-06-01 16:49:48 +00:00
// A Reply to our ping!
if ( in - > seq = = current - > pingSeq ) {
current - > pingSeq + + ;
}
else {
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : got out of sequence ping reply. Got: " < < in - > seq < < " expecting: " < < current - > pingSeq ;
2021-02-23 20:49:26 +00:00
}
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 ] ;
}
2021-05-14 08:55:02 +00:00
2021-06-01 16:49:48 +00:00
emit haveDataFromServer ( r . mid ( 0x15 ) ) ;
}
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 ;
}
}
}
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 ) ) ;
2021-02-17 23:10:26 +00:00
current - > pingTimer - > 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-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 ) {
if ( in - > seq = = current - > pingSeq | | in - > seq = = current - > pingSeq - 1 )
2021-02-23 20:49:26 +00:00
{
2021-06-01 16:49:48 +00:00
// A Reply to our ping!
if ( in - > seq = = current - > pingSeq ) {
current - > pingSeq + + ;
}
else {
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " : got out of sequence ping reply. Got: " < < in - > seq < < " expecting: " < < current - > pingSeq ;
2021-02-23 20:49:26 +00:00
}
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 :
{
//break;
}
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 )
{
auto match = std : : find_if ( current - > txSeqBuf . begin ( ) , current - > txSeqBuf . end ( ) , [ & cs = in - > seq ] ( SEQBUFENTRY & s ) {
return s . seqNum = = cs ;
} ) ;
if ( match = = current - > txSeqBuf . end ( ) ) {
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < current - > ipAddress . toString ( ) < < " ( " < < current - > type < < " ): Requested packet " < < hex < < in - > 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 ) )
{
// Add incoming packet to the received buffer and if it is in the missing buffer, remove it.
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
{
2021-11-10 20:45:59 +00:00
if ( current - > rxSeqBuf . size ( ) > 400 )
{
current - > rxSeqBuf . remove ( 0 ) ;
}
current - > rxSeqBuf . insert ( in - > seq , QTime : : currentTime ( ) ) ;
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 ) ) )
{
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 ) ) )
{
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-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Sending Capabilities : " < < c - > txSeq ;
2021-02-17 23:10:26 +00:00
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 . len = sizeof ( p ) ;
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 ;
p . code = 0x0298 ;
p . res = 0x02 ;
p . capa = 0x01 ;
p . commoncap = c - > commonCap ;
2021-03-22 09:10:03 +00:00
memcpy ( p . macaddress , macAddress . toLocal8Bit ( ) , 6 ) ;
2021-02-28 20:10:07 +00:00
// IRU seems to expect an "Icom" mac address so replace the first 3 octets of our Mac with one in their range!
memcpy ( p . macaddress , QByteArrayLiteral ( " \x00 \x90 \xc7 " ) . constData ( ) , 3 ) ;
2021-02-23 20:49:26 +00:00
2021-03-22 09:10:03 +00:00
memcpy ( p . name , rigCaps . modelName . toLocal8Bit ( ) , rigCaps . modelName . length ( ) ) ;
2021-02-28 20:10:07 +00:00
memcpy ( p . audio , QByteArrayLiteral ( " ICOM_VAUDIO " ) . constData ( ) , 11 ) ;
if ( rigCaps . hasWiFi & & ! rigCaps . hasEthernet ) {
p . conntype = 0x0707 ; // 0x0707 for wifi rig.
}
else {
2021-03-22 09:10:03 +00:00
p . conntype = 0x073f ; // 0x073f for ethernet rig.
2021-02-28 20:10:07 +00:00
}
p . civ = rigCaps . civ ;
2021-05-21 15:30:52 +00:00
p . baudrate = ( quint32 ) qToBigEndian ( config . baudRate ) ;
2021-03-01 16:28:15 +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
*/
2021-03-22 09:10:03 +00:00
if ( rxaudio = = Q_NULLPTR ) {
p . rxsample = 0x8b01 ; // all rx sample frequencies supported
}
else {
if ( rxSampleRate = = 48000 ) {
p . rxsample = 0x0800 ; // fixed rx sample frequency
}
else if ( rxSampleRate = = 32000 ) {
p . rxsample = 0x0400 ;
}
else if ( rxSampleRate = = 24000 ) {
p . rxsample = 0x0001 ;
}
else if ( rxSampleRate = = 16000 ) {
p . rxsample = 0x0200 ;
}
else if ( rxSampleRate = = 12000 ) {
p . rxsample = 0x8000 ;
}
}
if ( txaudio = = Q_NULLPTR ) {
p . txsample = 0x8b01 ; // all tx sample frequencies supported
p . enablea = 0x01 ; // 0x01 enables TX 24K mode?
2021-05-22 10:32:57 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Client will have TX audio " ;
2021-03-22 09:10:03 +00:00
}
else {
2021-05-22 10:32:57 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Disable tx audio for client " ;
p . txsample = 0 ;
2021-03-22 09:10:03 +00:00
}
2021-02-28 20:10:07 +00:00
// I still don't know what these are?
2021-03-01 16:28:15 +00:00
p . enableb = 0x01 ; // 0x01 doesn't seem to do anything?
p . enablec = 0x01 ; // 0x01 doesn't seem to do anything?
2021-06-01 16:49:48 +00:00
p . capf = 0x5001 ;
2021-02-28 20:10:07 +00:00
p . capg = 0x0190 ;
2021-05-14 08:55:02 +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-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
{
2021-11-10 20:45:59 +00:00
if ( c - > txSeqBuf . size ( ) > 400 )
{
c - > txSeqBuf . remove ( 0 ) ;
}
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 ) ) )
{
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-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.
2021-02-16 16:16:46 +00:00
void udpServer : : sendConnectionInfo ( CLIENT * c )
{
2021-05-15 17:53:16 +00:00
qInfo ( logUdpServer ( ) ) < < c - > ipAddress . toString ( ) < < " ( " < < c - > type < < " ): Sending ConnectionInfo : " < < c - > txSeq ;
2021-02-23 20:49:26 +00:00
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 ;
2021-02-28 20:10:07 +00:00
//p.innerseq = c->authInnerSeq; // Innerseq not used in user packet
2021-02-23 20:49:26 +00:00
p . tokrequest = c - > tokenRx ;
p . token = c - > tokenTx ;
p . code = 0x0380 ;
p . commoncap = c - > commonCap ;
2021-03-22 09:10:03 +00:00
p . identa = c - > identa ;
p . identb = c - > identb ;
2021-02-16 16:16:46 +00:00
// 0x1a-0x1f is authid (random number?
2021-02-17 23:10:26 +00:00
// memcpy(p + 0x40, QByteArrayLiteral("IC-7851").constData(), 7);
2021-02-16 16:16:46 +00:00
2021-03-22 09:10:03 +00:00
memcpy ( p . packet + 0x40 , rigCaps . modelName . toLocal8Bit ( ) , rigCaps . modelName . length ( ) ) ;
2021-02-17 23:10:26 +00:00
// This is the current streaming client (should we support multiple clients?)
if ( c - > isStreaming ) {
2021-02-23 20:49:26 +00:00
p . busy = 0x01 ;
memcpy ( p . computer , c - > clientName . constData ( ) , c - > clientName . length ( ) ) ;
p . ipaddress = qToBigEndian ( c - > ipAddress . toIPv4Address ( ) ) ;
2021-03-22 09:10:03 +00:00
p . identa = c - > identa ;
p . identb = c - > identb ;
2021-02-17 23:10:26 +00:00
}
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
{
2021-11-10 20:45:59 +00:00
if ( c - > txSeqBuf . size ( ) > 400 )
{
c - > txSeqBuf . remove ( 0 ) ;
}
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 ) ) )
{
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-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
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 ;
2021-03-22 09:10:03 +00:00
p . identa = c - > identa ;
p . identb = c - > identb ;
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
{
2021-11-10 20:45:59 +00:00
if ( c - > txSeqBuf . size ( ) > 400 )
{
c - > txSeqBuf . remove ( 0 ) ;
}
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-02-28 20:10:07 +00:00
# define PURGE_SECONDS 60
2021-02-18 13:49:19 +00:00
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
2021-06-11 11:53:00 +00:00
emit haveNetworkStatus ( QString ( " <pre>Server connections: Control:%1 CI-V:%2 Audio:%3</pre> " ) . arg ( controlClients . size ( ) ) . arg ( civClients . size ( ) ) . arg ( audioClients . size ( ) ) ) ;
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 ;
2021-03-22 09:10:03 +00:00
p . identa = c - > identa ;
p . identb = c - > identb ;
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
{
2021-11-10 20:45:59 +00:00
if ( c - > txSeqBuf . size ( ) > 400 )
{
c - > txSeqBuf . remove ( 0 ) ;
}
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 )
{
2021-05-15 17:53:16 +00:00
//qInfo(logUdpServer()) << "Server got:" << d;
2021-02-18 09:14:41 +00:00
foreach ( CLIENT * client , civClients )
{
2021-05-14 08:55:02 +00:00
int lastFE = d . lastIndexOf ( ( quint8 ) 0xfe ) ;
2021-06-07 11:26:29 +00:00
if ( client ! = Q_NULLPTR & & client - > connected & & d . length ( ) > lastFE + 2 & &
( ( quint8 ) d [ lastFE + 1 ] = = client - > civId | | ( quint8 ) d [ lastFE + 2 ] = = client - > civId | |
2021-06-09 08:24:20 +00:00
( quint8 ) d [ lastFE + 1 ] = = 0x00 | | ( quint8 ) d [ lastFE + 2 ] = = 0x00 | | ( quint8 ) d [ lastFE + 1 ] = = 0xE1 | | ( quint8 ) d [ lastFE + 2 ] = = 0xE1 ) ) {
2021-02-23 20:49:26 +00:00
data_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
p . len = ( quint16 ) d . length ( ) + sizeof ( p ) ;
2021-02-23 20:49:26 +00:00
p . seq = client - > txSeq ;
p . sentid = client - > myId ;
p . rcvdid = client - > remoteId ;
p . reply = ( char ) 0xc1 ;
2021-02-28 20:10:07 +00:00
p . datalen = ( quint16 ) d . length ( ) ;
p . sendseq = client - > innerSeq ;
2021-02-23 20:49:26 +00:00
QByteArray t = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2021-02-18 13:49:19 +00:00
t . append ( d ) ;
2021-06-01 22:32:39 +00:00
SEQBUFENTRY s ;
s . seqNum = p . seq ;
s . timeSent = QTime : : currentTime ( ) ;
s . retransmitCount = 0 ;
s . data = t ;
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( client - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2021-11-10 20:45:59 +00:00
if ( client - > txSeqBuf . size ( ) > 400 )
{
client - > txSeqBuf . remove ( 0 ) ;
}
client - > txSeqBuf . insert ( p . seq , s ) ;
client - > txSeq + + ;
client - > innerSeq + + ;
client - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
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-01 22:32:39 +00:00
}
2021-06-02 09:43:52 +00:00
2021-06-07 11:26:29 +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
void udpServer : : sendRxAudio ( )
{
2021-05-28 09:45:09 +00:00
QByteArray audio ;
2021-05-27 13:42:28 +00:00
if ( rxaudio ) {
2021-11-15 19:28:44 +00:00
if ( audioMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
audio . clear ( ) ;
rxaudio - > getNextAudioChunk ( audio ) ;
// Now we have the next audio chunk, we can release the mutex.
audioMutex . unlock ( ) ;
int len = 0 ;
while ( len < audio . length ( ) ) {
audioPacket partial ;
partial . data = audio . mid ( len , 1364 ) ;
receiveAudioData ( partial ) ;
len = len + partial . data . length ( ) ;
}
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock mutex for rxaudio " ;
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
{
2021-05-15 17:53:16 +00:00
//qInfo(logUdpServer()) << "Server got:" << d.data.length();
2021-02-28 20:10:07 +00:00
foreach ( CLIENT * client , audioClients )
{
if ( client ! = Q_NULLPTR & & client - > connected ) {
audio_packet p ;
memset ( p . packet , 0x0 , sizeof ( p ) ) ; // We can't be sure it is initialized with 0x00!
2021-05-27 10:41:08 +00:00
p . len = sizeof ( p ) + d . data . length ( ) ;
2021-02-28 20:10:07 +00:00
p . sentid = client - > myId ;
p . rcvdid = client - > remoteId ;
p . ident = 0x0080 ; // audio is always this?
2021-05-27 10:41:08 +00:00
p . datalen = ( quint16 ) qToBigEndian ( ( quint16 ) d . data . length ( ) ) ;
2021-02-28 20:10:07 +00:00
p . sendseq = ( quint16 ) qToBigEndian ( ( quint16 ) client - > sendAudioSeq ) ; // THIS IS BIG ENDIAN!
2021-03-22 09:10:03 +00:00
p . seq = client - > txSeq ;
2021-02-28 20:10:07 +00:00
QByteArray t = QByteArray : : fromRawData ( ( const char * ) p . packet , sizeof ( p ) ) ;
2021-05-27 10:41:08 +00:00
t . append ( d . data ) ;
2021-05-14 08:55:02 +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 = t ;
2021-11-10 20:45:59 +00:00
if ( client - > txMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2021-11-10 20:45:59 +00:00
if ( client - > txSeqBuf . size ( ) > 400 )
{
client - > txSeqBuf . remove ( 0 ) ;
}
client - > txSeqBuf . insert ( p . seq , s ) ;
client - > txSeq + + ;
client - > sendAudioSeq + + ;
client - > txMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock txMutex() " ;
}
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-01 16:49:48 +00:00
}
2021-06-02 09:43:52 +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
QByteArray missingSeqs ;
2021-06-01 22:32:39 +00:00
if ( ! c - > rxSeqBuf . empty ( ) & & c - > rxSeqBuf . size ( ) < = c - > rxSeqBuf . lastKey ( ) - c - > rxSeqBuf . firstKey ( ) )
2021-02-28 20:10:07 +00:00
{
2021-06-01 22:32:39 +00:00
if ( ( c - > rxSeqBuf . lastKey ( ) - c - > rxSeqBuf . firstKey ( ) - c - > rxSeqBuf . size ( ) ) > 20 )
2021-02-28 20:10:07 +00:00
{
2021-06-01 22:32:39 +00:00
// Too many packets to process, flush buffers and start again!
qDebug ( logUdp ( ) ) < < " Too many missing packets, flushing buffer: " < < c - > rxSeqBuf . lastKey ( ) < < " missing= " < < c - > rxSeqBuf . lastKey ( ) - c - > rxSeqBuf . firstKey ( ) - c - > rxSeqBuf . size ( ) + 1 ;
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 ( 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-02 09:43:52 +00:00
2021-06-01 22:32:39 +00:00
}
else {
// We have at least 1 missing packet!
qDebug ( logUdp ( ) ) < < " Missing Seq: size= " < < c - > rxSeqBuf . size ( ) < < " firstKey= " < < c - > rxSeqBuf . firstKey ( ) < < " lastKey= " < < c - > rxSeqBuf . lastKey ( ) < < " missing= " < < c - > rxSeqBuf . lastKey ( ) - c - > rxSeqBuf . firstKey ( ) - c - > rxSeqBuf . size ( ) + 1 ;
// We are missing packets so iterate through the buffer and add the missing ones to missing packet list
for ( int i = 0 ; i < c - > rxSeqBuf . keys ( ) . length ( ) - 1 ; i + + ) {
for ( quint16 j = c - > rxSeqBuf . keys ( ) [ i ] + 1 ; j < c - > rxSeqBuf . keys ( ) [ i + 1 ] ; j + + ) {
auto s = c - > rxMissing . find ( j ) ;
2021-02-28 20:10:07 +00:00
if ( s = = c - > rxMissing . end ( ) )
{
// We haven't seen this missing packet before
2021-06-01 22:32:39 +00:00
qDebug ( logUdp ( ) ) < < this - > metaObject ( ) - > className ( ) < < " : Adding to missing buffer (len= " < < c - > rxMissing . size ( ) < < " ): " < < j ;
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( c - > missMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
c - > rxMissing . insert ( j , 0 ) ;
c - > missMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock missMutex() " ;
}
2021-06-02 09:43:52 +00:00
2021-11-10 20:45:59 +00:00
if ( c - > rxMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
2021-06-01 22:32:39 +00:00
{
2021-11-10 20:45:59 +00:00
if ( c - > rxSeqBuf . size ( ) > 400 )
{
c - > rxSeqBuf . remove ( 0 ) ;
}
c - > rxSeqBuf . insert ( j , QTime : : currentTime ( ) ) ; // Add this missing packet to the rxbuffer as we now long about it.
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
2021-02-28 20:10:07 +00:00
}
else {
2021-06-01 22:32:39 +00:00
if ( s . value ( ) = = 4 )
2021-02-28 20:10:07 +00:00
{
// We have tried 4 times to request this packet, time to give up!
2021-11-10 20:45:59 +00:00
if ( c - > missMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
s = c - > rxMissing . erase ( s ) ;
c - > missMutex . unlock ( ) ;
}
else {
qInfo ( logUdpServer ( ) ) < < " Unable to lock missMutex() " ;
}
2021-02-28 20:10:07 +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
{
2021-11-10 20:45:59 +00:00
if ( it . value ( ) < 10 )
{
missingSeqs . append ( it . key ( ) & 0xff ) ;
missingSeqs . append ( it . key ( ) > > 8 & 0xff ) ;
missingSeqs . append ( it . key ( ) & 0xff ) ;
missingSeqs . append ( it . key ( ) > > 8 & 0xff ) ;
it . value ( ) + + ;
}
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 ( ) ;
if ( udpMutex . try_lock_for ( std : : chrono : : milliseconds ( LOCK_PERIOD ) ) )
{
missingSeqs . insert ( 0 , p . packet , sizeof ( p . packet ) ) ;
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-05-14 08:55:02 +00:00
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
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 ) ;
}
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
if ( l - > length ( ) = = 0 ) {
if ( rxAudioTimer ! = Q_NULLPTR ) {
rxAudioTimer - > stop ( ) ;
delete rxAudioTimer ;
rxAudioTimer = Q_NULLPTR ;
}
if ( rxAudioThread ! = Q_NULLPTR ) {
rxAudioThread - > quit ( ) ;
rxAudioThread - > wait ( ) ;
rxaudio = Q_NULLPTR ;
rxAudioThread = Q_NULLPTR ;
}
if ( txAudioThread ! = Q_NULLPTR ) {
txAudioThread - > quit ( ) ;
txAudioThread - > wait ( ) ;
txaudio = Q_NULLPTR ;
txAudioThread = Q_NULLPTR ;
}
2021-06-01 16:49:48 +00:00
2021-03-22 09:10:03 +00:00
}
2021-02-18 13:49:19 +00:00
}