mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-07 14:46:33 +02:00
Support multiple SipInfos per peer
This commit is contained in:
@@ -21,60 +21,39 @@
|
|||||||
|
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
|
TomahawkXmppMessage::TomahawkXmppMessage() : m_sipInfo()
|
||||||
class TomahawkXmppMessagePrivate
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
QString ip;
|
|
||||||
int port;
|
|
||||||
QString uniqname;
|
|
||||||
QString key;
|
|
||||||
bool visible;
|
|
||||||
};
|
|
||||||
|
|
||||||
TomahawkXmppMessage::TomahawkXmppMessage(const QString &ip, unsigned int port, const QString &uniqname, const QString &key) : d_ptr(new TomahawkXmppMessagePrivate)
|
|
||||||
{
|
|
||||||
Q_D(TomahawkXmppMessage);
|
|
||||||
d->ip = ip;
|
|
||||||
d->port = port;
|
|
||||||
d->uniqname = uniqname;
|
|
||||||
d->key = key;
|
|
||||||
d->visible = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TomahawkXmppMessage::TomahawkXmppMessage() : d_ptr(new TomahawkXmppMessagePrivate)
|
TomahawkXmppMessage::TomahawkXmppMessage( const QList<SipInfo> &sipInfo ) : m_sipInfo( sipInfo )
|
||||||
{
|
{
|
||||||
Q_D(TomahawkXmppMessage);
|
|
||||||
d->visible = false;
|
|
||||||
d->port = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TomahawkXmppMessage::~TomahawkXmppMessage()
|
TomahawkXmppMessage::~TomahawkXmppMessage()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString TomahawkXmppMessage::ip() const
|
const QList<SipInfo>
|
||||||
|
TomahawkXmppMessage::sipInfo() const
|
||||||
{
|
{
|
||||||
return d_func()->ip;
|
return m_sipInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TomahawkXmppMessage::port() const
|
|
||||||
|
const QString
|
||||||
|
TomahawkXmppMessage::key() const
|
||||||
{
|
{
|
||||||
return d_func()->port;
|
if ( m_sipInfo.length() > 0 )
|
||||||
|
return m_sipInfo.first().key();
|
||||||
|
else
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString TomahawkXmppMessage::uniqname() const
|
const QString
|
||||||
|
TomahawkXmppMessage::uniqname() const
|
||||||
{
|
{
|
||||||
return d_func()->uniqname;
|
if ( m_sipInfo.length() > 0 )
|
||||||
}
|
return m_sipInfo.first().nodeId();
|
||||||
|
else
|
||||||
const QString TomahawkXmppMessage::key() const
|
return QString();
|
||||||
{
|
|
||||||
return d_func()->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TomahawkXmppMessage::visible() const
|
|
||||||
{
|
|
||||||
return d_func()->visible;
|
|
||||||
}
|
}
|
||||||
|
@@ -22,30 +22,29 @@
|
|||||||
|
|
||||||
#include <jreen/stanzaextension.h>
|
#include <jreen/stanzaextension.h>
|
||||||
|
|
||||||
|
#include "sip/SipInfo.h"
|
||||||
|
|
||||||
#define TOMAHAWK_SIP_MESSAGE_NS QLatin1String("http://www.tomhawk-player.org/sip/transports")
|
#define TOMAHAWK_SIP_MESSAGE_NS QLatin1String("http://www.tomhawk-player.org/sip/transports")
|
||||||
|
|
||||||
#include "accounts/AccountDllMacro.h"
|
#include "accounts/AccountDllMacro.h"
|
||||||
|
|
||||||
class TomahawkXmppMessagePrivate;
|
|
||||||
class ACCOUNTDLLEXPORT TomahawkXmppMessage : public Jreen::Payload
|
class ACCOUNTDLLEXPORT TomahawkXmppMessage : public Jreen::Payload
|
||||||
{
|
{
|
||||||
J_PAYLOAD(TomahawkXmppMessage)
|
J_PAYLOAD(TomahawkXmppMessage)
|
||||||
Q_DECLARE_PRIVATE(TomahawkXmppMessage)
|
|
||||||
public:
|
public:
|
||||||
// sets visible to true
|
|
||||||
TomahawkXmppMessage(const QString &ip, unsigned int port, const QString &uniqname, const QString &key);
|
|
||||||
|
|
||||||
// sets visible to false as we dont have any extra information
|
|
||||||
TomahawkXmppMessage();
|
TomahawkXmppMessage();
|
||||||
|
TomahawkXmppMessage(const QList<SipInfo>& sipInfo);
|
||||||
~TomahawkXmppMessage();
|
~TomahawkXmppMessage();
|
||||||
|
|
||||||
const QString ip() const;
|
//! The SipInfo objects that are wrapped in this XmppMessage
|
||||||
unsigned int port() const;
|
const QList<SipInfo> sipInfo() const;
|
||||||
const QString uniqname() const;
|
//! The name of the peer contained in this message
|
||||||
const QString key() const;
|
const QString key() const;
|
||||||
bool visible() const;
|
//! The name of the peer contained in this message
|
||||||
|
const QString uniqname() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<TomahawkXmppMessagePrivate> d_ptr;
|
QList<SipInfo> m_sipInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ENTITYTIME_H
|
#endif // ENTITYTIME_H
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "TomahawkXmppMessageFactory.h"
|
#include "TomahawkXmppMessageFactory.h"
|
||||||
|
|
||||||
|
#include "network/Servent.h"
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@@ -28,7 +29,7 @@
|
|||||||
|
|
||||||
using namespace Jreen;
|
using namespace Jreen;
|
||||||
|
|
||||||
TomahawkXmppMessageFactory::TomahawkXmppMessageFactory()
|
TomahawkXmppMessageFactory::TomahawkXmppMessageFactory() : m_sipInfo()
|
||||||
{
|
{
|
||||||
m_depth = 0;
|
m_depth = 0;
|
||||||
m_state = AtNowhere;
|
m_state = AtNowhere;
|
||||||
@@ -54,31 +55,35 @@ void TomahawkXmppMessageFactory::handleStartElement(const QStringRef &name, cons
|
|||||||
const QXmlStreamAttributes &attributes)
|
const QXmlStreamAttributes &attributes)
|
||||||
{
|
{
|
||||||
m_depth++;
|
m_depth++;
|
||||||
if (m_depth == 1) {
|
if ( m_depth == 1 )
|
||||||
|
{
|
||||||
m_state = AtNowhere;
|
m_state = AtNowhere;
|
||||||
m_ip = QString();
|
|
||||||
m_port = -1;
|
|
||||||
m_uniqname = QString();
|
m_uniqname = QString();
|
||||||
m_key = QString();
|
m_key = QString();
|
||||||
m_visible = false;
|
m_sipInfo = QList<SipInfo>();
|
||||||
} else if (m_depth == 2) {
|
}
|
||||||
|
else if ( m_depth == 2 )
|
||||||
|
{
|
||||||
if ( name == QLatin1String( "transport" ) )
|
if ( name == QLatin1String( "transport" ) )
|
||||||
{
|
{
|
||||||
// qDebug() << "Found Transport";
|
|
||||||
m_state = AtTransport;
|
m_state = AtTransport;
|
||||||
|
|
||||||
m_uniqname = attributes.value( QLatin1String( "uniqname" ) ).toString();
|
m_uniqname = attributes.value( QLatin1String( "uniqname" ) ).toString();
|
||||||
m_key = attributes.value( QLatin1String( "pwd" ) ).toString();
|
m_key = attributes.value( QLatin1String( "pwd" ) ).toString();
|
||||||
}
|
}
|
||||||
} else if(m_depth == 3) {
|
}
|
||||||
|
else if(m_depth == 3)
|
||||||
|
{
|
||||||
if ( name == QLatin1String( "candidate" ) )
|
if ( name == QLatin1String( "candidate" ) )
|
||||||
{
|
{
|
||||||
m_state = AtCandidate;
|
m_state = AtCandidate;
|
||||||
// qDebug() << "Found candidate";
|
SipInfo info = SipInfo();
|
||||||
m_ip = attributes.value(QLatin1String("ip")).toString();
|
info.setVisible( true );
|
||||||
m_port = attributes.value(QLatin1String("port")).toString().toInt();
|
info.setHost( attributes.value( QLatin1String( "ip" ) ).toString() );
|
||||||
|
info.setPort( attributes.value( QLatin1String( "port" ) ).toString().toInt() );
|
||||||
m_visible = true;
|
info.setKey( m_key );
|
||||||
|
info.setNodeId( m_uniqname );
|
||||||
|
Q_ASSERT( info.isValid() );
|
||||||
|
m_sipInfo.append( info );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Q_UNUSED(uri);
|
Q_UNUSED(uri);
|
||||||
@@ -88,7 +93,21 @@ void TomahawkXmppMessageFactory::handleStartElement(const QStringRef &name, cons
|
|||||||
void TomahawkXmppMessageFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
|
void TomahawkXmppMessageFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
|
||||||
{
|
{
|
||||||
if ( m_depth == 3 )
|
if ( m_depth == 3 )
|
||||||
|
m_state = AtTransport;
|
||||||
|
else if ( m_depth == 2 )
|
||||||
|
{
|
||||||
m_state = AtNowhere;
|
m_state = AtNowhere;
|
||||||
|
// Check that we have at least one SipInfo so that we provide some information about invisible peers.
|
||||||
|
if ( m_sipInfo.length() == 0 )
|
||||||
|
{
|
||||||
|
SipInfo info = SipInfo();
|
||||||
|
info.setVisible( false );
|
||||||
|
info.setKey( m_key );
|
||||||
|
info.setNodeId( m_uniqname );
|
||||||
|
Q_ASSERT( info.isValid() );
|
||||||
|
m_sipInfo.append( info );
|
||||||
|
}
|
||||||
|
}
|
||||||
Q_UNUSED(name);
|
Q_UNUSED(name);
|
||||||
Q_UNUSED(uri);
|
Q_UNUSED(uri);
|
||||||
m_depth--;
|
m_depth--;
|
||||||
@@ -114,35 +133,66 @@ void TomahawkXmppMessageFactory::serialize(Payload *extension, QXmlStreamWriter
|
|||||||
writer->writeStartElement( QLatin1String( "tomahawk" ) );
|
writer->writeStartElement( QLatin1String( "tomahawk" ) );
|
||||||
writer->writeDefaultNamespace( TOMAHAWK_SIP_MESSAGE_NS );
|
writer->writeDefaultNamespace( TOMAHAWK_SIP_MESSAGE_NS );
|
||||||
|
|
||||||
if(sipMessage->visible())
|
// Get a copy of the list, so that we can modify it here.
|
||||||
|
QList<SipInfo> sipInfo = QList<SipInfo>( sipMessage->sipInfo() );
|
||||||
|
QSharedPointer<SipInfo> lastInfo = QSharedPointer<SipInfo>();
|
||||||
|
foreach ( SipInfo info, sipInfo )
|
||||||
{
|
{
|
||||||
// add transport tag
|
if ( info.isVisible() )
|
||||||
|
{
|
||||||
|
QHostAddress ha = QHostAddress( info.host() );
|
||||||
|
if ( Servent::isValidExternalIP( ha ) && ha.protocol() == QAbstractSocket::IPv4Protocol )
|
||||||
|
{
|
||||||
|
// For comapability reasons, this shall be put as the last candidate
|
||||||
|
lastInfo = QSharedPointer<SipInfo>( new SipInfo( info ) );
|
||||||
|
sipInfo.removeOne( info );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writer->writeStartElement( QLatin1String( "transport" ) );
|
writer->writeStartElement( QLatin1String( "transport" ) );
|
||||||
writer->writeAttribute( QLatin1String( "pwd" ), sipMessage->key() );
|
writer->writeAttribute( QLatin1String( "pwd" ), sipMessage->key() );
|
||||||
writer->writeAttribute( QLatin1String( "uniqname" ), sipMessage->uniqname() );
|
writer->writeAttribute( QLatin1String( "uniqname" ), sipMessage->uniqname() );
|
||||||
|
|
||||||
writer->writeEmptyElement(QLatin1String("candidate"));
|
foreach ( SipInfo info, sipInfo )
|
||||||
writer->writeAttribute(QLatin1String("component"), "1");
|
|
||||||
writer->writeAttribute(QLatin1String("id"), "el0747fg11"); // FIXME
|
|
||||||
writer->writeAttribute(QLatin1String("ip"), sipMessage->ip());
|
|
||||||
writer->writeAttribute(QLatin1String("network"), "1");
|
|
||||||
writer->writeAttribute(QLatin1String("port"), QVariant(sipMessage->port()).toString());
|
|
||||||
writer->writeAttribute(QLatin1String("priority"), "1"); //TODO
|
|
||||||
writer->writeAttribute(QLatin1String("protocol"), "tcp");
|
|
||||||
writer->writeAttribute(QLatin1String("type"), "host"); //FIXME: correct?!
|
|
||||||
writer->writeEndElement();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
writer->writeEmptyElement(QLatin1String("transport"));
|
if ( info.isVisible() )
|
||||||
|
serializeSipInfo( info, writer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !lastInfo.isNull() )
|
||||||
|
{
|
||||||
|
Q_ASSERT( lastInfo->isVisible() );
|
||||||
|
serializeSipInfo( *lastInfo, writer );
|
||||||
|
}
|
||||||
|
|
||||||
|
// </transport>
|
||||||
writer->writeEndElement();
|
writer->writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
Payload::Ptr TomahawkXmppMessageFactory::createPayload()
|
Payload::Ptr
|
||||||
|
TomahawkXmppMessageFactory::createPayload()
|
||||||
{
|
{
|
||||||
if(m_visible)
|
if ( ( ( m_sipInfo.length() == 1 ) && ( !m_sipInfo.first().isVisible() ) ) || ( m_sipInfo.length() < 1 ) )
|
||||||
return Payload::Ptr(new TomahawkXmppMessage(m_ip, m_port, m_uniqname, m_key));
|
|
||||||
else
|
|
||||||
return Payload::Ptr( new TomahawkXmppMessage() );
|
return Payload::Ptr( new TomahawkXmppMessage() );
|
||||||
|
else
|
||||||
|
return Payload::Ptr( new TomahawkXmppMessage( m_sipInfo ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TomahawkXmppMessageFactory::serializeSipInfo(SipInfo &info, QXmlStreamWriter *writer)
|
||||||
|
{
|
||||||
|
if ( info.isVisible() )
|
||||||
|
{
|
||||||
|
writer->writeEmptyElement( QLatin1String( "candidate" ) );
|
||||||
|
writer->writeAttribute( QLatin1String( "component" ), "1" );
|
||||||
|
writer->writeAttribute( QLatin1String( "id" ), "el0747fg11" ); // FIXME
|
||||||
|
writer->writeAttribute( QLatin1String( "ip" ), info.host() );
|
||||||
|
writer->writeAttribute( QLatin1String( "network" ), "1" );
|
||||||
|
writer->writeAttribute( QLatin1String( "port" ), QVariant( info.port() ).toString() );
|
||||||
|
writer->writeAttribute( QLatin1String( "priority" ), "1" ); //TODO
|
||||||
|
writer->writeAttribute( QLatin1String( "protocol" ), "tcp" );
|
||||||
|
writer->writeAttribute( QLatin1String( "type" ), "host" ); //FIXME: correct?!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -39,13 +39,18 @@ public:
|
|||||||
void serialize(Jreen::Payload *extension, QXmlStreamWriter *writer);
|
void serialize(Jreen::Payload *extension, QXmlStreamWriter *writer);
|
||||||
Jreen::Payload::Ptr createPayload();
|
Jreen::Payload::Ptr createPayload();
|
||||||
private:
|
private:
|
||||||
|
void serializeSipInfo(SipInfo& info, QXmlStreamWriter *writer);
|
||||||
|
|
||||||
enum State { AtNowhere, AtTransport, AtCandidate } m_state;
|
enum State { AtNowhere, AtTransport, AtCandidate } m_state;
|
||||||
|
|
||||||
|
//! All the provided Sip informations
|
||||||
|
QList<SipInfo> m_sipInfo;
|
||||||
|
//! The current parsing depth
|
||||||
int m_depth;
|
int m_depth;
|
||||||
QString m_ip;
|
//! The unique name of the peer
|
||||||
int m_port;
|
|
||||||
QString m_uniqname;
|
QString m_uniqname;
|
||||||
|
//! The authentication key of the peer
|
||||||
QString m_key;
|
QString m_key;
|
||||||
bool m_visible;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ENTITYTIMEFACTORY_P_H
|
#endif // ENTITYTIMEFACTORY_P_H
|
||||||
|
@@ -435,22 +435,15 @@ XmppSipPlugin::errorMessage( Jreen::Client::DisconnectReason reason )
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
XmppSipPlugin::sendSipInfo( const Tomahawk::peerinfo_ptr& receiver, const SipInfo& info )
|
XmppSipPlugin::sendSipInfoList( const Tomahawk::peerinfo_ptr& receiver, const QList<SipInfo>& info )
|
||||||
{
|
{
|
||||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << receiver << info;
|
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << receiver << info;
|
||||||
|
|
||||||
if ( !m_client )
|
if ( !m_client )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TomahawkXmppMessage *sipMessage;
|
TomahawkXmppMessage* sipMessage = new TomahawkXmppMessage( info );
|
||||||
if ( info.isVisible() )
|
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Send sip messsage to" << receiver;
|
||||||
{
|
|
||||||
sipMessage = new TomahawkXmppMessage( info.host(), info.port(), info.nodeId(), info.key() );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sipMessage = new TomahawkXmppMessage();
|
|
||||||
|
|
||||||
qDebug() << "Send sip messsage to" << receiver;
|
|
||||||
Jreen::IQ iq( Jreen::IQ::Set, receiver->id() );
|
Jreen::IQ iq( Jreen::IQ::Set, receiver->id() );
|
||||||
iq.addExtension( sipMessage );
|
iq.addExtension( sipMessage );
|
||||||
Jreen::IQReply *reply = m_client->send( iq );
|
Jreen::IQReply *reply = m_client->send( iq );
|
||||||
@@ -687,6 +680,7 @@ XmppSipPlugin::onNewMessage( const Jreen::Message& message )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: We do not sent SipInfo in JSON via XMPP, why do we receive it here?
|
||||||
SipInfo info = SipInfo::fromJson( msg );
|
SipInfo info = SipInfo::fromJson( msg );
|
||||||
if ( !info.isValid() )
|
if ( !info.isValid() )
|
||||||
{
|
{
|
||||||
@@ -912,30 +906,22 @@ XmppSipPlugin::onNewIq( const Jreen::IQ& iq )
|
|||||||
if ( sipMessage )
|
if ( sipMessage )
|
||||||
{
|
{
|
||||||
iq.accept();
|
iq.accept();
|
||||||
|
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Received Sip Information from:" << iq.from().full();
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Got SipMessage ..."
|
// Check that all received SipInfos are valid.
|
||||||
<< "ip" << sipMessage->ip() << "port" << sipMessage->port() << "nodeId" << sipMessage->uniqname() << "key" << sipMessage->key() << "visible" << sipMessage->visible();
|
foreach ( SipInfo info, sipMessage->sipInfo() )
|
||||||
|
|
||||||
SipInfo info;
|
|
||||||
info.setVisible( sipMessage->visible() );
|
|
||||||
if ( sipMessage->visible() )
|
|
||||||
{
|
{
|
||||||
info.setHost( sipMessage->ip() );
|
Q_ASSERT( info.isValid() );
|
||||||
info.setPort( sipMessage->port() );
|
|
||||||
info.setNodeId( sipMessage->uniqname() );
|
|
||||||
info.setKey( sipMessage->key() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT( info.isValid() );
|
// Get the peer information for the sender.
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "From:" << iq.from().full() << ":" << info;
|
|
||||||
Tomahawk::peerinfo_ptr peerInfo = PeerInfo::get( this, iq.from().full() );
|
Tomahawk::peerinfo_ptr peerInfo = PeerInfo::get( this, iq.from().full() );
|
||||||
if ( peerInfo.isNull() )
|
if ( peerInfo.isNull() )
|
||||||
{
|
{
|
||||||
tDebug() << Q_FUNC_INFO << "no valid peerInfo for" << iq.from().full();
|
tDebug() << Q_FUNC_INFO << "no valid peerInfo for" << iq.from().full();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peerInfo->setSipInfo( info );
|
peerInfo->setSipInfo( sipMessage->sipInfo() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -90,7 +90,7 @@ public slots:
|
|||||||
virtual void configurationChanged();
|
virtual void configurationChanged();
|
||||||
virtual void addContact( const QString& peerId, const QString& msg = QString() );
|
virtual void addContact( const QString& peerId, const QString& msg = QString() );
|
||||||
|
|
||||||
virtual void sendSipInfo( const Tomahawk::peerinfo_ptr& receiver, const SipInfo& info );
|
virtual void sendSipInfoList( const Tomahawk::peerinfo_ptr& receiver, const QList<SipInfo>& info );
|
||||||
|
|
||||||
void showAddFriendDialog();
|
void showAddFriendDialog();
|
||||||
void publishTune( const QUrl& url, const Tomahawk::InfoSystem::InfoStringHash& trackInfo );
|
void publishTune( const QUrl& url, const Tomahawk::InfoSystem::InfoStringHash& trackInfo );
|
||||||
|
@@ -161,7 +161,9 @@ ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name
|
|||||||
sipInfo.setVisible( true );
|
sipInfo.setVisible( true );
|
||||||
|
|
||||||
Tomahawk::peerinfo_ptr peerInfo = Tomahawk::PeerInfo::get( this, host, Tomahawk::PeerInfo::AutoCreate );
|
Tomahawk::peerinfo_ptr peerInfo = Tomahawk::PeerInfo::get( this, host, Tomahawk::PeerInfo::AutoCreate );
|
||||||
peerInfo->setSipInfo( sipInfo );
|
QList<SipInfo> sipInfoList = QList<SipInfo>();
|
||||||
|
sipInfoList.append( sipInfo );
|
||||||
|
peerInfo->setSipInfo( sipInfoList );
|
||||||
peerInfo->setContactId( host );
|
peerInfo->setContactId( host );
|
||||||
peerInfo->setFriendlyName( name );
|
peerInfo->setFriendlyName( name );
|
||||||
peerInfo->setType( PeerInfo::Local );
|
peerInfo->setType( PeerInfo::Local );
|
||||||
|
@@ -65,7 +65,7 @@ public slots:
|
|||||||
|
|
||||||
void advertise();
|
void advertise();
|
||||||
|
|
||||||
void sendSipInfo( const Tomahawk::peerinfo_ptr&, const SipInfo& ) {}
|
virtual void sendSipInfoList( const Tomahawk::peerinfo_ptr& receiver, const QList<SipInfo>& info ) {}
|
||||||
void broadcastMsg( const QString & ) {}
|
void broadcastMsg( const QString & ) {}
|
||||||
void addContact( const QString &, const QString& ) {}
|
void addContact( const QString &, const QString& ) {}
|
||||||
|
|
||||||
|
@@ -306,6 +306,7 @@ list(APPEND libSources
|
|||||||
network/Servent.cpp
|
network/Servent.cpp
|
||||||
network/Connection.cpp
|
network/Connection.cpp
|
||||||
network/ControlConnection.cpp
|
network/ControlConnection.cpp
|
||||||
|
network/QTcpSocketExtra.cpp
|
||||||
|
|
||||||
playlist/PlaylistUpdaterInterface.cpp
|
playlist/PlaylistUpdaterInterface.cpp
|
||||||
playlist/dynamic/DynamicPlaylist.cpp
|
playlist/dynamic/DynamicPlaylist.cpp
|
||||||
|
64
src/libtomahawk/network/QTcpSocketExtra.cpp
Normal file
64
src/libtomahawk/network/QTcpSocketExtra.cpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "QTcpSocketExtra.h"
|
||||||
|
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
QTcpSocketExtra::connectToHost( const QHostAddress& host, quint16 port, OpenMode openMode )
|
||||||
|
{
|
||||||
|
if ( m_connectTimer->isActive() == true )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Connection already establishing.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTcpSocket::connectToHost( host, port, openMode);
|
||||||
|
if ( m_connectTimeout > 0 )
|
||||||
|
m_connectTimer->start( m_connectTimeout );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QTcpSocketExtra::connectToHost(const QString& host, quint16 port, OpenMode openMode)
|
||||||
|
{
|
||||||
|
if ( m_connectTimer->isActive() == true )
|
||||||
|
{
|
||||||
|
tLog() << Q_FUNC_INFO << "Connection already establishing.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTcpSocket::connectToHost( host, port, openMode);
|
||||||
|
if ( m_connectTimeout > 0 )
|
||||||
|
m_connectTimer->start( m_connectTimeout );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QTcpSocketExtra::connectTimeout()
|
||||||
|
{
|
||||||
|
m_connectTimer->stop();
|
||||||
|
if ( state() != ConnectedState )
|
||||||
|
{
|
||||||
|
// We did not manage to connect in the given timespan, so abort the attempt...
|
||||||
|
close();
|
||||||
|
// .. and notify error handlers.
|
||||||
|
emit error( SocketTimeoutError );
|
||||||
|
}
|
||||||
|
}
|
82
src/libtomahawk/network/QTcpSocketExtra.h
Normal file
82
src/libtomahawk/network/QTcpSocketExtra.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QTCPSOCKETEXTRA_H
|
||||||
|
#define QTCPSOCKETEXTRA_H
|
||||||
|
|
||||||
|
// time before new connection terminates if no auth received
|
||||||
|
#define AUTH_TIMEOUT 180000
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "Msg.h"
|
||||||
|
#include "DllMacro.h"
|
||||||
|
|
||||||
|
class Connection;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
// In addition, functionality to limit the connection timeout is implemented.
|
||||||
|
class DLLEXPORT QTcpSocketExtra : public QTcpSocket
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QTcpSocketExtra() : QTcpSocket(), m_connectTimeout( -1 )
|
||||||
|
{
|
||||||
|
QTimer::singleShot( AUTH_TIMEOUT, this, SLOT( authTimeout() ) ) ;
|
||||||
|
m_connectTimer = new QTimer( this );
|
||||||
|
connect( m_connectTimer, SIGNAL( timeout() ), this, SLOT( connectTimeout() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void connectToHost(const QString& host, quint16 port, OpenMode openMode = ReadWrite );
|
||||||
|
void connectToHost( const QHostAddress& host, quint16 port, OpenMode openMode = ReadWrite );
|
||||||
|
|
||||||
|
QPointer<Connection> _conn;
|
||||||
|
bool _outbound;
|
||||||
|
bool _disowned;
|
||||||
|
msg_ptr _msg;
|
||||||
|
|
||||||
|
//! Set a time limit for establishing a connection.
|
||||||
|
void setConnectTimeout( qint32 timeout ) { m_connectTimeout = timeout; }
|
||||||
|
//! Get the current timeout for establishing a connection.
|
||||||
|
qint32 connectTimeout() const { return m_connectTimeout; }
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void connectTimeout();
|
||||||
|
void authTimeout()
|
||||||
|
{
|
||||||
|
if( _disowned )
|
||||||
|
return;
|
||||||
|
|
||||||
|
qDebug() << "Connection timed out before providing a valid offer-key";
|
||||||
|
this->disconnectFromHost();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
//! How long we will wait for a connection to establish
|
||||||
|
qint32 m_connectTimeout;
|
||||||
|
//! Timer to measure the connection initialisation
|
||||||
|
QTimer* m_connectTimer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QTCPSOCKETEXTRA_H
|
@@ -34,6 +34,7 @@
|
|||||||
#include "sip/SipPlugin.h"
|
#include "sip/SipPlugin.h"
|
||||||
#include "PortFwdThread.h"
|
#include "PortFwdThread.h"
|
||||||
#include "TomahawkSettings.h"
|
#include "TomahawkSettings.h"
|
||||||
|
#include "utils/Closure.h"
|
||||||
#include "utils/TomahawkUtils.h"
|
#include "utils/TomahawkUtils.h"
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
#include "accounts/AccountManager.h"
|
#include "accounts/AccountManager.h"
|
||||||
@@ -50,6 +51,10 @@
|
|||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
typedef QPair< QList< SipInfo >, Connection* > sipConnectionPair;
|
||||||
|
Q_DECLARE_METATYPE( sipConnectionPair )
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
Servent* Servent::s_instance = 0;
|
Servent* Servent::s_instance = 0;
|
||||||
@@ -70,7 +75,6 @@ Servent::Servent( QObject* parent )
|
|||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
|
||||||
m_lanHack = qApp->arguments().contains( "--lanhack" );
|
|
||||||
m_noAuth = qApp->arguments().contains( "--noauth" );
|
m_noAuth = qApp->arguments().contains( "--noauth" );
|
||||||
|
|
||||||
setProxy( QNetworkProxy::NoProxy );
|
setProxy( QNetworkProxy::NoProxy );
|
||||||
@@ -113,6 +117,7 @@ Servent::~Servent()
|
|||||||
bool
|
bool
|
||||||
Servent::startListening( QHostAddress ha, bool upnp, int port )
|
Servent::startListening( QHostAddress ha, bool upnp, int port )
|
||||||
{
|
{
|
||||||
|
m_externalAddresses = QList<QHostAddress>();
|
||||||
m_port = port;
|
m_port = port;
|
||||||
int defPort = TomahawkSettings::instance()->defaultPort();
|
int defPort = TomahawkSettings::instance()->defaultPort();
|
||||||
|
|
||||||
@@ -125,8 +130,8 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
|||||||
{
|
{
|
||||||
if ( !listen( ha, defPort ) )
|
if ( !listen( ha, defPort ) )
|
||||||
{
|
{
|
||||||
tLog() << "Failed to listen on both port" << m_port << "and port" << defPort;
|
tLog() << Q_FUNC_INFO << "Failed to listen on both port" << m_port << "and port" << defPort;
|
||||||
tLog() << "Error string is:" << errorString();
|
tLog() << Q_FUNC_INFO << "Error string is:" << errorString();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -134,38 +139,63 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TomahawkSettings::ExternalAddressMode mode = TomahawkSettings::instance()->externalAddressMode();
|
if ( ha == QHostAddress::AnyIPv6 )
|
||||||
|
{
|
||||||
|
// We are listening on all available addresses, so we should send a SipInfo for all of them.
|
||||||
|
foreach ( QHostAddress addr, QNetworkInterface::allAddresses() )
|
||||||
|
{
|
||||||
|
if ( addr.toString() == "127.0.0.1" )
|
||||||
|
continue; // IPv4 localhost
|
||||||
|
if ( addr.toString() == "::1" )
|
||||||
|
continue; // IPv6 localhost
|
||||||
|
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Listening to " << addr.toString();
|
||||||
|
m_externalAddresses.append( addr );
|
||||||
|
}
|
||||||
|
|
||||||
tLog() << "Servent listening on port" << m_port << "- servent thread:" << thread()
|
}
|
||||||
|
else if ( ( ha.toString() != "127.0.0.1" ) && ( ha.toString() != "::1" ) )
|
||||||
|
{
|
||||||
|
// We listen only to one specific Address, only announce this.
|
||||||
|
m_externalAddresses.append( ha );
|
||||||
|
}
|
||||||
|
// If we only accept connections via localhost, we'll announce nothing.
|
||||||
|
|
||||||
|
TomahawkSettings::ExternalAddressMode mode = TomahawkSettings::instance()->externalAddressMode();
|
||||||
|
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Servent listening on port" << m_port << "- servent thread:" << thread()
|
||||||
<< "- address mode:" << (int)( mode );
|
<< "- address mode:" << (int)( mode );
|
||||||
|
|
||||||
// --lanhack means to advertise your LAN IP as if it were externally visible
|
|
||||||
switch ( mode )
|
switch ( mode )
|
||||||
{
|
{
|
||||||
case TomahawkSettings::Static:
|
case TomahawkSettings::Static:
|
||||||
m_externalHostname = TomahawkSettings::instance()->externalHostname();
|
m_externalHostname = TomahawkSettings::instance()->externalHostname();
|
||||||
m_externalPort = TomahawkSettings::instance()->externalPort();
|
m_externalPort = TomahawkSettings::instance()->externalPort();
|
||||||
m_ready = true;
|
m_ready = true;
|
||||||
|
// All setup is made, were done.
|
||||||
emit ready();
|
emit ready();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TomahawkSettings::Lan:
|
case TomahawkSettings::Lan:
|
||||||
setInternalAddress();
|
// Nothing has to be done here.
|
||||||
|
m_ready = true;
|
||||||
|
emit ready();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TomahawkSettings::Upnp:
|
case TomahawkSettings::Upnp:
|
||||||
if ( !upnp )
|
if ( upnp )
|
||||||
{
|
{
|
||||||
setInternalAddress();
|
// upnp could be turned of on the cli with --noupnp
|
||||||
break;
|
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "External address mode set to upnp...";
|
||||||
}
|
|
||||||
// TODO check if we have a public/internet IP on this machine directly
|
|
||||||
tLog() << "External address mode set to upnp...";
|
|
||||||
m_portfwd = QPointer< PortFwdThread >( new PortFwdThread( m_port ) );
|
m_portfwd = QPointer< PortFwdThread >( new PortFwdThread( m_port ) );
|
||||||
Q_ASSERT( m_portfwd );
|
Q_ASSERT( m_portfwd );
|
||||||
connect( m_portfwd.data(), SIGNAL( externalAddressDetected( QHostAddress, unsigned int ) ),
|
connect( m_portfwd.data(), SIGNAL( externalAddressDetected( QHostAddress, unsigned int ) ),
|
||||||
SLOT( setExternalAddress( QHostAddress, unsigned int ) ) );
|
SLOT( setExternalAddress( QHostAddress, unsigned int ) ) );
|
||||||
m_portfwd.data()->start();
|
m_portfwd.data()->start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ready = true;
|
||||||
|
emit ready();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +203,25 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Servent::setExternalAddress( QHostAddress ha, unsigned int port )
|
||||||
|
{
|
||||||
|
if ( isValidExternalIP( ha ) )
|
||||||
|
{
|
||||||
|
m_externalHostname = ha.toString();
|
||||||
|
m_externalPort = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_externalPort == 0 || !isValidExternalIP( ha ) )
|
||||||
|
tLog() << Q_FUNC_INFO << "UPnP failed, no further external address could be acquired!";
|
||||||
|
else
|
||||||
|
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "UPnP setup successful";
|
||||||
|
|
||||||
|
m_ready = true;
|
||||||
|
emit ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QString
|
QString
|
||||||
Servent::createConnectionKey( const QString& name, const QString &nodeid, const QString &key, bool onceOnly )
|
Servent::createConnectionKey( const QString& name, const QString &nodeid, const QString &key, bool onceOnly )
|
||||||
{
|
{
|
||||||
@@ -192,10 +241,55 @@ Servent::createConnectionKey( const QString& name, const QString &nodeid, const
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Servent::isValidExternalIP( const QHostAddress& addr ) const
|
Servent::isValidExternalIP( const QHostAddress& addr )
|
||||||
{
|
{
|
||||||
QString ip = addr.toString();
|
QString ip = addr.toString();
|
||||||
if ( !m_lanHack && ( ip.startsWith( "10." ) || ip.startsWith( "172.16." ) || ip.startsWith( "192.168." ) ) )
|
if (addr.protocol() == QAbstractSocket::IPv4Protocol)
|
||||||
|
{
|
||||||
|
// private network
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("10.0.0.0/8")) )
|
||||||
|
return false;
|
||||||
|
// localhost
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("127.0.0.0/8")) )
|
||||||
|
return false;
|
||||||
|
// private network
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("169.254.0.0/16")) )
|
||||||
|
return false;
|
||||||
|
// private network
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("172.16.0.0/12")) )
|
||||||
|
return false;
|
||||||
|
// private network
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("192.168.0.0/16")) )
|
||||||
|
return false;
|
||||||
|
// multicast
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("224.0.0.0/4")) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (addr.protocol() == QAbstractSocket::IPv4Protocol)
|
||||||
|
{
|
||||||
|
// "unspecified address"
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("::/128")) )
|
||||||
|
return false;
|
||||||
|
// link-local
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("fe80::/10")) )
|
||||||
|
return false;
|
||||||
|
// unique local addresses
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("fc00::/7")) )
|
||||||
|
return false;
|
||||||
|
// benchmarking only
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("2001:2::/48")) )
|
||||||
|
return false;
|
||||||
|
// non-routed IPv6 addresses used for Cryptographic Hash Identifiers
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("2001:10::/28")) )
|
||||||
|
return false;
|
||||||
|
// documentation prefix
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("2001:db8::/32")) )
|
||||||
|
return false;
|
||||||
|
// multicast
|
||||||
|
if ( addr.isInSubnet(QHostAddress::parseSubnet("ff00::0/8 ")) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -203,54 +297,6 @@ Servent::isValidExternalIP( const QHostAddress& addr ) const
|
|||||||
return !addr.isNull();
|
return !addr.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Servent::setInternalAddress()
|
|
||||||
{
|
|
||||||
foreach ( QHostAddress ha, QNetworkInterface::allAddresses() )
|
|
||||||
{
|
|
||||||
if ( ha.toString() == "127.0.0.1" )
|
|
||||||
continue;
|
|
||||||
if ( ha.toString().contains( ":" ) )
|
|
||||||
continue; //ipv6
|
|
||||||
|
|
||||||
if ( m_lanHack && isValidExternalIP( ha ) )
|
|
||||||
{
|
|
||||||
tLog() << "LANHACK: set external address to lan address" << ha.toString();
|
|
||||||
setExternalAddress( ha, m_port );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_ready = true;
|
|
||||||
emit ready();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Servent::setExternalAddress( QHostAddress ha, unsigned int port )
|
|
||||||
{
|
|
||||||
if ( isValidExternalIP( ha ) )
|
|
||||||
{
|
|
||||||
m_externalAddress = ha;
|
|
||||||
m_externalPort = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( m_externalPort == 0 || !isValidExternalIP( ha ) )
|
|
||||||
{
|
|
||||||
tLog() << "UPnP failed, LAN and outbound connections only!";
|
|
||||||
setInternalAddress();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tLog() << "UPnP setup successful";
|
|
||||||
m_ready = true;
|
|
||||||
emit ready();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Servent::registerOffer( const QString& key, Connection* conn )
|
Servent::registerOffer( const QString& key, Connection* conn )
|
||||||
{
|
{
|
||||||
@@ -312,7 +358,7 @@ Servent::registerPeer( const Tomahawk::peerinfo_ptr& peerInfo )
|
|||||||
if ( peerInfo->type() == Tomahawk::PeerInfo::Local )
|
if ( peerInfo->type() == Tomahawk::PeerInfo::Local )
|
||||||
{
|
{
|
||||||
peerInfoDebug(peerInfo) << "we need to establish the connection now... thinking";
|
peerInfoDebug(peerInfo) << "we need to establish the connection now... thinking";
|
||||||
if ( !connectedToSession( peerInfo->sipInfo().nodeId() ) )
|
if ( !connectedToSession( peerInfo->sipInfo().first().nodeId() ) )
|
||||||
{
|
{
|
||||||
connectToPeer( peerInfo );
|
connectToPeer( peerInfo );
|
||||||
}
|
}
|
||||||
@@ -335,34 +381,47 @@ Servent::registerPeer( const Tomahawk::peerinfo_ptr& peerInfo )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SipInfo info;
|
|
||||||
QString peerId = peerInfo->id();
|
|
||||||
QString key = uuid();
|
QString key = uuid();
|
||||||
ControlConnection* conn = new ControlConnection( this );
|
|
||||||
|
|
||||||
const QString& nodeid = Database::instance()->impl()->dbid();
|
const QString& nodeid = Database::instance()->impl()->dbid();
|
||||||
|
|
||||||
|
ControlConnection* conn = new ControlConnection( this );
|
||||||
conn->setName( peerInfo->contactId() );
|
conn->setName( peerInfo->contactId() );
|
||||||
conn->setId( nodeid );
|
conn->setId( nodeid );
|
||||||
conn->addPeerInfo( peerInfo );
|
conn->addPeerInfo( peerInfo );
|
||||||
|
|
||||||
if ( visibleExternally() )
|
QList<SipInfo> sipInfo = QList<SipInfo>();
|
||||||
|
foreach ( QHostAddress ha, m_externalAddresses )
|
||||||
{
|
{
|
||||||
registerOffer( key, conn );
|
SipInfo info = SipInfo();
|
||||||
|
info.setHost( ha.toString() );
|
||||||
|
info.setPort( m_port );
|
||||||
|
info.setKey( key );
|
||||||
info.setVisible( true );
|
info.setVisible( true );
|
||||||
info.setHost( externalAddress() );
|
info.setNodeId( nodeid );
|
||||||
info.setPort( externalPort() );
|
sipInfo.append( info );
|
||||||
|
}
|
||||||
|
if ( m_externalHostname.length() > 0)
|
||||||
|
{
|
||||||
|
SipInfo info = SipInfo();
|
||||||
|
info.setHost( m_externalHostname );
|
||||||
|
info.setPort( m_externalPort );
|
||||||
|
info.setKey( key );
|
||||||
|
info.setVisible( true );
|
||||||
|
info.setNodeId( nodeid );
|
||||||
|
sipInfo.append( info );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sipInfo.length() == 0 )
|
||||||
|
{
|
||||||
|
// We are not visible via any IP, send a dummy SipInfo
|
||||||
|
SipInfo info = SipInfo();
|
||||||
|
info.setVisible( false );
|
||||||
info.setKey( key );
|
info.setKey( key );
|
||||||
info.setNodeId( nodeid );
|
info.setNodeId( nodeid );
|
||||||
|
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Only accepting connections, no usable IP to listen to found.";
|
||||||
tDebug() << "Asking them (" << peerInfo->id() << ") to connect to us:" << info;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info.setVisible( false );
|
|
||||||
tDebug() << "We are not visible externally:" << info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
peerInfo->sendLocalSipInfo( info );
|
peerInfo->sendLocalSipInfo( sipInfo );
|
||||||
|
|
||||||
handleSipInfo( peerInfo );
|
handleSipInfo( peerInfo );
|
||||||
connect( peerInfo.data(), SIGNAL( sipInfoChanged() ), SLOT( onSipInfoChanged() ) );
|
connect( peerInfo.data(), SIGNAL( sipInfoChanged() ), SLOT( onSipInfoChanged() ) );
|
||||||
@@ -384,43 +443,29 @@ Servent::onSipInfoChanged()
|
|||||||
|
|
||||||
void Servent::handleSipInfo( const Tomahawk::peerinfo_ptr& peerInfo )
|
void Servent::handleSipInfo( const Tomahawk::peerinfo_ptr& peerInfo )
|
||||||
{
|
{
|
||||||
tLog() << Q_FUNC_INFO << peerInfo->id() << peerInfo->sipInfo();
|
// FIXME: Do we need this?
|
||||||
|
// SipInfo info = peerInfo->sipInfo();
|
||||||
|
// if ( !info.isValid() )
|
||||||
|
// return;
|
||||||
|
|
||||||
SipInfo info = peerInfo->sipInfo();
|
foreach ( SipInfo info, peerInfo->sipInfo() )
|
||||||
if ( !info.isValid() )
|
{
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
If only one party is externally visible, connection is obvious
|
|
||||||
If both are, peer with lowest IP address initiates the connection.
|
|
||||||
|
|
||||||
This avoids dupe connections.
|
|
||||||
*/
|
|
||||||
if (info.isVisible())
|
if (info.isVisible())
|
||||||
{
|
{
|
||||||
if ( !visibleExternally() ||
|
// There is at least one SipInfo that may be visible. Try connecting.
|
||||||
externalAddress() < info.host() ||
|
// Duplicate Connections are checked by connectToPeer, so we do not need to take care of this
|
||||||
( externalAddress() == info.host() && externalPort() < info.port() ) )
|
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Initiate connection to" << peerInfo->id() << "at" << info.host() << "peer of:" << peerInfo->sipPlugin()->account()->accountFriendlyName();
|
||||||
{
|
|
||||||
|
|
||||||
tDebug() << "Initiate connection to" << peerInfo->id() << "at" << info.host() << "peer of:" << peerInfo->sipPlugin()->account()->accountFriendlyName();
|
|
||||||
connectToPeer( peerInfo );
|
connectToPeer( peerInfo );
|
||||||
}
|
// We connected to the peer, so we are done here.
|
||||||
else
|
return;
|
||||||
{
|
|
||||||
tDebug() << Q_FUNC_INFO << "They should be conecting to us...";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
tDebug() << Q_FUNC_INFO << "They are not visible, doing nothing atm";
|
|
||||||
|
|
||||||
if ( !visibleExternally() )
|
// If we reach this point none of the previous SipInfos was visible.
|
||||||
{
|
|
||||||
if ( peerInfo->controlConnection() )
|
if ( peerInfo->controlConnection() )
|
||||||
delete peerInfo->controlConnection();
|
delete peerInfo->controlConnection();
|
||||||
}
|
|
||||||
}
|
tDebug() << Q_FUNC_INFO << peerInfo->id() << "They are not visible, doing nothing atm";
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -616,10 +661,13 @@ Servent::createParallelConnection( Connection* orig_conn, Connection* new_conn,
|
|||||||
// if we can connect to them directly:
|
// if we can connect to them directly:
|
||||||
if ( orig_conn && orig_conn->outbound() )
|
if ( orig_conn && orig_conn->outbound() )
|
||||||
{
|
{
|
||||||
connectToPeer( orig_conn->socket()->peerAddress().toString(),
|
QList<SipInfo> sipInfo = QList<SipInfo>();
|
||||||
orig_conn->peerPort(),
|
SipInfo info = SipInfo();
|
||||||
key,
|
info.setKey( key );
|
||||||
new_conn );
|
info.setHost( orig_conn->socket()->peerAddress().toString() );
|
||||||
|
info.setPort( orig_conn->peerPort() );
|
||||||
|
sipInfo.append( info );
|
||||||
|
connectToPeer( sipInfo, new_conn );
|
||||||
}
|
}
|
||||||
else // ask them to connect to us:
|
else // ask them to connect to us:
|
||||||
{
|
{
|
||||||
@@ -631,7 +679,6 @@ Servent::createParallelConnection( Connection* orig_conn, Connection* new_conn,
|
|||||||
m.insert( "conntype", "request-offer" );
|
m.insert( "conntype", "request-offer" );
|
||||||
m.insert( "key", tmpkey );
|
m.insert( "key", tmpkey );
|
||||||
m.insert( "offer", key );
|
m.insert( "offer", key );
|
||||||
m.insert( "port", externalPort() );
|
|
||||||
m.insert( "controlid", Database::instance()->impl()->dbid() );
|
m.insert( "controlid", Database::instance()->impl()->dbid() );
|
||||||
|
|
||||||
QJson::Serializer ser;
|
QJson::Serializer ser;
|
||||||
@@ -680,45 +727,11 @@ void Servent::handoverSocket( Connection* conn, QTcpSocketExtra* sock )
|
|||||||
conn->start( sock );
|
conn->start( sock );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Servent::socketError( QAbstractSocket::SocketError e )
|
|
||||||
{
|
|
||||||
QTcpSocketExtra* sock = (QTcpSocketExtra*)sender();
|
|
||||||
if ( !sock )
|
|
||||||
{
|
|
||||||
tLog() << "SocketError, sock is null";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !sock->_conn.isNull() )
|
|
||||||
{
|
|
||||||
Connection* conn = sock->_conn.data();
|
|
||||||
tLog() << "Servent::SocketError:" << e << conn->id() << conn->name();
|
|
||||||
|
|
||||||
if ( !sock->_disowned )
|
|
||||||
{
|
|
||||||
// connection will delete if we already transferred ownership, otherwise:
|
|
||||||
sock->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->markAsFailed(); // will emit failed, then finished
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tLog() << "SocketError, connection is null";
|
|
||||||
sock->deleteLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Servent::connectToPeer( const peerinfo_ptr& peerInfo )
|
Servent::connectToPeer( const peerinfo_ptr& peerInfo )
|
||||||
{
|
{
|
||||||
Q_ASSERT( this->thread() == QThread::currentThread() );
|
Q_ASSERT( this->thread() == QThread::currentThread() );
|
||||||
|
|
||||||
SipInfo sipInfo = peerInfo->sipInfo();
|
|
||||||
|
|
||||||
peerInfoDebug( peerInfo ) << "connectToPeer: search for already established connections to the same nodeid:" << m_controlconnections.count() << "connections";
|
peerInfoDebug( peerInfo ) << "connectToPeer: search for already established connections to the same nodeid:" << m_controlconnections.count() << "connections";
|
||||||
if ( peerInfo->controlConnection() )
|
if ( peerInfo->controlConnection() )
|
||||||
delete peerInfo->controlConnection();
|
delete peerInfo->controlConnection();
|
||||||
@@ -731,7 +744,7 @@ Servent::connectToPeer( const peerinfo_ptr& peerInfo )
|
|||||||
{
|
{
|
||||||
Q_ASSERT( c );
|
Q_ASSERT( c );
|
||||||
|
|
||||||
if ( c->id() == sipInfo.nodeId() )
|
if ( c->id() == peerInfo->nodeId() )
|
||||||
{
|
{
|
||||||
conn = c;
|
conn = c;
|
||||||
|
|
||||||
@@ -773,8 +786,7 @@ Servent::connectToPeer( const peerinfo_ptr& peerInfo )
|
|||||||
|
|
||||||
QVariantMap m;
|
QVariantMap m;
|
||||||
m["conntype"] = "accept-offer";
|
m["conntype"] = "accept-offer";
|
||||||
m["key"] = sipInfo.key();
|
m["key"] = peerInfo->key();
|
||||||
m["port"] = externalPort();
|
|
||||||
m["nodeid"] = Database::instance()->impl()->dbid();
|
m["nodeid"] = Database::instance()->impl()->dbid();
|
||||||
|
|
||||||
peerInfoDebug(peerInfo) << "No match found, creating a new ControlConnection...";
|
peerInfoDebug(peerInfo) << "No match found, creating a new ControlConnection...";
|
||||||
@@ -784,58 +796,132 @@ Servent::connectToPeer( const peerinfo_ptr& peerInfo )
|
|||||||
|
|
||||||
if ( peerInfo->id().length() )
|
if ( peerInfo->id().length() )
|
||||||
conn->setName( peerInfo->contactId() );
|
conn->setName( peerInfo->contactId() );
|
||||||
if ( sipInfo.nodeId().length() )
|
if ( peerInfo->nodeId().length() )
|
||||||
conn->setId( sipInfo.nodeId() );
|
conn->setId( peerInfo->nodeId() );
|
||||||
|
|
||||||
conn->setProperty( "nodeid", sipInfo.nodeId() );
|
conn->setProperty( "nodeid", peerInfo->nodeId() );
|
||||||
|
|
||||||
registerControlConnection( conn );
|
registerControlConnection( conn );
|
||||||
connectToPeer( sipInfo.host(), sipInfo.port(), sipInfo.key(), conn );
|
connectToPeer( peerInfo->sipInfo(), conn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Servent::connectToPeer( const QString& ha, int port, const QString& key, Connection* conn )
|
Servent::connectToPeer(const QList<SipInfo>& sipInfoList, Connection* conn )
|
||||||
{
|
{
|
||||||
tDebug( LOGVERBOSE ) << "Servent::connectToPeer:" << ha << ":" << port
|
if ( sipInfoList.isEmpty() )
|
||||||
<< thread() << QThread::currentThread();
|
|
||||||
|
|
||||||
Q_ASSERT( port > 0 );
|
|
||||||
Q_ASSERT( conn );
|
|
||||||
|
|
||||||
if ( ( ha == m_externalAddress.toString() || ha == m_externalHostname ) &&
|
|
||||||
( port == m_externalPort ) )
|
|
||||||
{
|
{
|
||||||
tDebug() << "ERROR: Tomahawk won't try to connect to" << ha << ":" << port << ": identified as ourselves.";
|
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "No more possible SIP endpoints for " << conn->name() << " skipping.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QList<SipInfo> sipInfo = QList<SipInfo>(sipInfoList);
|
||||||
|
// Use first available SIP endpoint and remove it from the list
|
||||||
|
SipInfo info = sipInfo.takeFirst();
|
||||||
|
if ( !info.isVisible() )
|
||||||
|
{
|
||||||
|
// Try next SipInfo, we can't connect to this one
|
||||||
|
connectToPeer( sipInfo, conn );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( key.length() && conn->firstMessage().isNull() )
|
tDebug( LOGVERBOSE ) << "Servent::connectToPeer:" << info.host() << ":" << info.port() << thread() << QThread::currentThread();
|
||||||
|
|
||||||
|
Q_ASSERT( info.port() > 0 );
|
||||||
|
Q_ASSERT( conn );
|
||||||
|
|
||||||
|
// Check that we are not connecting to ourselves
|
||||||
|
foreach( QHostAddress ha, m_externalAddresses )
|
||||||
|
{
|
||||||
|
if ( QHostAddress( info.host() ) == ha)
|
||||||
|
{
|
||||||
|
tDebug() << "Tomahawk won't try to connect to" << info.host() << ":" << info.port() << ": same IP as ourselves.";
|
||||||
|
connectToPeer( sipInfo, conn );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( info.host() == m_externalHostname )
|
||||||
|
{
|
||||||
|
tDebug() << "Tomahawk won't try to connect to" << info.host() << ":" << info.port() << ": same IP as ourselves.";
|
||||||
|
connectToPeer( sipInfo, conn );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( info.key().length() && conn->firstMessage().isNull() )
|
||||||
{
|
{
|
||||||
QVariantMap m;
|
QVariantMap m;
|
||||||
m["conntype"] = "accept-offer";
|
m["conntype"] = "accept-offer";
|
||||||
m["key"] = key;
|
m["key"] = info.key();
|
||||||
m["port"] = externalPort();
|
|
||||||
m["controlid"] = Database::instance()->impl()->dbid();
|
m["controlid"] = Database::instance()->impl()->dbid();
|
||||||
conn->setFirstMessage( m );
|
conn->setFirstMessage( m );
|
||||||
}
|
}
|
||||||
|
|
||||||
QTcpSocketExtra* sock = new QTcpSocketExtra();
|
QTcpSocketExtra* sock = new QTcpSocketExtra();
|
||||||
|
sock->setConnectTimeout( CONNECT_TIMEOUT );
|
||||||
sock->_disowned = false;
|
sock->_disowned = false;
|
||||||
sock->_conn = conn;
|
sock->_conn = conn;
|
||||||
sock->_outbound = true;
|
sock->_outbound = true;
|
||||||
|
|
||||||
connect( sock, SIGNAL( connected() ), SLOT( socketConnected() ) );
|
connect( sock, SIGNAL( connected() ), SLOT( socketConnected() ) );
|
||||||
connect( sock, SIGNAL( error( QAbstractSocket::SocketError ) ),
|
NewClosure( sock, SIGNAL( error( QAbstractSocket::SocketError ) ),
|
||||||
SLOT( socketError( QAbstractSocket::SocketError ) ) );
|
this, SLOT( connectToPeerFailed( QAbstractSocket::SocketError, QPair<QList<SipInfo>, Connection*> ) ),
|
||||||
|
QPair<QList<SipInfo>, Connection*>(sipInfo, conn) );
|
||||||
|
|
||||||
if ( !conn->peerIpAddress().isNull() )
|
if ( !conn->peerIpAddress().isNull() )
|
||||||
sock->connectToHost( conn->peerIpAddress(), port, QTcpSocket::ReadWrite );
|
sock->connectToHost( conn->peerIpAddress(), info.port(), QTcpSocket::ReadWrite );
|
||||||
else
|
else
|
||||||
sock->connectToHost( ha, port, QTcpSocket::ReadWrite );
|
sock->connectToHost( info.host(), info.port(), QTcpSocket::ReadWrite );
|
||||||
sock->moveToThread( thread() );
|
sock->moveToThread( thread() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Servent::connectToPeerFailed( QAbstractSocket::SocketError e, QPair<QList<SipInfo>, Connection*> pair )
|
||||||
|
{
|
||||||
|
QList<SipInfo> sipInfo = pair.first;
|
||||||
|
Connection* conn = pair.second;
|
||||||
|
|
||||||
|
// Call default handler
|
||||||
|
socketError( e );
|
||||||
|
|
||||||
|
if ( e != QAbstractSocket::SocketResourceError )
|
||||||
|
{
|
||||||
|
// If we do not have run out of resource, try next SipInfo
|
||||||
|
connectToPeer( sipInfo, conn );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Servent::socketError( QAbstractSocket::SocketError e )
|
||||||
|
{
|
||||||
|
QTcpSocketExtra* sock = (QTcpSocketExtra*)sender();
|
||||||
|
if ( !sock )
|
||||||
|
{
|
||||||
|
tLog() << "SocketError, sock is null";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !sock->_conn.isNull() )
|
||||||
|
{
|
||||||
|
Connection* conn = sock->_conn.data();
|
||||||
|
tLog() << "Servent::SocketError:" << e << conn->id() << conn->name();
|
||||||
|
|
||||||
|
if ( !sock->_disowned )
|
||||||
|
{
|
||||||
|
// connection will delete if we already transferred ownership, otherwise:
|
||||||
|
sock->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->markAsFailed(); // will emit failed, then finished
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tLog() << "SocketError, connection is null";
|
||||||
|
sock->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Servent::reverseOfferRequest( ControlConnection* orig_conn, const QString& theirdbid, const QString& key, const QString& theirkey )
|
Servent::reverseOfferRequest( ControlConnection* orig_conn, const QString& theirdbid, const QString& key, const QString& theirkey )
|
||||||
@@ -854,13 +940,11 @@ Servent::reverseOfferRequest( ControlConnection* orig_conn, const QString& their
|
|||||||
QVariantMap m;
|
QVariantMap m;
|
||||||
m["conntype"] = "push-offer";
|
m["conntype"] = "push-offer";
|
||||||
m["key"] = theirkey;
|
m["key"] = theirkey;
|
||||||
m["port"] = externalPort();
|
|
||||||
m["controlid"] = Database::instance()->impl()->dbid();
|
m["controlid"] = Database::instance()->impl()->dbid();
|
||||||
new_conn->setFirstMessage( m );
|
new_conn->setFirstMessage( m );
|
||||||
createParallelConnection( orig_conn, new_conn, QString() );
|
createParallelConnection( orig_conn, new_conn, QString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return the appropriate connection for a given offer key, or NULL if invalid
|
// return the appropriate connection for a given offer key, or NULL if invalid
|
||||||
Connection*
|
Connection*
|
||||||
Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString &key, const QHostAddress peer )
|
Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString &key, const QHostAddress peer )
|
||||||
|
@@ -21,8 +21,8 @@
|
|||||||
#ifndef SERVENT_H
|
#ifndef SERVENT_H
|
||||||
#define SERVENT_H
|
#define SERVENT_H
|
||||||
|
|
||||||
// time before new connection terminates if no auth received
|
// time before new connection terminate if it could not be established
|
||||||
#define AUTH_TIMEOUT 180000
|
#define CONNECT_TIMEOUT 10000
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include "Typedefs.h"
|
#include "Typedefs.h"
|
||||||
#include "Msg.h"
|
#include "Msg.h"
|
||||||
|
#include "network/QTcpSocketExtra.h"
|
||||||
|
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
@@ -58,48 +59,19 @@ class SipInfo;
|
|||||||
typedef boost::function< void( const Tomahawk::result_ptr&,
|
typedef boost::function< void( const Tomahawk::result_ptr&,
|
||||||
boost::function< void( QSharedPointer< QIODevice >& ) > )> IODeviceFactoryFunc;
|
boost::function< void( QSharedPointer< QIODevice >& ) > )> IODeviceFactoryFunc;
|
||||||
|
|
||||||
// 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.
|
|
||||||
class DLLEXPORT QTcpSocketExtra : public QTcpSocket
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
QTcpSocketExtra() : QTcpSocket()
|
|
||||||
{
|
|
||||||
QTimer::singleShot( AUTH_TIMEOUT, this, SLOT( authTimeout() ) ) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPointer<Connection> _conn;
|
|
||||||
bool _outbound;
|
|
||||||
bool _disowned;
|
|
||||||
msg_ptr _msg;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void authTimeout()
|
|
||||||
{
|
|
||||||
if( _disowned )
|
|
||||||
return;
|
|
||||||
|
|
||||||
qDebug() << "Connection timed out before providing a valid offer-key";
|
|
||||||
this->disconnectFromHost();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLLEXPORT Servent : public QTcpServer
|
class DLLEXPORT Servent : public QTcpServer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Servent* instance();
|
static Servent* instance();
|
||||||
|
static bool isValidExternalIP( const QHostAddress& addr );
|
||||||
|
|
||||||
explicit Servent( QObject* parent = 0 );
|
explicit Servent( QObject* parent = 0 );
|
||||||
virtual ~Servent();
|
virtual ~Servent();
|
||||||
|
|
||||||
bool startListening( QHostAddress ha, bool upnp, int port );
|
bool startListening( QHostAddress ha, bool upnp, int port );
|
||||||
|
|
||||||
int port() const { return m_port; }
|
|
||||||
|
|
||||||
// creates new token that allows a controlconnection to be set up
|
// creates new token that allows a controlconnection to be set up
|
||||||
QString createConnectionKey( const QString& name = "", const QString &nodeid = "", const QString &key = "", bool onceOnly = true );
|
QString createConnectionKey( const QString& name = "", const QString &nodeid = "", const QString &key = "", bool onceOnly = true );
|
||||||
|
|
||||||
@@ -118,12 +90,18 @@ public slots:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void connectToPeer( const Tomahawk::peerinfo_ptr& ha );
|
void connectToPeer( const Tomahawk::peerinfo_ptr& ha );
|
||||||
void connectToPeer( const QString& ha, int port, const QString& key, Connection* conn );
|
void connectToPeer( const QList<SipInfo>& sipInfoList, Connection* conn );
|
||||||
void reverseOfferRequest( ControlConnection* orig_conn, const QString &theirdbid, const QString& key, const QString& theirkey );
|
void reverseOfferRequest( ControlConnection* orig_conn, const QString &theirdbid, const QString& key, const QString& theirkey );
|
||||||
|
|
||||||
bool visibleExternally() const { return !m_externalHostname.isNull() || (m_externalPort > 0 && !m_externalAddress.isNull()); }
|
bool visibleExternally() const { return (!m_externalHostname.isNull()) || (m_externalAddresses.length() > 0); }
|
||||||
QString externalAddress() const { return !m_externalHostname.isNull() ? m_externalHostname : m_externalAddress.toString(); }
|
//! The port this Peer listens directly (per default)
|
||||||
int externalPort() const { return m_externalPort; }
|
int port() const { return m_port; }
|
||||||
|
//! The IP addresses this Peer listens directly (per default)
|
||||||
|
QList< QHostAddress > addresses() const { return m_externalAddresses; }
|
||||||
|
//! An additional address this peer listens to, e.g. via UPnP.
|
||||||
|
QString additionalAddress() const { return m_externalHostname; }
|
||||||
|
//! An additional port this peer listens to, e.g. via UPnP (only in combination with additionalAddress.
|
||||||
|
int additionalPort() const { return m_externalPort; }
|
||||||
|
|
||||||
static bool isIPWhitelisted( QHostAddress ip );
|
static bool isIPWhitelisted( QHostAddress ip );
|
||||||
|
|
||||||
@@ -138,7 +116,7 @@ public:
|
|||||||
void localFileIODeviceFactory( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
|
void localFileIODeviceFactory( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
|
||||||
void httpIODeviceFactory( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
|
void httpIODeviceFactory( const Tomahawk::result_ptr& result, boost::function< void ( QSharedPointer< QIODevice >& ) > callback );
|
||||||
|
|
||||||
bool isReady() const { return m_ready; };
|
bool isReady() const { return m_ready; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dbSyncTriggered();
|
void dbSyncTriggered();
|
||||||
@@ -150,10 +128,10 @@ protected:
|
|||||||
void incomingConnection( int sd );
|
void incomingConnection( int sd );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setInternalAddress();
|
|
||||||
void setExternalAddress( QHostAddress ha, unsigned int port );
|
void setExternalAddress( QHostAddress ha, unsigned int port );
|
||||||
|
|
||||||
void socketError( QAbstractSocket::SocketError );
|
void connectToPeerFailed( QAbstractSocket::SocketError e, QPair<QList<SipInfo>, Connection*> pair );
|
||||||
|
void socketError( QAbstractSocket::SocketError e );
|
||||||
void createParallelConnection( Connection* orig_conn, Connection* new_conn, const QString& key );
|
void createParallelConnection( Connection* orig_conn, Connection* new_conn, const QString& key );
|
||||||
|
|
||||||
void registerStreamConnection( StreamConnection* );
|
void registerStreamConnection( StreamConnection* );
|
||||||
@@ -168,7 +146,6 @@ private slots:
|
|||||||
Connection* claimOffer( ControlConnection* cc, const QString &nodeid, const QString &key, const QHostAddress peer = QHostAddress::Any );
|
Connection* claimOffer( ControlConnection* cc, const QString &nodeid, const QString &key, const QHostAddress peer = QHostAddress::Any );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isValidExternalIP( const QHostAddress& addr ) const;
|
|
||||||
void handoverSocket( Connection* conn, QTcpSocketExtra* sock );
|
void handoverSocket( Connection* conn, QTcpSocketExtra* sock );
|
||||||
void printCurrentTransfers();
|
void printCurrentTransfers();
|
||||||
|
|
||||||
@@ -177,11 +154,16 @@ private:
|
|||||||
QMap< QString, QPointer< Connection > > m_offers;
|
QMap< QString, QPointer< Connection > > m_offers;
|
||||||
QStringList m_connectedNodes;
|
QStringList m_connectedNodes;
|
||||||
|
|
||||||
int m_port, m_externalPort;
|
//! The external port used by all address except those obtained via UPnP or the static configuration option
|
||||||
QHostAddress m_externalAddress;
|
int m_port;
|
||||||
|
//! Either the static set or the UPnP set external port
|
||||||
|
int m_externalPort;
|
||||||
|
//! All available external IPs
|
||||||
|
QList<QHostAddress> m_externalAddresses;
|
||||||
|
//! Either the static set or the UPnP set external host
|
||||||
QString m_externalHostname;
|
QString m_externalHostname;
|
||||||
|
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
bool m_lanHack;
|
|
||||||
bool m_noAuth;
|
bool m_noAuth;
|
||||||
|
|
||||||
// currently active file transfers:
|
// currently active file transfers:
|
||||||
|
@@ -202,9 +202,9 @@ PeerInfo::sipPlugin() const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PeerInfo::sendLocalSipInfo( const SipInfo& sipInfo )
|
PeerInfo::sendLocalSipInfo( const QList<SipInfo>& sipInfoList )
|
||||||
{
|
{
|
||||||
sipPlugin()->sendSipInfo( weakRef().toStrongRef(), sipInfo );
|
sipPlugin()->sendSipInfoList( weakRef().toStrongRef(), sipInfoList );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -228,6 +228,23 @@ PeerInfo::contactId() const
|
|||||||
return m_contactId;
|
return m_contactId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString
|
||||||
|
PeerInfo::nodeId() const
|
||||||
|
{
|
||||||
|
Q_ASSERT( m_sipInfo.length() > 0 );
|
||||||
|
// All sip infos share the same nodeId
|
||||||
|
return m_sipInfo.first().nodeId();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString
|
||||||
|
PeerInfo::key() const
|
||||||
|
{
|
||||||
|
Q_ASSERT( m_sipInfo.length() > 0 );
|
||||||
|
// All sip infos share the same key
|
||||||
|
return m_sipInfo.first().key();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PeerInfo::setStatus( PeerInfo::Status status )
|
PeerInfo::setStatus( PeerInfo::Status status )
|
||||||
@@ -259,19 +276,16 @@ PeerInfo::status() const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PeerInfo::setSipInfo( const SipInfo& sipInfo )
|
PeerInfo::setSipInfo( const QList<SipInfo>& sipInfo )
|
||||||
{
|
{
|
||||||
if ( sipInfo == m_sipInfo )
|
m_sipInfo = QList<SipInfo>(sipInfo);
|
||||||
return;
|
|
||||||
|
|
||||||
m_sipInfo = sipInfo;
|
|
||||||
|
|
||||||
tLog() << "id:" << id() << "info changed" << sipInfo;
|
tLog() << "id:" << id() << "info changed" << sipInfo;
|
||||||
emit sipInfoChanged();
|
emit sipInfoChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const SipInfo
|
const QList<SipInfo>
|
||||||
PeerInfo::sipInfo() const
|
PeerInfo::sipInfo() const
|
||||||
{
|
{
|
||||||
return m_sipInfo;
|
return m_sipInfo;
|
||||||
@@ -389,7 +403,6 @@ PeerInfo::setData( const QVariant& data )
|
|||||||
m_data = data;
|
m_data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
QVariant PeerInfo::data() const
|
QVariant PeerInfo::data() const
|
||||||
{
|
{
|
||||||
|
@@ -74,7 +74,7 @@ public:
|
|||||||
const QString id() const;
|
const QString id() const;
|
||||||
SipPlugin* sipPlugin() const;
|
SipPlugin* sipPlugin() const;
|
||||||
const QString debugName() const;
|
const QString debugName() const;
|
||||||
void sendLocalSipInfo( const SipInfo& sipInfo );
|
void sendLocalSipInfo( const QList<SipInfo>& sipInfoList );
|
||||||
|
|
||||||
QWeakPointer< Tomahawk::PeerInfo > weakRef();
|
QWeakPointer< Tomahawk::PeerInfo > weakRef();
|
||||||
void setWeakRef( QWeakPointer< Tomahawk::PeerInfo > weakRef );
|
void setWeakRef( QWeakPointer< Tomahawk::PeerInfo > weakRef );
|
||||||
@@ -96,8 +96,8 @@ public:
|
|||||||
void setStatus( Status status );
|
void setStatus( Status status );
|
||||||
Status status() const;
|
Status status() const;
|
||||||
|
|
||||||
void setSipInfo( const SipInfo& sipInfo );
|
void setSipInfo( const QList<SipInfo>& sipInfo );
|
||||||
const SipInfo sipInfo() const;
|
const QList<SipInfo> sipInfo() const;
|
||||||
|
|
||||||
void setFriendlyName( const QString& friendlyName );
|
void setFriendlyName( const QString& friendlyName );
|
||||||
const QString friendlyName() const;
|
const QString friendlyName() const;
|
||||||
@@ -112,6 +112,12 @@ public:
|
|||||||
void setData( const QVariant& data );
|
void setData( const QVariant& data );
|
||||||
const QVariant data() const;
|
const QVariant data() const;
|
||||||
|
|
||||||
|
//! Get the node id of this peer
|
||||||
|
const QString nodeId() const;
|
||||||
|
|
||||||
|
//! Get the authentication key for this host
|
||||||
|
const QString key() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sipInfoChanged();
|
void sipInfoChanged();
|
||||||
|
|
||||||
@@ -131,7 +137,7 @@ private:
|
|||||||
QString m_id;
|
QString m_id;
|
||||||
QString m_contactId;
|
QString m_contactId;
|
||||||
Status m_status;
|
Status m_status;
|
||||||
SipInfo m_sipInfo;
|
QList<SipInfo> m_sipInfo;
|
||||||
QString m_friendlyName;
|
QString m_friendlyName;
|
||||||
QString m_versionString;
|
QString m_versionString;
|
||||||
QVariant m_data;
|
QVariant m_data;
|
||||||
|
@@ -70,7 +70,8 @@ public slots:
|
|||||||
virtual void configurationChanged() = 0;
|
virtual void configurationChanged() = 0;
|
||||||
|
|
||||||
virtual void addContact( const QString& peerId, const QString& msg = QString() ) = 0;
|
virtual void addContact( const QString& peerId, const QString& msg = QString() ) = 0;
|
||||||
virtual void sendSipInfo( const Tomahawk::peerinfo_ptr& receiver, const SipInfo& info ) = 0;
|
//! Send a list of SipInfos to all contacts.
|
||||||
|
virtual void sendSipInfoList( const Tomahawk::peerinfo_ptr& receiver, const QList<SipInfo>& info ) = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void peerStatusChanged( const Tomahawk::peerinfo_ptr& );
|
void peerStatusChanged( const Tomahawk::peerinfo_ptr& );
|
||||||
|
@@ -64,24 +64,26 @@ DiagnosticsDialog::updateLogView()
|
|||||||
log.append( QString( "TOMAHAWK DIAGNOSTICS LOG -%1 \n\n" ).arg( QDateTime::currentDateTime().toString() ) );
|
log.append( QString( "TOMAHAWK DIAGNOSTICS LOG -%1 \n\n" ).arg( QDateTime::currentDateTime().toString() ) );
|
||||||
log.append( "TOMAHAWK-VERSION: " TOMAHAWK_VERSION "\n" );
|
log.append( "TOMAHAWK-VERSION: " TOMAHAWK_VERSION "\n" );
|
||||||
log.append( "PLATFORM: " TOMAHAWK_SYSTEM "\n\n");
|
log.append( "PLATFORM: " TOMAHAWK_SYSTEM "\n\n");
|
||||||
log.append( "NETWORK:\n General:\n" );
|
log.append( "NETWORK:\n Listening to:\n" );
|
||||||
|
|
||||||
if ( Servent::instance()->visibleExternally() )
|
if ( Servent::instance()->visibleExternally() )
|
||||||
{
|
{
|
||||||
log.append(
|
foreach ( QHostAddress ha, Servent::instance()->addresses() )
|
||||||
QString(
|
{
|
||||||
" visible: true\n"
|
if ( ha.protocol() == QAbstractSocket::IPv6Protocol )
|
||||||
" host: %1\n"
|
log.append( QString( " [%1]:%2\n" ).arg( ha.toString() ).arg( Servent::instance()->port() ) );
|
||||||
" port: %2\n"
|
else
|
||||||
"\n"
|
log.append( QString( " %1:%2\n" ).arg( ha.toString() ).arg( Servent::instance()->port() ) );
|
||||||
).arg( Servent::instance()->externalAddress() )
|
}
|
||||||
.arg( Servent::instance()->externalPort() )
|
if ( !Servent::instance()->additionalAddress().isNull() )
|
||||||
|
{
|
||||||
|
log.append( QString( " [%1]:%2\n" ).arg( Servent::instance()->additionalAddress() ).arg( Servent::instance()->additionalPort() ) );
|
||||||
|
}
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log.append( " visible: false\n" );
|
log.append( " not listening to any interface, outgoing connections only\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
log.append( "\n\nINFOPLUGINS:\n" );
|
log.append( "\n\nINFOPLUGINS:\n" );
|
||||||
@@ -162,54 +164,17 @@ DiagnosticsDialog::accountLog( Tomahawk::Accounts::Account* account )
|
|||||||
|
|
||||||
foreach( const Tomahawk::peerinfo_ptr& peerInfo, account->sipPlugin()->peersOnline() )
|
foreach( const Tomahawk::peerinfo_ptr& peerInfo, account->sipPlugin()->peersOnline() )
|
||||||
{
|
{
|
||||||
QString peerId = peerInfo->id();
|
accountInfo.append( QString( " %1: " ).arg( peerInfo->id() ) );
|
||||||
QString versionString = peerInfo->versionString();
|
foreach ( SipInfo info, peerInfo->sipInfo() )
|
||||||
SipInfo sipInfo = peerInfo->sipInfo();
|
|
||||||
if ( !sipInfo.isValid() )
|
|
||||||
{
|
{
|
||||||
accountInfo.append(
|
if ( info.isValid() )
|
||||||
QString(" %1: %2 %3" /*"(%4)"*/)
|
accountInfo.append( QString( "[%1]:%2; " ).arg( info.host() ).arg( info.port() ) );
|
||||||
.arg( peerInfo->id() )
|
|
||||||
.arg( "sipinfo invalid" )
|
|
||||||
.arg( versionString )
|
|
||||||
// .arg( connected ? "connected" : "not connected")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if ( sipInfo.isVisible() )
|
|
||||||
{
|
|
||||||
accountInfo.append(
|
|
||||||
QString(" %1: %2:%3 %4" /*" (%5)"*/)
|
|
||||||
.arg( peerId )
|
|
||||||
.arg( sipInfo.host() )
|
|
||||||
.arg( sipInfo.port() )
|
|
||||||
.arg( versionString )
|
|
||||||
// .arg( connected ? "connected" : "not connected")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
accountInfo.append( "SipInfo invalid; " );
|
||||||
accountInfo.append(
|
|
||||||
QString(" %1: visible: false %2" /*" (%3)"*/)
|
|
||||||
.arg( peerId )
|
|
||||||
.arg( versionString )
|
|
||||||
// .arg( connected ? "connected" : "not connected")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
if ( ( peerInfo->sipInfo().length() == 1 ) && ( !peerInfo->sipInfo().first().isVisible() ) || ( peerInfo->sipInfo().length() == 0 ) )
|
||||||
if( sipInfo.isValid() )
|
accountInfo.append( "(outbound connections only) ");
|
||||||
{
|
accountInfo.append( QString( " (%1)\n" ).arg( peerInfo->versionString() ) );
|
||||||
if( !Servent::instance()->visibleExternally() ||
|
|
||||||
Servent::instance()->externalAddress() < sipInfo.host() ||
|
|
||||||
( Servent::instance()->externalAddress() == sipInfo.host() && Servent::instance()->externalPort() < sipInfo.port() ) )
|
|
||||||
{
|
|
||||||
accountInfo.append(" (outbound)");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
accountInfo.append(" (inbound)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
accountInfo.append("\n");
|
|
||||||
}
|
}
|
||||||
accountInfo.append( "\n" );
|
accountInfo.append( "\n" );
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user