1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-04-13 12:31:52 +02:00

* Port-Forwards are now being setuped in a separate thread to avoid blocking the GUI.

This commit is contained in:
Christian Muehlhaeuser 2011-01-13 17:23:52 +01:00
parent b95d8a6b93
commit e828972b95
7 changed files with 170 additions and 81 deletions

View File

@ -77,13 +77,15 @@ public:
signals:
void settingsChanged();
private slots:
void setupSIP();
private:
void initLocalCollection();
void loadPlugins();
void registerMetaTypes();
void startServent();
void setupDatabase();
void setupSIP();
void setupPipeline();
void startHTTP();

View File

@ -29,6 +29,7 @@ set( libSources
network/filetransferconnection.cpp
network/dbsyncconnection.cpp
network/remotecollection.cpp
network/portfwdthread.cpp
database/fuzzyindex.cpp
database/databaseworker.cpp
@ -122,6 +123,7 @@ set( libHeaders
network/servent.h
network/connection.h
network/controlconnection.h
network/portfwdthread.h
)
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..

View File

@ -0,0 +1,89 @@
#include "portfwdthread.h"
#include <QApplication>
#include <QDebug>
#include <QStringList>
#include <QTime>
#include <QTimer>
#include "portfwd/portfwd.h"
PortFwdThread::PortFwdThread( unsigned int port )
: QThread()
, m_externalPort( 0 )
, m_port( port )
{
moveToThread( this );
start();
}
PortFwdThread::~PortFwdThread()
{
qDebug() << Q_FUNC_INFO << "waiting for event loop to finish...";
quit();
wait( 2500 );
delete m_portfwd;
}
void
PortFwdThread::work()
{
qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );
m_portfwd = new Portfwd();
// try and pick an available port:
if( m_portfwd->init( 2000 ) )
{
int tryport = m_port;
// last.fm office firewall policy hack
// (corp. firewall allows outgoing connections to this port,
// so listen on this if you want lastfmers to connect to you)
if( qApp->arguments().contains( "--porthack" ) )
{
tryport = 3389;
m_portfwd->remove( tryport );
}
for( int r = 0; r < 5; ++r )
{
qDebug() << "Trying to setup portfwd on" << tryport;
if( m_portfwd->add( tryport, m_port ) )
{
QString pubip = QString( m_portfwd->external_ip().c_str() );
m_externalAddress = QHostAddress( pubip );
m_externalPort = tryport;
qDebug() << "External servent address detected as" << pubip << ":" << m_externalPort;
qDebug() << "Max upstream " << m_portfwd->max_upstream_bps() << "bps";
qDebug() << "Max downstream" << m_portfwd->max_downstream_bps() << "bps";
break;
}
tryport = qAbs( 10000 + 50000 * (float)qrand() / RAND_MAX );
}
}
else
qDebug() << "No UPNP Gateway device found?";
if( !m_externalPort )
qDebug() << "Could not setup fwd for port:" << m_port;
emit externalAddressDetected( m_externalAddress, m_externalPort );
}
void
PortFwdThread::run()
{
QTimer::singleShot( 0, this, SLOT( work() ) );
exec();
if ( m_externalPort )
{
qDebug() << "Unregistering port fwd";
m_portfwd->remove( m_externalPort );
}
}

View File

@ -0,0 +1,32 @@
#ifndef PORTFWDTHREAD_H
#define PORTFWDTHREAD_H
#include <QThread>
#include <QMutex>
#include <QHostAddress>
class Portfwd;
class PortFwdThread : public QThread
{
Q_OBJECT
public:
explicit PortFwdThread( unsigned int port );
~PortFwdThread();
signals:
void externalAddressDetected( QHostAddress ha, unsigned int port );
private slots:
void work();
private:
void run();
Portfwd* m_portfwd;
QHostAddress m_externalAddress;
unsigned int m_externalPort, m_port;
};
#endif // PORTFWDTHREAD_H

View File

