1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-04-14 04:51:53 +02:00

Revamp proxy system. Use a factory, and allow for noproxy hosts. Don't try to set the proxies everywhere, set the application proxy factory and fall back to it. Except for specifically-threaded things.

This commit is contained in:
Jeff Mitchell 2011-05-25 17:37:27 -04:00
parent af0fe52cd1
commit 03f6b416b6
17 changed files with 252 additions and 89 deletions

View File

@ -182,7 +182,7 @@ InfoSystemWorker::newNam()
QNetworkAccessManager *oldNam = TomahawkUtils::nam();
if ( oldNam && oldNam->thread() == thread() )
{
qDebug() << Q_FUNC_INFO << " using old nam as it's the same thread as me";
qDebug() << Q_FUNC_INFO << " using old nam as it's the same thread (GUI) as me";
m_nam = QWeakPointer< QNetworkAccessManager >( oldNam );
emit namChanged( m_nam.data() );
return;
@ -199,17 +199,23 @@ InfoSystemWorker::newNam()
delete m_nam.data();
if ( !oldNam )
{
m_nam = QWeakPointer< QNetworkAccessManager >( newNam );
return;
}
oldNam = new QNetworkAccessManager();
TomahawkUtils::NetworkProxyFactory* oldProxyFactory = TomahawkUtils::proxyFactory();
if ( !oldProxyFactory )
oldProxyFactory = new TomahawkUtils::NetworkProxyFactory();
newNam->setConfiguration( oldNam->configuration() );
newNam->setNetworkAccessible( oldNam->networkAccessible() );
newNam->setProxy( oldNam->proxy() );
TomahawkUtils::NetworkProxyFactory* newProxyFactory = new TomahawkUtils::NetworkProxyFactory();
newProxyFactory->setNoProxyHosts( oldProxyFactory->noProxyHosts() );
newProxyFactory->setProxy( oldProxyFactory->proxy() );
newNam->setProxyFactory( newProxyFactory );
m_nam = QWeakPointer< QNetworkAccessManager >( newNam );
emit namChanged( m_nam.data() );
//FIXME: Currently leaking nam/proxyfactory above -- how to change in a thread-safe way?
}

View File

@ -389,7 +389,7 @@ SipHandler::connectPlugin( bool startup, const QString &pluginId )
if ( sip->pluginId() == pluginId )
{
Q_ASSERT( m_enabledPlugins.contains( sip ) ); // make sure the plugin we're connecting is enabled. should always be the case
sip->setProxy( m_proxy );
sip->refreshProxy();
sip->connectPlugin( startup );
}
}
@ -446,14 +446,12 @@ SipHandler::toggleConnect()
void
SipHandler::setProxy( const QNetworkProxy& proxy )
SipHandler::refreshProxy()
{
qDebug() << Q_FUNC_INFO;
m_proxy = proxy;
foreach( SipPlugin* sip, m_allPlugins )
sip->setProxy( proxy );
sip->refreshProxy();
}

View File

@ -68,7 +68,7 @@ public slots:
void toggleConnect();
void setProxy( const QNetworkProxy &proxy );
void refreshProxy();
// create a new plugin of the given name. the name is the value returned in SipPluginFactory::pluginName
// be default sip plugins are NOt connected when created
@ -121,7 +121,6 @@ private:
QList< SipPlugin* > m_enabledPlugins;
QList< SipPlugin* > m_connectedPlugins;
bool m_connected;
QNetworkProxy m_proxy;
//TODO: move this to source
QHash<QString, SipInfo> m_peersSipInfos;

View File

@ -77,9 +77,8 @@ SipPlugin::peersOnline() const
void
SipPlugin::setProxy( const QNetworkProxy& proxy )
SipPlugin::refreshProxy()
{
Q_UNUSED( proxy );
qDebug() << Q_FUNC_INFO << "Not implemented";
}

View File

