Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/JSON-RPC.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,34 @@ Results:
| result | string | Always "ok". |


### jamulusdirectory/getServerList

Returns the list of registered servers along with details about them.

Parameters:

| Name | Type | Description |
| --- | --- | --- |
| params | object | No parameters (empty object). |

Results:

| Name | Type | Description |
| --- | --- | --- |
| result.numservers | number | The number of registered servers. |
| result.servers | array | The list of registered servers. |
| result.servers[*].id | number | The server's index. |
| result.servers[*].name | string | The server's name. |
| result.servers[*].countryName | string | The text name of the country specified by the user for this channel (see QLocale::Country). |
| result.servers[*].city | string | The city name provided by the operator of this server. |
| result.servers[*].maxClients | number | The max number of clients supported by the server. |
| result.servers[*].permanent | bool | The permanent status of the server. |
| result.servers[*].ipv4addr | string | The IPv4 address the server registered from (ip:port) |
| result.servers[*].ipv4addrLocal | string | The local IPv4 address provided by the server (ip:port) |
| result.servers[*].ipv6addr | string | The IPv6 address the server registered from ([ipv6]:port) |
| result.servers[*].ipv6addrLocal | string | The local IPv6 address provided by the server ([ipv6]:port) |


### jamulusserver/broadcastChatMessage

Sends a message (as the server) to all connected clients. This can be used to broadcast messages from external sources (e.g. scripts or monitoring tools).
Expand Down
8 changes: 4 additions & 4 deletions src/clientrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,14 @@ CClientRpc::CClientRpc ( CClient* pClient, CClientSettings* pSettings, CRpcServe
for ( const auto& serverInfo : vecServerInfo )
{
QJsonObject objServerInfo{
{ "address", serverInfo.HostAddr.toString() },
{ "address", serverInfo.HostAddr4.toString() },
{ "name", serverInfo.strName },
{ "countryId", serverInfo.eCountry },
{ "country", QLocale::countryToString ( serverInfo.eCountry ) },
{ "city", serverInfo.strCity },
};
arrServerInfo.append ( objServerInfo );
pClient->CreateCLServerListPingMes ( serverInfo.HostAddr );
pClient->CreateCLServerListPingMes ( serverInfo.HostAddr4 );
}
pRpcServer->BroadcastNotification ( "jamulusclient/serverListReceived",
QJsonObject{
Expand Down Expand Up @@ -189,8 +189,8 @@ CClientRpc::CClientRpc ( CClient* pClient, CClientSettings* pSettings, CRpcServe

CHostAddress haDirectoryAddress;

// Allow IPv4 only for communicating with Directories
if ( !NetworkUtil::ParseNetworkAddress ( jsonDirectoryIp.toString(), haDirectoryAddress, false ) )
// Allow IPv4 and IPv6 for communicating with Directories
if ( !NetworkUtil::ParseNetworkAddress ( jsonDirectoryIp.toString(), haDirectoryAddress, pClient->IsIPv6Available() ) )
{
response["error"] =
CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: directory is not a valid socket address" );
Expand Down
6 changes: 3 additions & 3 deletions src/connectdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ void CConnectDlg::RequestServerList()
if ( NetworkUtil::ParseNetworkAddress (
NetworkUtil::GetDirectoryAddress ( pSettings->eDirectoryType, pSettings->vstrDirectoryAddress[pSettings->iCustomDirectoryIndex] ),
haDirectoryAddress,
false ) )
pClient->IsIPv6Available() ) )
{
// send the request for the server list
emit ReqServerListQuery ( haDirectoryAddress );
Expand Down Expand Up @@ -419,7 +419,7 @@ void CConnectDlg::SetServerList ( const CHostAddress& InetAddr, const CVector<CS

if ( iIdx > 0 )
{
CurHostAddress = vecServerInfo[iIdx].HostAddr;
CurHostAddress = vecServerInfo[iIdx].HostAddr4;
}
else
{
Expand Down Expand Up @@ -447,7 +447,7 @@ void CConnectDlg::SetServerList ( const CHostAddress& InetAddr, const CVector<CS
// IP address and port (use IP number without last byte)
// Definition: If the port number is the default port number, we do
// not show it.
if ( vecServerInfo[iIdx].HostAddr.iPort == DEFAULT_PORT_NUMBER )
if ( vecServerInfo[iIdx].HostAddr4.iPort == DEFAULT_PORT_NUMBER )
{
// only show IP number, no port number
pNewListViewItem->setText ( LVC_NAME, CurHostAddress.toString ( CHostAddress::SM_IP_NO_LAST_BYTE ) );
Expand Down
2 changes: 1 addition & 1 deletion src/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,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_IP_ADDRESS 15
#define MAX_LEN_IP_ADDRESS 39 // 15 for IPv4, 39 for IPv6
#define MAX_LEN_SERVER_CITY 20
#define MAX_LEN_VERSION_TEXT 50

Expand Down
8 changes: 4 additions & 4 deletions src/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2109,11 +2109,11 @@ void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr, const CVec

// IP address (4 bytes)
// note the Server List manager has put the internal details in HostAddr where required
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 );
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr4.InetAddr.toIPv4Address() ), 4 );

// port number (2 bytes)
// note the Server List manager has put the internal details in HostAddr where required
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.iPort ), 2 );
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr4.iPort ), 2 );

// country (2 bytes)
PutCountryOnStream ( vecData, iPos, vecServerInfo[i].eCountry );
Expand Down Expand Up @@ -2232,11 +2232,11 @@ void CProtocol::CreateCLRedServerListMes ( const CHostAddress& InetAddr, const C

// IP address (4 bytes)
// note the Server List manager has put the internal details in HostAddr where required
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 );
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr4.InetAddr.toIPv4Address() ), 4 );

