From cb18b046f8049e691800f6fc4601ad149104f05d Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 17 May 2026 00:05:02 +0200 Subject: [PATCH 1/4] Add connection-less message to query enabled server features --- src/protocol.cpp | 35 +++++++++++++++++++++++++++++++++++ src/protocol.h | 5 +++++ src/server.cpp | 19 +++++++++++++++++++ src/server.h | 2 ++ 4 files changed, 61 insertions(+) diff --git a/src/protocol.cpp b/src/protocol.cpp index a595a24e45..374a5bdce7 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -459,6 +459,19 @@ CONNECTION LESS MESSAGES five times for one registration request at 500ms intervals. Beyond this, it should "ping" every 15 minutes (standard re-registration timeout). + + +- PROTMESSID_CLM_SERVER_INFO: Bitmask of enabled server features + + +------------------+ + | 4 bytes number n | + +------------------+ + + +- PROTMESSID_CLM_REQ_SERVER_INFO: Request bitmask of enabled server features + + note: does not have any data -> n = 0 + */ #include "protocol.h" @@ -947,6 +960,10 @@ void CProtocol::ParseConnectionLessMessageBody ( const CVector& vecbyMe case PROTMESSID_CLM_REGISTER_SERVER_RESP: EvaluateCLRegisterServerResp ( InetAddr, vecbyMesBodyData ); break; + + case PROTMESSID_CLM_REQ_SERVER_INFO: + EvaluateCLReqServerInfoMes ( InetAddr ); + break; } } @@ -2620,6 +2637,24 @@ bool CProtocol::EvaluateCLRegisterServerResp ( const CHostAddress& InetAddr, con return false; // no error } +bool CProtocol::EvaluateCLReqServerInfoMes ( const CHostAddress& InetAddr ) +{ + // invoke message action + emit CLReqServerInfo ( InetAddr ); + + return false; // no error +} + +void CProtocol::CreateCLServerInfoMes ( const CHostAddress& InetAddr, const uint32_t iFeatures ) +{ + int iPos = 0; // init position pointer + CVector vecData ( 1 ); + + PutValOnStream ( vecData, iPos, iFeatures, 4 ); + + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_INFO, vecData, InetAddr ); +} + /******************************************************************************\ * Message generation and parsing * \******************************************************************************/ diff --git a/src/protocol.h b/src/protocol.h index 4621fe31b7..61b654f03e 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -106,6 +106,8 @@ #define PROTMESSID_CLM_REGISTER_SERVER_RESP 1016 // status of server registration request #define PROTMESSID_CLM_REGISTER_SERVER_EX 1017 // register server with extended information #define PROTMESSID_CLM_RED_SERVER_LIST 1018 // reduced server list +#define PROTMESSID_CLM_SERVER_INFO 1019 // server info message +#define PROTMESSID_CLM_REQ_SERVER_INFO 1020 // request server info // special IDs #define PROTMESSID_SPECIAL_SPLIT_MESSAGE 2001 // a container for split messages @@ -177,6 +179,7 @@ class CProtocol : public QObject void CreateCLReqConnClientsListMes ( const CHostAddress& InetAddr ); void CreateCLChannelLevelListMes ( const CHostAddress& InetAddr, const CVector& vecLevelList, const int iNumClients ); void CreateCLRegisterServerResp ( const CHostAddress& InetAddr, const ESvrRegResult eResult ); + void CreateCLServerInfoMes ( const CHostAddress& InetAddr, const uint32_t iResult ); static bool ParseMessageFrame ( const CVector& vecbyData, const int iNumBytesIn, @@ -304,6 +307,7 @@ class CProtocol : public QObject bool EvaluateCLReqConnClientsListMes ( const CHostAddress& InetAddr ); bool EvaluateCLChannelLevelListMes ( const CHostAddress& InetAddr, const CVector& vecData ); bool EvaluateCLRegisterServerResp ( const CHostAddress& InetAddr, const CVector& vecData ); + bool EvaluateCLReqServerInfoMes ( const CHostAddress& InetAddr ); int iOldRecID; int iOldRecCnt; @@ -371,4 +375,5 @@ public slots: void CLReqConnClientsList ( CHostAddress InetAddr ); void CLChannelLevelListReceived ( CHostAddress InetAddr, CVector vecLevelList ); void CLRegisterServerResp ( CHostAddress InetAddr, ESvrRegResult eStatus ); + void CLReqServerInfo ( CHostAddress InetAddr ); }; diff --git a/src/server.cpp b/src/server.cpp index 67274965bc..8d7cc8337e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -45,6 +45,7 @@ \******************************************************************************/ #include "server.h" +#include "util.h" // CServer implementation ****************************************************** CServer::CServer ( const int iNewMaxNumChan, @@ -291,6 +292,8 @@ CServer::CServer ( const int iNewMaxNumChan, QObject::connect ( &ConnLessProtocol, &CProtocol::CLReqConnClientsList, this, &CServer::OnCLReqConnClientsList ); + QObject::connect ( &ConnLessProtocol, &CProtocol::CLReqServerInfo, this, &CServer::OnCLReqServerInfo ); + QObject::connect ( &ServerListManager, &CServerListManager::SvrRegStatusChanged, this, &CServer::SvrRegStatusChanged ); QObject::connect ( &JamController, &recorder::CJamController::RestartRecorder, this, &CServer::RestartRecorder ); @@ -472,6 +475,22 @@ void CServer::OnNewConnection ( int iChID, int iTotChans, CHostAddress RecHostAd Logging.AddNewConnection ( RecHostAddr.InetAddr, iTotChans ); } +void CServer::OnCLReqServerInfo ( CHostAddress RecHostAddr ) +{ + uint32_t iFeatures = 0; + + iFeatures |= (bUseDoubleSystemFrameSize << 0); + iFeatures |= (bUseMultithreading << 1); + iFeatures |= (GetRecorderInitialised() << 2); + iFeatures |= (GetDisableRecording() << 3); + iFeatures |= ((JamController.GetRecorderState() != RS_RECORDING) << 4); + iFeatures |= (bDelayPan << 5); + iFeatures |= (bEnableIPv6 << 6); + // iFeatures |= (bDisableRaw << 5); + + ConnLessProtocol.CreateCLServerInfoMes ( RecHostAddr, iFeatures ); +} + void CServer::OnServerFull ( CHostAddress RecHostAddr ) { // note: no mutex required here diff --git a/src/server.h b/src/server.h index 2e6b13e835..8617c94f77 100644 --- a/src/server.h +++ b/src/server.h @@ -396,6 +396,8 @@ public slots: void OnCLUnregisterServerReceived ( CHostAddress InetAddr ) { ServerListManager.Remove ( InetAddr ); } + void OnCLReqServerInfo ( CHostAddress InetAddr ); + void OnCLDisconnection ( CHostAddress InetAddr ); void OnAboutToQuit(); From 7797998a235ffeda6a7632c59d897c2a2abd62f5 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 17 May 2026 00:21:35 +0200 Subject: [PATCH 2/4] add enum for feature set --- src/server.cpp | 17 +++++++++-------- src/util.h | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 8d7cc8337e..d2abe7baa7 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -479,14 +479,15 @@ void CServer::OnCLReqServerInfo ( CHostAddress RecHostAddr ) { uint32_t iFeatures = 0; - iFeatures |= (bUseDoubleSystemFrameSize << 0); - iFeatures |= (bUseMultithreading << 1); - iFeatures |= (GetRecorderInitialised() << 2); - iFeatures |= (GetDisableRecording() << 3); - iFeatures |= ((JamController.GetRecorderState() != RS_RECORDING) << 4); - iFeatures |= (bDelayPan << 5); - iFeatures |= (bEnableIPv6 << 6); - // iFeatures |= (bDisableRaw << 5); + iFeatures |= ( !bUseDoubleSystemFrameSize << FS_FAST_UPDATE ); + iFeatures |= ( bUseMultithreading << FS_MULTITHREADING ); + iFeatures |= ( ( GetRecorderInitialised() && !GetDisableRecording() ) << FS_RECORDER_ENABLED ); + iFeatures |= ( ( JamController.GetRecorderState() == RS_RECORDING ) << FS_IS_RECORDING ); + iFeatures |= ( bDelayPan << FS_DELAY_PAN ); + iFeatures |= ( IsIPv6Available() << FS_IPV6_AVAILABLE ); + iFeatures |= ( bDisableRaw << FS_RAW_AUDIO ); + iFeatures |= ( bDisconnectAllClientsOnQuit << FS_DISCONONQUIT ); + iFeatures |= ( !strWelcomeMessage.isEmpty() << FS_HAS_WELCOME_MESSAGE ); ConnLessProtocol.CreateCLServerInfoMes ( RecHostAddr, iFeatures ); } diff --git a/src/util.h b/src/util.h index 84ce8e3261..29e22aba64 100644 --- a/src/util.h +++ b/src/util.h @@ -617,6 +617,21 @@ enum EDirectoryType AT_CUSTOM = 7 // Must be the last entry! }; +// Server feature set ---------------------------------------------------------- +enum EFeatureSet +{ + // used for protocol -> enum values must be fixed + FS_FAST_UPDATE = 0, + FS_MULTITHREADING = 1, + FS_RECORDER_ENABLED = 2, + FS_IS_RECORDING = 3, + FS_DELAY_PAN = 4, + FS_IPV6_AVAILABLE = 5, + FS_RAW_AUDIO = 6, + FS_DISCONONQUIT = 7, + FS_HAS_WELCOME_MESSAGE = 8 +}; + inline QString DirectoryTypeToString ( EDirectoryType eAddrType ) { switch ( eAddrType ) From a609fa639782f7f19b3e13db35d7e961848622a4 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Tue, 9 Jun 2026 22:19:33 +0200 Subject: [PATCH 3/4] add FS_IS_LOGGING and FS_HAS_LICENCE flags to feature set message --- src/server.cpp | 2 ++ src/serverlogging.h | 1 + src/util.h | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index d2abe7baa7..10c58bea98 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -488,6 +488,8 @@ void CServer::OnCLReqServerInfo ( CHostAddress RecHostAddr ) iFeatures |= ( bDisableRaw << FS_RAW_AUDIO ); iFeatures |= ( bDisconnectAllClientsOnQuit << FS_DISCONONQUIT ); iFeatures |= ( !strWelcomeMessage.isEmpty() << FS_HAS_WELCOME_MESSAGE ); + iFeatures |= ( Logging.bIsLogging() << FS_IS_LOGGING ); + iFeatures |= ( ( eLicenceType != LT_NO_LICENCE ) << FS_HAS_LICENCE ); ConnLessProtocol.CreateCLServerInfoMes ( RecHostAddr, iFeatures ); } diff --git a/src/serverlogging.h b/src/serverlogging.h index 1ce0a7fba6..7a6c7ac5cf 100644 --- a/src/serverlogging.h +++ b/src/serverlogging.h @@ -66,6 +66,7 @@ class CServerLogging void AddServerStopped(); void AddNewConnection ( const QHostAddress& ClientInetAddr, const int iNumberOfConnectedClients ); + bool bIsLogging() { return bDoLogging; } protected: void operator<< ( const QString& sNewStr ); diff --git a/src/util.h b/src/util.h index 29e22aba64..4c97d9a4fa 100644 --- a/src/util.h +++ b/src/util.h @@ -629,7 +629,9 @@ enum EFeatureSet FS_IPV6_AVAILABLE = 5, FS_RAW_AUDIO = 6, FS_DISCONONQUIT = 7, - FS_HAS_WELCOME_MESSAGE = 8 + FS_HAS_WELCOME_MESSAGE = 8, + FS_IS_LOGGING = 9, + FS_HAS_LICENCE = 10 }; inline QString DirectoryTypeToString ( EDirectoryType eAddrType ) From 693153ab3170edbdde82cbff2bb5a75cd94d081d Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Thu, 11 Jun 2026 10:26:20 +0200 Subject: [PATCH 4/4] Add comments for documentation --- src/server.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 10c58bea98..9643021481 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -477,20 +477,48 @@ void CServer::OnNewConnection ( int iChID, int iTotChans, CHostAddress RecHostAd void CServer::OnCLReqServerInfo ( CHostAddress RecHostAddr ) { + // This is a bitmask of features enabled at the server. + // EFeatureSet from util.h is used to shift each bool into position uint32_t iFeatures = 0; + // Use 64 samples frame size mode? (argument -F) iFeatures |= ( !bUseDoubleSystemFrameSize << FS_FAST_UPDATE ); + + // Multithreading enabled? (argument -T) iFeatures |= ( bUseMultithreading << FS_MULTITHREADING ); - iFeatures |= ( ( GetRecorderInitialised() && !GetDisableRecording() ) << FS_RECORDER_ENABLED ); + + // Recording directory set? (argument -R) + // If a recording directory is set a server could potentially record all client audio + iFeatures |= ( GetRecorderInitialised() << FS_RECORDER_ENABLED ); + + // Will an idle server start recording when a client joins? (argument --norecord) + // Also reflects if the active server is recording or not. iFeatures |= ( ( JamController.GetRecorderState() == RS_RECORDING ) << FS_IS_RECORDING ); + + // Delay pan enabled? (argument -P) iFeatures |= ( bDelayPan << FS_DELAY_PAN ); + + // IPv6 available? (argument --noipv6 disables this feature) iFeatures |= ( IsIPv6Available() << FS_IPV6_AVAILABLE ); - iFeatures |= ( bDisableRaw << FS_RAW_AUDIO ); + + // "Max" audio quality setting enabled? (argument --noraw disables this feature) + iFeatures |= ( !bDisableRaw << FS_RAW_AUDIO ); + + // Disconnect all clients on quit? (argument -d) iFeatures |= ( bDisconnectAllClientsOnQuit << FS_DISCONONQUIT ); + + // Has welcome message? (argument -w) iFeatures |= ( !strWelcomeMessage.isEmpty() << FS_HAS_WELCOME_MESSAGE ); + + // Logging enabled? (argument -l) iFeatures |= ( Logging.bIsLogging() << FS_IS_LOGGING ); + + // Licence agreement required? (argument -L) iFeatures |= ( ( eLicenceType != LT_NO_LICENCE ) << FS_HAS_LICENCE ); + // qDebug() << QString::number(iFeatures, 2).rightJustified(32, '0'); + + // Create and send the message ConnLessProtocol.CreateCLServerInfoMes ( RecHostAddr, iFeatures ); }