1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-11 16:44:05 +02:00

Add libsip_jreen

This commit is contained in:
Dominik Schmidt
2011-02-28 01:29:00 +01:00
parent 9967fea0ac
commit a728c9643c
6 changed files with 646 additions and 3 deletions

View File

@@ -1,7 +1,10 @@
IF(GLOOX_FOUND)
# only build one of them, if ENABLE_JREEN is true, GLOOX_FOUND is automatically set to "false"
IF( GLOOX_FOUND )
ADD_SUBDIRECTORY( jabber )
ENDIF(GLOOX_FOUND)
ENDIF( GLOOX_FOUND )
IF( ENABLE_JREEN )
ADD_SUBDIRECTORY( jreen )
ENDIF( ENABLE_JREEN)
ADD_SUBDIRECTORY( twitter )
ADD_SUBDIRECTORY( zeroconf )

View File

@@ -0,0 +1,46 @@
project( tomahawk )
include( ${QT_USE_FILE} )
add_definitions( ${QT_DEFINITIONS} )
add_definitions( -DQT_PLUGIN )
add_definitions( -DQT_SHARED )
add_definitions( -DSIPDLLEXPORT_PRO )
set( jabberSources
jabber.cpp
jabber_p.cpp
)
set( jabberHeaders
jabber.h
jabber_p.h
)
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
${QT_INCLUDE_DIR}
${LIBJREEN_INCLUDE_DIR}
)
qt4_wrap_cpp( jabberMoc ${jabberHeaders} )
add_library( sip_jreen SHARED ${jabberSources} ${jabberMoc} )
IF( WIN32 )
SET( OS_SPECIFIC_LINK_LIBRARIES
${OS_SPECIFIC_LINK_LIBRARIES}
"secur32.dll"
"crypt32.dll"
${TOMAHAWK_LIBRARIES}
)
ENDIF( WIN32 )
target_link_libraries( sip_jreen
${QT_LIBRARIES}
${LIBJREEN_LIBRARY}
${OS_SPECIFIC_LINK_LIBRARIES}
)
IF( APPLE )
# SET( CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-undefined dynamic_lookup" )
ENDIF( APPLE )
install( TARGETS sip_jreen DESTINATION lib )

146
src/sip/jreen/jabber.cpp Normal file
View File

@@ -0,0 +1,146 @@
#include "jabber.h"
#include "tomahawksettings.h"
#include <QtPlugin>
#include <QStringList>
#include <QInputDialog>
#include <QLineEdit>
#include <QMessageBox>
JabberPlugin::JabberPlugin()
: p( 0 )
{
m_menu = new QMenu(QString("JREEN (").append(accountName()).append(")"));
m_addFriendAction = m_menu->addAction("Add Friend...");
QAction *connectAction = m_menu->addAction("Connect");
connect(m_addFriendAction, SIGNAL(triggered()),
this, SLOT(showAddFriendDialog()));
connect(connectAction, SIGNAL(triggered()), SLOT(connectPlugin()));
}
JabberPlugin::~JabberPlugin()
{
delete p;
}
void
JabberPlugin::setProxy( QNetworkProxy* proxy )
{
p->setProxy( proxy );
}
const QString
JabberPlugin::name()
{
return QString( MYNAME );
}
const QString
JabberPlugin::friendlyName()
{
return QString( "Jabber" );
}
const QString
JabberPlugin::accountName()
{
return TomahawkSettings::instance()->jabberUsername();
}
QMenu*
JabberPlugin::menu()
{
return m_menu;
}
bool
JabberPlugin::connectPlugin( bool startup )
{
qDebug() << Q_FUNC_INFO;
if ( startup && !TomahawkSettings::instance()->jabberAutoConnect() )
return false;
QString jid = TomahawkSettings::instance()->jabberUsername();
QString server = TomahawkSettings::instance()->jabberServer();
QString password = TomahawkSettings::instance()->jabberPassword();
unsigned int port = TomahawkSettings::instance()->jabberPort();
QStringList splitJid = jid.split( '@', QString::SkipEmptyParts );
if ( splitJid.size() < 2 )
{
qDebug() << "JID did not have an @ in it, could not find a server part";
return false;
}
if ( server.isEmpty() )
server = splitJid[1];
if ( port < 1 || port > 65535 || jid.isEmpty() || password.isEmpty() )
{
qDebug() << "Jabber credentials look wrong, not connecting";
return false;
}
delete p;
p = new Jabber_p( jid, password, server, port );
QObject::connect( p, SIGNAL( peerOnline( QString ) ), SIGNAL( peerOnline( QString ) ) );
QObject::connect( p, SIGNAL( peerOffline( QString ) ), SIGNAL( peerOffline( QString ) ) );
QObject::connect( p, SIGNAL( msgReceived( QString, QString ) ), SIGNAL( msgReceived( QString, QString ) ) );
QObject::connect( p, SIGNAL( connected() ), SIGNAL( connected() ) );
QObject::connect( p, SIGNAL( disconnected() ), SIGNAL( disconnected() ) );
return true;
}
void
JabberPlugin::disconnectPlugin()
{
if ( p )
p->disconnect();
delete p;
p = 0;
}
void
JabberPlugin::sendMsg(const QString& to, const QString& msg)
{
if ( p )
p->sendMsg( to, msg );
}
void
JabberPlugin::broadcastMsg(const QString& msg)
{
if ( p )
p->broadcastMsg( msg );
}
void
JabberPlugin::addContact(const QString& jid, const QString& msg)
{
if ( p )
p->addContact( jid, msg );
}
void
JabberPlugin::showAddFriendDialog()
{
bool ok;
QString id = QInputDialog::getText( 0, tr( "Add Friend" ),
tr( "Enter Jabber ID:" ), QLineEdit::Normal,
"", &ok );
if ( !ok )
return;
qDebug() << "Attempting to add jabber contact to roster:" << id;
addContact( id );
}
Q_EXPORT_PLUGIN2( sip, JabberPlugin )