// port number (2 bytes)
// note the Server List manager has put the internal details in HostAddr where required
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.iPort ), 2 );
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr4.iPort ), 2 );

// name (note that the string length indicator is 1 in this special case)
PutStringUTF8OnStream ( vecData, iPos, strUTF8Name, 1 );
Expand Down
2 changes: 2 additions & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ class CServer : public QObject, public CServerSlots<MAX_NUM_CHANNELS>
void SetServerCountry ( const QLocale::Country eNewCountry ) { ServerListManager.SetServerCountry ( eNewCountry ); }
QLocale::Country GetServerCountry() { return ServerListManager.GetServerCountry(); }

bool GetDirectoryServerList ( CVector<CServerInfo>& vecServerInfo ) { return ServerListManager.GetDirectoryServerList ( vecServerInfo ); }

bool GetRecorderInitialised() { return JamController.GetRecorderInitialised(); }
void SetEnableRecording ( bool bNewEnableRecording );
bool GetDisableRecording() { return bDisableRecording; }
Expand Down
84 changes: 60 additions & 24 deletions src/serverlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ QString CServerListEntry::toCSV()
{
QStringList sl;

sl.append ( this->HostAddr.toString() );
sl.append ( this->LHostAddr.toString() );
sl.append ( this->HostAddr4.toString() );
sl.append ( this->LHostAddr4.toString() );
sl.append ( ToBase64 ( this->strName ) );
sl.append ( ToBase64 ( this->strCity ) );
sl.append ( QString::number ( this->eCountry ) );
Expand Down Expand Up @@ -543,7 +543,7 @@ void CServerListManager::OnTimerPingServerInList()
for ( int iIdx = 1; iIdx < iCurServerListSize; iIdx++ )
{
// send empty message to keep NAT port open at registered server
pConnLessProtocol->CreateCLEmptyMes ( ServerList[iIdx].HostAddr );
pConnLessProtocol->CreateCLEmptyMes ( ServerList[iIdx].HostAddr4 );
}
}

