Use server internal address in server list

This commit is contained in:
Peter L Jones 2020-04-09 19:06:34 +01:00
parent ed46357ac4
commit bc04ff2fb2
10 changed files with 143 additions and 74 deletions

View file

@ -231,7 +231,7 @@ LED bar: lbr
#define MAX_LEN_CHAT_TEXT 1600
#define MAX_LEN_CHAT_TEXT_PLUS_HTML 1800
#define MAX_LEN_SERVER_NAME 20
#define MAX_LEN_SERVER_TOPIC 32
#define MAX_LEN_IP_ADDRESS 15
#define MAX_LEN_SERVER_CITY 20
#define MAX_LEN_VERSION_TEXT 20

View file

@ -203,26 +203,28 @@ CONNECTION LESS MESSAGES
... -----------------+----------------------------------+ ...
... 2 bytes country | 1 byte maximum connected clients | ...
... -----------------+----------------------------------+ ...
... ---------------------+------------------+ ...
... 1 byte is permanent | 2 bytes number n | ...
... ---------------------+------------------+ ...
... ----------------------------------+ ...
... n bytes UTF-8 string server name | ...
... ----------------------------------+ ...
... ------------------+----------------------------+ ...
... 2 bytes number n | n bytes UTF-8 string topic | ...
... ------------------+----------------------------+ ...
... ---------------------+ ...
... 1 byte is permanent | ...
... ---------------------+ ...
... ------------------+----------------------------------+ ...
... 2 bytes number n | n bytes UTF-8 string server name | ...
... ------------------+----------------------------------+ ...
... ------------------+---------------------------------------------+ ...
... 2 bytes number n | n bytes UTF-8 string server interal address | ...
... ------------------+---------------------------------------------+ ...
... ------------------+---------------------------+
... 2 bytes number n | n bytes UTF-8 string city |
... ------------------+---------------------------+
- "country" is according to "Common Locale Data Repository" which is used in
the QLocale class
- "maximum connected clients" is the maximum number of clients which can
be connected to the server at the same time
- "is permanent" is a flag which indicates if the server is permanent
online or not. If this value is any value <> 0 indicates that the server
is permanent online.
- "country" is according to "Common Locale Data Repository" which is used in
the QLocale class
- "server interal address" represents the IPv4 address as a dotted quad to
be used by clients with the same external IP address as the server.
- PROTMESSID_CLM_UNREGISTER_SERVER: Unregister a server
@ -1401,13 +1403,14 @@ bool CProtocol::EvaluateCLServerFullMes()
}
void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr,
const CHostAddress& LInetAddr,
const CServerCoreInfo& ServerInfo )
{
int iPos = 0; // init position pointer
// convert server info strings to utf-8
const QByteArray strUTF8LInetAddr = LInetAddr.InetAddr.toString().toUtf8();
const QByteArray strUTF8Name = ServerInfo.strName.toUtf8();
const QByteArray strUTF8Topic = ServerInfo.strTopic.toUtf8();
const QByteArray strUTF8City = ServerInfo.strCity.toUtf8();
// size of current message body
@ -1417,7 +1420,7 @@ void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr,
1 /* maximum number of connected clients */ +
1 /* is permanent flag */ +
2 /* name utf-8 string size */ + strUTF8Name.size() +
2 /* topic utf-8 string size */ + strUTF8Topic.size() +
2 /* server internal address utf-8 string size */ + strUTF8LInetAddr.size() +
2 /* city utf-8 string size */ + strUTF8City.size();
// build data vector
@ -1442,8 +1445,8 @@ void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr,
// name
PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
// topic
PutStringUTF8OnStream ( vecData, iPos, strUTF8Topic );
// server internal address (formerly unused topic)
PutStringUTF8OnStream ( vecData, iPos, strUTF8LInetAddr );
// city
PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
@ -1458,6 +1461,8 @@ bool CProtocol::EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr,
{
int iPos = 0; // init position pointer
const int iDataLen = vecData.Size();
QString sLocHost; // temp string for server internal address
CHostAddress LInetAddr;
CServerCoreInfo RecServerInfo;
// check size (the first 6 bytes)
@ -1468,7 +1473,7 @@ bool CProtocol::EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr,
// port number (2 bytes)
RecServerInfo.iLocalPortNumber =
static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
static_cast<uint16_t> ( GetValFromStream ( vecData, iPos, 2 ) );
// country (2 bytes)
RecServerInfo.eCountry =
@ -1491,11 +1496,21 @@ bool CProtocol::EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr,
return true; // return error code
}
// server topic
// server internal address
if ( GetStringFromStream ( vecData,
iPos,
MAX_LEN_SERVER_TOPIC,
RecServerInfo.strTopic ) )
MAX_LEN_IP_ADDRESS,
sLocHost ) )
{
return true; // return error code
}
if ( sLocHost.isEmpty() )
{
// old server, empty "topic", register as external address
LInetAddr = InetAddr;
}
else if ( !LInetAddr.InetAddr.setAddress( sLocHost ) )
{
return true; // return error code
}
@ -1516,7 +1531,7 @@ bool CProtocol::EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr,
}
// invoke message action
emit CLRegisterServerReceived ( InetAddr, RecServerInfo );
emit CLRegisterServerReceived ( InetAddr, LInetAddr, RecServerInfo );
return false; // no error
}
@ -1549,7 +1564,7 @@ void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr,
{
// convert server list strings to utf-8
const QByteArray strUTF8Name = vecServerInfo[i].strName.toUtf8();
const QByteArray strUTF8Topic = vecServerInfo[i].strTopic.toUtf8();
const QByteArray strUTF8LHostAddr = vecServerInfo[i].LHostAddr.InetAddr.toString().toUtf8();
const QByteArray strUTF8City = vecServerInfo[i].strCity.toUtf8();
// size of current list entry
@ -1560,7 +1575,7 @@ void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr,
1 /* maximum number of connected clients */ +
1 /* is permanent flag */ +
2 /* name utf-8 string size */ + strUTF8Name.size() +
2 /* topic utf-8 string size */ + strUTF8Topic.size() +
2 /* server internal address utf-8 string size */ + strUTF8LHostAddr.size() +
2 /* city utf-8 string size */ + strUTF8City.size();
// make space for new data
@ -1590,7 +1605,7 @@ void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr,
PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
// topic
PutStringUTF8OnStream ( vecData, iPos, strUTF8Topic );
PutStringUTF8OnStream ( vecData, iPos, strUTF8LHostAddr );
// city
PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
@ -1618,11 +1633,11 @@ bool CProtocol::EvaluateCLServerListMes ( const CHostAddress& InetAddr,
// IP address (4 bytes)
const quint32 iIpAddr =
static_cast<int> ( GetValFromStream ( vecData, iPos, 4 ) );
static_cast<uint32_t> ( GetValFromStream ( vecData, iPos, 4 ) );
// port number (2 bytes)
const quint16 iPort =
static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
static_cast<uint16_t> ( GetValFromStream ( vecData, iPos, 2 ) );
// country (2 bytes)
const QLocale::Country eCountry =
@ -1646,12 +1661,23 @@ bool CProtocol::EvaluateCLServerListMes ( const CHostAddress& InetAddr,
return true; // return error code
}
// server topic
QString strTopic;
// server internal address
QString strLHostAddr;
if ( GetStringFromStream ( vecData,
iPos,
MAX_LEN_SERVER_TOPIC,
strTopic ) )
MAX_LEN_IP_ADDRESS,
strLHostAddr ) )
{
return true; // return error code
}
CHostAddress LInetAddr;
if ( strLHostAddr.isEmpty() )
{
// old central server, empty "topic", default to server address
LInetAddr.InetAddr.setAddress( iIpAddr );
}
else if ( !LInetAddr.InetAddr.setAddress( strLHostAddr ) )
{
return true; // return error code
}
@ -1669,9 +1695,9 @@ bool CProtocol::EvaluateCLServerListMes ( const CHostAddress& InetAddr,
// add server information to vector
vecServerInfo.Add (
CServerInfo ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ),
LInetAddr,
iPort,
strName,
strTopic,
eCountry,
strCity,
iMaxNumClients,

View file

@ -112,6 +112,7 @@ public:
const int iNumClients );
void CreateCLServerFullMes ( const CHostAddress& InetAddr );
void CreateCLRegisterServerMes ( const CHostAddress& InetAddr,
const CHostAddress& LInetAddr,
const CServerCoreInfo& ServerInfo );
void CreateCLUnregisterServerMes ( const CHostAddress& InetAddr );
void CreateCLServerListMes ( const CHostAddress& InetAddr,
@ -287,6 +288,7 @@ signals:
int iMs,
int iNumClients );
void CLRegisterServerReceived ( CHostAddress InetAddr,
CHostAddress LInetAddr,
CServerCoreInfo ServerInfo );
void CLUnregisterServerReceived ( CHostAddress InetAddr );
void CLServerListReceived ( CHostAddress InetAddr,

View file

@ -427,8 +427,8 @@ CServer::CServer ( const int iNewMaxNumChan,
this, SLOT ( OnCLPingWithNumClientsReceived ( CHostAddress, int, int ) ) );
QObject::connect ( &ConnLessProtocol,
SIGNAL ( CLRegisterServerReceived ( CHostAddress, CServerCoreInfo ) ),
this, SLOT ( OnCLRegisterServerReceived ( CHostAddress, CServerCoreInfo ) ) );
SIGNAL ( CLRegisterServerReceived ( CHostAddress, CHostAddress, CServerCoreInfo ) ),
this, SLOT ( OnCLRegisterServerReceived ( CHostAddress, CHostAddress, CServerCoreInfo ) ) );
QObject::connect ( &ConnLessProtocol,
SIGNAL ( CLUnregisterServerReceived ( CHostAddress ) ),

View file

@ -367,9 +367,10 @@ public slots:
{ ConnLessProtocol.CreateCLConnClientsListMes ( InetAddr, CreateChannelList() ); }
void OnCLRegisterServerReceived ( CHostAddress InetAddr,
CHostAddress LInetAddr,
CServerCoreInfo ServerInfo )
{
ServerListManager.CentralServerRegisterServer ( InetAddr, ServerInfo );
ServerListManager.CentralServerRegisterServer ( InetAddr, LInetAddr, ServerInfo );
}
void OnCLUnregisterServerReceived ( CHostAddress InetAddr )

View file

@ -24,7 +24,6 @@
#include "serverlist.h"
/* Implementation *************************************************************/
CServerListManager::CServerListManager ( const quint16 iNPortNum,
const QString& sNCentServAddr,
@ -41,6 +40,9 @@ CServerListManager::CServerListManager ( const quint16 iNPortNum,
// set the central server address
SetCentralServerAddress ( sNCentServAddr );
// set the server internal address
SlaveCurLocalHostAddress = CHostAddress( NetworkUtil::GetLocalAddress().InetAddr, iNPortNum );
// prepare the server info information
QStringList slServInfoSeparateParams;
int iServInfoNumSplitItems = 0;
@ -63,9 +65,9 @@ CServerListManager::CServerListManager ( const quint16 iNPortNum,
// itself for his server list. If we are the central server, we assume that
// we have a permanent server.
CServerListEntry ThisServerListEntry ( CHostAddress(),
SlaveCurLocalHostAddress,
iPortNumber,
"",
"",
QLocale::system().country(),
"",
iNumChannels,
@ -112,9 +114,9 @@ CServerListManager::CServerListManager ( const quint16 iNPortNum,
// create a new server list entry, we assume that servers which are
// registered via the command line are permanent servers
CServerListEntry NewServerListEntry ( CHostAddress(),
CHostAddress(),
0, // port number not used
"",
"",
QLocale::AnyCountry,
"",
iNumChannels,
@ -125,6 +127,10 @@ CServerListManager::CServerListManager ( const quint16 iNPortNum,
slServInfoSeparateParams[iCurUsedServInfoSplitItems],
NewServerListEntry.HostAddr );
// [server n server internal address]
// Not included in the static server info, so use external address
NewServerListEntry.LHostAddr = NewServerListEntry.HostAddr;
// [server n name]
NewServerListEntry.strName =
slServInfoSeparateParams[iCurUsedServInfoSplitItems + 1];
@ -307,6 +313,7 @@ void CServerListManager::OnTimerPollList()
}
void CServerListManager::CentralServerRegisterServer ( const CHostAddress& InetAddr,
const CHostAddress& LInetAddr,
const CServerCoreInfo& ServerInfo )
{
QMutexLocker locker ( &Mutex );
@ -321,13 +328,17 @@ void CServerListManager::CentralServerRegisterServer ( const CHostAddress& In
// 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 external address and local port to identify a server
// (there could be more than one server on the external address
// but they would have to use separate ports).
// The very first list entry must not be checked since
// this is per definition the central server (i.e., this server)
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
&& ServerList[iIdx].iLocalPortNumber == ServerInfo.iLocalPortNumber )
{
// store entry index
iSelIdx = iIdx;
@ -341,7 +352,7 @@ void CServerListManager::CentralServerRegisterServer ( const CHostAddress& In
if ( iSelIdx == ciInvalidIdx )
{
// create a new server list entry and init with received data
ServerList.append ( CServerListEntry ( InetAddr, ServerInfo ) );
ServerList.append ( CServerListEntry ( InetAddr, LInetAddr, ServerInfo ) );
}
else
{
@ -349,9 +360,8 @@ void CServerListManager::CentralServerRegisterServer ( const CHostAddress& In
if ( iSelIdx > iNumPredefinedServers )
{
// update all data and call update registration function
ServerList[iSelIdx].iLocalPortNumber = ServerInfo.iLocalPortNumber;
ServerList[iSelIdx].LHostAddr = LInetAddr;
ServerList[iSelIdx].strName = ServerInfo.strName;
ServerList[iSelIdx].strTopic = ServerInfo.strTopic;
ServerList[iSelIdx].eCountry = ServerInfo.eCountry;
ServerList[iSelIdx].strCity = ServerInfo.strCity;
ServerList[iSelIdx].iMaxNumClients = ServerInfo.iMaxNumClients;
@ -415,20 +425,19 @@ void CServerListManager::CentralServerQueryServerList ( const CHostAddress& Inet
{
// 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
// case he has to connect to the local host address and port
// to allow for NAT.
if ( vecServerInfo[iIdx].HostAddr.InetAddr == InetAddr.InetAddr )
{
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
// 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
// for a predefined server:
// - LHostAddr and HostAddr are the same
// - no local port number is supplied
// otherwise, use the supplied details
if ( iIdx > iNumPredefinedServers )
{
vecServerInfo[iIdx].HostAddr.InetAddr =
ServerList[iIdx].LHostAddr.InetAddr;
vecServerInfo[iIdx].HostAddr.iPort =
ServerList[iIdx].iLocalPortNumber;
}
@ -491,6 +500,7 @@ void CServerListManager::SlaveServerRegisterServer ( const bool bIsRegister )
{
// register server
pConnLessProtocol->CreateCLRegisterServerMes ( SlaveCurCentServerHostAddress,
SlaveCurLocalHostAddress,
ServerList[0] );
}
else

View file

@ -75,37 +75,38 @@ class CServerListEntry : public CServerInfo
public:
CServerListEntry() :
CServerInfo ( CHostAddress(),
CHostAddress(),
0,
"",
"",
QLocale::AnyCountry,
"",
0,
false ) { UpdateRegistration(); }
CServerListEntry ( const CHostAddress& NHAddr,
const CHostAddress& NLHAddr,
const quint16 NLocPort,
const QString& NsName,
const QString& NsTopic,
const QLocale::Country& NeCountry,
const QString& NsCity,
const int NiMaxNumClients,
const bool NbPermOnline)
: CServerInfo ( NHAddr,
NLHAddr,
NLocPort,
NsName,
NsTopic,
NeCountry,
NsCity,
NiMaxNumClients,
NbPermOnline ) { UpdateRegistration(); }
CServerListEntry ( const CHostAddress& NHAddr,
const CHostAddress& NLHAddr,
const CServerCoreInfo& NewCoreServerInfo )
: CServerInfo ( NHAddr,
NLHAddr,
NewCoreServerInfo.iLocalPortNumber,
NewCoreServerInfo.strName,
NewCoreServerInfo.strTopic,
NewCoreServerInfo.eCountry,
NewCoreServerInfo.strCity,
NewCoreServerInfo.iMaxNumClients,
@ -150,6 +151,7 @@ public:
bool GetIsCentralServer() const { return bIsCentralServer; }
void CentralServerRegisterServer ( const CHostAddress& InetAddr,
const CHostAddress& LInetAddr,
const CServerCoreInfo& ServerInfo );
void CentralServerUnregisterServer ( const CHostAddress& InetAddr );
@ -197,6 +199,7 @@ protected:
bool bCentServPingServerInList;
CHostAddress SlaveCurCentServerHostAddress;
CHostAddress SlaveCurLocalHostAddress;
CProtocol* pConnLessProtocol;

View file

@ -88,6 +88,15 @@ protected:
return strReturn;
}
QHostAddress GenRandomIPv4Address() const
{
uint32_t a = static_cast<uint32_t> ( 192 );
uint32_t b = static_cast<uint32_t> ( 168 );
uint32_t c = static_cast<uint32_t> ( GenRandomIntInRange ( 1, 253 ) );
uint32_t d = static_cast<uint32_t> ( GenRandomIntInRange ( 1, 253 ) );
return QHostAddress( a << 24 | b << 16 | c << 8 | d );
}
QString sAddress;
quint16 iPort;
QTimer Timer;
@ -102,6 +111,7 @@ public slots:
CServerCoreInfo ServerInfo;
CVector<CServerInfo> vecServerInfo ( 1 );
CHostAddress CurHostAddress ( QHostAddress ( sAddress ), iPort );
CHostAddress CurLocalAddress ( GenRandomIPv4Address(), iPort );
CChannelCoreInfo ChannelCoreInfo;
ELicenceType eLicenceType;
@ -123,7 +133,7 @@ public slots:
case 4: // PROTMESSID_CONN_CLIENTS_LIST
vecChanInfo[0].iChanID = GenRandomIntInRange ( -2, 20 );
vecChanInfo[0].iIpAddr = GenRandomIntInRange ( 0, 100000 );
vecChanInfo[0].iIpAddr = GenRandomIPv4Address().toIPv4Address();
vecChanInfo[0].strName = GenRandomString();
Protocol.CreateConClientListMes ( vecChanInfo );
@ -206,9 +216,9 @@ public slots:
ServerInfo.iMaxNumClients = GenRandomIntInRange ( -2, 10000 );
ServerInfo.strCity = GenRandomString();
ServerInfo.strName = GenRandomString();
ServerInfo.strTopic = GenRandomString();
Protocol.CreateCLRegisterServerMes ( CurHostAddress,
CurLocalAddress,
ServerInfo );
break;
@ -224,11 +234,11 @@ public slots:
static_cast<QLocale::Country> ( GenRandomIntInRange ( 0, 100 ) );
vecServerInfo[0].HostAddr = CurHostAddress;
vecServerInfo[0].LHostAddr = CurLocalAddress;
vecServerInfo[0].iLocalPortNumber = GenRandomIntInRange ( -2, 10000 );
vecServerInfo[0].iMaxNumClients = GenRandomIntInRange ( -2, 10000 );
vecServerInfo[0].strCity = GenRandomString();
vecServerInfo[0].strName = GenRandomString();
vecServerInfo[0].strTopic = GenRandomString();
Protocol.CreateCLServerListMes ( CurHostAddress,
vecServerInfo );

View file

@ -890,6 +890,20 @@ bool NetworkUtil::ParseNetworkAddress ( QString strAddress,
}
CHostAddress NetworkUtil::GetLocalAddress()
{
QTcpSocket socket;
socket.connectToHost("8.8.8.8", 53); // google DNS, or something else reliable
if (socket.waitForConnected()) {
return CHostAddress( socket.localAddress(), 0 );
} else {
qWarning()
<< "could not determine local IPv4 address:"
<< socket.errorString()
<< "- using localhost";
return CHostAddress( QHostAddress::LocalHost, 0 );
}
}
// Instrument picture data base ------------------------------------------------
CVector<CInstPictures::CInstPictProps>& CInstPictures::GetTable()
{

View file

@ -24,6 +24,7 @@
#pragma once
#include <QTcpSocket>
#include <QHostAddress>
#include <QHostInfo>
#include <QMenu>
@ -861,7 +862,6 @@ public:
CServerCoreInfo() :
iLocalPortNumber ( 0 ),
strName ( "" ),
strTopic ( "" ),
eCountry ( QLocale::AnyCountry ),
strCity ( "" ),
iMaxNumClients ( 0 ),
@ -870,14 +870,12 @@ public:
CServerCoreInfo (
const quint16 NLocPort,
const QString& NsName,
const QString& NsTopic,
const QLocale::Country& NeCountry,
const QString& NsCity,
const int NiMaxNumClients,
const bool NbPermOnline) :
iLocalPortNumber ( NLocPort ),
strName ( NsName ),
strTopic ( NsTopic ),
eCountry ( NeCountry ),
strCity ( NsCity ),
iMaxNumClients ( NiMaxNumClients ),
@ -889,9 +887,6 @@ public:
// name of the server
QString strName;
// topic of the current jam session or server
QString strTopic;
// country in which the server is located
QLocale::Country eCountry;
@ -910,27 +905,33 @@ class CServerInfo : public CServerCoreInfo
{
public:
CServerInfo() :
HostAddr ( CHostAddress() ) {}
HostAddr ( CHostAddress() ),
LHostAddr ( CHostAddress() )
{}
CServerInfo (
const CHostAddress& NHAddr,
const CHostAddress& NLAddr,
const quint16 NLocPort,
const QString& NsName,
const QString& NsTopic,
const QLocale::Country& NeCountry,
const QString& NsCity,
const int NiMaxNumClients,
const bool NbPermOnline) :
CServerCoreInfo ( NLocPort,
NsName,
NsTopic,
NeCountry,
NsCity,
NiMaxNumClients,
NbPermOnline ), HostAddr ( NHAddr ) {}
NbPermOnline ),
HostAddr ( NHAddr ),
LHostAddr ( NLAddr ) {}
// internet address of the server
CHostAddress HostAddr;
// server internal address
CHostAddress LHostAddr;
};
@ -977,6 +978,8 @@ class NetworkUtil
public:
static bool ParseNetworkAddress ( QString strAddress,
CHostAddress& HostAddress );
static CHostAddress GetLocalAddress();
};