support for sending ping messages to servers in the server list to keep to port open in the NAT of the slave server

This commit is contained in:
Volker Fischer 2012-06-05 06:25:19 +00:00
parent e32d80b9db
commit fa30a903a3
3 changed files with 468 additions and 437 deletions

View file

@ -168,6 +168,9 @@ LED bar: lbr
// poll time for server list (to check if entries are time-out) // poll time for server list (to check if entries are time-out)
#define SERVLIST_POLL_TIME_MINUTES 1 // minute #define SERVLIST_POLL_TIME_MINUTES 1 // minute
// time interval for sending ping messages to servers in the server list
#define SERVLIST_UPDATE_PING_SERVERS_MS 59000 // ms
// time until a slave server registers in the server list // time until a slave server registers in the server list
#define SERVLIST_REGIST_INTERV_MINUTES 30 // minutes #define SERVLIST_REGIST_INTERV_MINUTES 30 // minutes

View file

@ -1,437 +1,462 @@
/******************************************************************************\ /******************************************************************************\
* 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,
const int iNumChannels, const int iNumChannels,
CProtocol* pNConLProt ) CProtocol* pNConLProt )
: iPortNumber ( iNPortNum ), : iPortNumber ( iNPortNum ),
iNumPredefinedServers ( 0 ), iNumPredefinedServers ( 0 ),
bUseDefaultCentralServerAddress ( false ), bUseDefaultCentralServerAddress ( false ),
pConnLessProtocol ( pNConLProt ) pConnLessProtocol ( pNConLProt )
{ {
// set the central server address // set the central server address
SetCentralServerAddress ( sNCentServAddr ); SetCentralServerAddress ( sNCentServAddr );
// prepare the server info information // prepare the server info information
QStringList slServInfoSeparateParams; QStringList slServInfoSeparateParams;
int iServInfoNumSplitItems = 0; int iServInfoNumSplitItems = 0;
if ( !strServerInfo.isEmpty() ) if ( !strServerInfo.isEmpty() )
{ {
// split the different parameter strings // split the different parameter strings
slServInfoSeparateParams = strServerInfo.split ( ";" ); slServInfoSeparateParams = strServerInfo.split ( ";" );
// get the number of items in the split list // get the number of items in the split list
iServInfoNumSplitItems = slServInfoSeparateParams.count(); iServInfoNumSplitItems = slServInfoSeparateParams.count();
} }
// per definition, the very first entry is this server and this entry will // per definition, the very first entry is this server and this entry will
// never be deleted // never be deleted
ServerList.clear(); ServerList.clear();
// init server list entry (server info for this server) with defaults, per // init server list entry (server info for this server) with defaults, per
// definition the client substitudes the IP address of the central server // definition the client substitudes the IP address of the central server
// itself for his server list // itself for his server list
CServerListEntry ThisServerListEntry ( CHostAddress(), CServerListEntry ThisServerListEntry ( CHostAddress(),
iPortNumber, iPortNumber,
"", "",
"", "",
QLocale::system().country(), QLocale::system().country(),
"", "",
iNumChannels, iNumChannels,
true ); true );
// parse the server info string according to definition: // parse the server info string according to definition:
// [this server name];[this server city]; ... // [this server name];[this server city]; ...
// [this server country as QLocale ID]; ... // [this server country as QLocale ID]; ...
// per definition, we expect at least three parameters // per definition, we expect at least three parameters
if ( iServInfoNumSplitItems >= 3 ) if ( iServInfoNumSplitItems >= 3 )
{ {
// [this server name] // [this server name]
ThisServerListEntry.strName = slServInfoSeparateParams[0]; ThisServerListEntry.strName = slServInfoSeparateParams[0];
// [this server city] // [this server city]
ThisServerListEntry.strCity = slServInfoSeparateParams[1]; ThisServerListEntry.strCity = slServInfoSeparateParams[1];
// [this server country as QLocale ID] // [this server country as QLocale ID]
const int iCountry = slServInfoSeparateParams[2].toInt(); const int iCountry = slServInfoSeparateParams[2].toInt();
if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) ) if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) )
{ {
ThisServerListEntry.eCountry = static_cast<QLocale::Country> ( ThisServerListEntry.eCountry = static_cast<QLocale::Country> (
iCountry ); iCountry );
} }
} }
// per definition, the first entry in the server list is the own server // per definition, the first entry in the server list is the own server
ServerList.append ( ThisServerListEntry ); ServerList.append ( ThisServerListEntry );
// parse the predefined server infos (if any) according to definition: // parse the predefined server infos (if any) according to definition:
// [server1 address];[server1 name];[server1 city]; ... // [server1 address];[server1 name];[server1 city]; ...
// [server1 country as QLocale ID]; ... // [server1 country as QLocale ID]; ...
// [server2 address];[server2 name];[server2 city]; ... // [server2 address];[server2 name];[server2 city]; ...
// [server2 country as QLocale ID]; ... // [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 // we always expect four items per new server, also check for maximum
// allowed number of servers in the server list // allowed number of servers in the server list
while ( ( iServInfoNumSplitItems - iCurUsedServInfoSplitItems >= 4 ) && while ( ( iServInfoNumSplitItems - iCurUsedServInfoSplitItems >= 4 ) &&
( iNumPredefinedServers <= MAX_NUM_SERVERS_IN_SERVER_LIST ) ) ( iNumPredefinedServers <= MAX_NUM_SERVERS_IN_SERVER_LIST ) )
{ {
// create a new server list entry // create a new server list entry
CServerListEntry NewServerListEntry ( CHostAddress(), CServerListEntry NewServerListEntry ( CHostAddress(),
0, // port number not used 0, // port number not used
"", "",
"", "",
QLocale::AnyCountry, QLocale::AnyCountry,
"", "",
iNumChannels, iNumChannels,
true ); true );
// [server n address] // [server n address]
LlconNetwUtil().ParseNetworkAddress ( LlconNetwUtil().ParseNetworkAddress (
slServInfoSeparateParams[iCurUsedServInfoSplitItems], slServInfoSeparateParams[iCurUsedServInfoSplitItems],
NewServerListEntry.HostAddr ); NewServerListEntry.HostAddr );
// [server n name] // [server n name]
NewServerListEntry.strName = NewServerListEntry.strName =
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 1]; slServInfoSeparateParams[iCurUsedServInfoSplitItems + 1];
// [server n city] // [server n city]
NewServerListEntry.strCity = NewServerListEntry.strCity =
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 2]; slServInfoSeparateParams[iCurUsedServInfoSplitItems + 2];
// [server n country as QLocale ID] // [server n country as QLocale ID]
const int iCountry = const int iCountry =
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 3].toInt(); slServInfoSeparateParams[iCurUsedServInfoSplitItems + 3].toInt();
if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) ) if ( ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) )
{ {
NewServerListEntry.eCountry = NewServerListEntry.eCountry = static_cast<QLocale::Country> (
static_cast<QLocale::Country> ( iCountry ); iCountry );
} }
// add the new server to the server list // add the new server to the server list
ServerList.append ( NewServerListEntry ); ServerList.append ( NewServerListEntry );
// we have used four items and have created one predefined server // we have used four items and have created one predefined server
// (adjust counters) // (adjust counters)
iCurUsedServInfoSplitItems += 4; iCurUsedServInfoSplitItems += 4;
iNumPredefinedServers++;
iNumPredefinedServers++; }
}
// Connections -------------------------------------------------------------
// Connections ------------------------------------------------------------- QObject::connect ( &TimerPollList, SIGNAL ( timeout() ),
QObject::connect ( &TimerPollList, SIGNAL ( timeout() ), this, SLOT ( OnTimerPollList() ) );
this, SLOT ( OnTimerPollList() ) );
QObject::connect ( &TimerPingServerInList, SIGNAL ( timeout() ),
QObject::connect ( &TimerRegistering, SIGNAL ( timeout() ), this, SLOT ( OnTimerPingServerInList() ) );
this, SLOT ( OnTimerRegistering() ) );
} QObject::connect ( &TimerRegistering, SIGNAL ( timeout() ),
this, SLOT ( OnTimerRegistering() ) );
void CServerListManager::SetCentralServerAddress ( const QString sNCentServAddr ) }
{
QMutexLocker locker ( &Mutex ); void CServerListManager::SetCentralServerAddress ( const QString sNCentServAddr )
{
strCentralServerAddress = sNCentServAddr; QMutexLocker locker ( &Mutex );
// per definition: If the central server address is empty, the server list strCentralServerAddress = sNCentServAddr;
// is disabled.
// per definition: If we are in server mode and the central server address // per definition: If the central server address is empty, the server list
// is the localhost address, we are in central server mode. For the central // is disabled.
// server, the server list is always enabled. // per definition: If we are in server mode and the central server address
if ( !strCentralServerAddress.isEmpty() ) // is the localhost address, we are in central server mode. For the central
{ // server, the server list is always enabled.
bIsCentralServer = if ( !strCentralServerAddress.isEmpty() )
( !strCentralServerAddress.toLower().compare ( "localhost" ) || {
!strCentralServerAddress.compare ( "127.0.0.1" ) ); bIsCentralServer =
( !strCentralServerAddress.toLower().compare ( "localhost" ) ||
bEnabled = true; !strCentralServerAddress.compare ( "127.0.0.1" ) );
}
else bEnabled = true;
{ }
bIsCentralServer = false; else
bEnabled = true; {
} bIsCentralServer = false;
} bEnabled = true;
}
void CServerListManager::Update() }
{
QMutexLocker locker ( &Mutex ); void CServerListManager::Update()
{
if ( bEnabled ) QMutexLocker locker ( &Mutex );
{
if ( bIsCentralServer ) if ( bEnabled )
{ {
// start timer for polling the server list if enabled if ( bIsCentralServer )
// 1 minute = 60 * 1000 ms {
TimerPollList.start ( SERVLIST_POLL_TIME_MINUTES * 60000 ); // start timer for polling the server list if enabled
} // 1 minute = 60 * 1000 ms
else TimerPollList.start ( SERVLIST_POLL_TIME_MINUTES * 60000 );
{
// initiate registration right away so that we do not have to wait // start timer for sending ping messages to servers in the list
// for the first time out of the timer until the slave server gets TimerPingServerInList.start ( SERVLIST_UPDATE_PING_SERVERS_MS );
// registered at the central server, note that we have to unlock }
// the mutex before calling the function since inside this function else
// the mutex is locked, too {
locker.unlock(); // 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
OnTimerRegistering(); // registered at the central server, note that we have to unlock
} // the mutex before calling the function since inside this function
locker.relock(); // the mutex is locked, too
locker.unlock();
// start timer for registering this server at the central server {
// 1 minute = 60 * 1000 ms OnTimerRegistering();
TimerRegistering.start ( SERVLIST_REGIST_INTERV_MINUTES * 60000 ); }
} locker.relock();
}
else // start timer for registering this server at the central server
{ // 1 minute = 60 * 1000 ms
// disable service -> stop timer TimerRegistering.start ( SERVLIST_REGIST_INTERV_MINUTES * 60000 );
if ( bIsCentralServer ) }
{ }
TimerPollList.stop(); else
} {
else // disable service -> stop timer
{ if ( bIsCentralServer )
TimerRegistering.stop(); {
} TimerPollList.stop();
} TimerPingServerInList.stop();
} }
else
{
/* Central server functionality ***********************************************/ TimerRegistering.stop();
void CServerListManager::OnTimerPollList() }
{ }
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. /* Central server functionality ***********************************************/
// Note that we have to use "ServerList.size()" function in the for loop void CServerListManager::OnTimerPingServerInList()
// since we may remove elements from the server list inside the for loop. {
for ( int iIdx = 1 + iNumPredefinedServers; iIdx < ServerList.size(); iIdx++ ) QMutexLocker locker ( &Mutex );
{
// 1 minute = 60 * 1000 ms const int iCurServerListSize = ServerList.size();
if ( ServerList[iIdx].RegisterTime.elapsed() >
( SERVLIST_TIME_OUT_MINUTES * 60000 ) ) // Send ping to list entries except of the very first one (which is the central
{ // server entry) and the predefined servers. Also, do not send the ping to
// remove this list entry // servers which use the local port number since no port translation has
ServerList.removeAt ( iIdx ); // been done and therefore the probability is high that a port forwarding was
} // installed by the user of this server.
} for ( int iIdx = 1 + iNumPredefinedServers; iIdx < iCurServerListSize; iIdx++ )
} {
if ( ServerList[iIdx].HostAddr.iPort != ServerList[iIdx].iLocalPortNumber )
void CServerListManager::CentralServerRegisterServer ( const CHostAddress& InetAddr, {
const CServerCoreInfo& ServerInfo ) // send ping message to keep NAT port open at slave server
{ pConnLessProtocol->CreateCLPingMes (
QMutexLocker locker ( &Mutex ); ServerList[iIdx].HostAddr,
0 /* dummy */ );
if ( bIsCentralServer && bEnabled ) }
{ }
const int iCurServerListSize = ServerList.size(); }
// check for maximum allowed number of servers in the server list void CServerListManager::OnTimerPollList()
if ( iCurServerListSize < MAX_NUM_SERVERS_IN_SERVER_LIST ) {
{ QMutexLocker locker ( &Mutex );
// define invalid index used as a flag
const int ciInvalidIdx = -1; // 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 if server is already registered. Use address to identify // Note that we have to use "ServerList.size()" function in the for loop
// a server. The very first list entry must not be checked since // since we may remove elements from the server list inside the for loop.
// this is per definition the central server (i.e., this server) for ( int iIdx = 1 + iNumPredefinedServers; iIdx < ServerList.size(); iIdx++ )
int iSelIdx = ciInvalidIdx; // initialize with an illegal value {
// 1 minute = 60 * 1000 ms
for ( int iIdx = 1; iIdx < iCurServerListSize; iIdx++ ) if ( ServerList[iIdx].RegisterTime.elapsed() >
{ ( SERVLIST_TIME_OUT_MINUTES * 60000 ) )
if ( ServerList[iIdx].HostAddr == InetAddr ) {
{ // remove this list entry
// store entry index ServerList.removeAt ( iIdx );
iSelIdx = iIdx; }
}
// entry found, leave for-loop }
continue;
} void CServerListManager::CentralServerRegisterServer ( const CHostAddress& InetAddr,
} const CServerCoreInfo& ServerInfo )
{
// if server is not yet registered, we have to create a new entry QMutexLocker locker ( &Mutex );
if ( iSelIdx == ciInvalidIdx )
{ if ( bIsCentralServer && bEnabled )
// create a new server list entry and init with received data {
// (note that the "update registration" is called in the const int iCurServerListSize = ServerList.size();
// constructor of the server list entry)
ServerList.append ( CServerListEntry ( InetAddr, ServerInfo ) ); // check for maximum allowed number of servers in the server list
} if ( iCurServerListSize < MAX_NUM_SERVERS_IN_SERVER_LIST )
else {
{ // define invalid index used as a flag
// do not update the information in the predefined servers const int ciInvalidIdx = -1;
if ( iSelIdx > iNumPredefinedServers )
{ // Check if server is already registered. Use address to identify
// update all data and call update registration function // a server. The very first list entry must not be checked since
ServerList[iSelIdx].iLocalPortNumber = ServerInfo.iLocalPortNumber; // this is per definition the central server (i.e., this server)
ServerList[iSelIdx].strName = ServerInfo.strName; int iSelIdx = ciInvalidIdx; // initialize with an illegal value
ServerList[iSelIdx].strTopic = ServerInfo.strTopic; for ( int iIdx = 1; iIdx < iCurServerListSize; iIdx++ )
ServerList[iSelIdx].eCountry = ServerInfo.eCountry; {
ServerList[iSelIdx].strCity = ServerInfo.strCity; if ( ServerList[iIdx].HostAddr == InetAddr )
ServerList[iSelIdx].iMaxNumClients = ServerInfo.iMaxNumClients; {
ServerList[iSelIdx].bPermanentOnline = ServerInfo.bPermanentOnline; // store entry index
iSelIdx = iIdx;
ServerList[iSelIdx].UpdateRegistration();
} // entry found, leave for-loop
} continue;
} }
} }
}
// if server is not yet registered, we have to create a new entry
void CServerListManager::CentralServerUnregisterServer ( const CHostAddress& InetAddr ) if ( iSelIdx == ciInvalidIdx )
{ {
QMutexLocker locker ( &Mutex ); // create a new server list entry and init with received data
ServerList.append ( CServerListEntry ( InetAddr, ServerInfo ) );
if ( bIsCentralServer && bEnabled ) }
{ else
const int iCurServerListSize = ServerList.size(); {
// do not update the information in the predefined servers
// Find the server to unregister in the list. The very first list entry if ( iSelIdx > iNumPredefinedServers )
// must not be checked since this is per definition the central server {
// (i.e., this server), also the predefined servers must not be checked. // update all data and call update registration function
for ( int iIdx = 1 + iNumPredefinedServers; iIdx < iCurServerListSize; iIdx++ ) ServerList[iSelIdx].iLocalPortNumber = ServerInfo.iLocalPortNumber;
{ ServerList[iSelIdx].strName = ServerInfo.strName;
if ( ServerList[iIdx].HostAddr == InetAddr ) ServerList[iSelIdx].strTopic = ServerInfo.strTopic;
{ ServerList[iSelIdx].eCountry = ServerInfo.eCountry;
// remove this list entry ServerList[iSelIdx].strCity = ServerInfo.strCity;
ServerList.removeAt ( iIdx ); ServerList[iSelIdx].iMaxNumClients = ServerInfo.iMaxNumClients;
ServerList[iSelIdx].bPermanentOnline = ServerInfo.bPermanentOnline;
// entry found, leave for-loop (it is important to exit the
// for loop since when we remove an item from the server list, ServerList[iSelIdx].UpdateRegistration();
// "iCurServerListSize" is not correct anymore and we could get }
// a segmentation fault) }
break; }
} }
} }
}
} void CServerListManager::CentralServerUnregisterServer ( 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(); // 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
// allocate memory for the entire list // (i.e., this server), also the predefined servers must not be checked.
CVector<CServerInfo> vecServerInfo ( iCurServerListSize ); for ( int iIdx = 1 + iNumPredefinedServers; iIdx < iCurServerListSize; iIdx++ )
{
// copy the list (we have to copy it since the message requires if ( ServerList[iIdx].HostAddr == InetAddr )
// a vector but the list is actually stored in a QList object and {
// not in a vector object) // remove this list entry
for ( int iIdx = 0; iIdx < iCurServerListSize; iIdx++ ) ServerList.removeAt ( iIdx );
{
// copy list item // entry found, leave for-loop (it is important to exit the
vecServerInfo[iIdx] = ServerList[iIdx]; // for loop since when we remove an item from the server list,
// "iCurServerListSize" is not correct anymore and we could get
if ( iIdx > 0 ) // a segmentation fault)
{ break;
// check if the address of the client which is requesting the }
// list is the same address as one server in the list -> in this }
// case he has to connect to the local host address }
if ( vecServerInfo[iIdx].HostAddr.InetAddr == InetAddr.InetAddr ) }
{
vecServerInfo[iIdx].HostAddr.InetAddr = void CServerListManager::CentralServerQueryServerList ( const CHostAddress& InetAddr )
QHostAddress ( QHostAddress::LocalHost ); {
QMutexLocker locker ( &Mutex );
// take the local port number instead of the received port
// number since some NAT (network address translation) might if ( bIsCentralServer && bEnabled )
// have changed the port, note that the predefined servers {
// are treated differently, for these we assume that the const int iCurServerListSize = ServerList.size();
// received port number is the same as the actual port
// number // allocate memory for the entire list
if ( iIdx > iNumPredefinedServers ) CVector<CServerInfo> vecServerInfo ( iCurServerListSize );
{
vecServerInfo[iIdx].HostAddr.iPort = // copy the list (we have to copy it since the message requires
ServerList[iIdx].iLocalPortNumber; // a vector but the list is actually stored in a QList object and
} // not in a vector object
} for ( int iIdx = 0; iIdx < iCurServerListSize; iIdx++ )
else {
{ // copy list item
// create "send empty message" for all registered servers vecServerInfo[iIdx] = ServerList[iIdx];
// (except of the very first list entry since this is this
// server (central server) per definition) and also it is if ( iIdx > 0 )
// not required to send this message, if the server is on {
// the same computer // check if the address of the client which is requesting the
pConnLessProtocol->CreateCLSendEmptyMesMes ( // list is the same address as one server in the list -> in this
vecServerInfo[iIdx].HostAddr, // case he has to connect to the local host address
InetAddr ); if ( vecServerInfo[iIdx].HostAddr.InetAddr == InetAddr.InetAddr )
} {
} vecServerInfo[iIdx].HostAddr.InetAddr =
} QHostAddress ( QHostAddress::LocalHost );
// send the server list to the client // take the local port number instead of the received port
pConnLessProtocol->CreateCLServerListMes ( InetAddr, vecServerInfo ); // number since some NAT (network address translation) might
} // have changed the port, note that the predefined servers
} // are treated differently, for these we assume that the
// received port number is the same as the actual port
// number
/* Slave server functionality *************************************************/ if ( iIdx > iNumPredefinedServers )
void CServerListManager::SlaveServerRegisterServer ( const bool bIsRegister ) {
{ vecServerInfo[iIdx].HostAddr.iPort =
// we need the lock since the user might change the server properties at ServerList[iIdx].iLocalPortNumber;
// any time }
QMutexLocker locker ( &Mutex ); }
else
// get the correct central server address {
const QString strCurCentrServAddr = // create "send empty message" for all registered servers
SELECT_SERVER_ADDRESS ( bUseDefaultCentralServerAddress, // (except of the very first list entry since this is this
strCentralServerAddress ); // server (central server) per definition) and also it is
// not required to send this message, if the server is on
// For the slave server, the slave server properties are store in the // the same computer
// very first item in the server list (which is actually no server list pConnLessProtocol->CreateCLSendEmptyMesMes (
// but just one item long for the slave server). vecServerInfo[iIdx].HostAddr,
// Note that we always have to parse the server address again since if InetAddr );
// it is an URL of a dynamic IP address, the IP address might have }
// changed in the meanwhile. }
CHostAddress HostAddress; }
if ( LlconNetwUtil().ParseNetworkAddress ( strCurCentrServAddr, // send the server list to the client
HostAddress ) ) pConnLessProtocol->CreateCLServerListMes ( InetAddr, vecServerInfo );
{ }
if ( bIsRegister ) }
{
// register server
pConnLessProtocol->CreateCLRegisterServerMes ( HostAddress, /* Slave server functionality *************************************************/
ServerList[0] ); void CServerListManager::SlaveServerRegisterServer ( const bool bIsRegister )
} {
else // we need the lock since the user might change the server properties at
{ // any time
// unregister server QMutexLocker locker ( &Mutex );
pConnLessProtocol->CreateCLUnregisterServerMes ( HostAddress );
} // get the correct central server address
} const QString strCurCentrServAddr =
} SELECT_SERVER_ADDRESS ( bUseDefaultCentralServerAddress,
strCentralServerAddress );
// 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
// but just one item long for the slave server).
// 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
// changed in the meanwhile.
CHostAddress HostAddress;
if ( LlconNetwUtil().ParseNetworkAddress ( strCurCentrServAddr,
HostAddress ) )
{
if ( bIsRegister )
{
// register server
pConnLessProtocol->CreateCLRegisterServerMes ( HostAddress,
ServerList[0] );
}
else
{
// unregister server
pConnLessProtocol->CreateCLUnregisterServerMes ( HostAddress );
}
}
}

View file

@ -181,6 +181,8 @@ protected:
QTimer TimerPollList; QTimer TimerPollList;
QTimer TimerRegistering; QTimer TimerRegistering;
QTimer TimerPingServerInList;
QMutex Mutex; QMutex Mutex;
QList<CServerListEntry> ServerList; QList<CServerListEntry> ServerList;
@ -196,6 +198,7 @@ protected:
public slots: public slots:
void OnTimerPollList(); void OnTimerPollList();
void OnTimerPingServerInList();
void OnTimerRegistering() { SlaveServerRegisterServer ( true ); } void OnTimerRegistering() { SlaveServerRegisterServer ( true ); }
}; };