Expand All @@ -560,7 +560,7 @@ void CServerListManager::OnTimerPollList()
if ( ServerList[iIdx].RegisterTime.elapsed() > ( SERVLIST_TIME_OUT_MINUTES * 60000 ) )
{
// remove this list entry
vecRemovedHostAddr.Add ( ServerList[iIdx].HostAddr );
vecRemovedHostAddr.Add ( ServerList[iIdx].HostAddr4 );
ServerList.removeAt ( iIdx );
}
}
Expand Down Expand Up @@ -637,7 +637,7 @@ void CServerListManager::Append ( const CHostAddress& InetAddr,
else
{
// update all data and call update registration function
ServerList[iSelIdx].LHostAddr = LInetAddr;
ServerList[iSelIdx].LHostAddr4 = LInetAddr;
ServerList[iSelIdx].strName = ServerInfo.strName;
ServerList[iSelIdx].eCountry = ServerInfo.eCountry;
ServerList[iSelIdx].strCity = ServerInfo.strCity;
Expand Down Expand Up @@ -695,12 +695,12 @@ void CServerListManager::RetrieveAll ( const CHostAddress& InetAddr )
bool clientIsInternal = NetworkUtil::IsPrivateNetworkIP ( InetAddr.InetAddr );

CHostAddress clientPublicAddr = InetAddr;
if ( clientIsInternal && CHostAddress().InetAddr != ServerList[0].LHostAddr.InetAddr &&
!NetworkUtil::IsPrivateNetworkIP ( ServerList[0].LHostAddr.InetAddr ) )
if ( clientIsInternal && CHostAddress().InetAddr != ServerList[0].LHostAddr4.InetAddr &&
!NetworkUtil::IsPrivateNetworkIP ( ServerList[0].LHostAddr4.InetAddr ) )
{
// client and directory on same LAN, directory has public IP set, that should be suitable for the
// client, too (i.e. same router with same public IP will be used for both), so use it for client public IP
clientPublicAddr.InetAddr = ServerList[0].LHostAddr.InetAddr;
clientPublicAddr.InetAddr = ServerList[0].LHostAddr4.InetAddr;
}

const ushort iCurServerListSize = static_cast<ushort> ( ServerList.size() );
Expand All @@ -709,8 +709,8 @@ void CServerListManager::RetrieveAll ( const CHostAddress& InetAddr )
CVector<CServerInfo> vecServerInfo ( iCurServerListSize );

// copy list item for the directory and just let the protocol sort out the actual details
vecServerInfo[0] = ServerList[0];
vecServerInfo[0].HostAddr = CHostAddress();
vecServerInfo[0] = ServerList[0];
vecServerInfo[0].HostAddr4 = CHostAddress();

// 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 not in a vector object)
Expand All @@ -719,25 +719,25 @@ void CServerListManager::RetrieveAll ( const CHostAddress& InetAddr )
// copy list item
CServerInfo& siCurListEntry = vecServerInfo[iIdx] = ServerList[iIdx];

bool serverIsInternal = NetworkUtil::IsPrivateNetworkIP ( siCurListEntry.HostAddr.InetAddr );
bool serverIsInternal = NetworkUtil::IsPrivateNetworkIP ( siCurListEntry.HostAddr4.InetAddr );

bool wantHostAddr = clientIsInternal /* HostAddr is local IP if local server else external IP, so do not replace */ ||
bool wantHostAddr = clientIsInternal /* HostAddr4 is local IP if local server else external IP, so do not replace */ ||
( !serverIsInternal &&
InetAddr.InetAddr != siCurListEntry.HostAddr.InetAddr /* external server and client have different public IPs */ );
InetAddr.InetAddr != siCurListEntry.HostAddr4.InetAddr /* external server and client have different public IPs */ );

if ( !wantHostAddr )
{
vecServerInfo[iIdx].HostAddr = siCurListEntry.LHostAddr;
vecServerInfo[iIdx].HostAddr4 = siCurListEntry.LHostAddr4;
}

// do not send a "ping" to a server local to the directory (no need)
if ( !serverIsInternal )
{
// create "send empty message" for all other registered servers
// this causes the server (vecServerInfo[iIdx].HostAddr)
// this causes the server (vecServerInfo[iIdx].HostAddr4)
// to send a "reply" to the client (InetAddr or best guess public IP address if internal to directory)
// - with the intent of opening the server firewall for the client
pConnLessProtocol->CreateCLSendEmptyMesMes ( siCurListEntry.HostAddr, clientPublicAddr );
pConnLessProtocol->CreateCLSendEmptyMesMes ( siCurListEntry.HostAddr4, clientPublicAddr );
}
}

Expand All @@ -749,6 +749,31 @@ void CServerListManager::RetrieveAll ( const CHostAddress& InetAddr )
}
}

// fetch copy of registered server list for use by JSON-RPC
// return false if not a directory
bool CServerListManager::GetDirectoryServerList ( CVector<CServerInfo>& vecServerInfo )
{
QMutexLocker locker ( &Mutex );

if ( !bIsDirectory )
{
return false;
}

const ushort iCurServerListSize = static_cast<ushort> ( ServerList.size() );

// allocate memory for the entire list
vecServerInfo.Init ( iCurServerListSize );

// copy the list
for ( int iIdx = 0; iIdx < iCurServerListSize; iIdx++ )
{
vecServerInfo[iIdx] = ServerList[iIdx];
}

return true;
}

