diff options
| author | Ian Geiser <ian.geiser@gmail.com> | 2009-11-11 11:09:28 +0000 |
|---|---|---|
| committer | Ian Geiser <ian.geiser@gmail.com> | 2009-11-11 11:09:28 +0000 |
| commit | d9745efcd24e547ba0185732bfc9b0c9f931162e (patch) | |
| tree | c66bc1c52329ea1a21771b74845009a9a0addd70 | |
| parent | 5b0870ddaac421af2639058648a218c7061cdd6f (diff) | |
| download | qxmpp-d9745efcd24e547ba0185732bfc9b0c9f931162e.tar.gz | |
This is the rest of XEP-009. This needs some cleanup and testing still. I am not happy with the implementation, but I am happy with the interface on QXmppClient.
| -rw-r--r-- | example/example.pro | 3 | ||||
| -rw-r--r-- | example/example_6_rpcClient/example_6_rpcClient.pro | 15 | ||||
| -rw-r--r-- | example/example_6_rpcClient/main.cpp | 39 | ||||
| -rw-r--r-- | example/example_6_rpcClient/rpcClient.cpp | 66 | ||||
| -rw-r--r-- | example/example_6_rpcClient/rpcClient.h | 46 | ||||
| -rw-r--r-- | source/QXmppClient.cpp | 36 | ||||
| -rw-r--r-- | source/QXmppClient.h | 14 | ||||
| -rw-r--r-- | source/QXmppInvokable.h | 6 | ||||
| -rw-r--r-- | source/QXmppRemoteMethod.cpp | 51 | ||||
| -rw-r--r-- | source/QXmppRemoteMethod.h | 41 | ||||
| -rw-r--r-- | source/QXmppStream.cpp | 12 | ||||
| -rw-r--r-- | source/QXmppStream.h | 4 | ||||
| -rw-r--r-- | source/source.pro | 6 |
13 files changed, 334 insertions, 5 deletions
diff --git a/example/example.pro b/example/example.pro index c1700be6..612ec5b9 100644 --- a/example/example.pro +++ b/example/example.pro @@ -5,5 +5,6 @@ SUBDIRS = example_0_connected\ example_2_rosterHandling\ example_3_ibbTransferSource\ example_4_ibbTransferTarget\ - example_5_rpcInterface + example_5_rpcInterface\ + example_6_rpcClient diff --git a/example/example_6_rpcClient/example_6_rpcClient.pro b/example/example_6_rpcClient/example_6_rpcClient.pro new file mode 100644 index 00000000..3bfd6032 --- /dev/null +++ b/example/example_6_rpcClient/example_6_rpcClient.pro @@ -0,0 +1,15 @@ +TEMPLATE = app +TARGET = example_6_rpcClient +SOURCES += main.cpp \ + rpcClient.cpp +HEADERS += rpcClient.h +INCLUDEPATH += ../../source +QT += network \ + xml +CONFIG += console \ + debug_and_release +CONFIG(debug, debug|release):LIBS += -L../../source/debug \ + -lQXmppClient_d +else:LIBS += -L../../source/release \ + -lQXmppClient +OTHER_FILES += README diff --git a/example/example_6_rpcClient/main.cpp b/example/example_6_rpcClient/main.cpp new file mode 100644 index 00000000..35f1dd8d --- /dev/null +++ b/example/example_6_rpcClient/main.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008-2009 QXmpp Developers + * + * Author: + * Ian Reinhart Geiser + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + */ + + +#include <QtCore/QCoreApplication> +#include "rpcClient.h" +#include "QXmppLogger.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + QXmppLogger::getLogger()->setLoggingType(QXmppLogger::STDOUT); + + rpcClient client; + client.getConfiguration().setUseSASLAuthentication( false ); + client.connectToServer("jabber.geiseri.com", "client", "Passw0rd", "geiseri.com"); + return a.exec(); +} diff --git a/example/example_6_rpcClient/rpcClient.cpp b/example/example_6_rpcClient/rpcClient.cpp new file mode 100644 index 00000000..1723feeb --- /dev/null +++ b/example/example_6_rpcClient/rpcClient.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2008-2009 QXmpp Developers + * + * Author: + * Ian Reinhart Geiser + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + */ + + +#include "rpcClient.h" +#include "QXmppRemoteMethod.h" +#include <qdebug.h> +#include <QTimer> + +rpcClient::rpcClient(QObject *parent) + : QXmppClient(parent) +{ + connect( this, SIGNAL(connected()), this, SLOT(isConnected())); +} + +rpcClient::~rpcClient() +{ + +} + +void rpcClient::isConnected() +{ + //We need to wait until we have sent the presense stuff, or for some + //reason the server ignores us... + QTimer::singleShot(5000, this, SLOT(invokeRemoteMethod())); +} + +void rpcClient::invokeRemoteMethod() +{ + QXmppRemoteMethodResult methodResult = callRemoteMethod( + "server@geiseri.com/QXmpp", "RemoteInterface.echoString", "This is a test" ); + if( methodResult.hasError ) + error( methodResult.code, methodResult.errorMessage ); + else + result( methodResult.result ); +} + +void rpcClient::result(const QVariant &value ) +{ + qDebug() << "Result:" << value; +} + +void rpcClient::error( int code, const QString &message ) +{ + qDebug() << "Error:" << code << message; +} diff --git a/example/example_6_rpcClient/rpcClient.h b/example/example_6_rpcClient/rpcClient.h new file mode 100644 index 00000000..9079a908 --- /dev/null +++ b/example/example_6_rpcClient/rpcClient.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2009 QXmpp Developers + * + * Author: + * Ian Reinhart Geiser + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + */ + + +#ifndef RPCCLIENT_H +#define RPCCLIENT_H + +#include "QXmppClient.h" + +class rpcClient : public QXmppClient +{ + Q_OBJECT + +public: + rpcClient(QObject *parent = 0); + ~rpcClient(); + +public slots: + void isConnected(); + void invokeRemoteMethod(); + void result(const QVariant &value ); + void error( int code, const QString &message ); + +}; + +#endif // RPCCLIENT_H diff --git a/source/QXmppClient.cpp b/source/QXmppClient.cpp index c8b16041..21c96d23 100644 --- a/source/QXmppClient.cpp +++ b/source/QXmppClient.cpp @@ -30,6 +30,7 @@ #include "QXmppIbbTransferManager.h" #include "QXmppInvokable.h" #include "QXmppRpcIq.h" +#include "QXmppRemoteMethod.h" #include "QXmppUtils.h" /// Creates a QXmppClient object. @@ -436,3 +437,38 @@ QXmppIbbTransferManager* QXmppClient::getIbbTransferManager() const { return m_ibbTransferManager; } + +QXmppRemoteMethodResult QXmppClient::callRemoteMethod( const QString &jid, + const QString &interface, + const QVariant &arg1, + const QVariant &arg2, + const QVariant &arg3, + const QVariant &arg4, + const QVariant &arg5, + const QVariant &arg6, + const QVariant &arg7, + const QVariant &arg8, + const QVariant &arg9, + const QVariant &arg10 ) +{ + QVariantList args; + if( arg1.isValid() ) args << arg1; + if( arg2.isValid() ) args << arg2; + if( arg3.isValid() ) args << arg3; + if( arg4.isValid() ) args << arg4; + if( arg5.isValid() ) args << arg5; + if( arg6.isValid() ) args << arg6; + if( arg7.isValid() ) args << arg7; + if( arg8.isValid() ) args << arg8; + if( arg9.isValid() ) args << arg9; + if( arg10.isValid() ) args << arg10; + + QXmppRemoteMethod method( jid, interface, args, this ); + connect( m_stream, SIGNAL(rpcCallResponse(QXmppRpcResponseIq)), + &method, SLOT(gotResult(QXmppRpcResponseIq))); + connect( m_stream, SIGNAL(rpcCallError(QXmppRpcErrorIq)), + &method, SLOT(gotError(QXmppRpcErrorIq))); + + + return method.call(); +} diff --git a/source/QXmppClient.h b/source/QXmppClient.h index 06d2b7b6..0503195b 100644 --- a/source/QXmppClient.h +++ b/source/QXmppClient.h @@ -59,6 +59,7 @@ class QXmppInvokable; class QXmppRpcInvokeIq; class QXmppRemoteMethod; class QXmppIbbTransferManager; +class QXmppRemoteMethodResult; class QXmppClient : public QObject { @@ -156,8 +157,21 @@ signals: public: QAbstractSocket::SocketError getSocketError(); + void addInvokableInterface( QXmppInvokable *interface ); void invokeInterfaceMethod( const QXmppRpcInvokeIq &iq ); + QXmppRemoteMethodResult callRemoteMethod( const QString &jid, + const QString &interface, + const QVariant &arg1 = QVariant(), + const QVariant &arg2 = QVariant(), + const QVariant &arg3 = QVariant(), + const QVariant &arg4 = QVariant(), + const QVariant &arg5 = QVariant(), + const QVariant &arg6 = QVariant(), + const QVariant &arg7 = QVariant(), + const QVariant &arg8 = QVariant(), + const QVariant &arg9 = QVariant(), + const QVariant &arg10 = QVariant() ); // QXmppStanza::Error getXmppStreamError(); diff --git a/source/QXmppInvokable.h b/source/QXmppInvokable.h index c7f9c687..a55299a3 100644 --- a/source/QXmppInvokable.h +++ b/source/QXmppInvokable.h @@ -52,9 +52,15 @@ public: */ static QList<QByteArray> paramTypes( const QList<QVariant> ¶ms ); + /** + * Reimplement this method to return a true if the invoking JID is allowed to execute the method. + */ virtual bool isAuthorized( const QString &jid ) const = 0; public slots: + /** + * This provides a list of interfaces for introspection of the presented interface. + */ QStringList interfaces() const; private: diff --git a/source/QXmppRemoteMethod.cpp b/source/QXmppRemoteMethod.cpp new file mode 100644 index 00000000..835a67bf --- /dev/null +++ b/source/QXmppRemoteMethod.cpp @@ -0,0 +1,51 @@ +#include "QXmppRemoteMethod.h" +#include "QXmppClient.h" +#include "QXmppUtils.h" +#include "QXmppConfiguration.h" + +#include <QEventLoop> +#include <QTimer> + +QXmppRemoteMethod::QXmppRemoteMethod(const QString &jid, const QString &method, const QVariantList &args, QXmppClient *client) : + QObject(client), m_client(client) +{ + m_payload.setId( generateStanzaHash() ); + m_payload.setTo( jid ); + m_payload.setFrom( client->getConfiguration().getJid() ); + m_payload.setInterface( method.section('.', 0 ) ); + m_payload.setMethod( method.section('.', 1) ); + m_payload.setPayload( args ); +} + +QXmppRemoteMethodResult QXmppRemoteMethod::call( ) +{ + QEventLoop loop(this); + connect( this, SIGNAL(callDone()), &loop, SLOT(quit())); + QTimer::singleShot(30000,&loop, SLOT(quit())); // Timeout incase the other end hangs... + + m_client->sendPacket( m_payload ); + + loop.exec( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents ); + return m_result; +} + +void QXmppRemoteMethod::gotError( const QXmppRpcErrorIq &iq ) +{ + if ( iq.getId() == m_payload.getId() ) + { + m_result.hasError = true; + m_result.errorMessage = iq.getError().getText(); + m_result.code = iq.getError().getType(); + emit callDone(); + } +} + +void QXmppRemoteMethod::gotResult( const QXmppRpcResponseIq &iq ) +{ + if ( iq.getId() == m_payload.getId() ) + { + m_result.hasError = false; + m_result.result = iq.getPayload(); + emit callDone(); + } +} diff --git a/source/QXmppRemoteMethod.h b/source/QXmppRemoteMethod.h new file mode 100644 index 00000000..b1a8c00d --- /dev/null +++ b/source/QXmppRemoteMethod.h @@ -0,0 +1,41 @@ +#ifndef QXMPPREMOTEMETHOD_H +#define QXMPPREMOTEMETHOD_H + +#include <QObject> +#include <QVariant> + +#include "QXmppRpcIq.h" + +class QXmppClient; +class QXmppStream; + +struct QXmppRemoteMethodResult { + QXmppRemoteMethodResult() : hasError(false), code(0) { } + bool hasError; + int code; + QString errorMessage; + QVariant result; +}; + +class QXmppRemoteMethod : public QObject +{ + Q_OBJECT +public: + QXmppRemoteMethod(const QString &jid, const QString &method, const QVariantList &args, QXmppClient *client); + QXmppRemoteMethodResult call( ); + +private slots: + void gotError( const QXmppRpcErrorIq &iq ); + void gotResult( const QXmppRpcResponseIq &iq ); + +signals: + void callDone(); + +private: + QXmppRpcInvokeIq m_payload; + QXmppClient *m_client; + QXmppRemoteMethodResult m_result; + +}; + +#endif // QXMPPREMOTEMETHOD_H diff --git a/source/QXmppStream.cpp b/source/QXmppStream.cpp index 307ad543..0e18b404 100644 --- a/source/QXmppStream.cpp +++ b/source/QXmppStream.cpp @@ -431,6 +431,18 @@ void QXmppStream::parser(const QByteArray& data) rpcIqPacket.parse(nodeRecv); m_client->invokeInterfaceMethod(rpcIqPacket); } + else if ( QXmppRpcResponseIq::isRpcResponseIq( nodeRecv ) ) + { + QXmppRpcResponseIq rpcResponseIq; + rpcResponseIq.parse(nodeRecv); + emit rpcCallResponse( rpcResponseIq ); + } + else if ( QXmppRpcErrorIq::isRpcErrorIq( nodeRecv ) ) + { + QXmppRpcErrorIq rpcErrorIq; + rpcErrorIq.parse(nodeRecv); + emit rpcCallError( rpcErrorIq ); + } else if(id == m_sessionId) { // get back add configuration whether to send diff --git a/source/QXmppStream.h b/source/QXmppStream.h index 8936abe3..d31e7a27 100644 --- a/source/QXmppStream.h +++ b/source/QXmppStream.h @@ -85,8 +85,8 @@ signals: void rosterRequestIqReceived(const QXmppRosterIq&); void vCardIqReceived(const QXmppVCard&); - void rpcRequestFinished( const QString &id, const QXmppRpcResponseIq& result ); - void rpcRequestError( const QString &id, const QXmppRpcErrorIq& err ); + void rpcCallResponse(const QXmppRpcResponseIq& result ); + void rpcCallError(const QXmppRpcErrorIq& err ); private slots: void socketHostFound(); diff --git a/source/source.pro b/source/source.pro index a61972ed..6866e87b 100644 --- a/source/source.pro +++ b/source/source.pro @@ -39,7 +39,8 @@ HEADERS += QXmppUtils.h \ QXmppIbbTransferManager.h \ xmlrpc.h \ QXmppInvokable.h \ - QXmppRpcIq.h + QXmppRpcIq.h \ + QXmppRemoteMethod.h # Source files SOURCES += QXmppUtils.cpp \ @@ -68,4 +69,5 @@ SOURCES += QXmppUtils.cpp \ QXmppIbbTransferManager.cpp \ xmlrpc.cpp \ QXmppInvokable.cpp \ - QXmppRpcIq.cpp + QXmppRpcIq.cpp \ + QXmppRemoteMethod.cpp |