@ -89,7 +89,7 @@ public slots:
virtual void addContact( const QString &jid, const QString& msg = QString() ) = 0;
virtual void sendMsg( const QString& to, const QString& msg ) = 0;
virtual void setProxy( const QNetworkProxy &proxy );
virtual void refreshProxy();
signals:
void error( int, const QString& );

View File

@ -228,6 +228,20 @@ TomahawkSettings::setProxyHost( const QString& host )
}
QString
TomahawkSettings::proxyNoProxyHosts() const
{
return value( "network/proxy/noproxyhosts", QString() ).toString();
}
void
TomahawkSettings::setProxyNoProxyHosts( const QString& hosts )
{
setValue( "network/proxy/noproxyhosts", hosts );
}
qulonglong
TomahawkSettings::proxyPort() const
{

View File

@ -106,7 +106,10 @@ public:
QString proxyHost() const;
void setProxyHost( const QString &host );
QString proxyNoProxyHosts() const;
void setProxyNoProxyHosts( const QString &hosts );
qulonglong proxyPort() const;
void setProxyPort( const qulonglong port );

View File

@ -340,7 +340,78 @@ createDragPixmap( int itemCount )
QWeakPointer< QNetworkAccessManager > s_nam;
QNetworkProxy* s_proxy = 0;
NetworkProxyFactory* s_proxyFactory = 0;
QList< QNetworkProxy >
NetworkProxyFactory::proxyForQuery( const QNetworkProxyQuery& query )
{
Q_UNUSED( query );
QList< QNetworkProxy > proxies;
proxies << QNetworkProxy( QNetworkProxy::NoProxy );
return proxies;
}
QList< QNetworkProxy >
NetworkProxyFactory::queryProxy( const QNetworkProxyQuery& query )
{
QList< QNetworkProxy > proxies;
QString hostname = query.peerHostName();
if ( hostname.isEmpty() || m_noProxyHosts.contains( hostname ) )
proxies << QNetworkProxy( QNetworkProxy::NoProxy );
else
proxies << m_proxy << QNetworkProxy( QNetworkProxy::NoProxy ) << QNetworkProxy( QNetworkProxy::DefaultProxy );
return proxies;
}
void
NetworkProxyFactory::setNoProxyHosts( const QStringList& hosts )
{
QStringList newList;
foreach( QString host, hosts )
{
QString munge = host.simplified();
newList << munge;
}
qDebug() << Q_FUNC_INFO << " No-proxy hosts: " << newList;
m_noProxyHosts = newList;
}
void
NetworkProxyFactory::setProxy( const QNetworkProxy& proxy )
{
m_proxy = proxy;
if ( !TomahawkSettings::instance()->proxyDns() )
m_proxy.setCapabilities( QNetworkProxy::TunnelingCapability | QNetworkProxy::ListeningCapability | QNetworkProxy::UdpTunnelingCapability );
qDebug() << Q_FUNC_INFO << " Proxy using host " << proxy.hostName() << " and port " << proxy.port();
qDebug() << Q_FUNC_INFO << " setting proxy to use proxy DNS?" << (TomahawkSettings::instance()->proxyDns() ? "true" : "false");
}
NetworkProxyFactory*
proxyFactory()
{
// Don't use this anywhere! It's provided here for access reasons, but QNAM deletes this at will!
if ( !s_proxyFactory )
s_proxyFactory = new NetworkProxyFactory();
return s_proxyFactory;
}
void
setProxyFactory( NetworkProxyFactory* factory )
{
Q_ASSERT( factory );
s_proxyFactory = factory;
NetworkProxyFactory::setApplicationProxyFactory( s_proxyFactory );
}
QNetworkAccessManager*
nam()
@ -352,28 +423,12 @@ nam()
}
QNetworkProxy*
proxy()
{
return s_proxy;
}
void
setNam( QNetworkAccessManager* nam )
{
Q_ASSERT( nam );
s_nam = QWeakPointer< QNetworkAccessManager >( nam );
}
void
setProxy( QNetworkProxy* proxy )
{
s_proxy = proxy;
s_nam.data()->setProxy( *proxy );
qDebug() << Q_FUNC_INFO << "setting proxy to use proxy DNS?" << (TomahawkSettings::instance()->proxyDns() ? "true" : "false");
if ( !TomahawkSettings::instance()->proxyDns() )
s_proxy->setCapabilities( QNetworkProxy::TunnelingCapability | QNetworkProxy::ListeningCapability | QNetworkProxy::UdpTunnelingCapability );
}
} // ns

