From d7183e15969eef00843616f4c91337959cd034b7 Mon Sep 17 00:00:00 2001 From: Tony Mountifield Date: Sat, 30 May 2026 10:31:42 +0100 Subject: [PATCH] Auto-enable IPv6 by default, unless disabled Removes -6 and --enableipv6, replacing with --noipv6. If --noipv6 is not specified, it will try first to open an IPv6 socket, and if the host does not support it, will fall back to an IPv4 socket. CSocket informs CClient or CServer of IPv6 availability via a reference. The bool bEnableIPv6 is gone, and the actual availability of IPv6 is published by a method in CClient or CServer. --- src/client.cpp | 8 ++-- src/client.h | 10 +++-- src/clientdlg.cpp | 8 ++-- src/clientdlg.h | 2 - src/connectdlg.cpp | 10 +++-- src/connectdlg.h | 4 +- src/main.cpp | 27 +++++------- src/server.cpp | 10 ++--- src/server.h | 10 ++--- src/serverdlg.cpp | 4 +- src/serverlist.cpp | 26 +++++++----- src/serverlist.h | 13 ++++-- src/socket.cpp | 103 ++++++++++++++++++++++++++------------------- src/socket.h | 45 ++++++++++++++------ src/util.cpp | 20 ++++----- src/util.h | 8 ++-- 16 files changed, 173 insertions(+), 135 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 13eac289b6..07fc6afb6a 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -32,7 +32,7 @@ CClient::CClient ( const quint16 iPortNumber, const QString& strConnOnStartupAddress, const bool bNoAutoJackConnect, const QString& strNClientName, - const bool bNEnableIPv6, + const bool bNDisableIPv6, const bool bNMuteMeInPersonalMix ) : ChannelInfo(), strClientName ( strNClientName ), @@ -50,7 +50,8 @@ CClient::CClient ( const quint16 iPortNumber, bIsInitializationPhase ( true ), bMuteOutStream ( false ), fMuteOutStreamGain ( 1.0f ), - Socket ( &Channel, iPortNumber, iQosNumber, "", bNEnableIPv6 ), + bIPv6Available ( false ), + Socket ( &Channel, iPortNumber, iQosNumber, "", bNDisableIPv6, bIPv6Available ), Sound ( AudioCallback, this, bNoAutoJackConnect, strNClientName ), iAudioInFader ( AUD_FADER_IN_MIDDLE ), bReverbOnLeftChan ( false ), @@ -68,7 +69,6 @@ CClient::CClient ( const quint16 iPortNumber, bEnableAudioAlerts ( false ), bEnableOPUS64 ( false ), bJitterBufferOK ( true ), - bEnableIPv6 ( bNEnableIPv6 ), bMuteMeInPersonalMix ( bNMuteMeInPersonalMix ), iServerSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ), bRawAudioIsSupported ( false ) @@ -599,7 +599,7 @@ void CClient::SetRemoteChanPan ( const int iId, const float fPan ) bool CClient::SetServerAddr ( QString strNAddr ) { CHostAddress HostAddress; - if ( NetworkUtil::ParseNetworkAddress ( strNAddr, HostAddress, bEnableIPv6 ) ) + if ( NetworkUtil::ParseNetworkAddress ( strNAddr, HostAddress, bIPv6Available ) ) { // apply address to the channel Channel.SetAddress ( HostAddress ); diff --git a/src/client.h b/src/client.h index c71fc414ab..b0de01af5e 100644 --- a/src/client.h +++ b/src/client.h @@ -131,7 +131,7 @@ class CClient : public QObject const QString& strConnOnStartupAddress, const bool bNoAutoJackConnect, const QString& strNClientName, - const bool bNEnableIPv6, + const bool bNDisableIPv6, const bool bNMuteMeInPersonalMix ); virtual ~CClient(); @@ -142,6 +142,9 @@ class CClient : public QObject bool IsCallbackEntered() const { return Sound.IsCallbackEntered(); } bool SetServerAddr ( QString strNAddr ); + // IPv6 Available + bool IsIPv6Available() { return bIPv6Available; } + double GetLevelForMeterdBLeft() { return SignalLevelMeter.GetLevelForMeterdBLeftOrMono(); } double GetLevelForMeterdBRight() { return SignalLevelMeter.GetLevelForMeterdBRight(); } @@ -369,7 +372,9 @@ class CClient : public QObject float fMuteOutStreamGain; CVector vecCeltData; - CHighPrioSocket Socket; + bool bIPv6Available; // must be before Socket - passed by reference to Socket + CHighPrioSocket Socket; + CSound Sound; CStereoSignalLevelMeter SignalLevelMeter; @@ -405,7 +410,6 @@ class CClient : public QObject bool bEnableOPUS64; bool bJitterBufferOK; - bool bEnableIPv6; bool bMuteMeInPersonalMix; QMutex MutexDriverReinit; diff --git a/src/clientdlg.cpp b/src/clientdlg.cpp index 9fdb52f3a1..02a98737ee 100644 --- a/src/clientdlg.cpp +++ b/src/clientdlg.cpp @@ -32,19 +32,17 @@ CClientDlg::CClientDlg ( CClient* pNCliP, const bool bNewShowComplRegConnList, const bool bShowAnalyzerConsole, const bool bMuteStream, - const bool bNEnableIPv6, QWidget* parent ) : CBaseDlg ( parent, Qt::Window ), // use Qt::Window to get min/max window buttons pClient ( pNCliP ), pSettings ( pNSetP ), bConnectDlgWasShown ( false ), bDetectFeedback ( false ), - bEnableIPv6 ( bNEnableIPv6 ), eLastRecorderState ( RS_UNDEFINED ), // for SetMixerBoardDeco eLastDesign ( GD_DEFAULT ), // " ClientSettingsDlg ( pNCliP, pNSetP, parent ), ChatDlg ( parent ), - ConnectDlg ( pNSetP, bNewShowComplRegConnList, bNEnableIPv6, parent ), + ConnectDlg ( pNCliP, pNSetP, bNewShowComplRegConnList, parent ), AnalyzerConsole ( pNCliP, parent ) { setupUi ( this ); @@ -597,12 +595,12 @@ CClientDlg::CClientDlg ( CClient* pNCliP, // Don't use SRV resolution when resolving update servers. - if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK1_ADDRESS, UpdateServerHostAddress, bEnableIPv6 ) ) + if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK1_ADDRESS, UpdateServerHostAddress, pClient->IsIPv6Available() ) ) { pClient->CreateCLServerListReqVerAndOSMes ( UpdateServerHostAddress ); } - if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK2_ADDRESS, UpdateServerHostAddress, bEnableIPv6 ) ) + if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK2_ADDRESS, UpdateServerHostAddress, pClient->IsIPv6Available() ) ) { pClient->CreateCLServerListReqVerAndOSMes ( UpdateServerHostAddress ); } diff --git a/src/clientdlg.h b/src/clientdlg.h index a5d327676a..e9901dac74 100644 --- a/src/clientdlg.h +++ b/src/clientdlg.h @@ -83,7 +83,6 @@ class CClientDlg : public CBaseDlg, private Ui_CClientDlgBase const bool bNewShowComplRegConnList, const bool bShowAnalyzerConsole, const bool bMuteStream, - const bool bNEnableIPv6, QWidget* parent = nullptr ); protected: @@ -108,7 +107,6 @@ class CClientDlg : public CBaseDlg, private Ui_CClientDlgBase bool bConnected; bool bConnectDlgWasShown; bool bDetectFeedback; - bool bEnableIPv6; ERecorderState eLastRecorderState; EGUIDesign eLastDesign; QTimer TimerSigMet; diff --git a/src/connectdlg.cpp b/src/connectdlg.cpp index 212e35d684..9cc06cd545 100644 --- a/src/connectdlg.cpp +++ b/src/connectdlg.cpp @@ -100,8 +100,9 @@ bool CMappedTreeWidgetItem::operator<( const QTreeWidgetItem& other ) const return lhs.toString() < rhs.toString(); } -CConnectDlg::CConnectDlg ( CClientSettings* pNSetP, const bool bNewShowCompleteRegList, const bool bNEnableIPv6, QWidget* parent ) : +CConnectDlg::CConnectDlg ( CClient* pNCliP, CClientSettings* pNSetP, const bool bNewShowCompleteRegList, QWidget* parent ) : CBaseDlg ( parent, Qt::Dialog ), + pClient ( pNCliP ), pSettings ( pNSetP ), strSelectedAddress ( "" ), strSelectedServerName ( "" ), @@ -110,8 +111,7 @@ CConnectDlg::CConnectDlg ( CClientSettings* pNSetP, const bool bNewShowCompleteR bReducedServerListReceived ( false ), bServerListItemWasChosen ( false ), bListFilterWasActive ( false ), - bShowAllMusicians ( true ), - bEnableIPv6 ( bNEnableIPv6 ) + bShowAllMusicians ( true ) { setupUi ( this ); @@ -870,7 +870,9 @@ void CConnectDlg::OnTimerPing() // try to parse host address string which is stored as user data // in the server list item GUI control element // the data to be parsed is just IP:port, so no SRV discovery is needed - if ( NetworkUtil::ParseNetworkAddressBare ( pCurListViewItem->data ( LVC_NAME, Qt::UserRole ).toString(), haServerAddress, bEnableIPv6 ) ) + if ( NetworkUtil::ParseNetworkAddressBare ( pCurListViewItem->data ( LVC_NAME, Qt::UserRole ).toString(), + haServerAddress, + pClient->IsIPv6Available() ) ) { // if address is valid, send ping message using a new thread #if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) diff --git a/src/connectdlg.h b/src/connectdlg.h index 435169edf7..3c3dbbb457 100644 --- a/src/connectdlg.h +++ b/src/connectdlg.h @@ -62,7 +62,7 @@ class CConnectDlg : public CBaseDlg, private Ui_CConnectDlgBase Q_OBJECT public: - CConnectDlg ( CClientSettings* pNSetP, const bool bNewShowCompleteRegList, const bool bNEnableIPv6, QWidget* parent = nullptr ); + CConnectDlg ( CClient* pNCliP, CClientSettings* pNSetP, const bool bNewShowCompleteRegList, QWidget* parent = nullptr ); void SetShowAllMusicians ( const bool bState ) { ShowAllMusicians ( bState ); } bool GetShowAllMusicians() { return bShowAllMusicians; } @@ -105,6 +105,7 @@ class CConnectDlg : public CBaseDlg, private Ui_CConnectDlgBase void EmitCLServerListPingMes ( const CHostAddress& haServerAddress, const bool bNeedVersion ); void UpdateDirectoryComboBox(); + CClient* pClient; CClientSettings* pSettings; QTimer TimerPing; @@ -119,7 +120,6 @@ class CConnectDlg : public CBaseDlg, private Ui_CConnectDlgBase bool bServerListItemWasChosen; bool bListFilterWasActive; bool bShowAllMusicians; - bool bEnableIPv6; public slots: void OnServerListItemDoubleClicked ( QTreeWidgetItem* Item, int ); diff --git a/src/main.cpp b/src/main.cpp index a034218f8a..62e7375487 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -96,7 +96,7 @@ int main ( int argc, char** argv ) bool bNoAutoJackConnect = false; bool bUseTranslation = true; bool bCustomPortNumberGiven = false; - bool bEnableIPv6 = false; + bool bDisableIPv6 = false; int iNumServerChannels = DEFAULT_USED_NUM_CHANNELS; quint16 iPortNumber = DEFAULT_PORT_NUMBER; int iJsonRpcPortNumber = INVALID_PORT; @@ -242,11 +242,11 @@ int main ( int argc, char** argv ) } // Enable IPv6 --------------------------------------------------------- - if ( GetFlagArgument ( argv, i, "-6", "--enableipv6" ) ) + if ( GetFlagArgument ( argv, i, "--noipv6", "--noipv6" ) ) { - bEnableIPv6 = true; - qInfo() << "- IPv6 enabled"; - CommandLineOptions << "--enableipv6"; + bDisableIPv6 = true; + qInfo() << "- IPv6 disabled"; + CommandLineOptions << "--noipv6"; continue; } @@ -935,7 +935,8 @@ int main ( int argc, char** argv ) #ifndef SERVER_ONLY if ( bIsClient ) { - CClient Client ( iPortNumber, iQosNumber, strConnOnStartupAddress, bNoAutoJackConnect, strClientName, bEnableIPv6, bMuteMeInPersonalMix ); + CClient + Client ( iPortNumber, iQosNumber, strConnOnStartupAddress, bNoAutoJackConnect, strClientName, bDisableIPv6, bMuteMeInPersonalMix ); // Create Settings with the client pointer CClientSettings Settings ( &Client, strIniFileName ); @@ -960,14 +961,8 @@ int main ( int argc, char** argv ) } // GUI object - CClientDlg ClientDlg ( &Client, - &Settings, - strConnOnStartupAddress, - bShowComplRegConnList, - bShowAnalyzerConsole, - bMuteStream, - bEnableIPv6, - nullptr ); + CClientDlg + ClientDlg ( &Client, &Settings, strConnOnStartupAddress, bShowComplRegConnList, bShowAnalyzerConsole, bMuteStream, nullptr ); // show dialog ClientDlg.show(); @@ -1007,7 +1002,7 @@ int main ( int argc, char** argv ) bUseMultithreading, bDisableRecording, bDelayPan, - bEnableIPv6, + bDisableIPv6, eLicenceType ); #ifndef NO_JSON_RPC @@ -1109,7 +1104,7 @@ QString UsageArguments ( char** argv ) " -Q, --qos set the QoS value. Default is 128. Disable with 0\n" " (see the Jamulus website to enable QoS on Windows)\n" " -t, --notranslation disable translation (use English language)\n" - " -6, --enableipv6 enable IPv6 addressing (IPv4 is always enabled)\n" + " --noipv6 disable IPv6 addressing (IPv4 is always enabled)\n" "\n" "Server only:\n" " -d, --discononquit disconnect all Clients on quit\n" diff --git a/src/server.cpp b/src/server.cpp index d6cd2bf0cc..b9383a7833 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -44,33 +44,33 @@ CServer::CServer ( const int iNewMaxNumChan, const bool bNUseMultithreading, const bool bDisableRecording, const bool bNDelayPan, - const bool bNEnableIPv6, + const bool bNDisableIPv6, const ELicenceType eNLicenceType ) : bUseDoubleSystemFrameSize ( bNUseDoubleSystemFrameSize ), bUseMultithreading ( bNUseMultithreading ), iMaxNumChannels ( iNewMaxNumChan ), iCurNumChannels ( 0 ), bDisableRaw ( bNDisableRaw ), - Socket ( this, iPortNumber, iQosNumber, strServerBindIP, bNEnableIPv6 ), + bIPv6Available ( false ), + Socket ( this, iPortNumber, iQosNumber, strServerBindIP, bNDisableIPv6, bIPv6Available ), Logging(), iFrameCount ( 0 ), bWriteStatusHTMLFile ( false ), strServerHTMLFileListName ( strHTMLStatusFileName ), HighPrecisionTimer ( bNUseDoubleSystemFrameSize ), - ServerListManager ( iPortNumber, + ServerListManager ( this, + iPortNumber, strDirectoryAddress, strServerListFileName, strServerInfo, strServerPublicIP, strServerListFilter, iNewMaxNumChan, - bNEnableIPv6, &ConnLessProtocol ), JamController ( this ), bDisableRecording ( bDisableRecording ), bAutoRunMinimized ( false ), bDelayPan ( bNDelayPan ), - bEnableIPv6 ( bNEnableIPv6 ), eLicenceType ( eNLicenceType ), bDisconnectAllClientsOnQuit ( bNDisconnectAllClientsOnQuit ), pSignalHandler ( CSignalHandler::getSingletonP() ) diff --git a/src/server.h b/src/server.h index 6a42a8f9b8..5f2ea64ffd 100644 --- a/src/server.h +++ b/src/server.h @@ -104,7 +104,7 @@ class CServer : public QObject, public CServerSlots const bool bNUseMultithreading, const bool bDisableRecording, const bool bNDelayPan, - const bool bNEnableIPv6, + const bool bNDisableIPv6, const ELicenceType eNLicenceType ); virtual ~CServer(); @@ -125,8 +125,8 @@ class CServer : public QObject, public CServerSlots void CreateCLServerListReqVerAndOSMes ( const CHostAddress& InetAddr ) { ConnLessProtocol.CreateCLReqVersionAndOSMes ( InetAddr ); } - // IPv6 Enabled - bool IsIPv6Enabled() { return bEnableIPv6; } + // IPv6 Available + bool IsIPv6Available() { return bIPv6Available; } // GUI settings ------------------------------------------------------------ int GetClientNumAudioChannels ( const int iChanNum ) { return vecChannels[iChanNum].GetNumAudioChannels(); } @@ -273,6 +273,7 @@ class CServer : public QObject, public CServerSlots CVector vecChannelLevels; // actual working objects + bool bIPv6Available; // must be before Socket - passed by reference to Socket CHighPrioSocket Socket; // logging @@ -300,9 +301,6 @@ class CServer : public QObject, public CServerSlots // for delay panning bool bDelayPan; - // enable IPv6 - bool bEnableIPv6; - // messaging QString strWelcomeMessage; ELicenceType eLicenceType; diff --git a/src/serverdlg.cpp b/src/serverdlg.cpp index 8367600bf5..adf1d027fb 100644 --- a/src/serverdlg.cpp +++ b/src/serverdlg.cpp @@ -484,12 +484,12 @@ CServerDlg::CServerDlg ( CServer* pNServP, CServerSettings* pNSetP, const bool b // Don't use SRV resolution when resolving update servers. - if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK1_ADDRESS, UpdateServerHostAddress, pServer->IsIPv6Enabled() ) ) + if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK1_ADDRESS, UpdateServerHostAddress, pServer->IsIPv6Available() ) ) { pServer->CreateCLServerListReqVerAndOSMes ( UpdateServerHostAddress ); } - if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK2_ADDRESS, UpdateServerHostAddress, pServer->IsIPv6Enabled() ) ) + if ( NetworkUtil::ParseNetworkAddressBare ( UPDATECHECK2_ADDRESS, UpdateServerHostAddress, pServer->IsIPv6Available() ) ) { pServer->CreateCLServerListReqVerAndOSMes ( UpdateServerHostAddress ); } diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 4dabe4c7ef..4c2f6589dd 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -62,10 +62,10 @@ CServerListEntry CServerListEntry::parse ( QString strHAddr, QString strCountry, QString strNumClients, bool isPermanent, - bool bEnableIPv6 ) + bool bIPv6Available ) { CHostAddress haServerHostAddr; - NetworkUtil::ParseNetworkAddress ( strHAddr, haServerHostAddr, bEnableIPv6 ); + NetworkUtil::ParseNetworkAddress ( strHAddr, haServerHostAddr, bIPv6Available ); if ( CHostAddress() == haServerHostAddr ) { // do not proceed without server host address! @@ -73,7 +73,7 @@ CServerListEntry CServerListEntry::parse ( QString strHAddr, } CHostAddress haServerLocalAddr; - NetworkUtil::ParseNetworkAddress ( strLHAddr, haServerLocalAddr, bEnableIPv6 ); + NetworkUtil::ParseNetworkAddress ( strLHAddr, haServerLocalAddr, bIPv6Available ); if ( haServerLocalAddr.iPort == 0 ) { haServerLocalAddr.iPort = haServerHostAddr.iPort; @@ -120,17 +120,17 @@ QString CServerListEntry::toCSV() } // --- CServerListManager --- -CServerListManager::CServerListManager ( const quint16 iNPortNum, +CServerListManager::CServerListManager ( CServer* pServer, + const quint16 iNPortNum, const QString& sNDirectoryAddress, const QString& strServerListFileName, const QString& strServerInfo, const QString& strServerListFilter, const QString& strServerPublicIP, const int iNumChannels, - const bool bNEnableIPv6, CProtocol* pNConLProt ) : + pServer ( pServer ), DirectoryType ( AT_NONE ), - bEnableIPv6 ( bNEnableIPv6 ), ServerListFileName ( strServerListFileName ), strDirectoryAddress ( "" ), bIsDirectory ( false ), @@ -158,7 +158,7 @@ CServerListManager::CServerListManager ( const quint16 iNPortNum, qDebug() << "Using" << qhaServerPublicIP.toString() << "as external IP."; ServerPublicIP = CHostAddress ( qhaServerPublicIP, iNPortNum ); - if ( bEnableIPv6 ) + if ( pServer->IsIPv6Available() ) { // set the server internal address, including internal port number QHostAddress qhaServerPublicIP6; @@ -807,7 +807,7 @@ bool CServerListManager::Load() // This uses ParseNetworkAddressBare because it is just parsing ip:host that was saved to the file. // Therefore no SRV lookup is appropriate. - NetworkUtil::ParseNetworkAddressBare ( slLine[0], haServerHostAddr, bEnableIPv6 ); + NetworkUtil::ParseNetworkAddressBare ( slLine[0], haServerHostAddr, pServer->IsIPv6Available() ); int iIdx = IndexOf ( haServerHostAddr ); if ( iIdx != INVALID_INDEX ) { @@ -815,8 +815,14 @@ bool CServerListManager::Load() continue; } - serverListEntry = - CServerListEntry::parse ( slLine[0], slLine[1], slLine[2], slLine[3], slLine[4], slLine[5], slLine[6].toInt() != 0, bEnableIPv6 ); + serverListEntry = CServerListEntry::parse ( slLine[0], + slLine[1], + slLine[2], + slLine[3], + slLine[4], + slLine[5], + slLine[6].toInt() != 0, + pServer->IsIPv6Available() ); // We expect servers to have addresses... if ( ( CHostAddress() == serverListEntry.HostAddr ) ) diff --git a/src/serverlist.h b/src/serverlist.h index cdf1d0f7e6..bcc3102dee 100644 --- a/src/serverlist.h +++ b/src/serverlist.h @@ -75,6 +75,9 @@ Note: this mechanism will not work in a private network. #include "util.h" #include "protocol.h" +// Forward declaration - see end of this file for the actual #include +class CServer; + /* Classes ********************************************************************/ class CServerListEntry : public CServerInfo { @@ -133,14 +136,14 @@ class CServerListManager : public QObject Q_OBJECT public: - CServerListManager ( const quint16 iNPortNum, + CServerListManager ( CServer* pServer, + const quint16 iNPortNum, const QString& sNDirectoryAddress, const QString& strServerListFileName, const QString& strServerInfo, const QString& strServerListFilter, const QString& strServerPublicIP, const int iNumChannels, - const bool bNEnableIPv6, CProtocol* pNConLProt ); void SetServerName ( const QString& strNewName ); @@ -188,11 +191,11 @@ class CServerListManager : public QObject QMutex Mutex; + CServer* pServer; + CHostAddress DirectoryAddress; EDirectoryType DirectoryType; - bool bEnableIPv6; - CHostAddress ServerPublicIP; CHostAddress ServerPublicIP6; @@ -234,3 +237,5 @@ public slots: signals: void SvrRegStatusChanged(); }; + +#include "server.h" diff --git a/src/socket.cpp b/src/socket.cpp index 78885226fc..664bb49fb5 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -40,13 +40,18 @@ // we have different connections for client and server, created after Init in corresponding constructor -CSocket::CSocket ( CChannel* pNewChannel, const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP, bool bEnableIPv6 ) : +CSocket::CSocket ( CChannel* pNewChannel, + const quint16 iPortNumber, + const quint16 iQosNumber, + const QString& strServerBindIP, + const bool bDisableIPv6, + bool& bIPv6Available ) : pChannel ( pNewChannel ), bIsClient ( true ), bJitterBufferOK ( true ), - bEnableIPv6 ( bEnableIPv6 ) + bIPv6Available ( bIPv6Available ) { - Init ( iPortNumber, iQosNumber, strServerBindIP ); + Init ( iPortNumber, iQosNumber, strServerBindIP, bDisableIPv6 ); // client connections: QObject::connect ( this, &CSocket::ProtocolMessageReceived, pChannel, &CChannel::OnProtocolMessageReceived ); @@ -56,13 +61,18 @@ CSocket::CSocket ( CChannel* pNewChannel, const quint16 iPortNumber, const quint QObject::connect ( this, static_cast ( &CSocket::NewConnection ), pChannel, &CChannel::OnNewConnection ); } -CSocket::CSocket ( CServer* pNServP, const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP, bool bEnableIPv6 ) : +CSocket::CSocket ( CServer* pNServP, + const quint16 iPortNumber, + const quint16 iQosNumber, + const QString& strServerBindIP, + const bool bDisableIPv6, + bool& bIPv6Available ) : pServer ( pNServP ), bIsClient ( false ), bJitterBufferOK ( true ), - bEnableIPv6 ( bEnableIPv6 ) + bIPv6Available ( bIPv6Available ) { - Init ( iPortNumber, iQosNumber, strServerBindIP ); + Init ( iPortNumber, iQosNumber, strServerBindIP, bDisableIPv6 ); // server connections: QObject::connect ( this, &CSocket::ProtocolMessageReceived, pServer, &CServer::OnProtocolMessageReceived ); @@ -77,7 +87,7 @@ CSocket::CSocket ( CServer* pNServP, const quint16 iPortNumber, const quint16 iQ QObject::connect ( this, &CSocket::ServerFull, pServer, &CServer::OnServerFull ); } -void CSocket::Init ( const quint16 iNewPortNumber, const quint16 iNewQosNumber, const QString& strNewServerBindIP ) +void CSocket::Init ( const quint16 iNewPortNumber, const quint16 iNewQosNumber, const QString& strNewServerBindIP, const bool bDisableIPv6 ) { uSockAddr UdpSocketAddr; @@ -102,57 +112,60 @@ void CSocket::Init ( const quint16 iNewPortNumber, const quint16 iNewQosNumber, memset ( &UdpSocketAddr, 0, sizeof ( UdpSocketAddr ) ); - if ( bEnableIPv6 ) + if ( !bDisableIPv6 ) { // try to create a IPv6 UDP socket UdpSocket = socket ( AF_INET6, SOCK_DGRAM, 0 ); - if ( UdpSocket == -1 ) + if ( UdpSocket != -1 ) { - // IPv6 requested but not available, throw error - throw CGenErr ( "IPv6 requested but not available on this system.", "Network Error" ); - } - // The IPV6_V6ONLY socket option must be false in order for the socket to listen on both protocols. - // On Linux it's false by default on most (all?) distros, but on Windows it is true by default - const int no = 0; - if ( setsockopt ( UdpSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &no, sizeof ( no ) ) == -1 ) - { - throw CGenErr ( "request to support IPv4 over IPv6 failed", "Network Error" ); - } + // The IPV6_V6ONLY socket option must be false in order for the socket to listen on both protocols. + // On Linux it's false by default on most (all?) distros, but on Windows it is true by default + const int no = 0; + if ( setsockopt ( UdpSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &no, sizeof ( no ) ) == -1 ) + { + throw CGenErr ( "request to support IPv4 over IPv6 failed", "Network Error" ); + } - // set the QoS - const int tos = (int) iQosNumber; // Quality of Service + // set the QoS + const int tos = (int) iQosNumber; // Quality of Service #if !defined( Q_OS_WIN ) - if ( setsockopt ( UdpSocket, IPPROTO_IPV6, IPV6_TCLASS, (const char*) &tos, sizeof ( tos ) ) == -1 ) - { - throw CGenErr ( "request to set ToS for IPv6 failed", "Network Error" ); - } + if ( setsockopt ( UdpSocket, IPPROTO_IPV6, IPV6_TCLASS, (const char*) &tos, sizeof ( tos ) ) == -1 ) + { + throw CGenErr ( "request to set ToS for IPv6 failed", "Network Error" ); + } #endif #if !defined( Q_OS_BSD4 ) && !defined( Q_OS_WIN ) - // set the QoS for IPv4 as well, as this is a dual-protocol socket - if ( setsockopt ( UdpSocket, IPPROTO_IP, IP_TOS, (const char*) &tos, sizeof ( tos ) ) == -1 ) - { - throw CGenErr ( "request to set ToS for IPv4 over IPv6 failed", "Network Error" ); - } + // set the QoS for IPv4 as well, as this is a dual-protocol socket + if ( setsockopt ( UdpSocket, IPPROTO_IP, IP_TOS, (const char*) &tos, sizeof ( tos ) ) == -1 ) + { + throw CGenErr ( "request to set ToS for IPv4 over IPv6 failed", "Network Error" ); + } #endif - UdpSocketAddr.sa6.sin6_family = AF_INET6; - UdpSocketAddr.sa6.sin6_addr = in6addr_any; - UdpSocketAddrLen = sizeof ( UdpSocketAddr.sa6 ); + UdpSocketAddr.sa6.sin6_family = AF_INET6; + UdpSocketAddr.sa6.sin6_addr = in6addr_any; + UdpSocketAddrLen = sizeof ( UdpSocketAddr.sa6 ); + + UdpPort = &UdpSocketAddr.sa6.sin6_port; // where to put the port number - UdpPort = &UdpSocketAddr.sa6.sin6_port; // where to put the port number + // FIXME: If binding a dual-protocol interface to a specific address, does it cease to be dual-protocol? - // FIXME: If binding a dual-protocol interface to a specific address, does it cease to be dual-protocol? + // TODO - ALLOW IPV6 ADDRESS + // if ( !strServerBindIP.isEmpty() ) + //{ + // UdpSocketInAddr.sin_addr.s_addr = htonl ( QHostAddress ( strServerBindIP ).toIPv4Address() ); + //} + // END TODO - ALLOW IPV6 ADDRESS - // TODO - ALLOW IPV6 ADDRESS - // if ( !strServerBindIP.isEmpty() ) - //{ - // UdpSocketInAddr.sin_addr.s_addr = htonl ( QHostAddress ( strServerBindIP ).toIPv4Address() ); - //} - // END TODO - ALLOW IPV6 ADDRESS + bIPv6Available = true; // this is a reference to CClient::bIPv6Available or CServer::bIPv6Available + + qInfo() << "IPv6 socket created"; + } } - else + + if ( !bIPv6Available ) { // create the UDP socket for IPv4 UdpSocket = socket ( AF_INET, SOCK_DGRAM, 0 ); @@ -182,6 +195,8 @@ void CSocket::Init ( const quint16 iNewPortNumber, const quint16 iNewQosNumber, { UdpSocketAddr.sa4.sin_addr.s_addr = htonl ( QHostAddress ( strServerBindIP ).toIPv4Address() ); } + + qInfo() << "IPv4 socket created"; } #ifdef Q_OS_IOS @@ -349,7 +364,7 @@ void CSocket::SendPacket ( const CVector& vecbySendBuf, const CHostAddr { if ( HostAddr.InetAddr.protocol() == QAbstractSocket::IPv4Protocol ) { - if ( bEnableIPv6 ) + if ( bIPv6Available ) { // Linux and Mac allow to pass an AF_INET address to a dual-stack socket, // but Windows does not. So use a V4MAPPED address in an AF_INET6 sockaddr, @@ -397,7 +412,7 @@ void CSocket::SendPacket ( const CVector& vecbySendBuf, const CHostAddr sizeof ( UdpSocketAddr.sa4 ) ); } } - else if ( bEnableIPv6 ) + else if ( bIPv6Available ) { UdpSocketAddr.sa6.sin6_family = AF_INET6; UdpSocketAddr.sa6.sin6_port = htons ( HostAddr.iPort ); diff --git a/src/socket.h b/src/socket.h index 77fdf24452..1385cea376 100644 --- a/src/socket.h +++ b/src/socket.h @@ -53,8 +53,19 @@ class CSocket : public QObject Q_OBJECT public: - CSocket ( CChannel* pNewChannel, const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP, bool bEnableIPv6 ); - CSocket ( CServer* pNServP, const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP, bool bEnableIPv6 ); + CSocket ( CChannel* pNewChannel, + const quint16 iPortNumber, + const quint16 iQosNumber, + const QString& strServerBindIP, + const bool bDisableIPv6, + bool& bIPv6Available ); + + CSocket ( CServer* pNServP, + const quint16 iPortNumber, + const quint16 iQosNumber, + const QString& strServerBindIP, + const bool bDisableIPv6, + bool& bIPv6Available ); virtual ~CSocket(); @@ -64,7 +75,7 @@ class CSocket : public QObject void Close(); protected: - void Init ( const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP ); + void Init ( const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP, const bool bDisableIPv6 ); quint16 iPortNumber; quint16 iQosNumber; QString strServerBindIP; @@ -86,7 +97,9 @@ class CSocket : public QObject bool bJitterBufferOK; - bool bEnableIPv6; + // This is a reference to CClient::bIPv6Available or CServer::bIPv6Available, + // to inform the Client or Server which type of socket was created at startup. + bool& bIPv6Available; public: void OnDataReceived(); @@ -116,20 +129,24 @@ class CHighPrioSocket : public QObject Q_OBJECT public: - CHighPrioSocket ( CChannel* pNewChannel, const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP, bool bEnableIPv6 ) : - Socket ( pNewChannel, iPortNumber, iQosNumber, strServerBindIP, bEnableIPv6 ) + CHighPrioSocket ( CChannel* pNewChannel, + const quint16 iPortNumber, + const quint16 iQosNumber, + const QString& strServerBindIP, + const bool bDisableIPv6, + bool& bIPv6Available ) : + Socket ( pNewChannel, iPortNumber, iQosNumber, strServerBindIP, bDisableIPv6, bIPv6Available ) { Init(); } - CHighPrioSocket ( CChannel* pNewChannel, const quint16 iPortNumber, const quint16 iQosNumber, bool bEnableIPv6 ) : - Socket ( pNewChannel, iPortNumber, iQosNumber, "", bEnableIPv6 ) - { - Init(); - } - - CHighPrioSocket ( CServer* pNewServer, const quint16 iPortNumber, const quint16 iQosNumber, const QString& strServerBindIP, bool bEnableIPv6 ) : - Socket ( pNewServer, iPortNumber, iQosNumber, strServerBindIP, bEnableIPv6 ) + CHighPrioSocket ( CServer* pNewServer, + const quint16 iPortNumber, + const quint16 iQosNumber, + const QString& strServerBindIP, + const bool bDisableIPv6, + bool& bIPv6Available ) : + Socket ( pNewServer, iPortNumber, iQosNumber, strServerBindIP, bDisableIPv6, bIPv6Available ) { Init(); } diff --git a/src/util.cpp b/src/util.cpp index b1221ae339..033ade448e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -725,7 +725,7 @@ QSize CMinimumStackedLayout::sizeHint() const * Other Classes * \******************************************************************************/ // Network utility functions --------------------------------------------------- -bool NetworkUtil::ParseNetworkAddressString ( QString strAddress, QHostAddress& InetAddr, bool bEnableIPv6 ) +bool NetworkUtil::ParseNetworkAddressString ( QString strAddress, QHostAddress& InetAddr, const bool bIPv6Available ) { // try to get host by name, assuming // that the string contains a valid host name string or IP address @@ -741,7 +741,7 @@ bool NetworkUtil::ParseNetworkAddressString ( QString strAddress, QHostAddress& { // qInfo() << qUtf8Printable ( QString ( "Resolved network address to %1 for proto %2" ) .arg ( HostAddr.toString() ) .arg ( // HostAddr.protocol() ) ); - if ( HostAddr.protocol() == QAbstractSocket::IPv4Protocol || ( bEnableIPv6 && HostAddr.protocol() == QAbstractSocket::IPv6Protocol ) ) + if ( HostAddr.protocol() == QAbstractSocket::IPv4Protocol || ( bIPv6Available && HostAddr.protocol() == QAbstractSocket::IPv6Protocol ) ) { InetAddr = HostAddr; return true; @@ -751,7 +751,7 @@ bool NetworkUtil::ParseNetworkAddressString ( QString strAddress, QHostAddress& } #ifndef DISABLE_SRV_DNS -bool NetworkUtil::ParseNetworkAddressSrv ( QString strAddress, CHostAddress& HostAddress, bool bEnableIPv6 ) +bool NetworkUtil::ParseNetworkAddressSrv ( QString strAddress, CHostAddress& HostAddress, const bool bIPv6Available ) { // init requested host address with invalid address first HostAddress = CHostAddress(); @@ -799,7 +799,7 @@ bool NetworkUtil::ParseNetworkAddressSrv ( QString strAddress, CHostAddress& Hos QString ( "resolved %1 to a single SRV record: %2:%3" ).arg ( strAddress ).arg ( record.target() ).arg ( record.port() ) ); QHostAddress InetAddr; - if ( ParseNetworkAddressString ( record.target(), InetAddr, bEnableIPv6 ) ) + if ( ParseNetworkAddressString ( record.target(), InetAddr, bIPv6Available ) ) { HostAddress = CHostAddress ( InetAddr, record.port() ); return true; @@ -808,20 +808,20 @@ bool NetworkUtil::ParseNetworkAddressSrv ( QString strAddress, CHostAddress& Hos } #endif -bool NetworkUtil::ParseNetworkAddress ( QString strAddress, CHostAddress& HostAddress, bool bEnableIPv6 ) +bool NetworkUtil::ParseNetworkAddress ( QString strAddress, CHostAddress& HostAddress, const bool bIPv6Available ) { #ifndef DISABLE_SRV_DNS // Try SRV-based discovery first: - if ( ParseNetworkAddressSrv ( strAddress, HostAddress, bEnableIPv6 ) ) + if ( ParseNetworkAddressSrv ( strAddress, HostAddress, bIPv6Available ) ) { return true; } #endif // Try regular connect via plain IP or host name lookup (A/AAAA): - return ParseNetworkAddressBare ( strAddress, HostAddress, bEnableIPv6 ); + return ParseNetworkAddressBare ( strAddress, HostAddress, bIPv6Available ); } -bool NetworkUtil::ParseNetworkAddressBare ( QString strAddress, CHostAddress& HostAddress, bool bEnableIPv6 ) +bool NetworkUtil::ParseNetworkAddressBare ( QString strAddress, CHostAddress& HostAddress, const bool bIPv6Available ) { QHostAddress InetAddr; unsigned int iNetPort = DEFAULT_PORT_NUMBER; @@ -886,7 +886,7 @@ bool NetworkUtil::ParseNetworkAddressBare ( QString strAddress, CHostAddress& Ho // first try if this is an IP number an can directly applied to QHostAddress if ( InetAddr.setAddress ( strAddress ) ) { - if ( !bEnableIPv6 && InetAddr.protocol() == QAbstractSocket::IPv6Protocol ) + if ( !bIPv6Available && InetAddr.protocol() == QAbstractSocket::IPv6Protocol ) { // do not allow IPv6 addresses if not enabled // qInfo() << qUtf8Printable ( QString ( "IPv6 addresses disabled" ) ); @@ -902,7 +902,7 @@ bool NetworkUtil::ParseNetworkAddressBare ( QString strAddress, CHostAddress& Ho return false; // invalid address } - if ( !ParseNetworkAddressString ( strAddress, InetAddr, bEnableIPv6 ) ) + if ( !ParseNetworkAddressString ( strAddress, InetAddr, bIPv6Available ) ) { // no valid address found // qInfo() << qUtf8Printable ( QString ( "No IP address found for hostname" ) ); diff --git a/src/util.h b/src/util.h index 04bf94b0e9..50bf86bfb4 100644 --- a/src/util.h +++ b/src/util.h @@ -1054,13 +1054,13 @@ class CNetworkTransportProps class NetworkUtil { public: - static bool ParseNetworkAddressString ( QString strAddress, QHostAddress& InetAddr, bool bEnableIPv6 ); + static bool ParseNetworkAddressString ( QString strAddress, QHostAddress& InetAddr, const bool bIPv6Available ); #ifndef DISABLE_SRV_DNS - static bool ParseNetworkAddressSrv ( QString strAddress, CHostAddress& HostAddress, bool bEnableIPv6 ); + static bool ParseNetworkAddressSrv ( QString strAddress, CHostAddress& HostAddress, const bool bIPv6Available ); #endif - static bool ParseNetworkAddress ( QString strAddress, CHostAddress& HostAddress, bool bEnableIPv6 ); - static bool ParseNetworkAddressBare ( QString strAddress, CHostAddress& HostAddress, bool bEnableIPv6 ); + static bool ParseNetworkAddress ( QString strAddress, CHostAddress& HostAddress, const bool bIPv6Available ); + static bool ParseNetworkAddressBare ( QString strAddress, CHostAddress& HostAddress, const bool bIPv6Available ); static QString FixAddress ( const QString& strAddress ); static CHostAddress GetLocalAddress();