46
src/sip/jreen/jabber.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef JABBER_H
#define JABBER_H
#include "sip/SipPlugin.h"
#include "jabber_p.h"
#include "../sipdllmacro.h"
#define MYNAME "SIPJABBER"
class SIPDLLEXPORT JabberPlugin : public SipPlugin
{
Q_OBJECT
Q_INTERFACES( SipPlugin )
public:
JabberPlugin();
virtual ~JabberPlugin();
//FIXME: Make this more correct
virtual bool isValid() { return true; }
virtual const QString name();
virtual const QString friendlyName();
virtual const QString accountName();
virtual QMenu* menu();
void setProxy( QNetworkProxy* proxy );
public slots:
virtual bool connectPlugin( bool startup );
void disconnectPlugin();
void sendMsg( const QString& to, const QString& msg );
void broadcastMsg( const QString &msg );
void addContact( const QString &jid, const QString& msg = QString() );
private slots:
void onAuthError( int, const QString& );
void showAddFriendDialog();
private:
Jabber_p* p;
QMenu* m_menu;
QAction* m_addFriendAction;
};
#endif

320
src/sip/jreen/jabber_p.cpp Normal file
View File

@@ -0,0 +1,320 @@
#include "jabber_p.h"
#include <QDebug>
#include <QTime>
#include <QTimer>
#include <QString>
#include <QRegExp>
#include <QThread>
#include <utils/tomahawkutils.h>
#include <jreen/abstractroster.h>
#include <jreen/capabilities.h>
//remove
#include <QMessageBox>
#include <jreen/connection.h>
using namespace std;
#define TOMAHAWK_CAP_NODE_NAME QLatin1String("http://tomahawk-player.org/")
Jabber_p::Jabber_p( const QString& jid, const QString& password, const QString& server, const int port )
: QObject()
, m_server()
{
qDebug() << Q_FUNC_INFO;
//qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );
qsrand(QDateTime::currentDateTime().toTime_t());
m_presences[jreen::Presence::Available] = "available";
m_presences[jreen::Presence::Chat] = "chat";
m_presences[jreen::Presence::Away] = "away";
m_presences[jreen::Presence::DND] = "dnd";
m_presences[jreen::Presence::XA] = "xa";
m_presences[jreen::Presence::Unavailable] = "unavailable";
m_presences[jreen::Presence::Probe] = "probe";
m_presences[jreen::Presence::Error] = "error";
m_presences[jreen::Presence::Invalid] = "invalid";
m_jid = jreen::JID( jid );
m_client = new jreen::Client( jid, password );
m_client->setResource( QString( "tomahawk%1" ).arg( "DOMME" ) );
jreen::Capabilities::Ptr caps = m_client->presence().findExtension<jreen::Capabilities>();
caps->setNode(TOMAHAWK_CAP_NODE_NAME);
qDebug() << "Our JID set to:" << m_client->jid().full();
qDebug() << "Our Server set to:" << m_client->server();
qDebug() << "Our Port set to" << m_client->port();
connect(m_client->connection(), SIGNAL(error(SocketError)), SLOT(onError(SocketError)));
connect(m_client, SIGNAL(serverFeaturesReceived(QSet<QString>)), SLOT(onConnect()));
connect(m_client, SIGNAL(disconnected(jreen::Client::DisconnectReason)), SLOT(onDisconnect(jreen::Client::DisconnectReason)));
connect(m_client, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroy()));
connect(m_client, SIGNAL(newMessage(jreen::Message)), SLOT(onNewMessage(jreen::Message)));
connect(m_client, SIGNAL(newPresence(jreen::Presence)), SLOT(onNewPresence(jreen::Presence)));
qDebug() << "Connecting to the XMPP server...";
m_client->connectToServer();
}
Jabber_p::~Jabber_p()
{
delete m_client;
}
void
Jabber_p::setProxy( QNetworkProxy* proxy )
{
qDebug() << Q_FUNC_INFO << "NOT IMPLEMENTED";
}
void
Jabber_p::disconnect()
{
if ( m_client )
{
m_client->disconnect();
}
}
void
Jabber_p::sendMsg( const QString& to, const QString& msg )
{
qDebug() << Q_FUNC_INFO;
if ( QThread::currentThread() != thread() )
{
qDebug() << Q_FUNC_INFO << "invoking in correct thread, not"
<< QThread::currentThread();
QMetaObject::invokeMethod( this, "sendMsg",
Qt::QueuedConnection,
Q_ARG( const QString, to ),
Q_ARG( const QString, msg )
);
return;
}
if ( !m_client ) {
return;
}
qDebug() << Q_FUNC_INFO << to << msg;
jreen::Message m( jreen::Message::Chat, jreen::JID(to), msg);
m_client->send( m ); // assuming this is threadsafe
}
void
Jabber_p::broadcastMsg( const QString &msg )
{
qDebug() << Q_FUNC_INFO;
if ( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this, "broadcastMsg",
Qt::QueuedConnection,
Q_ARG(const QString, msg)
);
return;
}
if ( !m_client )
return;
foreach( const QString& jidstr, m_peers.keys() )
{
qDebug() << "Broadcasting to" << jidstr <<"...";
jreen::Message m(jreen::Message::Chat, jreen::JID(jidstr), msg, "");
m_client->send( m );
}
}
void
Jabber_p::addContact( const QString& jid, const QString& msg )
{
if ( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this, "addContact",
Qt::QueuedConnection,
Q_ARG(const QString, jid),
Q_ARG(const QString, msg)
);
return;
}
//FIXME: implement it when I dont suck that much :-)
//handleSubscription(Subscription());
return;
}
void
Jabber_p::onConnect()
{
qDebug() << Q_FUNC_INFO;
// update jid resource, servers like gtalk use resource binding and may
// have changed our requested /resource
if ( m_client->jid().resource() != m_jid.resource() )
{
m_jid.setResource( m_client->jid().resource() );
QString jidstr( m_jid.full() );
emit jidChanged( jidstr );
}
emit connected();
qDebug() << "Connected as:" << m_jid.full();
m_client->setPresence(jreen::Presence::Available, "Tomahawk-JREEN available", 1);
m_client->disco()->setSoftwareVersion( "Tomahawk JREEN", "0.0.0.0", "Foobar" );
m_client->setPingInterval(60000);
jreen::AbstractRoster *roster = new jreen::AbstractRoster( m_client );
roster->load();
}
void
Jabber_p::onDisconnect( jreen::Client::DisconnectReason reason )
{
qDebug() << Q_FUNC_INFO << reason;
QString error;
switch( reason )
{
case jreen::Client::User:
break;
case jreen::Client::HostUnknown:
break;
case jreen::Client::ItemNotFound:
break;
case jreen::Client::AuthorizationError:
break;
case jreen::Client::RemoteStreamError:
break;
case jreen::Client::RemoteConnectionFailed:
break;
case jreen::Client::InternalServerError:
break;
case jreen::Client::SystemShutdown:
break;
case jreen::Client::Conflict:
break;
case jreen::Client::Unknown:
default:
break;
}
qDebug() << "Connection error msg:" << error;
emit disconnected();
}
void
Jabber_p::onNewMessage( const jreen::Message& m )
{
QString from = m.from().full();
QString msg = m.body();
if ( msg.isEmpty() )
return;
qDebug() << Q_FUNC_INFO << m.from().full() << ":" << m.body();
emit msgReceived( from, msg );
}
void Jabber_p::onNewPresence( const jreen::Presence& presence)
{
jreen::JID jid = presence.from();
QString fulljid( jid.full() );
qDebug() << Q_FUNC_INFO << "handle presence" << fulljid << presence.subtype();
if( jid == m_jid )
return;
if ( presence.error() ) {
qDebug() << Q_FUNC_INFO << "presence error: no tomahawk";
return;
}
// ignore anyone not running tomahawk:
jreen::Capabilities::Ptr caps = presence.findExtension<jreen::Capabilities>();
if ( caps && (caps->node() == TOMAHAWK_CAP_NODE_NAME ))
{
qDebug() << Q_FUNC_INFO << presence.from().full() << "tomahawk detected by caps";
}
// this is a hack actually as long as gloox based libsip_jabber is around
// remove this as soon as everyone is using jreen
else if( presence.from().resource().startsWith( QLatin1String("tomahawk") ) )
{
qDebug() << Q_FUNC_INFO << presence.from().full() << "tomahawk detected by resource";
}
else if( caps && caps->node() != TOMAHAWK_CAP_NODE_NAME )
{
qDebug() << Q_FUNC_INFO << presence.from().full() << "*no tomahawk* detected by caps!" << caps->node() << presence.from().resource();
return;
}
else if( !caps )
{
qDebug() << Q_FUNC_INFO << "no tomahawk detected by resource and !caps";
return;
}
qDebug() << Q_FUNC_INFO << fulljid << " is a tomahawk resource.";
// "going offline" event
if ( !presenceMeansOnline( presence.subtype() ) &&
( !m_peers.contains( fulljid ) ||
presenceMeansOnline( m_peers.value( fulljid ) )
)
)
{
m_peers[ fulljid ] = presence.subtype();
qDebug() << Q_FUNC_INFO << "* Peer goes offline:" << fulljid;
emit peerOffline( fulljid );
return;
}
// "coming online" event
if( presenceMeansOnline( presence.subtype() ) &&
( !m_peers.contains( fulljid ) ||
!presenceMeansOnline( m_peers.value( fulljid ) )
)
)
{
m_peers[ fulljid ] = presence.subtype();
qDebug() << Q_FUNC_INFO << "* Peer goes online:" << fulljid;
emit peerOnline( fulljid );
return;
}
//qDebug() << "Updating presence data for" << fulljid;
m_peers[ fulljid ] = presence.subtype();
}
bool
Jabber_p::presenceMeansOnline( jreen::Presence::Type p )
{
switch(p)
{
case jreen::Presence::Invalid:
case jreen::Presence::Unavailable:
case jreen::Presence::Error:
return false;
break;
default:
return true;
}
}