View File

@ -22,6 +22,8 @@
#include "dllmacro.h"
#include <QObject>
#include <QThread>
#include <QNetworkProxy>
#include <QStringList>
#define RESPATH ":/data/"
@ -52,6 +54,25 @@ namespace TomahawkUtils
}
};
class DLLEXPORT NetworkProxyFactory : public QNetworkProxyFactory
{
public:
NetworkProxyFactory() {}
virtual ~NetworkProxyFactory() {}
virtual QList< QNetworkProxy > queryProxy( const QNetworkProxyQuery & query = QNetworkProxyQuery() );
static QList< QNetworkProxy > proxyForQuery( const QNetworkProxyQuery & query );
void setNoProxyHosts( const QStringList &hosts );
QStringList noProxyHosts() const { return m_noProxyHosts; }
void setProxy( const QNetworkProxy &proxy );
QNetworkProxy proxy() { return m_proxy; }
private:
QStringList m_noProxyHosts;
QNetworkProxy m_proxy;
};
DLLEXPORT QDir appConfigDir();
DLLEXPORT QDir appDataDir();
DLLEXPORT QDir appLogDir();
@ -64,11 +85,11 @@ namespace TomahawkUtils
DLLEXPORT QColor alphaBlend( const QColor& colorFrom, const QColor& colorTo, float opacity );
DLLEXPORT QPixmap createDragPixmap( int itemCount = 1 );
DLLEXPORT NetworkProxyFactory* proxyFactory();
DLLEXPORT QNetworkAccessManager* nam();
DLLEXPORT QNetworkProxy* proxy();
DLLEXPORT void setProxyFactory( TomahawkUtils::NetworkProxyFactory* factory );
DLLEXPORT void setNam( QNetworkAccessManager* nam );
DLLEXPORT void setProxy( QNetworkProxy* proxy );
}
#endif // TOMAHAWKUTILS_H

View File

@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>200</height>
<height>222</height>
</rect>
</property>
<property name="windowTitle">
@ -137,13 +137,27 @@
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>No Proxy Hosts:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="noHostLineEdit">
<property name="placeholderText">
<string>localhost, *.example.com</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="dnsLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QCheckBox" name="checkBoxUseProxyForDns">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>

View File