int CServerListManager::IndexOf ( const CHostAddress& haSearchTerm )
{
// Called with lock set.
Expand All @@ -758,7 +783,7 @@ int CServerListManager::IndexOf ( const CHostAddress& haSearchTerm )
// (i.e., this server).
for ( int iIdx = ServerList.size() - 1; iIdx > 0; iIdx-- )
{
if ( ServerList[iIdx].HostAddr == haSearchTerm )
if ( ServerList[iIdx].HostAddr4 == haSearchTerm )
{
return iIdx;
}
Expand Down Expand Up @@ -847,15 +872,15 @@ bool CServerListManager::Load()
pServer->IsIPv6Available() );

// We expect servers to have addresses...
if ( ( CHostAddress() == serverListEntry.HostAddr ) )
if ( ( CHostAddress() == serverListEntry.HostAddr4 ) )
{
qWarning() << qUtf8Printable ( QString ( "Could not parse '%1' successfully - invalid host" ).arg ( line ) );
continue;
}

qInfo() << qUtf8Printable ( QString ( "Loading registration for %1 (%2): %3" )
.arg ( serverListEntry.HostAddr.toString() )
.arg ( serverListEntry.LHostAddr.toString() )
.arg ( serverListEntry.HostAddr4.toString() )
.arg ( serverListEntry.LHostAddr4.toString() )
.arg ( serverListEntry.strName ) );
ServerList.append ( serverListEntry );
}
Expand Down Expand Up @@ -889,8 +914,8 @@ void CServerListManager::Save()
for ( int iIdx = ServerList.size() - 1; iIdx > 0; iIdx-- )
{
qInfo() << qUtf8Printable ( QString ( tr ( "Saving registration for %1 (%2): %3" ) )
.arg ( ServerList[iIdx].HostAddr.toString() )
.arg ( ServerList[iIdx].LHostAddr.toString() )
.arg ( ServerList[iIdx].HostAddr4.toString() )
.arg ( ServerList[iIdx].LHostAddr4.toString() )
.arg ( ServerList[iIdx].strName ) );
out << ServerList[iIdx].toCSV() << '\n';
}
Expand Down Expand Up @@ -1012,7 +1037,7 @@ void CServerListManager::SetRegistered ( const bool bIsRegister )
// Allow IPv4 only for communicating with Directories
// Use SRV DNS discovery for directory connections, fallback to A/AAAA if none.
const QString strNetworkAddress = NetworkUtil::GetDirectoryAddress ( DirectoryType, strDirectoryAddress );
const bool bDirectoryAddressValid = NetworkUtil::ParseNetworkAddress ( strNetworkAddress, DirectoryAddress, false );
const bool bDirectoryAddressValid = NetworkUtil::ParseNetworkAddress ( strNetworkAddress, DirectoryAddress, pServer->IsIPv6Available() );

// lock the mutex again now that the address has been resolved.
locker.relock();
Expand All @@ -1027,7 +1052,18 @@ void CServerListManager::SetRegistered ( const bool bIsRegister )
// For a registered server, the server properties are stored in the
// very first item in the server list (which is actually no server list
// but just one item long for the registered server).
pConnLessProtocol->CreateCLRegisterServerExMes ( DirectoryAddress, ServerList[0].LHostAddr, ServerList[0] );
if ( DirectoryAddress.InetAddr.protocol() == QAbstractSocket::IPv4Protocol )
{
pConnLessProtocol->CreateCLRegisterServerExMes ( DirectoryAddress, ServerPublicIP, ServerList[0] );
}
else if ( DirectoryAddress.InetAddr.protocol() == QAbstractSocket::IPv6Protocol )
{
pConnLessProtocol->CreateCLRegisterServerExMes ( DirectoryAddress, ServerPublicIP6, ServerList[0] );
}
else
{
SetSvrRegStatus ( SRS_BAD_ADDRESS );
}
}
else
{
Expand Down
4 changes: 3 additions & 1 deletion src/serverlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class CServerListEntry : public CServerInfo
QString strCountry,
QString strNumClients,
bool isPermanent,
bool bEnableIPv6 );
bool bIPv6Available );
QString toCSV();

// time on which the entry was registered
Expand Down Expand Up @@ -195,6 +195,8 @@ class CServerListManager : public QObject
void Remove ( const CHostAddress& InetAddr );
void RetrieveAll ( const CHostAddress& InetAddr );

bool GetDirectoryServerList ( CVector<CServerInfo>& vecServerInfo );

void StoreRegistrationResult ( ESvrRegResult eStatus );

QString GetServerListFileName() { return ServerListFileName; }
Expand Down
Loading
Loading