Skip to content

Commit b12ce7e

Browse files
pgScorpioann0see
andcommitted
Fix connection status issue (#2519)
This is a manual port of #2550 by @pgScorpio Co-authored-by: ann0see <20726856+ann0see@users.noreply.github.com>
1 parent 5227d1c commit b12ce7e

File tree

8 files changed

+209
-220
lines changed

8 files changed

+209
-220
lines changed

src/channel.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ CChannel::CChannel ( const bool bNIsServer ) :
3737
bIsEnabled ( false ),
3838
bIsServer ( bNIsServer ),
3939
bIsIdentified ( false ),
40+
bDisconnectAndDisable ( false ),
4041
iAudioFrameSizeSamples ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ),
4142
SignalLevelMeter ( false, 0.5 ) // server mode with mono out and faster smoothing
4243
{
@@ -125,7 +126,8 @@ void CChannel::SetEnable ( const bool bNEnStat )
125126
QMutexLocker locker ( &Mutex );
126127

127128
// set internal parameter
128-
bIsEnabled = bNEnStat;
129+
bIsEnabled = bNEnStat;
130+
bDisconnectAndDisable = false;
129131

130132
// The support for the packet sequence number must be reset if the client
131133
// disconnects from a server since we do not yet know if the next server we
@@ -506,11 +508,24 @@ void CChannel::Disconnect()
506508
// we only have to disconnect the channel if it is actually connected
507509
if ( IsConnected() )
508510
{
511+
// for a Client, block further audio data and disable the channel as soon as Disconnect() is called
512+
// TODO: Add reasoning from #2550
513+
514+
bDisconnectAndDisable = !bIsServer;
515+
509516
// set time out counter to a small value > 0 so that the next time a
510517
// received audio block is queried, the disconnection is performed
511518
// (assuming that no audio packet is received in the meantime)
512519
iConTimeOut = 1; // a small number > 0
513520
}
521+
else if ( !bIsServer )
522+
{
523+
// For clients (?) set defaults
524+
525+
bDisconnectAndDisable = false;
526+
bIsEnabled = false;
527+
iConTimeOut = 0;
528+
}
514529
}
515530