@ -627,23 +627,62 @@ ProxyDialog::ProxyDialog( QWidget *parent )
ui->setupUi( this );
// ugly, I know, but...
QHash<int,int> enumMap;
int i = 0;
ui->typeBox->insertItem( i, "No Proxy", QNetworkProxy::NoProxy );
enumMap[QNetworkProxy::NoProxy] = i++;
m_forwardMap[ QNetworkProxy::NoProxy ] = i;
m_backwardMap[ i ] = QNetworkProxy::NoProxy;
i++;
ui->typeBox->insertItem( i, "SOCKS 5", QNetworkProxy::Socks5Proxy );
enumMap[QNetworkProxy::Socks5Proxy] = i++;
m_forwardMap[ QNetworkProxy::Socks5Proxy ] = i;
m_backwardMap[ i ] = QNetworkProxy::Socks5Proxy;
i++;
TomahawkSettings* s = TomahawkSettings::instance();
ui->typeBox->setCurrentIndex( enumMap[s->proxyType()] );
ui->typeBox->setCurrentIndex( m_forwardMap[s->proxyType()] );
ui->hostLineEdit->setText( s->proxyHost() );
ui->portSpinBox->setValue( s->proxyPort() );
ui->userLineEdit->setText( s->proxyUsername() );
ui->passwordLineEdit->setText( s->proxyPassword() );
ui->checkBoxUseProxyForDns->setChecked( s->proxyDns() );
ui->noHostLineEdit->setText( s->proxyNoProxyHosts() );
if ( s->proxyType() == QNetworkProxy::NoProxy )
{
ui->hostLineEdit->setEnabled( false );
ui->portSpinBox->setEnabled( false );
ui->userLineEdit->setEnabled( false );
ui->passwordLineEdit->setEnabled( false );
ui->checkBoxUseProxyForDns->setEnabled( false );
ui->noHostLineEdit->setEnabled( false );
}
connect( ui->typeBox, SIGNAL( currentIndexChanged( int ) ), SLOT( proxyTypeChangedSlot( int ) ) );
}
void
ProxyDialog::proxyTypeChangedSlot( int index )
{
if ( m_backwardMap[ index ] == QNetworkProxy::NoProxy )
{
ui->hostLineEdit->setEnabled( false );
ui->portSpinBox->setEnabled( false );
ui->userLineEdit->setEnabled( false );
ui->passwordLineEdit->setEnabled( false );
ui->checkBoxUseProxyForDns->setEnabled( false );
ui->noHostLineEdit->setEnabled( false );
}
else
{
ui->hostLineEdit->setEnabled( true );
ui->portSpinBox->setEnabled( true );
ui->userLineEdit->setEnabled( true );
ui->passwordLineEdit->setEnabled( true );
ui->checkBoxUseProxyForDns->setEnabled( true );
ui->noHostLineEdit->setEnabled( true );
}
}
void
ProxyDialog::saveSettings()
@ -656,7 +695,7 @@ ProxyDialog::saveSettings()
int port = ui->portSpinBox->value();
s->setProxyPort( port );
s->setProxyNoProxyHosts( ui->noHostLineEdit->text() );
s->setProxyUsername( ui->userLineEdit->text() );
s->setProxyPassword( ui->passwordLineEdit->text() );
s->setProxyType( ui->typeBox->itemData( ui->typeBox->currentIndex() ).toInt() );
@ -665,16 +704,10 @@ ProxyDialog::saveSettings()
if( s->proxyHost().isEmpty() )
return;
// Now, set QNAM
QNetworkProxy proxy( static_cast<QNetworkProxy::ProxyType>(s->proxyType()), s->proxyHost(), s->proxyPort(), s->proxyUsername(), s->proxyPassword() );
Q_ASSERT( TomahawkUtils::nam() != 0 );
QNetworkAccessManager* nam = TomahawkUtils::nam();
nam->setProxy( proxy );
QNetworkProxy* globalProxy = TomahawkUtils::proxy();
QNetworkProxy* oldProxy = globalProxy;
globalProxy = new QNetworkProxy( proxy );
if( oldProxy )
delete oldProxy;
QNetworkProxy::setApplicationProxy( proxy );
TomahawkUtils::NetworkProxyFactory* proxyFactory = new TomahawkUtils::NetworkProxyFactory();
QNetworkProxy proxy( static_cast<QNetworkProxy::ProxyType>(s->proxyType()), s->proxyHost(), s->proxyPort(), s->proxyUsername(), s->proxyPassword() );
proxyFactory->setProxy( proxy );
if ( !ui->noHostLineEdit->text().isEmpty() )
proxyFactory->setNoProxyHosts( ui->noHostLineEdit->text().split( ',', QString::SkipEmptyParts ) );
TomahawkUtils::setProxyFactory( proxyFactory );
}

View File

@ -46,8 +46,13 @@ public:
void saveSettings();
private slots:
void proxyTypeChangedSlot( int index );
private:
Ui::ProxyDialog* ui;
QHash<int,int> m_forwardMap;
QHash<int,int> m_backwardMap;
};
class SettingsDialog : public QDialog

View File

