the maximum number of channel can be set via command line now, added some test functions in the buffer

This commit is contained in:
Volker Fischer 2011-05-13 18:23:00 +00:00
parent 7d24441887
commit 793b21f9d9
11 changed files with 552 additions and 465 deletions

View file

@ -345,7 +345,7 @@ void CAudioMixerBoard::SetServerName ( const QString& strNewServerName )
void CAudioMixerBoard::SetGUIDesign ( const EGUIDesign eNewDesign ) void CAudioMixerBoard::SetGUIDesign ( const EGUIDesign eNewDesign )
{ {
// apply GUI design to child GUI controls // apply GUI design to child GUI controls
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
{ {
vecpChanFader[i]->SetGUIDesign ( eNewDesign ); vecpChanFader[i]->SetGUIDesign ( eNewDesign );
} }
@ -354,7 +354,7 @@ void CAudioMixerBoard::SetGUIDesign ( const EGUIDesign eNewDesign )
void CAudioMixerBoard::HideAll() void CAudioMixerBoard::HideAll()
{ {
// make all controls invisible // make all controls invisible
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
{ {
vecpChanFader[i]->Hide(); vecpChanFader[i]->Hide();
} }
@ -370,7 +370,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelShortInfo>& vecCh
// search for channels with are already present and preserver their gain // search for channels with are already present and preserver their gain
// setting, for all other channels, reset gain // setting, for all other channels, reset gain
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
{ {
bool bFaderIsUsed = false; bool bFaderIsUsed = false;
@ -422,7 +422,7 @@ void CAudioMixerBoard::OnChSoloStateChanged ( const int iChannelIdx,
( static_cast<Qt::CheckState> ( iValue ) == Qt::Checked ); ( static_cast<Qt::CheckState> ( iValue ) == Qt::Checked );
// apply "other solo state" for all other channels // apply "other solo state" for all other channels
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
{ {
if ( i != iChannelIdx ) if ( i != iChannelIdx )
{ {

View file

@ -35,7 +35,7 @@ void CNetBuf::Init ( const int iNewBlockSize,
// store block size value // store block size value
iBlockSize = iNewBlockSize; iBlockSize = iNewBlockSize;
// total size -> size of one block times number of blocks // total size -> size of one block times the number of blocks
CBufferBase<uint8_t>::Init ( iNewBlockSize * iNewNumBlocks ); CBufferBase<uint8_t>::Init ( iNewBlockSize * iNewNumBlocks );
// use the "get" flag to make sure the buffer is cleared // use the "get" flag to make sure the buffer is cleared
@ -46,7 +46,7 @@ void CNetBuf::Init ( const int iNewBlockSize,
} }
bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData, bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData,
const int iInSize ) const int iInSize )
{ {
bool bPutOK = true; bool bPutOK = true;

View file

@ -54,7 +54,8 @@ public:
eBufState = CBufferBase<TData>::BS_EMPTY; eBufState = CBufferBase<TData>::BS_EMPTY;
} }
virtual bool Put ( const CVector<TData>& vecData, const int iInSize ) virtual bool Put ( const CVector<TData>& vecData,
const int iInSize )
{ {
// copy new data in internal buffer // copy new data in internal buffer
int iCurPos = 0; int iCurPos = 0;
@ -188,6 +189,58 @@ public:
protected: protected:
enum EBufState { BS_OK, BS_FULL, BS_EMPTY }; enum EBufState { BS_OK, BS_FULL, BS_EMPTY };
void PutSimulation ( const int iInSize )
{
// in this simulation only the buffer pointers and the buffer state
// is updated, no actual data is transferred
if ( iPutPos + iInSize > iMemSize )
{
// data must be written in two steps because of wrap around
iPutPos += iInSize - iMemSize - 1;
}
else
{
// data can be written in one step
iPutPos += iInSize - 1;
}
// set buffer state flag
if ( iPutPos == iGetPos )
{
eBufState = CBufferBase<TData>::BS_FULL;
}
else
{
eBufState = CBufferBase<TData>::BS_OK;
}
}
void GetSimulation ( const int iInSize )
{
// in this simulation only the buffer pointers and the buffer state
// is updated, no actual data is transferred
if ( iGetPos + iInSize > iMemSize )
{
// data must be read in two steps because of wrap around
iGetPos += iInSize - iMemSize - 1;
}
else
{
// data can be read in one step
iGetPos += iInSize - 1;
}
// set buffer state flag
if ( iPutPos == iGetPos )
{
eBufState = CBufferBase<TData>::BS_EMPTY;
}
else
{
eBufState = CBufferBase<TData>::BS_OK;
}
}
CVector<TData> vecMemory; CVector<TData> vecMemory;
int iMemSize; int iMemSize;
int iGetPos, iPutPos; int iGetPos, iPutPos;

View file

@ -27,7 +27,7 @@
// CChannel implementation ***************************************************** // CChannel implementation *****************************************************
CChannel::CChannel ( const bool bNIsServer ) : CChannel::CChannel ( const bool bNIsServer ) :
vecdGains ( USED_NUM_CHANNELS, (double) 1.0 ), vecdGains ( MAX_NUM_CHANNELS, (double) 1.0 ),
bIsEnabled ( false ), bIsEnabled ( false ),
bIsServer ( bNIsServer ), bIsServer ( bNIsServer ),
iNetwFrameSizeFact ( FRAME_SIZE_FACTOR_PREFERRED ), iNetwFrameSizeFact ( FRAME_SIZE_FACTOR_PREFERRED ),
@ -189,7 +189,7 @@ void CChannel::SetGain ( const int iChanID, const double dNewGain )
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
// set value (make sure channel ID is in range) // set value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) ) if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
{ {
vecdGains[iChanID] = dNewGain; vecdGains[iChanID] = dNewGain;
} }
@ -200,7 +200,7 @@ double CChannel::GetGain ( const int iChanID )
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
// get value (make sure channel ID is in range) // get value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) ) if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
{ {
return vecdGains[iChanID]; return vecdGains[iChanID];
} }

View file

@ -148,7 +148,7 @@ LED bar: lbr
// actual number of used channels in the server // actual number of used channels in the server
// this parameter can safely be changed from 1 to MAX_NUM_CHANNELS // this parameter can safely be changed from 1 to MAX_NUM_CHANNELS
// without any other changes in the code // without any other changes in the code
#define USED_NUM_CHANNELS 6 // used number channels for server #define DEFAULT_USED_NUM_CHANNELS 6 // default used number channels for server
// maximum number of servers registered in the server list // maximum number of servers registered in the server list
#define MAX_NUM_SERVERS_IN_SERVER_LIST 100 #define MAX_NUM_SERVERS_IN_SERVER_LIST 100

View file

@ -165,8 +165,8 @@ lvwClients->setMinimumHeight ( 140 );
// insert items in reverse order because in Windows all of them are // insert items in reverse order because in Windows all of them are
// always visible -> put first item on the top // always visible -> put first item on the top
vecpListViewItems.Init ( USED_NUM_CHANNELS ); vecpListViewItems.Init ( MAX_NUM_CHANNELS );
for ( int i = USED_NUM_CHANNELS - 1; i >= 0; i-- ) for ( int i = MAX_NUM_CHANNELS - 1; i >= 0; i-- )
{ {
vecpListViewItems[i] = new CServerListViewItem ( lvwClients ); vecpListViewItems[i] = new CServerListViewItem ( lvwClients );
vecpListViewItems[i]->setHidden ( true ); vecpListViewItems[i]->setHidden ( true );
@ -435,8 +435,11 @@ void CLlconServerDlg::OnTimer()
veciJitBufNumFrames, veciJitBufNumFrames,
veciNetwFrameSizeFact ); veciNetwFrameSizeFact );
// we assume that all vectors have the same length
const int iNumChannels = vecHostAddresses.Size();
// fill list with connected clients // fill list with connected clients
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( !( vecHostAddresses[i].InetAddr == QHostAddress ( (quint32) 0 ) ) ) if ( !( vecHostAddresses[i].InetAddr == QHostAddress ( (quint32) 0 ) ) )
{ {

View file

@ -58,6 +58,7 @@ int main ( int argc, char** argv )
bool bStartMinimized = false; bool bStartMinimized = false;
bool bConnectOnStartup = false; bool bConnectOnStartup = false;
bool bDisalbeLEDs = false; bool bDisalbeLEDs = false;
int iNumServerChannels = DEFAULT_USED_NUM_CHANNELS;
quint16 iPortNumber = LLCON_DEFAULT_PORT_NUMBER; quint16 iPortNumber = LLCON_DEFAULT_PORT_NUMBER;
QString strIniFileName = ""; QString strIniFileName = "";
QString strHTMLStatusFileName = ""; QString strHTMLStatusFileName = "";
@ -96,6 +97,27 @@ int main ( int argc, char** argv )
} }
// Maximum number of channels ------------------------------------------
if ( GetNumericArgument ( tsConsole,
argc,
argv,
i,
"-u",
"--numchannels",
1,
MAX_NUM_CHANNELS,
rDbleArgument ) )
{
iNumServerChannels = static_cast<int> ( rDbleArgument );
tsConsole << "- maximum number of channels: "
<< iNumServerChannels << endl;
continue;
}
// Start minimized ----------------------------------------------------- // Start minimized -----------------------------------------------------
if ( GetFlagArgument ( argv, if ( GetFlagArgument ( argv,
i, i,
@ -348,7 +370,8 @@ int main ( int argc, char** argv )
{ {
// Server: // Server:
// actual server object // actual server object
CServer Server ( strLoggingFileName, CServer Server ( iNumServerChannels,
strLoggingFileName,
iPortNumber, iPortNumber,
strHTMLStatusFileName, strHTMLStatusFileName,
strHistoryFileName, strHistoryFileName,
@ -433,6 +456,7 @@ QString UsageArguments ( char **argv )
"\nRecognized options:\n" "\nRecognized options:\n"
" -s, --server start server\n" " -s, --server start server\n"
" -n, --nogui disable GUI (server only)\n" " -n, --nogui disable GUI (server only)\n"
" -u, --numchannels maximum number of channels (server only)\n"
" -z, --startminimized start minimizied (server only)\n" " -z, --startminimized start minimizied (server only)\n"
" -l, --log enable logging, set file name\n" " -l, --log enable logging, set file name\n"
" -i, --inifile initialization file name (client only)\n" " -i, --inifile initialization file name (client only)\n"

View file

@ -164,27 +164,30 @@ void CHighPrecisionTimer::OnTimer()
// CServer implementation ****************************************************** // CServer implementation ******************************************************
CServer::CServer ( const QString& strLoggingFileName, CServer::CServer ( const int iNewNumChan,
const QString& strLoggingFileName,
const quint16 iPortNumber, const quint16 iPortNumber,
const QString& strHTMLStatusFileName, const QString& strHTMLStatusFileName,
const QString& strHistoryFileName, const QString& strHistoryFileName,
const QString& strServerNameForHTMLStatusFile, const QString& strServerNameForHTMLStatusFile,
const QString& strCentralServer, const QString& strCentralServer,
const QString& strServerInfo ) : const QString& strServerInfo ) :
Socket ( this, iPortNumber ), iNumChannels ( iNewNumChan ),
Socket ( this, iPortNumber ),
bWriteStatusHTMLFile ( false ), bWriteStatusHTMLFile ( false ),
ServerListManager ( iPortNumber, ServerListManager ( iPortNumber,
strCentralServer, strCentralServer,
strServerInfo, strServerInfo,
&ConnLessProtocol ), iNewNumChan,
bAutoRunMinimized ( false ) &ConnLessProtocol ),
bAutoRunMinimized ( false )
{ {
int i; int i;
// create CELT encoder/decoder for each channel (must be done before // create CELT encoder/decoder for each channel (must be done before
// enabling the channels), create a mono and stereo encoder/decoder // enabling the channels), create a mono and stereo encoder/decoder
// for each channel // for each channel
for ( i = 0; i < USED_NUM_CHANNELS; i++ ) for ( i = 0; i < iNumChannels; i++ )
{ {
// init audio endocder/decoder (mono) // init audio endocder/decoder (mono)
CeltModeMono[i] = celt_mode_create ( CeltModeMono[i] = celt_mode_create (
@ -268,7 +271,7 @@ CServer::CServer ( const QString& strLoggingFileName,
// enable all channels (for the server all channel must be enabled the // enable all channels (for the server all channel must be enabled the
// entire life time of the software) // entire life time of the software)
for ( i = 0; i < USED_NUM_CHANNELS; i++ ) for ( i = 0; i < iNumChannels; i++ )
{ {
vecChannels[i].SetEnable ( true ); vecChannels[i].SetEnable ( true );
} }
@ -459,7 +462,7 @@ void CServer::OnTimer()
{ {
// first, get number and IDs of connected channels // first, get number and IDs of connected channels
vecChanID.Init ( 0 ); vecChanID.Init ( 0 );
for ( i = 0; i < USED_NUM_CHANNELS; i++ ) for ( i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -785,7 +788,7 @@ CVector<CChannelShortInfo> CServer::CreateChannelList()
CVector<CChannelShortInfo> vecChanInfo ( 0 ); CVector<CChannelShortInfo> vecChanInfo ( 0 );
// look for free channels // look for free channels
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -806,7 +809,7 @@ void CServer::CreateAndSendChanListForAllConChannels()
CVector<CChannelShortInfo> vecChanInfo ( CreateChannelList() ); CVector<CChannelShortInfo> vecChanInfo ( CreateChannelList() );
// now send connected channels list to all connected clients // now send connected channels list to all connected clients
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -854,7 +857,7 @@ void CServer::CreateAndSendChatTextForAllConChannels ( const int iCurChanID
// Send chat text to all connected clients --------------------------------- // Send chat text to all connected clients ---------------------------------
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -867,7 +870,7 @@ void CServer::CreateAndSendChatTextForAllConChannels ( const int iCurChanID
int CServer::GetFreeChan() int CServer::GetFreeChan()
{ {
// look for a free channel // look for a free channel
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( !vecChannels[i].IsConnected() ) if ( !vecChannels[i].IsConnected() )
{ {
@ -884,7 +887,7 @@ int CServer::GetNumberOfConnectedClients()
int iNumConnClients = 0; int iNumConnClients = 0;
// check all possible channels for connection status // check all possible channels for connection status
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -901,7 +904,7 @@ int CServer::CheckAddr ( const CHostAddress& Addr )
CHostAddress InetAddr; CHostAddress InetAddr;
// check for all possible channels if IP is already in use // check for all possible channels if IP is already in use
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -956,7 +959,7 @@ bool CServer::PutData ( const CVector<uint8_t>& vecbyRecBuf,
// reset the channel gains of current channel, at the same // reset the channel gains of current channel, at the same
// time reset gains of this channel ID for all other channels // time reset gains of this channel ID for all other channels
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
vecChannels[iCurChanID].SetGain ( i, (double) 1.0 ); vecChannels[iCurChanID].SetGain ( i, (double) 1.0 );
@ -1062,13 +1065,13 @@ void CServer::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
CHostAddress InetAddr; CHostAddress InetAddr;
// init return values // init return values
vecHostAddresses.Init ( USED_NUM_CHANNELS ); vecHostAddresses.Init ( iNumChannels );
vecsName.Init ( USED_NUM_CHANNELS ); vecsName.Init ( iNumChannels );
veciJitBufNumFrames.Init ( USED_NUM_CHANNELS ); veciJitBufNumFrames.Init ( iNumChannels );
veciNetwFrameSizeFact.Init ( USED_NUM_CHANNELS ); veciNetwFrameSizeFact.Init ( iNumChannels );
// check all possible channels // check all possible channels
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].GetAddress ( InetAddr ) ) if ( vecChannels[i].GetAddress ( InetAddr ) )
{ {
@ -1112,7 +1115,7 @@ void CServer::WriteHTMLChannelList()
// get the number of connected clients // get the number of connected clients
int iNumConnClients = 0; int iNumConnClients = 0;
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -1129,7 +1132,7 @@ void CServer::WriteHTMLChannelList()
else else
{ {
// write entry for each connected client // write entry for each connected client
for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) for ( int i = 0; i < iNumChannels; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {

View file

@ -103,7 +103,8 @@ class CServer : public QObject
Q_OBJECT Q_OBJECT
public: public:
CServer ( const QString& strLoggingFileName, CServer ( const int iNewNumChan,
const QString& strLoggingFileName,
const quint16 iPortNumber, const quint16 iPortNumber,
const QString& strHTMLStatusFileName, const QString& strHTMLStatusFileName,
const QString& strHistoryFileName, const QString& strHistoryFileName,
@ -200,6 +201,7 @@ protected:
// do not use the vector class since CChannel does not have appropriate // do not use the vector class since CChannel does not have appropriate
// copy constructor/operator // copy constructor/operator
CChannel vecChannels[MAX_NUM_CHANNELS]; CChannel vecChannels[MAX_NUM_CHANNELS];
int iNumChannels;
CProtocol ConnLessProtocol; CProtocol ConnLessProtocol;
QMutex Mutex; QMutex Mutex;

View file

@ -1,428 +1,429 @@
/******************************************************************************\ /******************************************************************************\
* Copyright (c) 2004-2011 * Copyright (c) 2004-2011
* *
* Author(s): * Author(s):
* Volker Fischer * Volker Fischer
* *
****************************************************************************** ******************************************************************************
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., * this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
\******************************************************************************/ \******************************************************************************/
#include "serverlist.h" #include "serverlist.h"
/* Implementation *************************************************************/ /* Implementation *************************************************************/
CServerListManager::CServerListManager ( const quint16 iNPortNum, CServerListManager::CServerListManager ( const quint16 iNPortNum,
const QString& sNCentServAddr, const QString& sNCentServAddr,
const QString& strServerInfo, const QString& strServerInfo,
CProtocol* pNConLProt ) const int iNumChannels,
: iPortNumber ( iNPortNum ), CProtocol* pNConLProt )
iNumPredefinedServers ( 0 ), : iPortNumber ( iNPortNum ),
bUseDefaultCentralServerAddress ( false ), iNumPredefinedServers ( 0 ),
pConnLessProtocol ( pNConLProt ) bUseDefaultCentralServerAddress ( false ),
{ pConnLessProtocol ( pNConLProt )
// set the central server address {
SetCentralServerAddress ( sNCentServAddr ); // set the central server address
SetCentralServerAddress ( sNCentServAddr );
// prepare the server info information
QStringList slServInfoSeparateParams; // prepare the server info information
int iServInfoNumSplitItems = 0; QStringList slServInfoSeparateParams;
int iServInfoNumSplitItems = 0;
if ( !strServerInfo.isEmpty() )
{ if ( !strServerInfo.isEmpty() )
// split the different parameter strings {
slServInfoSeparateParams = strServerInfo.split ( ";" ); // split the different parameter strings
slServInfoSeparateParams = strServerInfo.split ( ";" );
// get the number of items in the split list
iServInfoNumSplitItems = slServInfoSeparateParams.count(); // get the number of items in the split list
} iServInfoNumSplitItems = slServInfoSeparateParams.count();
}
// per definition, the very first entry is this server and this entry will
// never be deleted // per definition, the very first entry is this server and this entry will
ServerList.clear(); // never be deleted
ServerList.clear();
// init server list entry (server info for this server) with defaults, per
// definition the client substitudes the IP address of the central server // init server list entry (server info for this server) with defaults, per
// itself for his server list // definition the client substitudes the IP address of the central server
CServerListEntry ThisServerListEntry ( // itself for his server list
CHostAddress(), CServerListEntry ThisServerListEntry (
iPortNumber, CHostAddress(),
"", iPortNumber,
"", "",
QLocale::system().country(), "",
"", QLocale::system().country(),
USED_NUM_CHANNELS, "",
true ); iNumChannels,
true );
// parse the server info string according to definition:
// [this server name];[this server city]; ... // parse the server info string according to definition:
// [this server country as QLocale ID]; ... // [this server name];[this server city]; ...
// per definition, we expect at least three parameters // [this server country as QLocale ID]; ...
if ( iServInfoNumSplitItems >= 3 ) // per definition, we expect at least three parameters
{ if ( iServInfoNumSplitItems >= 3 )
// [this server name] {
ThisServerListEntry.strName = slServInfoSeparateParams[0]; // [this server name]
ThisServerListEntry.strName = slServInfoSeparateParams[0];
// [this server city]
ThisServerListEntry.strCity = slServInfoSeparateParams[1]; // [this server city]
ThisServerListEntry.strCity = slServInfoSeparateParams[1];
// [this server country as QLocale ID]
const int iCountry = slServInfoSeparateParams[2].toInt(); // [this server country as QLocale ID]
if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) ) const int iCountry = slServInfoSeparateParams[2].toInt();
{ if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) )
ThisServerListEntry.eCountry = static_cast<QLocale::Country> ( {
iCountry ); ThisServerListEntry.eCountry = static_cast<QLocale::Country> (
} iCountry );
} }
}
// per definition, the first entry in the server list it the own server
ServerList.append ( ThisServerListEntry ); // per definition, the first entry in the server list it the own server
ServerList.append ( ThisServerListEntry );
// parse the predefined server infos (if any) according to definition:
// [server1 address];[server1 name];[server1 city]; ... // parse the predefined server infos (if any) according to definition:
// [server1 country as QLocale ID]; ... // [server1 address];[server1 name];[server1 city]; ...
// [server2 address];[server2 name];[server2 city]; ... // [server1 country as QLocale ID]; ...
// [server2 country as QLocale ID]; ... // [server2 address];[server2 name];[server2 city]; ...
// ... // [server2 country as QLocale ID]; ...
int iCurUsedServInfoSplitItems = 3; // three items are used for this server // ...
int iCurUsedServInfoSplitItems = 3; // three items are used for this server
// we always expect four items per new server, also check for maximum
// allowed number of servers in the server list // we always expect four items per new server, also check for maximum
while ( ( iServInfoNumSplitItems - iCurUsedServInfoSplitItems >= 4 ) && // allowed number of servers in the server list
( iNumPredefinedServers <= MAX_NUM_SERVERS_IN_SERVER_LIST ) ) while ( ( iServInfoNumSplitItems - iCurUsedServInfoSplitItems >= 4 ) &&
{ ( iNumPredefinedServers <= MAX_NUM_SERVERS_IN_SERVER_LIST ) )
// create a new server list entry {
CServerListEntry NewServerListEntry ( // create a new server list entry
CHostAddress(), CServerListEntry NewServerListEntry (
0, // port number not used CHostAddress(),
"", 0, // port number not used
"", "",
QLocale::AnyCountry, "",
"", QLocale::AnyCountry,
USED_NUM_CHANNELS, "",
true ); iNumChannels,
true );
// [server n address]
LlconNetwUtil().ParseNetworkAddress ( // [server n address]
slServInfoSeparateParams[iCurUsedServInfoSplitItems], LlconNetwUtil().ParseNetworkAddress (
NewServerListEntry.HostAddr ); slServInfoSeparateParams[iCurUsedServInfoSplitItems],
NewServerListEntry.HostAddr );
// [server n name]
NewServerListEntry.strName = // [server n name]
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 1]; NewServerListEntry.strName =
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 1];
// [server n city]
NewServerListEntry.strCity = // [server n city]
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 2]; NewServerListEntry.strCity =
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 2];
// [server n country as QLocale ID]
const int iCountry = // [server n country as QLocale ID]
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 3].toInt(); const int iCountry =
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 3].toInt();
if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) )
{ if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) )
NewServerListEntry.eCountry = static_cast<QLocale::Country> ( {
iCountry ); NewServerListEntry.eCountry = static_cast<QLocale::Country> (
} iCountry );
}
// add the new server to the server list
ServerList.append ( NewServerListEntry ); // add the new server to the server list
ServerList.append ( NewServerListEntry );
// we have used four items and have created one predefined server
// (adjust counters) // we have used four items and have created one predefined server
iCurUsedServInfoSplitItems += 4; // (adjust counters)
iNumPredefinedServers++; iCurUsedServInfoSplitItems += 4;
} iNumPredefinedServers++;
}
// Connections -------------------------------------------------------------
QObject::connect ( &TimerPollList, SIGNAL ( timeout() ), // Connections -------------------------------------------------------------
this, SLOT ( OnTimerPollList() ) ); QObject::connect ( &TimerPollList, SIGNAL ( timeout() ),
this, SLOT ( OnTimerPollList() ) );
QObject::connect ( &TimerRegistering, SIGNAL ( timeout() ),
this, SLOT ( OnTimerRegistering() ) ); QObject::connect ( &TimerRegistering, SIGNAL ( timeout() ),
} this, SLOT ( OnTimerRegistering() ) );
}
void CServerListManager::SetCentralServerAddress ( const QString sNCentServAddr )
{ void CServerListManager::SetCentralServerAddress ( const QString sNCentServAddr )
QMutexLocker locker ( &Mutex ); {
QMutexLocker locker ( &Mutex );
strCentralServerAddress = sNCentServAddr;
strCentralServerAddress = sNCentServAddr;
// per definition: If the central server address is empty, the server list
// is disabled. // per definition: If the central server address is empty, the server list
// per definition: If we are in server mode and the central server address // is disabled.
// is the localhost address, we are in central server mode. For the central // per definition: If we are in server mode and the central server address
// server, the server list is always enabled. // is the localhost address, we are in central server mode. For the central
if ( !strCentralServerAddress.isEmpty() ) // server, the server list is always enabled.
{ if ( !strCentralServerAddress.isEmpty() )
bIsCentralServer = {
( !strCentralServerAddress.toLower().compare ( "localhost" ) || bIsCentralServer =
!strCentralServerAddress.compare ( "127.0.0.1" ) ); ( !strCentralServerAddress.toLower().compare ( "localhost" ) ||
!strCentralServerAddress.compare ( "127.0.0.1" ) );
bEnabled = true;
} bEnabled = true;
else }
{ else
bIsCentralServer = false; {
bEnabled = true; bIsCentralServer = false;
} bEnabled = true;
} }
}
void CServerListManager::Update()
{ void CServerListManager::Update()
QMutexLocker locker ( &Mutex ); {
QMutexLocker locker ( &Mutex );
if ( bEnabled )
{ if ( bEnabled )
if ( bIsCentralServer ) {
{ if ( bIsCentralServer )
// start timer for polling the server list if enabled {
// 1 minute = 60 * 1000 ms // start timer for polling the server list if enabled
TimerPollList.start ( SERVLIST_POLL_TIME_MINUTES * 60000 ); // 1 minute = 60 * 1000 ms
} TimerPollList.start ( SERVLIST_POLL_TIME_MINUTES * 60000 );
else }
{ else
// initiate registration right away so that we do not have to wait {
// for the first time out of the timer until the slave server gets // initiate registration right away so that we do not have to wait
// registered at the central server, note that we have to unlock // for the first time out of the timer until the slave server gets
// the mutex before calling the function since inside this function // registered at the central server, note that we have to unlock
// the mutex is locked, too // the mutex before calling the function since inside this function
locker.unlock(); // the mutex is locked, too
{ locker.unlock();
OnTimerRegistering(); {
} OnTimerRegistering();
locker.relock(); }
locker.relock();
// start timer for registering this server at the central server
// 1 minute = 60 * 1000 ms // start timer for registering this server at the central server
TimerRegistering.start ( SERVLIST_REGIST_INTERV_MINUTES * 60000 ); // 1 minute = 60 * 1000 ms
} TimerRegistering.start ( SERVLIST_REGIST_INTERV_MINUTES * 60000 );
} }
else }
{ else
// disable service -> stop timer {
if ( bIsCentralServer ) // disable service -> stop timer
{ if ( bIsCentralServer )
TimerPollList.stop(); {
} TimerPollList.stop();
else }
{ else
TimerRegistering.stop(); {
} TimerRegistering.stop();
} }
} }
}
/* Central server functionality ***********************************************/
void CServerListManager::OnTimerPollList() /* Central server functionality ***********************************************/
{ void CServerListManager::OnTimerPollList()
QMutexLocker locker ( &Mutex ); {
QMutexLocker locker ( &Mutex );
// check all list entries except of the very first one (which is the central
// server entry) and the predefined servers if they are still valid // check all list entries except of the very first one (which is the central
for ( int iIdx = 1 + iNumPredefinedServers; iIdx < ServerList.size(); iIdx++ ) // server entry) and the predefined servers if they are still valid
{ for ( int iIdx = 1 + iNumPredefinedServers; iIdx < ServerList.size(); iIdx++ )
// 1 minute = 60 * 1000 ms {
if ( ServerList[iIdx].RegisterTime.elapsed() > // 1 minute = 60 * 1000 ms
( SERVLIST_TIME_OUT_MINUTES * 60000 ) ) if ( ServerList[iIdx].RegisterTime.elapsed() >
{ ( SERVLIST_TIME_OUT_MINUTES * 60000 ) )
// remove this list entry {
ServerList.removeAt ( iIdx ); // remove this list entry
} ServerList.removeAt ( iIdx );
} }
} }
}
void CServerListManager::CentralServerRegisterServer ( const CHostAddress& InetAddr,
const CServerCoreInfo& ServerInfo ) void CServerListManager::CentralServerRegisterServer ( const CHostAddress& InetAddr,
{ const CServerCoreInfo& ServerInfo )
QMutexLocker locker ( &Mutex ); {
QMutexLocker locker ( &Mutex );
if ( bIsCentralServer && bEnabled )
{ if ( bIsCentralServer && bEnabled )
const int iCurServerListSize = ServerList.size(); {
const int iCurServerListSize = ServerList.size();
// check for maximum allowed number of servers in the server list
if ( iCurServerListSize < MAX_NUM_SERVERS_IN_SERVER_LIST ) // check for maximum allowed number of servers in the server list
{ if ( iCurServerListSize < MAX_NUM_SERVERS_IN_SERVER_LIST )
// define invalid index used as a flag {
const int ciInvalidIdx = -1; // define invalid index used as a flag
const int ciInvalidIdx = -1;
// Check if server is already registered. Use address to identify
// a server. The very first list entry must not be checked since // Check if server is already registered. Use address to identify
// this is per definition the central server (i.e., this server) // a server. The very first list entry must not be checked since
int iSelIdx = ciInvalidIdx; // initialize with an illegal value // this is per definition the central server (i.e., this server)
for ( int iIdx = 1; iIdx < iCurServerListSize; iIdx++ ) int iSelIdx = ciInvalidIdx; // initialize with an illegal value
{ for ( int iIdx = 1; iIdx < iCurServerListSize; iIdx++ )
if ( ServerList[iIdx].HostAddr == InetAddr ) {
{ if ( ServerList[iIdx].HostAddr == InetAddr )
// store entry index {
iSelIdx = iIdx; // store entry index
iSelIdx = iIdx;
// entry found, leave for-loop
continue; // entry found, leave for-loop
} continue;
} }
}
// if server is not yet registered, we have to create a new entry
if ( iSelIdx == ciInvalidIdx ) // if server is not yet registered, we have to create a new entry
{ if ( iSelIdx == ciInvalidIdx )
// create a new server list entry and init with received data {
ServerList.append ( CServerListEntry ( InetAddr, ServerInfo ) ); // create a new server list entry and init with received data
} ServerList.append ( CServerListEntry ( InetAddr, ServerInfo ) );
else }
{ else
// do not update the information in the predefined servers {
if ( iSelIdx > iNumPredefinedServers ) // do not update the information in the predefined servers
{ if ( iSelIdx > iNumPredefinedServers )
// update all data and call update registration function {
ServerList[iSelIdx].iLocalPortNumber = ServerInfo.iLocalPortNumber; // update all data and call update registration function
ServerList[iSelIdx].strName = ServerInfo.strName; ServerList[iSelIdx].iLocalPortNumber = ServerInfo.iLocalPortNumber;
ServerList[iSelIdx].strTopic = ServerInfo.strTopic; ServerList[iSelIdx].strName = ServerInfo.strName;
ServerList[iSelIdx].eCountry = ServerInfo.eCountry; ServerList[iSelIdx].strTopic = ServerInfo.strTopic;
ServerList[iSelIdx].strCity = ServerInfo.strCity; ServerList[iSelIdx].eCountry = ServerInfo.eCountry;
ServerList[iSelIdx].iMaxNumClients = ServerInfo.iMaxNumClients; ServerList[iSelIdx].strCity = ServerInfo.strCity;
ServerList[iSelIdx].bPermanentOnline = ServerInfo.bPermanentOnline; ServerList[iSelIdx].iMaxNumClients = ServerInfo.iMaxNumClients;
ServerList[iSelIdx].bPermanentOnline = ServerInfo.bPermanentOnline;
ServerList[iSelIdx].UpdateRegistration();
} ServerList[iSelIdx].UpdateRegistration();
} }
} }
} }
} }
}
void CServerListManager::CentralServerUnregisterServer ( const CHostAddress& InetAddr )
{ void CServerListManager::CentralServerUnregisterServer ( const CHostAddress& InetAddr )
QMutexLocker locker ( &Mutex ); {
QMutexLocker locker ( &Mutex );
if ( bIsCentralServer && bEnabled )
{ if ( bIsCentralServer && bEnabled )
const int iCurServerListSize = ServerList.size(); {
const int iCurServerListSize = ServerList.size();
// Find the server to unregister in the list. The very first list entry
// must not be checked since this is per definition the central server // Find the server to unregister in the list. The very first list entry
// (i.e., this server), also the predefined servers must not be checked // must not be checked since this is per definition the central server
for ( int iIdx = 1 + iNumPredefinedServers; iIdx < iCurServerListSize; iIdx++ ) // (i.e., this server), also the predefined servers must not be checked
{ for ( int iIdx = 1 + iNumPredefinedServers; iIdx < iCurServerListSize; iIdx++ )
if ( ServerList[iIdx].HostAddr == InetAddr ) {
{ if ( ServerList[iIdx].HostAddr == InetAddr )
// remove this list entry {
ServerList.removeAt ( iIdx ); // remove this list entry
ServerList.removeAt ( iIdx );
// entry found, leave for-loop
continue; // entry found, leave for-loop
} continue;
} }
} }
} }
}
void CServerListManager::CentralServerQueryServerList ( const CHostAddress& InetAddr )
{ void CServerListManager::CentralServerQueryServerList ( const CHostAddress& InetAddr )
QMutexLocker locker ( &Mutex ); {
QMutexLocker locker ( &Mutex );
if ( bIsCentralServer && bEnabled )
{ if ( bIsCentralServer && bEnabled )
const int iCurServerListSize = ServerList.size(); {
const int iCurServerListSize = ServerList.size();
// allocate memory for the entire list
CVector<CServerInfo> vecServerInfo ( iCurServerListSize ); // allocate memory for the entire list
CVector<CServerInfo> vecServerInfo ( iCurServerListSize );
// copy the list (we have to copy it since the message requires
// a vector but the list is actually stored in a QList object and // copy the list (we have to copy it since the message requires
// not in a vector object // a vector but the list is actually stored in a QList object and
for ( int iIdx = 0; iIdx < iCurServerListSize; iIdx++ ) // not in a vector object
{ for ( int iIdx = 0; iIdx < iCurServerListSize; iIdx++ )
// copy list item {
vecServerInfo[iIdx] = ServerList[iIdx]; // copy list item
vecServerInfo[iIdx] = ServerList[iIdx];
if ( iIdx > 0 )
{ if ( iIdx > 0 )
// check if the address of the client which is requesting the {
// list is the same address as one server in the list -> in this // check if the address of the client which is requesting the
// case he has to connect to the local host address // list is the same address as one server in the list -> in this
if ( vecServerInfo[iIdx].HostAddr.InetAddr == InetAddr.InetAddr ) // case he has to connect to the local host address
{ if ( vecServerInfo[iIdx].HostAddr.InetAddr == InetAddr.InetAddr )
vecServerInfo[iIdx].HostAddr.InetAddr = {
QHostAddress ( QHostAddress::LocalHost ); vecServerInfo[iIdx].HostAddr.InetAddr =
QHostAddress ( QHostAddress::LocalHost );
// take the local port number instead of the received port
// number since some NAT (network address translation) might // take the local port number instead of the received port
// have changed the port, note that the predefined servers // number since some NAT (network address translation) might
// are treated differently, for these we assume that the // have changed the port, note that the predefined servers
// received port number is the same as the actual port // are treated differently, for these we assume that the
// number // received port number is the same as the actual port
if ( iIdx > iNumPredefinedServers ) // number
{ if ( iIdx > iNumPredefinedServers )
vecServerInfo[iIdx].HostAddr.iPort = {
ServerList[iIdx].iLocalPortNumber; vecServerInfo[iIdx].HostAddr.iPort =
} ServerList[iIdx].iLocalPortNumber;
} }
else }
{ else
// create "send empty message" for all registered servers {
// (except of the very first list entry since this is this // create "send empty message" for all registered servers
// server (central server) per definition) and also it is // (except of the very first list entry since this is this
// not required to send this message, if the server is on // server (central server) per definition) and also it is
// the same computer // not required to send this message, if the server is on
pConnLessProtocol->CreateCLSendEmptyMesMes ( // the same computer
vecServerInfo[iIdx].HostAddr, pConnLessProtocol->CreateCLSendEmptyMesMes (
InetAddr ); vecServerInfo[iIdx].HostAddr,
} InetAddr );
} }
} }
}
// send the server list to the client
pConnLessProtocol->CreateCLServerListMes ( InetAddr, vecServerInfo ); // send the server list to the client
} pConnLessProtocol->CreateCLServerListMes ( InetAddr, vecServerInfo );
} }
}
/* Slave server functionality *************************************************/
void CServerListManager::SlaveServerRegisterServer ( const bool bIsRegister ) /* Slave server functionality *************************************************/
{ void CServerListManager::SlaveServerRegisterServer ( const bool bIsRegister )
// we need the lock since the user might change the server properties at {
// any time // we need the lock since the user might change the server properties at
QMutexLocker locker ( &Mutex ); // any time
QMutexLocker locker ( &Mutex );
// get the correct central server address
// get the correct central server address
const QString strCurCentrServAddr = const QString strCurCentrServAddr =
SELECT_SERVER_ADDRESS ( bUseDefaultCentralServerAddress, SELECT_SERVER_ADDRESS ( bUseDefaultCentralServerAddress,
strCentralServerAddress ); strCentralServerAddress );
// For the slave server, the slave server properties are store in the // For the slave server, the slave server properties are store in the
// very first item in the server list (which is actually no server list // very first item in the server list (which is actually no server list
// but just one item long for the slave server). // but just one item long for the slave server).
// Note that we always have to parse the server address again since if // Note that we always have to parse the server address again since if
// it is an URL of a dynamic IP address, the IP address might have // it is an URL of a dynamic IP address, the IP address might have
// changed in the meanwhile. // changed in the meanwhile.
CHostAddress HostAddress; CHostAddress HostAddress;
if ( LlconNetwUtil().ParseNetworkAddress ( strCurCentrServAddr, if ( LlconNetwUtil().ParseNetworkAddress ( strCurCentrServAddr,
HostAddress ) ) HostAddress ) )
{ {
if ( bIsRegister ) if ( bIsRegister )
{ {
// register server // register server
pConnLessProtocol->CreateCLRegisterServerMes ( HostAddress, pConnLessProtocol->CreateCLRegisterServerMes ( HostAddress,
ServerList[0] ); ServerList[0] );
} }
else else
{ {
// unregister server // unregister server
pConnLessProtocol->CreateCLUnregisterServerMes ( HostAddress ); pConnLessProtocol->CreateCLUnregisterServerMes ( HostAddress );
} }
} }
} }

View file

@ -128,6 +128,7 @@ public:
CServerListManager ( const quint16 iNPortNum, CServerListManager ( const quint16 iNPortNum,
const QString& sNCentServAddr, const QString& sNCentServAddr,
const QString& strServerInfo, const QString& strServerInfo,
const int iNumChannels,
CProtocol* pNConLProt ); CProtocol* pNConLProt );
// the update has to be called if any change to the server list // the update has to be called if any change to the server list