516531
void CChannel::PutProtocolData ( const int iRecCounter, const int iRecID, const CVector<uint8_t>& vecbyMesBodyData, const CHostAddress& RecHostAddr )
@@ -534,7 +549,7 @@ EPutDataStat CChannel::PutAudioData ( const CVector<uint8_t>& vecbyData, const i
534549
// Only process audio data if:
535550
// - for client only: the packet comes from the server we want to talk to
536551
// - the channel is enabled
537-
if ( ( bIsServer || ( GetAddress() == RecHostAddr ) ) && IsEnabled() )
552+
if ( ( bIsServer || ( GetAddress() == RecHostAddr ) ) && IsEnabled() && !bDisconnectAndDisable )
538553
{
539554
MutexSocketBuf.lock();
540555
{
@@ -622,6 +637,11 @@ EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData, const int iNumByte
622637
eGetStatus = GS_CHAN_NOW_DISCONNECTED;
623638
iConTimeOut = 0; // make sure we do not have negative values
624639

640+
if ( bDisconnectAndDisable )
641+
{
642+
bDisconnectAndDisable = false;
643+
bIsEnabled = false;
644+
}
625645
// reset network transport properties
626646
ResetNetworkTransportProperties();
627647
}
@@ -643,6 +663,13 @@ EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData, const int iNumByte
643663
{
644664
// channel is disconnected
645665
eGetStatus = GS_CHAN_NOT_CONNECTED;
666+
667+
if ( bDisconnectAndDisable )
668+
{
669+
bDisconnectAndDisable = false;
670+
bIsEnabled = false;
671+
iConTimeOut = 0;
672+
}
646673
}
647674
}
648675
MutexSocketBuf.unlock();

src/channel.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class CChannel : public QObject
7676

7777
void PrepAndSendPacket ( CHighPrioSocket* pSocket, const CVector<uint8_t>& vecbyNPacket, const int iNPacketLen );
7878

79-
void ResetTimeOutCounter() { iConTimeOut = iConTimeOutStartVal; }
79+
void ResetTimeOutCounter() { iConTimeOut = bDisconnectAndDisable ? 1 : iConTimeOutStartVal; }
8080
bool IsConnected() const { return iConTimeOut > 0; }
8181
void Disconnect();
8282

@@ -216,6 +216,7 @@ class CChannel : public QObject
216216
bool bIsEnabled;
217217
bool bIsServer;
218218
bool bIsIdentified;
219+
bool bDisconnectAndDisable;
219220

220221
int iNetwFrameSizeFact;
221222
int iNetwFrameSize;

src/client.cpp

Lines changed: 98 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
/* Implementation *************************************************************/
2828
CClient::CClient ( const quint16 iPortNumber,
2929
const quint16 iQosNumber,
30-
const QString& strConnOnStartupAddress,
3130
const QString& strMIDISetup,
3231
const bool bNoAutoJackConnect,
3332
const QString& strNClientName,
@@ -184,13 +183,6 @@ CClient::CClient ( const quint16 iPortNumber,
184183
// start the socket (it is important to start the socket after all
185184
// initializations and connections)
186185
Socket.Start();
187-
188-
// do an immediate start if a server address is given
189-
if ( !strConnOnStartupAddress.isEmpty() )
190-
{
191-
SetServerAddr ( strConnOnStartupAddress );
192-
Start();
193-
}
194186
}
195187

196188
CClient::~CClient()
@@ -337,7 +329,7 @@ void CClient::CreateServerJitterBufferMessage()
337329
void CClient::OnCLPingReceived ( CHostAddress InetAddr, int iMs )
338330
{
339331
// make sure we are running and the server address is correct
340-
if ( IsRunning() && ( InetAddr == Channel.GetAddress() ) )
332+
if ( Channel.IsEnabled() && ( InetAddr == Channel.GetAddress() ) )
341333
{
342334
// take care of wrap arounds (if wrapping, do not use result)
343335
const int iCurDiff = EvaluatePingMessage ( iMs );
@@ -474,26 +466,6 @@ void CClient::StartDelayTimer()
474466
}
475467
}
476468

477-
bool CClient::SetServerAddr ( QString strNAddr )
478-
{
479-
CHostAddress HostAddress;
480-
#ifdef CLIENT_NO_SRV_CONNECT
481-
if ( NetworkUtil().ParseNetworkAddress ( strNAddr, HostAddress, bEnableIPv6 ) )
482-
#else
483-
if ( NetworkUtil().ParseNetworkAddressWithSrvDiscovery ( strNAddr, HostAddress, bEnableIPv6 ) )
484-
#endif
485-
{
486-
// apply address to the channel
487-
Channel.SetAddress ( HostAddress );
488-
489-
return true;
490-
}
491-
else
492-
{
493-
return false; // invalid address
494-
}
495-
}
496-
497469
bool CClient::GetAndResetbJitterBufferOKFlag()
498470
{
499471
// get the socket buffer put status flag and reset it
@@ -626,12 +598,16 @@ QString CClient::SetSndCrdDev ( const QString strNewDev )
626598
Sound.Start();
627599
}
628600

629-
// in case of an error inform the GUI about it
630601
if ( !strError.isEmpty() )
631602
{
632-
emit SoundDeviceChanged ( strError );
603+
// due to error, disconnect
604+
Disconnect();
633605
}
634606

607+
// in case of an error, this will inform the GUI about it
608+
609+
emit SoundDeviceChanged();
610+
635611
return strError;
636612
}
637613

@@ -758,8 +734,18 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType )
758734
}
759735
MutexDriverReinit.unlock();
760736

737+
if ( !strError.isEmpty() )
738+
{
739+
#ifndef HEADLESS
740+
QMessageBox::critical ( 0, APP_NAME, strError, tr ( "Ok" ) );
741+
#else
742+
qCritical() << qUtf8Printable ( strError );
743+
exit ( 1 );
744+
#endif
745+
}
746+
761747
// inform GUI about the sound card device change
762-
emit SoundDeviceChanged ( strError );
748+
emit SoundDeviceChanged();
763749
}
764750

