diff --git a/src/clientrpc.cpp b/src/clientrpc.cpp index 1f6671ca9e..98111c2a3e 100644 --- a/src/clientrpc.cpp +++ b/src/clientrpc.cpp @@ -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{ @@ -190,7 +190,7 @@ CClientRpc::CClientRpc ( CClient* pClient, CClientSettings* pSettings, CRpcServe CHostAddress haDirectoryAddress; // Allow IPv4 only for communicating with Directories - if ( !NetworkUtil::ParseNetworkAddress ( jsonDirectoryIp.toString(), haDirectoryAddress, false ) ) + if ( !NetworkUtil::ParseNetworkAddress ( jsonDirectoryIp.toString(), haDirectoryAddress, pClient->IsIPv6Available() ) ) { response["error"] = CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: directory is not a valid socket address" ); diff --git a/src/connectdlg.cpp b/src/connectdlg.cpp index 468296205d..a91aefb8c7 100644 --- a/src/connectdlg.cpp +++ b/src/connectdlg.cpp @@ -358,7 +358,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 ); @@ -457,7 +457,7 @@ void CConnectDlg::SetServerList ( const CHostAddress& InetAddr, const CVector 0 ) { - CurHostAddress = vecServerInfo[iIdx].HostAddr; + CurHostAddress = vecServerInfo[iIdx].HostAddr4; } else { @@ -485,7 +485,7 @@ void CConnectDlg::SetServerList ( const CHostAddress& InetAddr, const CVectorsetText ( LVC_NAME, CurHostAddress.toString ( CHostAddress::SM_IP_NO_LAST_BYTE ) ); diff --git a/src/global.h b/src/global.h index 5414a58c41..bfc0448c1e 100644 --- a/src/global.h +++ b/src/global.h @@ -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 diff --git a/src/protocol.cpp b/src/protocol.cpp index 3030c2dca1..1203ec9e69 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -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 ( vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 ); + PutValOnStream ( vecData, iPos, static_cast ( 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 ( vecServerInfo[i].HostAddr.iPort ), 2 ); + PutValOnStream ( vecData, iPos, static_cast ( vecServerInfo[i].HostAddr4.iPort ), 2 ); // country (2 bytes) PutCountryOnStream ( vecData, iPos, vecServerInfo[i].eCountry ); @@ -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 ( vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 ); + PutValOnStream ( vecData, iPos, static_cast ( 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 ( vecServerInfo[i].HostAddr.iPort ), 2 ); + PutValOnStream ( vecData, iPos, static_cast ( vecServerInfo[i].HostAddr4.iPort ), 2 ); // name (note that the string length indicator is 1 in this special case) PutStringUTF8OnStream ( vecData, iPos, strUTF8Name, 1 ); diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 0dafa73863..474cabbf37 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -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 ) ); @@ -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 ); } } @@ -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 ); } } @@ -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; @@ -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 ( ServerList.size() ); @@ -709,8 +709,8 @@ void CServerListManager::RetrieveAll ( const CHostAddress& InetAddr ) CVector 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) @@ -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 ); } } @@ -758,7 +758,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; } @@ -847,15 +847,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 ); } @@ -889,8 +889,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'; } @@ -1012,7 +1012,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(); @@ -1027,7 +1027,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 { diff --git a/src/serverlist.h b/src/serverlist.h index f18c40678d..171ffb47d3 100644 --- a/src/serverlist.h +++ b/src/serverlist.h @@ -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 diff --git a/src/testbench.h b/src/testbench.h index 233acd6351..97f5db8c0a 100644 --- a/src/testbench.h +++ b/src/testbench.h @@ -234,8 +234,8 @@ public slots: case 19: // PROTMESSID_CLM_SERVER_LIST vecServerInfo[0].bPermanentOnline = static_cast ( GenRandomIntInRange ( 0, 1 ) ); vecServerInfo[0].eCountry = static_cast ( GenRandomIntInRange ( 0, 100 ) ); - vecServerInfo[0].HostAddr = CurHostAddress; - vecServerInfo[0].LHostAddr = CurLocalAddress; + vecServerInfo[0].HostAddr4 = CurHostAddress; + vecServerInfo[0].LHostAddr4 = CurLocalAddress; vecServerInfo[0].iMaxNumClients = GenRandomIntInRange ( -2, 10000 ); vecServerInfo[0].strCity = GenRandomString(); vecServerInfo[0].strName = GenRandomString(); diff --git a/src/util.h b/src/util.h index f7f5afe189..79ecb53422 100644 --- a/src/util.h +++ b/src/util.h @@ -1035,7 +1035,7 @@ class CServerCoreInfo class CServerInfo : public CServerCoreInfo { public: - CServerInfo() : HostAddr ( CHostAddress() ), LHostAddr ( CHostAddress() ) {} + CServerInfo() : HostAddr4 ( CHostAddress() ), LHostAddr4 ( CHostAddress() ), HostAddr6 ( CHostAddress() ), LHostAddr6 ( CHostAddress() ) {} CServerInfo ( const CHostAddress& NHAddr, const CHostAddress& NLAddr, @@ -1044,16 +1044,40 @@ class CServerInfo : public CServerCoreInfo const QString& NsCity, const int NiMaxNumClients, const bool NbPermOnline ) : - CServerCoreInfo ( NsName, NeCountry, NsCity, NiMaxNumClients, NbPermOnline ), - HostAddr ( NHAddr ), - LHostAddr ( NLAddr ) - {} + CServerCoreInfo ( NsName, NeCountry, NsCity, NiMaxNumClients, NbPermOnline ) + { + if ( NHAddr.InetAddr.protocol() == QAbstractSocket::IPv4Protocol ) + { + HostAddr4 = NHAddr; + } + + if ( NLAddr.InetAddr.protocol() == QAbstractSocket::IPv4Protocol ) + { + LHostAddr4 = NLAddr; + } + + if ( NHAddr.InetAddr.protocol() == QAbstractSocket::IPv6Protocol ) + { + HostAddr6 = NHAddr; + } + + if ( NLAddr.InetAddr.protocol() == QAbstractSocket::IPv6Protocol ) + { + LHostAddr6 = NLAddr; + } + } + + // IPv4 address of the server + CHostAddress HostAddr4; + + // IPv4 internal address of the server + CHostAddress LHostAddr4; - // internet address of the server - CHostAddress HostAddr; + // IPv6 address of the server + CHostAddress HostAddr6; - // server internal address - CHostAddress LHostAddr; + // IPv6 internal address of the server + CHostAddress LHostAddr6; }; // Network transport properties ------------------------------------------------