From 20f2e3d4af84f42960127b50de4bf2009aaff2f6 Mon Sep 17 00:00:00 2001 From: jrd Date: Fri, 5 Jun 2026 03:14:57 +0000 Subject: [PATCH] feat: add CLM request for channel level list (message ID 1028) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds PROTMESSID_CLM_REQ_CHANNEL_LEVEL_LIST (1028): a connectionless request that causes the server to immediately reply with the existing PROTMESSID_CLM_CHANNEL_LEVEL_LIST (1015) response. This follows the established CLM request/response pattern used by CLReqConnClientsList (1014 → 1013), CLReqVersionAndOS (1012 → 1011), and CLReqServerList (1007 → 1002). The implementation is zero-cost: vecChannelLevels is already computed every server tick in OnTimer(). The handler simply forwards that existing data to the requesting address. Use case: external monitors can poll silence/activity level on any Jamulus server by sending a single UDP datagram to the server's game port, without establishing an audio connection or requiring additional open ports. Co-Authored-By: Claude Sonnet 4.6 --- src/protocol.cpp | 11 +++++++++++ src/protocol.h | 5 ++++- src/server.cpp | 2 ++ src/server.h | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/protocol.cpp b/src/protocol.cpp index a30534bc72..60a803f16c 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -922,6 +922,10 @@ void CProtocol::ParseConnectionLessMessageBody ( const CVector& vecbyMe EvaluateCLChannelLevelListMes ( InetAddr, vecbyMesBodyData ); break; + case PROTMESSID_CLM_REQ_CHANNEL_LEVEL_LIST: + EvaluateCLReqChannelLevelListMes ( InetAddr ); + break; + case PROTMESSID_CLM_REGISTER_SERVER_RESP: EvaluateCLRegisterServerResp ( InetAddr, vecbyMesBodyData ); break; @@ -2563,6 +2567,13 @@ bool CProtocol::EvaluateCLChannelLevelListMes ( const CHostAddress& InetAddr, co return false; // no error } +bool CProtocol::EvaluateCLReqChannelLevelListMes ( const CHostAddress& InetAddr ) +{ + emit CLReqChannelLevelList ( InetAddr ); + + return false; // no error +} + void CProtocol::CreateCLRegisterServerResp ( const CHostAddress& InetAddr, const ESvrRegResult eResult ) { int iPos = 0; // init position pointer diff --git a/src/protocol.h b/src/protocol.h index 03ac9f328f..f24223b836 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -83,7 +83,8 @@ #define PROTMESSID_CLM_CHANNEL_LEVEL_LIST 1015 // channel level list #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_RED_SERVER_LIST 1018 // reduced server list +#define PROTMESSID_CLM_REQ_CHANNEL_LEVEL_LIST 1028 // request channel level list (connectionless) // special IDs #define PROTMESSID_SPECIAL_SPLIT_MESSAGE 2001 // a container for split messages @@ -281,6 +282,7 @@ class CProtocol : public QObject bool EvaluateCLConnClientsListMes ( const CHostAddress& InetAddr, const CVector& vecData ); bool EvaluateCLReqConnClientsListMes ( const CHostAddress& InetAddr ); bool EvaluateCLChannelLevelListMes ( const CHostAddress& InetAddr, const CVector& vecData ); + bool EvaluateCLReqChannelLevelListMes ( const CHostAddress& InetAddr ); bool EvaluateCLRegisterServerResp ( const CHostAddress& InetAddr, const CVector& vecData ); int iOldRecID; @@ -348,5 +350,6 @@ public slots: void CLConnClientsListMesReceived ( CHostAddress InetAddr, CVector vecChanInfo ); void CLReqConnClientsList ( CHostAddress InetAddr ); void CLChannelLevelListReceived ( CHostAddress InetAddr, CVector vecLevelList ); + void CLReqChannelLevelList ( CHostAddress InetAddr ); void CLRegisterServerResp ( CHostAddress InetAddr, ESvrRegResult eStatus ); }; diff --git a/src/server.cpp b/src/server.cpp index d6cd2bf0cc..ab300781fd 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -280,6 +280,8 @@ CServer::CServer ( const int iNewMaxNumChan, QObject::connect ( &ConnLessProtocol, &CProtocol::CLReqConnClientsList, this, &CServer::OnCLReqConnClientsList ); + QObject::connect ( &ConnLessProtocol, &CProtocol::CLReqChannelLevelList, this, &CServer::OnCLReqChannelLevelList ); + QObject::connect ( &ServerListManager, &CServerListManager::SvrRegStatusChanged, this, &CServer::SvrRegStatusChanged ); QObject::connect ( &JamController, &recorder::CJamController::RestartRecorder, this, &CServer::RestartRecorder ); diff --git a/src/server.h b/src/server.h index 6a42a8f9b8..11b8a10aba 100644 --- a/src/server.h +++ b/src/server.h @@ -366,6 +366,8 @@ public slots: void OnCLReqConnClientsList ( CHostAddress InetAddr ) { ConnLessProtocol.CreateCLConnClientsListMes ( InetAddr, CreateChannelList() ); } + void OnCLReqChannelLevelList ( CHostAddress InetAddr ) { ConnLessProtocol.CreateCLChannelLevelListMes ( InetAddr, vecChannelLevels, GetNumberOfConnectedClients() ); } + void OnCLRegisterServerReceived ( CHostAddress InetAddr, CHostAddress LInetAddr, CServerCoreInfo ServerInfo ) { ServerListManager.Append ( InetAddr, LInetAddr, ServerInfo );