765751
void CClient::OnHandledSignal ( int sigNum )
@@ -773,11 +759,8 @@ void CClient::OnHandledSignal ( int sigNum )
773759
{
774760
case SIGINT:
775761
case SIGTERM:
776-
// if connected, terminate connection (needed for headless mode)
777-
if ( IsRunning() )
778-
{
779-
Stop();
780-
}
762+
// if connected, terminate connection
763+
Disconnect();
781764

782765
// this should trigger OnAboutToQuit
783766
QCoreApplication::instance()->exit();
@@ -862,50 +845,89 @@ void CClient::OnClientIDReceived ( int iChanID )
862845
emit ClientIDReceived ( iChanID );
863846
}
864847

865-
void CClient::Start()
848+
bool CClient::Connect ( QString strServerAddress, QString strServerName )
866849
{
867-
// init object
868-
Init();
850+
if ( !Channel.IsEnabled() )
851+
{
852+
CHostAddress HostAddress;
853+
854+
if ( NetworkUtil().ParseNetworkAddress ( strServerAddress, HostAddress, bEnableIPv6 ) )
855+
{
856+
// init object
857+
Init();
869858

870-
// enable channel
871-
Channel.SetEnable ( true );
859+
// apply address to the channel
860+
Channel.SetAddress ( HostAddress );
872861

873-
// start audio interface
874-
Sound.Start();
862+
// enable channel
863+
Channel.SetEnable ( true );
864+
865+
// start audio interface
866+
Sound.Start();
867+
868+
// Notify ClientDlg
869+
emit Connecting ( strServerName );
870+
871+
return true;
872+
}
873+
}
874+
875+
return false;
875876
}
876877

877-
void CClient::Stop()
878+
bool CClient::Disconnect()
878879
{
879-
// stop audio interface
880-
Sound.Stop();
881-
882-
// disable channel
883-
Channel.SetEnable ( false );
884-
885-
// wait for approx. 100 ms to make sure no audio packet is still in the
886-
// network queue causing the channel to be reconnected right after having
887-
// received the disconnect message (seems not to gain much, disconnect is
888-
// still not working reliably)
889-
QTime DieTime = QTime::currentTime().addMSecs ( 100 );
890-
while ( QTime::currentTime() < DieTime )
891-
{
892-
// exclude user input events because if we use AllEvents, it happens
893-
// that if the user initiates a connection and disconnection quickly
894-
// (e.g. quickly pressing enter five times), the software can get into
895-
// an unknown state
896-
QCoreApplication::processEvents ( QEventLoop::ExcludeUserInputEvents, 100 );
897-
}
898-
899-
// Send disconnect message to server (Since we disable our protocol
900-
// receive mechanism with the next command, we do not evaluate any
901-
// respond from the server, therefore we just hope that the message
902-
// gets its way to the server, if not, the old behaviour time-out
903-
// disconnects the connection anyway).
904-
ConnLessProtocol.CreateCLDisconnection ( Channel.GetAddress() );
905-
906-
// reset current signal level and LEDs
907-
bJitterBufferOK = true;
908-
SignalLevelMeter.Reset();
880+
if ( Channel.IsEnabled() )
881+
{
882+
// start disconnection
883+
Channel.Disconnect();
884+
885+
// Channel.Disconnect() should automatically disable Channel as soon as disconnected.
886+
// Note that this only works if Sound is Active !
887+
888+
QTime DieTime = QTime::currentTime().addMSecs ( 500 );
889+
while ( ( QTime::currentTime() < DieTime ) && Channel.IsEnabled() )
890+
{
891+
// exclude user input events because if we use AllEvents, it happens
892+
// that if the user initiates a connection and disconnection quickly
893+
// (e.g. quickly pressing enter five times), the software can get into
894+
// an unknown state
895+
QCoreApplication::processEvents ( QEventLoop::ExcludeUserInputEvents, 100 );
896+
}
897+
898+
// Now stop the audio interface
899+
Sound.Stop();
900+
901+
// in case we timed out, log warning and make sure Channel is disabled
902+
if ( Channel.IsEnabled() )
903+
{
904+
Channel.SetEnable ( false );
905+
}
906+
907+
// Send disconnect message to server (Since we disable our protocol
908+
// receive mechanism with the next command, we do not evaluate any
909+
// respond from the server, therefore we just hope that the message
910+
// gets its way to the server, if not, the old behaviour time-out
911+
// disconnects the connection anyway).
912+
ConnLessProtocol.CreateCLDisconnection ( Channel.GetAddress() );
913+
914+
// reset current signal level and LEDs
915+
bJitterBufferOK = true;
916+
SignalLevelMeter.Reset();
917+
918+
emit Disconnected();
919+
920+
return true;
921+
}
922+
else
923+
{
924+
// make sure sound is stopped too
925+
Sound.Stop();
926+
927+
emit Disconnected();
928+
929+
return false;
930+
}
909931
}
910932