82
src/sip/jreen/jabber_p.h Normal file
View File

@@ -0,0 +1,82 @@
/*
This is the Jabber client that the rest of the app sees
Gloox stuff should NOT leak outside this class.
We may replace jreen later, this interface should remain the same.
*/
#ifndef JABBER_P_H
#define JABBER_P_H
#include <QObject>
#include <QSharedPointer>
#include <QMap>
#include <QNetworkProxy>
#include <string>
#include <jreen/client.h>
#include <jreen/disco.h>
#include <jreen/message.h>
#include <jreen/messagesession.h>
#include <jreen/stanza.h>
#include <jreen/jreen.h>
#include <jreen/error.h>
#include <jreen/presence.h>
#include <jreen/vcard.h>
#include <jreen/abstractroster.h>
#if defined( WIN32 ) || defined( _WIN32 )
# include <windows.h>
#endif
#include "../sipdllmacro.h"
#include <jreen/connection.h>
class SIPDLLEXPORT Jabber_p :
public QObject
{
Q_OBJECT
public:
explicit Jabber_p( const QString& jid, const QString& password, const QString& server = "", const int port = -1 );
virtual ~Jabber_p();
void setProxy( QNetworkProxy* proxy );
signals:
void msgReceived( const QString&, const QString& ); //from, msg
void peerOnline( const QString& );
void peerOffline( const QString& );
void connected();
void disconnected();
void jidChanged( const QString& );
void authError( int, const QString& );
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 disconnect();
void onDisconnect(jreen::Client::DisconnectReason reason);
void onConnect();
void onDestroy();
private slots:
virtual void onNewPresence( const jreen::Presence& presence );
virtual void onNewMessage( const jreen::Message& msg );
virtual void onError( const jreen::Connection::SocketError& e )
{
qDebug() << e;
}
private:
bool presenceMeansOnline( jreen::Presence::Type p );
jreen::Client *m_client;
jreen::JID m_jid;
QMap<jreen::Presence::Type, QString> m_presences;
QMap<QString, jreen::Presence::Type> m_peers;
QString m_server;
};
#endif // JABBER_H