@ -46,6 +46,7 @@
#include <QMessageBox>
#include <QDateTime>
#include <QTimer>
#include <utils/tomahawkutils.h>
SipPlugin*
JabberFactory::createPlugin( const QString& pluginId )
@ -150,11 +151,19 @@ JabberPlugin::~JabberPlugin()
}
void
JabberPlugin::setProxy( const QNetworkProxy &proxy )
JabberPlugin::refreshProxy()
{
qDebug() << Q_FUNC_INFO;
if( ( proxy.type() != QNetworkProxy::NoProxy ) && ( m_currentServer.isEmpty() || !(m_currentPort > 0) ) )
if(!m_client->connection())
{
m_client->setConnection(new Jreen::TcpConnection(m_currentServer, m_currentPort));
}
QNetworkProxy proxyToUse = TomahawkUtils::proxyFactory()->queryProxy( QNetworkProxyQuery( m_currentServer, m_currentPort ) ).first();
m_usedProxy = proxyToUse;
if( proxyToUse.type() != QNetworkProxy::NoProxy && ( m_currentServer.isEmpty() || !(m_currentPort > 0) ) )
{
// patches are welcome in Jreen that implement jdns through proxy
emit error( SipPlugin::ConnectionError,
@ -162,12 +171,7 @@ JabberPlugin::setProxy( const QNetworkProxy &proxy )
return;
}
if(!m_client->connection())
{
m_client->setConnection(new Jreen::TcpConnection(m_currentServer, m_currentPort));
}
qobject_cast<Jreen::DirectConnection*>(m_client->connection())->setProxy(proxy);
qobject_cast<Jreen::DirectConnection*>( m_client->connection() )->setProxy( proxyToUse );
}
@ -221,10 +225,12 @@ JabberPlugin::connectPlugin( bool startup )
qDebug() << "Connecting to the XMPP server..." << m_client->jid().full();
refreshProxy();
//FIXME: we're badly workarounding some missing reconnection api here, to be fixed soon
QTimer::singleShot( 1000, m_client, SLOT( connectToServer() ) );
connect(m_client->connection(), SIGNAL(error(Jreen::Connection::SocketError)), SLOT(onError(Jreen::Connection::SocketError)));
connect(m_client->connection(), SIGNAL(error(SocketError)), SLOT(onError(SocketError)));
m_state = Connecting;
emit stateChanged( m_state );
@ -499,6 +505,18 @@ JabberPlugin::checkSettings()
if ( m_currentPort != readPort() )
reconnect = true;
QNetworkProxy proxyToUse = TomahawkUtils::proxyFactory()->queryProxy( QNetworkProxyQuery( m_currentServer, m_currentPort ) ).first();
if ( proxyToUse.hostName() != m_usedProxy.hostName() ||
proxyToUse.port() != m_usedProxy.port() ||
proxyToUse.user() != m_usedProxy.user() ||
proxyToUse.password() != m_usedProxy.password() ||
proxyToUse.type() != m_usedProxy.type() ||
proxyToUse.capabilities() != m_usedProxy.capabilities() )
{
m_usedProxy = proxyToUse;
reconnect = true;
}
m_currentUsername = accountName();
m_currentPassword = readPassword();
m_currentServer = readServer();

View File

@ -93,7 +93,7 @@ public slots:
void sendMsg( const QString& to, const QString& msg );
void broadcastMsg( const QString &msg );
void addContact( const QString &jid, const QString& msg = QString() );
void setProxy( const QNetworkProxy &proxy );
void refreshProxy();
protected:
Ui_JabberConfig* m_ui; // so the google wrapper can change the config dialog a bit
@ -152,6 +152,8 @@ private:
enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent, RequestedVCard, RequestVersion, RequestedVersion };
QStringList m_legacy_peers;
AvatarManager *m_avatarManager;
QNetworkProxy m_usedProxy;
};
#endif

View File

@ -746,9 +746,8 @@ TwitterPlugin::avatarUserDataSlot( const QTweetUser &user )
}
void
TwitterPlugin::setProxy( const QNetworkProxy& proxy )
TwitterPlugin::refreshProxy()
{
Q_UNUSED( proxy );
if ( !m_twitterAuth.isNull() )
m_twitterAuth.data()->setNetworkAccessManager( TomahawkUtils::nam() );
}