911933
void CClient::Init()
@@ -921,7 +943,7 @@ void CClient::Init()
921943
bFraSiFactSafeSupported = true;
922944
#else
923945
bFraSiFactPrefSupported = ( Sound.Init ( iFraSizePreffered ) == iFraSizePreffered );
924-
bFraSiFactDefSupported = ( Sound.Init ( iFraSizeDefault ) == iFraSizeDefault );
946+
bFraSiFactDefSupported = ( Sound.Init ( iFraSizeDefault ) == iFraSizeDefault );
925947
bFraSiFactSafeSupported = ( Sound.Init ( iFraSizeSafe ) == iFraSizeSafe );
926948
#endif
927949

src/client.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ class CClient : public QObject
110110
public:
111111
CClient ( const quint16 iPortNumber,
112112
const quint16 iQosNumber,
113-
const QString& strConnOnStartupAddress,
114113
const QString& strMIDISetup,
115114
const bool bNoAutoJackConnect,
116115
const QString& strNClientName,
@@ -119,19 +118,17 @@ class CClient : public QObject
119118

120119
virtual ~CClient();
121120

122-
void Start();
123-
void Stop();
124-
bool IsRunning() { return Sound.IsRunning(); }
125-
bool IsCallbackEntered() const { return Sound.IsCallbackEntered(); }
126-
bool SetServerAddr ( QString strNAddr );
121+
bool Connect ( QString strServerAddress, QString strServerName );
122+
bool Disconnect();
123+
124+
bool SoundIsRunning() const { return Sound.IsCallbackEntered(); } // For OnTimerCheckAudioDeviceOk only
125+
bool IsConnected() { return Channel.IsConnected(); }
127126

128127
double GetLevelForMeterdBLeft() { return SignalLevelMeter.GetLevelForMeterdBLeftOrMono(); }
129128
double GetLevelForMeterdBRight() { return SignalLevelMeter.GetLevelForMeterdBRight(); }
130129

131130
bool GetAndResetbJitterBufferOKFlag();
132131

133-
bool IsConnected() { return Channel.IsConnected(); }
134-
135132
EGUIDesign GetGUIDesign() const { return eGUIDesign; }
136133
void SetGUIDesign ( const EGUIDesign eNGD ) { eGUIDesign = eNGD; }
137134

@@ -427,8 +424,9 @@ protected slots:
427424

428425
void CLChannelLevelListReceived ( CHostAddress InetAddr, CVector<uint16_t> vecLevelList );
429426

427+
void Connecting ( QString strServerName );
430428
void Disconnected();
431-
void SoundDeviceChanged ( QString strError );
429+
void SoundDeviceChanged();
432430
void ControllerInFaderLevel ( int iChannelIdx, int iValue );
433431
void ControllerInPanValue ( int iChannelIdx, int iValue );
434432
void ControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo );

0 commit comments

Comments
 (0)