@ -4,7 +4,6 @@
#include <QMutexLocker>
#include <QNetworkInterface>
#include <QFile>
#include <QTime>
#include <QThread>
#include <QNetworkRequest>
#include <QNetworkReply>
@ -18,7 +17,7 @@
#include "filetransferconnection.h"
#include "sourcelist.h"
#include "portfwd/portfwd.h"
#include "portfwdthread.h"
using namespace Tomahawk;
@ -36,12 +35,9 @@ Servent::Servent( QObject* parent )
: QTcpServer( parent )
, m_port( 0 )
, m_externalPort( 0 )
, pf( new Portfwd() )
{
s_instance = this;
qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );
{
boost::function<QSharedPointer<QIODevice>(result_ptr)> fac =
boost::bind( &Servent::localFileIODeviceFactory, this, _1 );
@ -64,11 +60,7 @@ Servent::Servent( QObject* parent )
Servent::~Servent()
{
if( m_externalPort )
{
qDebug() << "Unregistering port fwd";
pf->remove( m_externalPort );
}
delete m_portfwd;
}
@ -88,52 +80,6 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
qDebug() << "Servent listening on port" << m_port << " servent thread:" << thread();
}
// TODO check if we have a public/internet IP on this machine directly
// FIXME the portfwd stuff is blocking, so we hang here for 2 secs atm
if( upnp )
{
// try and pick an available port:
if( pf->init( 2000 ) )
{
int tryport = m_port;
// last.fm office firewall policy hack
// (corp. firewall allows outgoing connections to this port,
// so listen on this if you want lastfmers to connect to you)
if( qApp->arguments().contains( "--porthack" ) )
{
tryport = 3389;
pf->remove( tryport );
}
for( int r=0; r<5; ++r )
{
qDebug() << "Trying to setup portfwd on" << tryport;
if( pf->add( tryport, m_port ) )
{
QString pubip = QString( pf->external_ip().c_str() );
m_externalAddress = QHostAddress( pubip );
m_externalPort = tryport;
qDebug() << "External servent address detected as" << pubip << ":" << m_externalPort;
qDebug() << "Max upstream " << pf->max_upstream_bps() << "bps";
qDebug() << "Max downstream" << pf->max_downstream_bps() << "bps";
break;
}
tryport = 10000 + 50000 * (float)qrand()/RAND_MAX;
}
if( !m_externalPort )
{
qDebug() << "Could not setup fwd for port:" << m_port;
}
}
else qDebug() << "No UPNP Gateway device found?";
}
if( m_externalPort == 0 )
{
qDebug() << "No external access, LAN and outbound connections only!";
}
// --lanhack means to advertise your LAN IP over jabber as if it were externallyVisible
if( qApp->arguments().contains( "--lanhack" ) )
{
@ -149,6 +95,13 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
break;
}
}
else if( upnp )
{
// TODO check if we have a public/internet IP on this machine directly
m_portfwd = new PortFwdThread( m_port );
connect( m_portfwd, SIGNAL( externalAddressDetected( QHostAddress, unsigned int ) ),
SLOT( setExternalAddress( QHostAddress, unsigned int ) ) );
}
return true;
}
@ -160,7 +113,7 @@ Servent::createConnectionKey( const QString& name )
Q_ASSERT( this->thread() == QThread::currentThread() );
QString key = uuid();
ControlConnection * cc = new ControlConnection( this );
ControlConnection* cc = new ControlConnection( this );
cc->setName( name.isEmpty() ? QString( "KEY(%1)" ).arg( key ) : name );
registerOffer( key, cc );
return key;
@ -168,10 +121,17 @@ Servent::createConnectionKey( const QString& name )
void
Servent::setExternalAddress( QHostAddress ha, int port )
Servent::setExternalAddress( QHostAddress ha, unsigned int port )
{
m_externalAddress = ha;
m_externalPort = port;
if( m_externalPort == 0 )
{
qDebug() << "No external access, LAN and outbound connections only!";
}
emit ready();
}
@ -217,8 +177,10 @@ void
Servent::incomingConnection( int sd )
{
Q_ASSERT( this->thread() == QThread::currentThread() );
QTcpSocketExtra* sock = new QTcpSocketExtra;
qDebug() << Q_FUNC_INFO << "Accepting connection, sock" << sock;
sock->moveToThread( thread() );
sock->_disowned = false;
sock->_outbound = false;
@ -381,7 +343,6 @@ Servent::socketConnected()
qDebug() << "Servent::SocketConnected" << thread() << "socket:" << sock;
Connection* conn = sock->_conn;
handoverSocket( conn, sock );
}
@ -421,7 +382,7 @@ Servent::socketError( QAbstractSocket::SocketError e )
Connection* conn = sock->_conn;
qDebug() << "Servent::SocketError:" << e << conn->id() << conn->name();
if(!sock->_disowned)
if( !sock->_disowned )
{
// connection will delete if we already transferred ownership, otherwise:
sock->deleteLater();
@ -749,7 +710,7 @@ QSharedPointer<QIODevice>
Servent::localFileIODeviceFactory( const Tomahawk::result_ptr& result )
{
// ignore "file://" at front of url
QFile * io = new QFile( result->url().mid( QString( "file://" ).length() ) );
QFile* io = new QFile( result->url().mid( QString( "file://" ).length() ) );
if ( io )
io->open( QIODevice::ReadOnly );

View File

@ -33,7 +33,7 @@ class ControlConnection;
class FileTransferConnection;
class ProxyConnection;
class RemoteCollectionConnection;
class Portfwd;
class PortFwdThread;
// this is used to hold a bit of state, so when a connected signal is emitted
// from a socket, we can associate it with a Connection object etc.
@ -90,7 +90,6 @@ public:
void connectToPeer( const QString& ha, int port, const QString &key, Connection* conn );
void reverseOfferRequest( ControlConnection* orig_conn, const QString& key, const QString& theirkey );
void setExternalAddress( QHostAddress ha, int port );
bool visibleExternally() const { return m_externalPort > 0 && !m_externalAddress.isNull(); }
QHostAddress externalAddress() const { return m_externalAddress; }
int externalPort() const { return m_externalPort; }
@ -111,11 +110,14 @@ public:
signals:
void fileTransferStarted( FileTransferConnection* );
void fileTransferFinished( FileTransferConnection* );
void ready();
protected:
void incomingConnection( int sd );
public slots:
void setExternalAddress( QHostAddress ha, unsigned int port );
void socketError( QAbstractSocket::SocketError );
void createParallelConnection( Connection* orig_conn, Connection* new_conn, const QString& key );
@ -145,9 +147,9 @@ private:
QList< FileTransferConnection* > m_ftsessions;
QMutex m_ftsession_mut;
Portfwd* pf;
QMap< QString,boost::function<QSharedPointer<QIODevice>(Tomahawk::result_ptr)> > m_iofactories;
PortFwdThread* m_portfwd;
static Servent* s_instance;
};

View File

@ -108,10 +108,6 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
{
qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );
new Pipeline( this );
new SourceList( this );
m_servent = new Servent( this );
#ifdef TOMAHAWK_HEADLESS
m_headless = true;
#else
@ -134,6 +130,13 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
new TomahawkSettings( this );
m_audioEngine = new AudioEngine;
new Pipeline( this );
new SourceList( this );
m_servent = new Servent( this );
connect( m_servent, SIGNAL( ready() ), SLOT( setupSIP() ) );
setupDatabase();
#ifndef NO_LIBLASTFM
@ -160,8 +163,8 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
{
qDebug() << "Setting proxy to saved values";
m_proxy = 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>(m_proxy->type()) );
qDebug() << "Proxy host = " << m_proxy->hostName();
qDebug() << "Proxy type =" << QString::number( static_cast<int>(m_proxy->type()) );
qDebug() << "Proxy host =" << m_proxy->hostName();
QNetworkAccessManager* nam = TomahawkApp::instance()->nam();
nam->setProxy( *m_proxy );
}
@ -170,14 +173,9 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
QNetworkProxy::setApplicationProxy( *m_proxy );
m_sipHandler = new SipHandler( this );
m_infoSystem = new Tomahawk::InfoSystem::InfoSystem( this );
if( !arguments().contains("--nojabber") )
{
setupSIP();
m_xmppBot = new XMPPBot( this );
}
#ifndef TOMAHAWK_HEADLESS
if ( !m_headless )
{
@ -196,8 +194,6 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
if( arguments().contains( "--http" ) || TomahawkSettings::instance()->value( "network/http", true ).toBool() )
startHTTP();
m_sipHandler->connect();
#ifndef TOMAHAWK_HEADLESS
if ( !TomahawkSettings::instance()->hasScannerPath() )
{
@ -258,6 +254,7 @@ TomahawkApp::registerMetaTypes()
qRegisterMetaType< QTcpSocket* >("QTcpSocket*");
qRegisterMetaType< QSharedPointer<QIODevice> >("QSharedPointer<QIODevice>");
qRegisterMetaType< QFileInfo >("QFileInfo");
qRegisterMetaType< QHostAddress >("QHostAddress");
qRegisterMetaType< QMap<QString, unsigned int> >("QMap<QString, unsigned int>");
qRegisterMetaType< QMap< QString, plentry_ptr > >("QMap< QString, plentry_ptr >");
qRegisterMetaType< QHash< QString, QMap<quint32, quint16> > >("QHash< QString, QMap<quint32, quint16> >");
@ -399,8 +396,12 @@ TomahawkApp::setupSIP()
{
qDebug() << Q_FUNC_INFO;
m_sipHandler = new SipHandler( this );
if( !arguments().contains( "--nojabber" ) )
{
m_xmppBot = new XMPPBot( this );
// m_sipHandler->setProxy( m_proxy );
m_sipHandler->connect();
// m_sipHandler->setProxy( m_proxy );
}
}