View File

@ -79,7 +79,7 @@ public slots:
virtual bool connectPlugin( bool startup );
void disconnectPlugin();
void checkSettings();
void setProxy( const QNetworkProxy &proxy );
void refreshProxy();
void sendMsg( const QString& to, const QString& msg )
{

View File

@ -182,7 +182,20 @@ TomahawkApp::init()
registerMetaTypes();
new TomahawkSettings( this );
TomahawkSettings* s = TomahawkSettings::instance();
TomahawkUtils::NetworkProxyFactory* proxyFactory = new TomahawkUtils::NetworkProxyFactory();
if( s->proxyType() != QNetworkProxy::NoProxy &&
!s->proxyHost().isEmpty() )
{
qDebug() << "Setting proxy to saved values";
QNetworkProxy proxy( static_cast<QNetworkProxy::ProxyType>( s->proxyType() ), s->proxyHost(), s->proxyPort(), s->proxyUsername(), s->proxyPassword() );
proxyFactory->setProxy( proxy );
}
proxyFactory->setNoProxyHosts( s->proxyNoProxyHosts().split( ',', QString::SkipEmptyParts ) );
TomahawkUtils::NetworkProxyFactory::setApplicationProxyFactory( proxyFactory );
#ifdef LIBLASTFM_FOUND
qDebug() << "Setting NAM.";
TomahawkUtils::setNam( lastfm::nam() );
@ -191,20 +204,6 @@ TomahawkApp::init()
TomahawkUtils::setNam( new QNetworkAccessManager() );
#endif
// Set up proxy
//FIXME: This overrides the lastfm proxy above?
if( TomahawkSettings::instance()->proxyType() != QNetworkProxy::NoProxy &&
!TomahawkSettings::instance()->proxyHost().isEmpty() )
{
qDebug() << "Setting proxy to saved values";
TomahawkUtils::setProxy( new QNetworkProxy( static_cast<QNetworkProxy::ProxyType>(TomahawkSettings::instance()->proxyType()), TomahawkSettings::instance()->proxyHost(), TomahawkSettings::instance()->proxyPort(), TomahawkSettings::instance()->proxyUsername(), TomahawkSettings::instance()->proxyPassword() ) );
qDebug() << "Proxy type =" << QString::number( static_cast<int>(TomahawkUtils::proxy()->type()) );
qDebug() << "Proxy host =" << TomahawkUtils::proxy()->hostName();
TomahawkUtils::nam()->setProxy( *TomahawkUtils::proxy() );
}
else
TomahawkUtils::setProxy( new QNetworkProxy( QNetworkProxy::NoProxy ) );
Echonest::Config::instance()->setAPIKey( "JRIHWEP6GPOER2QQ6" );
m_audioEngine = new AudioEngine;
@ -265,8 +264,6 @@ TomahawkApp::init()
Echonest::Config::instance()->setAPIKey( "JRIHWEP6GPOER2QQ6" );
Echonest::Config::instance()->setNetworkAccessManager( TomahawkUtils::nam() );
QNetworkProxy::setApplicationProxy( *TomahawkUtils::proxy() );
qDebug() << "Init SIP system.";
#ifndef TOMAHAWK_HEADLESS
@ -293,7 +290,7 @@ TomahawkApp::init()
}
#ifndef TOMAHAWK_HEADLESS
if ( !TomahawkSettings::instance()->hasScannerPaths() )
if ( !s->hasScannerPaths() )
{
m_mainwindow->showSettingsDialog();
}
@ -538,7 +535,7 @@ TomahawkApp::setupSIP()
#endif
qDebug() << "Connecting SIP classes";
SipHandler::instance()->setProxy( *TomahawkUtils::proxy() );
SipHandler::instance()->refreshProxy();
SipHandler::instance()->loadFromConfig( true );
}
}