From c069b063d378a56c055268b22f273e74f829b37c Mon Sep 17 00:00:00 2001 From: Matt Broadstone Date: Wed, 28 May 2014 12:25:28 -0400 Subject: [PATCH] use Q_Q/Q_D from Qt rather than P_Q/P_D, style cleanups for Qt coding style delete exception-related code, as Qt does not officially support them anymore --- src/qamqp/amqp.cpp | 766 ++++++++-------- src/qamqp/amqp.h | 190 ++-- src/qamqp/amqp_authenticator.cpp | 95 +- src/qamqp/amqp_authenticator.h | 75 +- src/qamqp/amqp_channel.cpp | 613 +++++++------ src/qamqp/amqp_channel.h | 118 ++- src/qamqp/amqp_channel_p.h | 170 ++-- src/qamqp/amqp_connection.cpp | 766 ++++++++-------- src/qamqp/amqp_connection.h | 115 ++- src/qamqp/amqp_connection_p.h | 121 +-- src/qamqp/amqp_exchange.cpp | 528 ++++++----- src/qamqp/amqp_exchange.h | 140 +-- src/qamqp/amqp_exchange_p.h | 84 +- src/qamqp/amqp_frame.cpp | 1409 +++++++++++++++--------------- src/qamqp/amqp_frame.h | 842 +++++++++--------- src/qamqp/amqp_global.h | 55 +- src/qamqp/amqp_message.cpp | 15 + src/qamqp/amqp_message.h | 61 +- src/qamqp/amqp_network.cpp | 519 ++++++----- src/qamqp/amqp_network.h | 153 ++-- src/qamqp/amqp_p.h | 102 +-- src/qamqp/amqp_queue.cpp | 1112 +++++++++++------------ src/qamqp/amqp_queue.h | 186 ++-- src/qamqp/amqp_queue_p.h | 143 +-- src/qamqp/qamqp.pri | 57 +- 25 files changed, 4134 insertions(+), 4301 deletions(-) create mode 100644 src/qamqp/amqp_message.cpp diff --git a/src/qamqp/amqp.cpp b/src/qamqp/amqp.cpp index eea2049..0c1a998 100644 --- a/src/qamqp/amqp.cpp +++ b/src/qamqp/amqp.cpp @@ -1,386 +1,380 @@ -#include "amqp.h" -#include "amqp_p.h" - -#include -#include -#include "amqp_exchange.h" -#include "amqp_exchange_p.h" -#include "amqp_queue.h" -#include "amqp_queue_p.h" -#include "amqp_authenticator.h" - -using namespace QAMQP; - -namespace QAMQP -{ -struct ClientExceptionCleaner -{ - /* this cleans up when the constructor throws an exception */ - static inline void cleanup(Client *that, ClientPrivate *d) - { -#ifdef QT_NO_EXCEPTIONS - Q_UNUSED(that); - Q_UNUSED(d); -#else - Q_UNUSED(that); - Q_UNUSED(d); -#endif - } -}; -} - -////////////////////////////////////////////////////////////////////////// - -ClientPrivate::ClientPrivate( Client * q ) : - port(AMQPPORT) - , host(QString::fromLatin1(AMQPHOST)) - , virtualHost(QString::fromLatin1(AMQPVHOST)) - , pq_ptr(q) -{ - -} - - -ClientPrivate::~ClientPrivate() -{ - -} - -void ClientPrivate::init(QObject * parent) -{ - pq_func()->setParent(parent); - if(!network_) - { - network_ = new QAMQP::Network(pq_func()); - } - - if(!connection_) - { - connection_ = new QAMQP::Connection(pq_func()); - } - - network_->setMethodHandlerConnection(connection_); - - setAuth(new AMQPlainAuthenticator(QString::fromLatin1(AMQPLOGIN), QString::fromLatin1(AMQPPSWD))); - - QObject::connect(connection_, SIGNAL(connected()), pq_func(), SIGNAL(connected())); - QObject::connect(connection_, SIGNAL(disconnected()), pq_func(), SIGNAL(disconnected())); -} - -void ClientPrivate::init(QObject * parent, const QUrl & con) -{ - init(parent); - parseCnnString(con); - ClientPrivate::connect(); -} - - -void ClientPrivate::setAuth( Authenticator* auth ) -{ - auth_ = QSharedPointer(auth); -} - - -void ClientPrivate::printConnect() const -{ - QTextStream stream(stdout); - stream << "port = " << port << endl; - stream << "host = " << host << endl; - stream << "vhost = " << virtualHost << endl; - - if(auth_ && auth_->type() == "AMQPLAIN") - { - QSharedPointer a = auth_.staticCast(); - stream << "user = " << a->login() << endl; - stream << "passw = " << a->password() << endl; - } - -} - -void ClientPrivate::connect() -{ - ClientPrivate::sockConnect(); - ClientPrivate::login(); -} - -void ClientPrivate::parseCnnString( const QUrl & con ) -{ - P_Q(QAMQP::Client); - if(con.scheme() == AMQPSCHEME || con.scheme() == AMQPSSCHEME ) - { - q->setSsl(con.scheme() == AMQPSSCHEME); - q->setPassword(con.password()); - q->setUser(con.userName()); - q->setPort(con.port(AMQPPORT)); - q->setHost(con.host()); - q->setVirtualHost(con.path()); - } -} - -void ClientPrivate::sockConnect() -{ - if(network_->state() != QAbstractSocket::UnconnectedState ) - { - disconnect(); - } - network_->connectTo(host, port); -} - -void ClientPrivate::login() -{ - -} - -Exchange * ClientPrivate::createExchange(int channelNumber, const QString &name ) -{ - Exchange * exchange_ = new Exchange(channelNumber, pq_func()); - - network_->addMethodHandlerForChannel(exchange_->channelNumber(), exchange_); - - QObject::connect(connection_, SIGNAL(connected()), exchange_, SLOT(_q_open())); - exchange_->pd_func()->open(); - QObject::connect(pq_func(), SIGNAL(disconnected()), exchange_, SLOT(_q_disconnected())); - exchange_->setName(name); - - return exchange_; -} - -Queue * ClientPrivate::createQueue(int channelNumber, const QString &name ) -{ - Queue * queue_ = new Queue(channelNumber, pq_func()); - - network_->addMethodHandlerForChannel(queue_->channelNumber(), queue_); - network_->addContentHandlerForChannel(queue_->channelNumber(), queue_); - network_->addContentBodyHandlerForChannel(queue_->channelNumber(), queue_); - - QObject::connect(connection_, SIGNAL(connected()), queue_, SLOT(_q_open())); - queue_->pd_func()->open(); - QObject::connect(pq_func(), SIGNAL(disconnected()), queue_, SLOT(_q_disconnected())); - queue_->setName(name); - - return queue_; -} - - -void ClientPrivate::disconnect() -{ - P_Q(QAMQP::Client); - Q_UNUSED(q); - if(network_->state() != QAbstractSocket::UnconnectedState) - { - network_->QAMQP::Network::disconnect(); - connection_->pd_func()->connected = false; - emit pq_func()->disconnected(); - } -} - - -////////////////////////////////////////////////////////////////////////// - - -QAMQP::Client::Client( QObject * parent /*= 0*/ ) - : pd_ptr(new ClientPrivate(this)) -{ - QT_TRY { - pd_func()->init(parent); - } QT_CATCH(...) { - ClientExceptionCleaner::cleanup(this, pd_func()); - QT_RETHROW; - } -} - -QAMQP::Client::Client( const QUrl & connectionString, QObject * parent /*= 0*/ ) - : pd_ptr(new ClientPrivate(this)) -{ - QT_TRY { - pd_func()->init(parent, connectionString); - } QT_CATCH(...) { - ClientExceptionCleaner::cleanup(this, pd_func()); - QT_RETHROW; - } -} - -QAMQP::Client::~Client() -{ - QT_TRY { - QEvent e(QEvent::Destroy); - QCoreApplication::sendEvent(this, &e); - } QT_CATCH(const std::exception&) { - // if this fails we can't do anything about it but at least we are not allowed to throw. - } -} - -quint32 QAMQP::Client::port() const -{ - return pd_func()->port; -} - -void QAMQP::Client::setPort( quint32 port ) -{ - pd_func()->port = port; -} - -QString QAMQP::Client::host() const -{ - return pd_func()->host; -} - -void QAMQP::Client::setHost( const QString & host ) -{ - pd_func()->host = host; -} - -QString QAMQP::Client::virtualHost() const -{ - return pd_func()->virtualHost; -} - -void QAMQP::Client::setVirtualHost( const QString & virtualHost ) -{ - pd_func()->virtualHost = virtualHost; -} - -QString QAMQP::Client::user() const -{ - const Authenticator * auth = pd_func()->auth_.data(); - - if(auth && auth->type() == "AMQPLAIN") - { - const AMQPlainAuthenticator * a = static_cast(auth); - return a->login(); - } - return QString(); -} - -void QAMQP::Client::setUser( const QString & user ) -{ - Authenticator * auth = pd_func()->auth_.data(); - - if(auth && auth->type() == "AMQPLAIN") - { - AMQPlainAuthenticator * a = static_cast(auth); - a->setLogin(user); - } -} - -QString QAMQP::Client::password() const -{ - const Authenticator * auth = pd_func()->auth_.data(); - - if(auth && auth->type() == "AMQPLAIN") - { - const AMQPlainAuthenticator * a = static_cast(auth); - return a->password(); - } - return QString(); -} - -void QAMQP::Client::setPassword( const QString & password ) -{ - Authenticator * auth = pd_func()->auth_.data(); - - if(auth && auth->type() == "AMQPLAIN") - { - AMQPlainAuthenticator * a = static_cast(auth); - a->setPassword(password); - } -} - -void QAMQP::Client::printConnect() const -{ -#ifdef _DEBUG - pd_func()->printConnect(); -#endif // _DEBUG -} - -void QAMQP::Client::closeChannel() -{ - -} - -Exchange * QAMQP::Client::createExchange(int channelNumber) -{ - return pd_func()->createExchange(channelNumber, QString()); -} - -Exchange * QAMQP::Client::createExchange( const QString &name, int channelNumber ) -{ - return pd_func()->createExchange(channelNumber, name); -} - -Queue * QAMQP::Client::createQueue(int channelNumber) -{ - return pd_func()->createQueue(channelNumber, QString()); -} - -Queue * QAMQP::Client::createQueue( const QString &name, int channelNumber ) -{ - return pd_func()->createQueue(channelNumber, name); -} - -void QAMQP::Client::open() -{ - return pd_func()->connect(); -} - -void QAMQP::Client::open( const QUrl & connectionString ) -{ - pd_func()->parseCnnString(connectionString); - open(); -} - -void QAMQP::Client::close() -{ - return pd_func()->disconnect(); -} - -void QAMQP::Client::reopen() -{ - pd_func()->disconnect(); - pd_func()->connect(); -} - -void QAMQP::Client::setAuth( Authenticator * auth ) -{ - pd_func()->setAuth(auth); -} - -Authenticator * QAMQP::Client::auth() const -{ - return pd_func()->auth_.data(); -} - -bool QAMQP::Client::isSsl() const -{ - return pd_func()->network_->isSsl(); -} - -void QAMQP::Client::setSsl( bool value ) -{ - pd_func()->network_->setSsl(value); -} - -bool QAMQP::Client::autoReconnect() const -{ - return pd_func()->network_->autoReconnect(); -} - -void QAMQP::Client::setAutoReconnect( bool value ) -{ - pd_func()->network_->setAutoReconnect(value); -} - -bool QAMQP::Client::isConnected() const -{ - return pd_func()->connection_->isConnected(); -} - -void QAMQP::Client::addCustomProperty( const QString & name, const QString & value ) -{ - return pd_func()->connection_->addCustomProperty(name, value); -} - -QString QAMQP::Client::customProperty( const QString & name ) const -{ - return pd_func()->connection_->customProperty(name); -} +#include "amqp.h" +#include "amqp_p.h" + +#include +#include +#include "amqp_exchange.h" +#include "amqp_exchange_p.h" +#include "amqp_queue.h" +#include "amqp_queue_p.h" +#include "amqp_connection_p.h" +#include "amqp_authenticator.h" + +using namespace QAMQP; + +namespace QAMQP +{ +struct ClientExceptionCleaner +{ + /* this cleans up when the constructor throws an exception */ + static inline void cleanup(Client *that, ClientPrivate *d) + { +#ifdef QT_NO_EXCEPTIONS + Q_UNUSED(that); + Q_UNUSED(d); +#else + Q_UNUSED(that); + Q_UNUSED(d); +#endif + } +}; +} + +////////////////////////////////////////////////////////////////////////// + +ClientPrivate::ClientPrivate(Client * q) + : port(AMQPPORT), + host(QString::fromLatin1(AMQPHOST)), + virtualHost(QString::fromLatin1(AMQPVHOST)), + q_ptr(q) +{ +} + +ClientPrivate::~ClientPrivate() +{ +} + +void ClientPrivate::init(QObject *parent) +{ + Q_Q(QAMQP::Client); + q->setParent(parent); + if (!network_) + network_ = new QAMQP::Network(q); + + if (!connection_) + connection_ = new QAMQP::Connection(q); + network_->setMethodHandlerConnection(connection_); + + setAuth(new AMQPlainAuthenticator(QString::fromLatin1(AMQPLOGIN), QString::fromLatin1(AMQPPSWD))); + + QObject::connect(connection_, SIGNAL(connected()), q, SIGNAL(connected())); + QObject::connect(connection_, SIGNAL(disconnected()), q, SIGNAL(disconnected())); +} + +void ClientPrivate::init(QObject *parent, const QUrl &connectionString) +{ + init(parent); + parseConnectionString(connectionString); + connect(); +} + +void ClientPrivate::setAuth(Authenticator *auth) +{ + auth_ = QSharedPointer(auth); +} + +void ClientPrivate::printConnect() const +{ + QTextStream stream(stdout); + stream << "port = " << port << endl; + stream << "host = " << host << endl; + stream << "vhost = " << virtualHost << endl; + + if (auth_ && auth_->type() == QLatin1String("AMQPLAIN")) { + QSharedPointer a = auth_.staticCast(); + stream << "user = " << a->login() << endl; + stream << "passw = " << a->password() << endl; + } +} + +void ClientPrivate::connect() +{ + sockConnect(); + login(); +} + +void ClientPrivate::parseConnectionString(const QUrl &connectionString) +{ + Q_Q(QAMQP::Client); + if (connectionString.scheme() != AMQPSCHEME && + connectionString.scheme() != AMQPSSCHEME) { + qDebug() << Q_FUNC_INFO << "invalid scheme: " << connectionString.scheme(); + return; + } + + q->setSsl(connectionString.scheme() == AMQPSSCHEME); + q->setPassword(connectionString.password()); + q->setUser(connectionString.userName()); + q->setPort(connectionString.port(AMQPPORT)); + q->setHost(connectionString.host()); + q->setVirtualHost(connectionString.path()); +} + +void ClientPrivate::sockConnect() +{ + if (network_->state() != QAbstractSocket::UnconnectedState) + disconnect(); + network_->connectTo(host, port); +} + +void ClientPrivate::login() +{ +} + +Exchange *ClientPrivate::createExchange(int channelNumber, const QString &name) +{ + Q_Q(QAMQP::Client); + Exchange * exchange_ = new Exchange(channelNumber, q); + + network_->addMethodHandlerForChannel(exchange_->channelNumber(), exchange_); + + QObject::connect(connection_, SIGNAL(connected()), exchange_, SLOT(_q_open())); + exchange_->d_func()->open(); + QObject::connect(q, SIGNAL(disconnected()), exchange_, SLOT(_q_disconnected())); + exchange_->setName(name); + + return exchange_; +} + +Queue *ClientPrivate::createQueue(int channelNumber, const QString &name ) +{ + Q_Q(QAMQP::Client); + Queue *queue_ = new Queue(channelNumber, q); + + network_->addMethodHandlerForChannel(queue_->channelNumber(), queue_); + network_->addContentHandlerForChannel(queue_->channelNumber(), queue_); + network_->addContentBodyHandlerForChannel(queue_->channelNumber(), queue_); + + QObject::connect(connection_, SIGNAL(connected()), queue_, SLOT(_q_open())); + queue_->d_func()->open(); + QObject::connect(q, SIGNAL(disconnected()), queue_, SLOT(_q_disconnected())); + queue_->setName(name); + + return queue_; +} + +void ClientPrivate::disconnect() +{ + Q_Q(QAMQP::Client); + if (network_->state() != QAbstractSocket::UnconnectedState) { + network_->disconnect(); + connection_->d_func()->connected = false; + Q_EMIT q->disconnected(); + } +} + +////////////////////////////////////////////////////////////////////////// + +QAMQP::Client::Client(QObject *parent) + : QObject(parent), + d_ptr(new ClientPrivate(this)) +{ + d_ptr->init(parent); +} + +QAMQP::Client::Client(const QUrl & connectionString, QObject * parent) + : d_ptr(new ClientPrivate(this)) +{ + d_ptr->init(parent, connectionString); +} + +QAMQP::Client::~Client() +{ +} + +quint16 QAMQP::Client::port() const +{ + Q_D(const QAMQP::Client); + return d->port; +} + +void QAMQP::Client::setPort(quint16 port) +{ + Q_D(QAMQP::Client); + d->port = port; +} + +QString QAMQP::Client::host() const +{ + Q_D(const QAMQP::Client); + return d->host; +} + +void QAMQP::Client::setHost( const QString & host ) +{ + Q_D(QAMQP::Client); + d->host = host; +} + +QString QAMQP::Client::virtualHost() const +{ + Q_D(const QAMQP::Client); + return d->virtualHost; +} + +void QAMQP::Client::setVirtualHost(const QString &virtualHost) +{ + Q_D(QAMQP::Client); + d->virtualHost = virtualHost; +} + +QString QAMQP::Client::user() const +{ + Q_D(const QAMQP::Client); + const Authenticator * auth = d->auth_.data(); + if (auth && auth->type() == QLatin1String("AMQPLAIN")) { + const AMQPlainAuthenticator * a = static_cast(auth); + return a->login(); + } + + return QString(); +} + +void QAMQP::Client::setUser(const QString &user) +{ + Q_D(const QAMQP::Client); + Authenticator * auth = d->auth_.data(); + if (auth && auth->type() == QLatin1String("AMQPLAIN")) { + AMQPlainAuthenticator * a = static_cast(auth); + a->setLogin(user); + } +} + +QString QAMQP::Client::password() const +{ + Q_D(const QAMQP::Client); + const Authenticator * auth = d->auth_.data(); + if (auth && auth->type() == "AMQPLAIN") { + const AMQPlainAuthenticator * a = static_cast(auth); + return a->password(); + } + + return QString(); +} + +void QAMQP::Client::setPassword(const QString &password) +{ + Q_D(QAMQP::Client); + Authenticator *auth = d->auth_.data(); + if (auth && auth->type() == QLatin1String("AMQPLAIN")) { + AMQPlainAuthenticator * a = static_cast(auth); + a->setPassword(password); + } +} + +void QAMQP::Client::printConnect() const +{ +#ifdef _DEBUG + Q_D(const QAMQP::Client); + d->printConnect(); +#endif // _DEBUG +} + +void QAMQP::Client::closeChannel() +{ +} + +Exchange *QAMQP::Client::createExchange(int channelNumber) +{ + Q_D(QAMQP::Client); + return d->createExchange(channelNumber, QString()); +} + +Exchange *QAMQP::Client::createExchange( const QString &name, int channelNumber ) +{ + Q_D(QAMQP::Client); + return d->createExchange(channelNumber, name); +} + +Queue *QAMQP::Client::createQueue(int channelNumber) +{ + Q_D(QAMQP::Client); + return d->createQueue(channelNumber, QString()); +} + +Queue *QAMQP::Client::createQueue( const QString &name, int channelNumber ) +{ + Q_D(QAMQP::Client); + return d->createQueue(channelNumber, name); +} + +void QAMQP::Client::open() +{ + Q_D(QAMQP::Client); + return d->connect(); +} + +void QAMQP::Client::open(const QUrl &connectionString) +{ + Q_D(QAMQP::Client); + d->parseConnectionString(connectionString); + open(); +} + +void QAMQP::Client::close() +{ + Q_D(QAMQP::Client); + return d->disconnect(); +} + +void QAMQP::Client::reopen() +{ + Q_D(QAMQP::Client); + d->disconnect(); + d->connect(); +} + +void QAMQP::Client::setAuth(Authenticator *auth) +{ + Q_D(QAMQP::Client); + d->setAuth(auth); +} + +Authenticator *QAMQP::Client::auth() const +{ + Q_D(const QAMQP::Client); + return d->auth_.data(); +} + +bool QAMQP::Client::isSsl() const +{ + Q_D(const QAMQP::Client); + return d->network_->isSsl(); +} + +void QAMQP::Client::setSsl(bool value) +{ + Q_D(QAMQP::Client); + d->network_->setSsl(value); +} + +bool QAMQP::Client::autoReconnect() const +{ + Q_D(const QAMQP::Client); + return d->network_->autoReconnect(); +} + +void QAMQP::Client::setAutoReconnect(bool value) +{ + Q_D(QAMQP::Client); + d->network_->setAutoReconnect(value); +} + +bool QAMQP::Client::isConnected() const +{ + Q_D(const QAMQP::Client); + return d->connection_->isConnected(); +} + +void QAMQP::Client::addCustomProperty(const QString &name, const QString &value) +{ + Q_D(QAMQP::Client); + return d->connection_->addCustomProperty(name, value); +} + +QString QAMQP::Client::customProperty(const QString &name) const +{ + Q_D(const QAMQP::Client); + return d->connection_->customProperty(name); +} + diff --git a/src/qamqp/amqp.h b/src/qamqp/amqp.h index 518d8be..fa84506 100644 --- a/src/qamqp/amqp.h +++ b/src/qamqp/amqp.h @@ -1,97 +1,93 @@ -#ifndef qamqp_amqp_h__ -#define qamqp_amqp_h__ - -#include -#include -#include "amqp_global.h" - -namespace QAMQP -{ - class Exchange; - class Queue; - class ClientPrivate; - class Authenticator; - class ConnectionPrivate; - class Client : public QObject - { - Q_OBJECT - - Q_PROPERTY(quint32 port READ port WRITE setPort); - Q_PROPERTY(QString host READ host WRITE setHost); - Q_PROPERTY(QString virtualHost READ virtualHost WRITE setVirtualHost); - Q_PROPERTY(QString user READ user WRITE setUser); - Q_PROPERTY(QString password READ password WRITE setPassword); - Q_PROPERTY(bool ssl READ isSsl WRITE setSsl); - Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect); - Q_PROPERTY(bool connected READ isConnected ); - - Q_DISABLE_COPY(Client) - - P_DECLARE_PRIVATE(QAMQP::Client) - - friend class ConnectionPrivate; - friend class ChannelPrivate; - - public: - Client(QObject * parent = 0); - Client(const QUrl & connectionString, QObject * parent = 0); - ~Client(); - - void printConnect() const; - void closeChannel(); - - void addCustomProperty(const QString & name, const QString & value); - QString customProperty(const QString & name) const; - - Exchange * createExchange(int channelNumber = -1); - Exchange * createExchange(const QString &name, int channelNumber = -1); - - Queue * createQueue(int channelNumber = -1); - Queue * createQueue(const QString &name, int channelNumber = -1); - - quint32 port() const; - void setPort(quint32 port); - - QString host() const; - void setHost(const QString & host); - - QString virtualHost() const; - void setVirtualHost(const QString & virtualHost); - - QString user() const; - void setUser(const QString & user); - - QString password() const; - void setPassword(const QString & password); - - void setAuth(Authenticator * auth); - Authenticator * auth() const; - void open(); - void open(const QUrl & connectionString); - void close(); - void reopen(); - - bool isSsl() const; - void setSsl(bool value); - - bool autoReconnect() const; - void setAutoReconnect(bool value); - - bool isConnected() const; - - signals: - void connected(); - void disconnected(); - - - protected: - ClientPrivate * const pd_ptr; - - private: - friend struct ClientExceptionCleaner; - - //void chanalConnect(); - }; -} - -#endif // qamqp_amqp_h__ \ No newline at end of file +#ifndef QAMQP_H +#define QAMQP_H + +#include +#include + +#include "amqp_global.h" + +namespace QAMQP +{ + +class Exchange; +class Queue; +class ClientPrivate; +class Authenticator; +class ConnectionPrivate; +class Client : public QObject +{ + Q_OBJECT + Q_PROPERTY(quint32 port READ port WRITE setPort) + Q_PROPERTY(QString host READ host WRITE setHost) + Q_PROPERTY(QString virtualHost READ virtualHost WRITE setVirtualHost) + Q_PROPERTY(QString user READ user WRITE setUser) + Q_PROPERTY(QString password READ password WRITE setPassword) + Q_PROPERTY(bool ssl READ isSsl WRITE setSsl) + Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect) + Q_PROPERTY(bool connected READ isConnected ) + +public: + Client(QObject *parent = 0); + Client(const QUrl &connectionString, QObject *parent = 0); + ~Client(); + + void printConnect() const; + void closeChannel(); + + void addCustomProperty(const QString &name, const QString &value); + QString customProperty(const QString &name) const; + + Exchange *createExchange(int channelNumber = -1); + Exchange *createExchange(const QString &name, int channelNumber = -1); + + Queue *createQueue(int channelNumber = -1); + Queue *createQueue(const QString &name, int channelNumber = -1); + + quint16 port() const; + void setPort(quint16 port); + + QString host() const; + void setHost(const QString &host); + + QString virtualHost() const; + void setVirtualHost(const QString &virtualHost); + + QString user() const; + void setUser(const QString &user); + + QString password() const; + void setPassword(const QString &password); + + void setAuth(Authenticator *auth); + Authenticator *auth() const; + + void open(); + void open(const QUrl &connectionString); + void close(); + void reopen(); + + bool isSsl() const; + void setSsl(bool value); + + bool autoReconnect() const; + void setAutoReconnect(bool value); + + bool isConnected() const; + +signals: + void connected(); + void disconnected(); + +private: + Q_DISABLE_COPY(Client) + Q_DECLARE_PRIVATE(QAMQP::Client) + QScopedPointer d_ptr; + + friend class ConnectionPrivate; + friend class ChannelPrivate; + friend struct ClientExceptionCleaner; +}; + +} // namespace QAMQP + +#endif // QAMQP diff --git a/src/qamqp/amqp_authenticator.cpp b/src/qamqp/amqp_authenticator.cpp index 4cc6b52..7d6095d 100644 --- a/src/qamqp/amqp_authenticator.cpp +++ b/src/qamqp/amqp_authenticator.cpp @@ -1,47 +1,48 @@ -#include "amqp_authenticator.h" -#include "amqp_frame.h" - -QString QAMQP::AMQPlainAuthenticator::login() const -{ - return login_; -} - -QString QAMQP::AMQPlainAuthenticator::password() const -{ - return password_; -} - -QAMQP::AMQPlainAuthenticator::AMQPlainAuthenticator( const QString & l /*= QString()*/, const QString & p /*= QString()*/ ) -{ - login_ = l; - password_ = p; -} - -QAMQP::AMQPlainAuthenticator::~AMQPlainAuthenticator() -{ - -} - -QString QAMQP::AMQPlainAuthenticator::type() const -{ - return "AMQPLAIN"; -} - -void QAMQP::AMQPlainAuthenticator::setLogin( const QString& l ) -{ - login_ = l; -} - -void QAMQP::AMQPlainAuthenticator::setPassword( const QString &p ) -{ - password_ = p; -} - -void QAMQP::AMQPlainAuthenticator::write( QDataStream & out ) -{ - QAMQP::Frame::writeField('s', out, type()); - QAMQP::Frame::TableField response; - response["LOGIN"] = login_; - response["PASSWORD"] = password_; - QAMQP::Frame::serialize(out, response); -} \ No newline at end of file +#include "amqp_authenticator.h" +#include "amqp_frame.h" + +using namespace QAMQP; + +AMQPlainAuthenticator::AMQPlainAuthenticator(const QString &l, const QString &p) + : login_(l), + password_(p) +{ +} + +AMQPlainAuthenticator::~AMQPlainAuthenticator() +{ +} + +QString AMQPlainAuthenticator::login() const +{ + return login_; +} + +QString AMQPlainAuthenticator::password() const +{ + return password_; +} + +QString AMQPlainAuthenticator::type() const +{ + return "AMQPLAIN"; +} + +void AMQPlainAuthenticator::setLogin(const QString &l) +{ + login_ = l; +} + +void AMQPlainAuthenticator::setPassword(const QString &p) +{ + password_ = p; +} + +void AMQPlainAuthenticator::write(QDataStream &out) +{ + QAMQP::Frame::writeField('s', out, type()); + QAMQP::Frame::TableField response; + response["LOGIN"] = login_; + response["PASSWORD"] = password_; + QAMQP::Frame::serialize(out, response); +} diff --git a/src/qamqp/amqp_authenticator.h b/src/qamqp/amqp_authenticator.h index b882b33..b2fd2d8 100644 --- a/src/qamqp/amqp_authenticator.h +++ b/src/qamqp/amqp_authenticator.h @@ -1,33 +1,42 @@ -#ifndef amqp_authenticator_h__ -#define amqp_authenticator_h__ - -#include "amqp_global.h" -#include -#include - -namespace QAMQP -{ - class Authenticator - { - public: - virtual ~Authenticator(){}; - virtual QString type() const = 0; - virtual void write(QDataStream & out) = 0; - }; - - class AMQPlainAuthenticator : public Authenticator - { - QString login_, password_; - public: - AMQPlainAuthenticator(const QString & login = QString(), const QString & password = QString()); - virtual ~AMQPlainAuthenticator(); - QString login() const; - void setLogin(const QString& l); - QString password() const; - void setPassword(const QString &p); - virtual QString type() const; - virtual void write(QDataStream & out); - }; - -} -#endif // amqp_authenticator_h__ \ No newline at end of file +#ifndef amqp_authenticator_h__ +#define amqp_authenticator_h__ + +#include +#include + +#include "amqp_global.h" + +namespace QAMQP +{ + +class Authenticator +{ +public: + virtual ~Authenticator() {} + virtual QString type() const = 0; + virtual void write(QDataStream &out) = 0; +}; + +class AMQPlainAuthenticator : public Authenticator +{ +public: + AMQPlainAuthenticator(const QString &login = QString(), const QString &password = QString()); + virtual ~AMQPlainAuthenticator(); + + QString login() const; + void setLogin(const QString &l); + + QString password() const; + void setPassword(const QString &p); + + virtual QString type() const; + virtual void write(QDataStream &out); + +private: + QString login_; + QString password_; + +}; + +} +#endif // amqp_authenticator_h__ diff --git a/src/qamqp/amqp_channel.cpp b/src/qamqp/amqp_channel.cpp index 4b33953..b3aa04d 100644 --- a/src/qamqp/amqp_channel.cpp +++ b/src/qamqp/amqp_channel.cpp @@ -1,320 +1,293 @@ -#include "amqp_channel.h" -#include "amqp_channel_p.h" - -#include "amqp.h" -#include "amqp_p.h" - -#include -#include -#include - -using namespace QAMQP; - -namespace QAMQP -{ - int ChannelPrivate::nextChannelNumber_ = 0; - struct ChannelExceptionCleaner - { - /* this cleans up when the constructor throws an exception */ - static inline void cleanup(Channel *that, ChannelPrivate *d) - { -#ifdef QT_NO_EXCEPTIONS - Q_UNUSED(that); - Q_UNUSED(d); -#else - Q_UNUSED(that); - Q_UNUSED(d); -#endif - } - }; -} - - -////////////////////////////////////////////////////////////////////////// - -QAMQP::Channel::Channel(int channelNumber /*= -1*/, Client * parent /*= 0*/ ) - : pd_ptr(new ChannelPrivate(this)) -{ - QT_TRY { - pd_func()->init(channelNumber, parent); - } QT_CATCH(...) { - ChannelExceptionCleaner::cleanup(this, pd_func()); - QT_RETHROW; - } -} - -QAMQP::Channel::Channel( ChannelPrivate * d ) - : pd_ptr(d) -{ - -} - -QAMQP::Channel::~Channel() -{ - - QT_TRY { - QEvent e(QEvent::Destroy); - QCoreApplication::sendEvent(this, &e); - } QT_CATCH(const std::exception&) { - // if this fails we can't do anything about it but at least we are not allowed to throw. - } -} - -void QAMQP::Channel::closeChannel() -{ - P_D(Channel); - d->needOpen = true; - if(d->opened) - d->close(0, QString(), 0,0); - -} - -void QAMQP::Channel::reopen() -{ - closeChannel(); - pd_func()->open(); -} - -QString QAMQP::Channel::name() -{ - return pd_func()->name; -} - -int QAMQP::Channel::channelNumber() -{ - return pd_func()->number; -} - -void QAMQP::Channel::setName( const QString &name ) -{ - pd_func()->name = name; -} - -void QAMQP::Channel::stateChanged( int state ) -{ - switch(ChannelPrivate::State(state)) - { - case ChannelPrivate::csOpened: - emit opened(); - break; - case ChannelPrivate::csClosed: - emit closed(); - break; - case ChannelPrivate::csIdle: - emit flowChanged(false); - break; - case ChannelPrivate::csRunning: - emit flowChanged(true); - break; - } -} - -void QAMQP::Channel::_q_method(const Frame::Method &frame) -{ - pd_func()->_q_method(frame); -} - -bool QAMQP::Channel::isOpened() const -{ - return pd_func()->opened; -} - -void QAMQP::Channel::onOpen() -{ - -} - -void QAMQP::Channel::onClose() -{ - -} - -void QAMQP::Channel::setQOS( qint32 prefetchSize, quint16 prefetchCount ) -{ - pd_func()->setQOS(prefetchSize, prefetchCount); -} -////////////////////////////////////////////////////////////////////////// - -ChannelPrivate::ChannelPrivate(Channel * q) - : number(0) - , opened(false) - , needOpen(true) - , pq_ptr(q) -{ - -} - -ChannelPrivate::~ChannelPrivate() -{ - -} - -void ChannelPrivate::init(int channelNumber, Client * parent) -{ - needOpen = channelNumber == -1 ? true : false; - number = channelNumber == -1 ? ++nextChannelNumber_ : channelNumber; - nextChannelNumber_ = qMax(channelNumber, (nextChannelNumber_ + 1)); - pq_func()->setParent(parent); - client_ = parent; -} - - -bool ChannelPrivate::_q_method( const QAMQP::Frame::Method & frame ) -{ - Q_ASSERT(frame.channel() == number); - if(frame.channel() != number ) - return true; - - if(frame.methodClass() != QAMQP::Frame::fcChannel) - return false; - - qDebug("Channel#%d:", number); - - switch(frame.id()) - { - case miOpenOk: - openOk(frame); - break; - case miFlow: - flow(frame); - break; - case miFlowOk: - flowOk(frame); - break; - case miClose: - close(frame); - break; - case miCloseOk: - closeOk(frame); - break; - } - return true; -} - -void ChannelPrivate::_q_open() -{ - open(); -} - - -void ChannelPrivate::sendFrame( const QAMQP::Frame::Base & frame ) -{ - if(client_) - { - client_->pd_func()->network_->sendFrame(frame); - } -} - - -void ChannelPrivate::open() -{ - if(!needOpen || opened) - return; - - if(!client_->pd_func()->connection_->isConnected()) - return; - qDebug("Open channel #%d", number); - QAMQP::Frame::Method frame(QAMQP::Frame::fcChannel, miOpen); - frame.setChannel(number); - QByteArray arguments_; - arguments_.resize(1); - arguments_[0] = 0; - frame.setArguments(arguments_); - sendFrame(frame); -} - - -void ChannelPrivate::flow() -{ - -} - -void ChannelPrivate::flow( const QAMQP::Frame::Method & frame ) -{ - Q_UNUSED(frame); -} - -void ChannelPrivate::flowOk() -{ - -} - -void ChannelPrivate::flowOk( const QAMQP::Frame::Method & frame ) -{ - Q_UNUSED(frame); -} - -void ChannelPrivate::close(int code, const QString & text, int classId, int methodId) -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcChannel, miClose); - QByteArray arguments_; - QDataStream stream(&arguments_, QIODevice::WriteOnly); - - QAMQP::Frame::writeField('s',stream, client_->virtualHost()); - - stream << qint16(code); - QAMQP::Frame::writeField('s', stream, text); - stream << qint16(classId); - stream << qint16(methodId); - - frame.setArguments(arguments_); - client_->pd_func()->network_->sendFrame(frame); -} - -void ChannelPrivate::close( const QAMQP::Frame::Method & frame ) -{ - pq_func()->stateChanged(csClosed); - - qDebug(">> CLOSE"); - QByteArray data = frame.arguments(); - QDataStream stream(&data, QIODevice::ReadOnly); - qint16 code_ = 0, classId, methodId; - stream >> code_; - QString text(QAMQP::Frame::readField('s', stream).toString()); - stream >> classId; - stream >> methodId; - - qDebug(">> code: %d", code_); - qDebug(">> text: %s", qPrintable(text)); - qDebug(">> class-id: %d", classId); - qDebug(">> method-id: %d", methodId); - -} - -void ChannelPrivate::closeOk() -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcChannel, miCloseOk); - sendFrame(frame); -} - -void ChannelPrivate::closeOk( const QAMQP::Frame::Method & frame ) -{ - Q_UNUSED(frame); - P_Q(Channel); - q->stateChanged(csClosed); - q->onClose(); - opened = false; -} - -void ChannelPrivate::openOk( const QAMQP::Frame::Method & frame ) -{ - Q_UNUSED(frame); - P_Q(Channel); - qDebug(">> OpenOK"); - opened = true; - q->stateChanged(csOpened); - q->onOpen(); - -} - -void ChannelPrivate::setQOS( qint32 prefetchSize, quint16 prefetchCount ) -{ - client_->pd_func()->connection_->pd_func()->setQOS(prefetchSize, prefetchCount, number, false); -} - - -void ChannelPrivate::_q_disconnected() -{ - nextChannelNumber_ = 0; - opened = false; -} +#include "amqp_channel.h" +#include "amqp_channel_p.h" +#include "amqp_connection_p.h" + +#include "amqp.h" +#include "amqp_p.h" + +#include +#include +#include + +using namespace QAMQP; + +////////////////////////////////////////////////////////////////////////// + +QAMQP::Channel::Channel(int channelNumber, Client *parent) + : QObject(parent), + d_ptr(new ChannelPrivate(this)) +{ + Q_D(QAMQP::Channel); + d->init(channelNumber, parent); +} + +QAMQP::Channel::Channel(ChannelPrivate *dd, Client *parent) + : QObject(parent), + d_ptr(dd) +{ +} + +QAMQP::Channel::~Channel() +{ +} + +void QAMQP::Channel::closeChannel() +{ + Q_D(QAMQP::Channel); + d->needOpen = true; + if (d->opened) + d->close(0, QString(), 0,0); + +} + +void QAMQP::Channel::reopen() +{ + Q_D(QAMQP::Channel); + closeChannel(); + d->open(); +} + +QString QAMQP::Channel::name() const +{ + Q_D(const QAMQP::Channel); + return d->name; +} + +int QAMQP::Channel::channelNumber() const +{ + Q_D(const QAMQP::Channel); + return d->number; +} + +void QAMQP::Channel::setName(const QString &name) +{ + Q_D(QAMQP::Channel); + d->name = name; +} + +void QAMQP::Channel::stateChanged(int state) +{ + switch(ChannelPrivate::State(state)) { + case ChannelPrivate::csOpened: + emit opened(); + break; + case ChannelPrivate::csClosed: + emit closed(); + break; + case ChannelPrivate::csIdle: + emit flowChanged(false); + break; + case ChannelPrivate::csRunning: + emit flowChanged(true); + break; + } +} + +void QAMQP::Channel::_q_method(const Frame::Method &frame) +{ + Q_D(QAMQP::Channel); + d->_q_method(frame); +} + +bool QAMQP::Channel::isOpened() const +{ + Q_D(const QAMQP::Channel); + return d->opened; +} + +void QAMQP::Channel::onOpen() +{ +} + +void QAMQP::Channel::onClose() +{ +} + +void QAMQP::Channel::setQOS(qint32 prefetchSize, quint16 prefetchCount) +{ + Q_D(QAMQP::Channel); + d->setQOS(prefetchSize, prefetchCount); +} + +////////////////////////////////////////////////////////////////////////// + +int ChannelPrivate::nextChannelNumber_ = 0; +ChannelPrivate::ChannelPrivate(Channel * q) + : number(0), + opened(false), + needOpen(true), + q_ptr(q) +{ +} + +ChannelPrivate::~ChannelPrivate() +{ +} + +void ChannelPrivate::init(int channelNumber, Client *parent) +{ + Q_Q(QAMQP::Channel); + needOpen = channelNumber == -1 ? true : false; + number = channelNumber == -1 ? ++nextChannelNumber_ : channelNumber; + nextChannelNumber_ = qMax(channelNumber, (nextChannelNumber_ + 1)); + q->setParent(parent); + client_ = parent; +} + + +bool ChannelPrivate::_q_method(const QAMQP::Frame::Method &frame) +{ + Q_ASSERT(frame.channel() == number); + if (frame.channel() != number) + return true; + + if (frame.methodClass() != QAMQP::Frame::fcChannel) + return false; + + qDebug("Channel#%d:", number); + + switch (frame.id()) { + case miOpenOk: + openOk(frame); + break; + case miFlow: + flow(frame); + break; + case miFlowOk: + flowOk(frame); + break; + case miClose: + close(frame); + break; + case miCloseOk: + closeOk(frame); + break; + } + return true; +} + +void ChannelPrivate::_q_open() +{ + open(); +} + + +void ChannelPrivate::sendFrame(const QAMQP::Frame::Base &frame) +{ + if (client_) { + client_->d_func()->network_->sendFrame(frame); + } +} + +void ChannelPrivate::open() +{ + if (!needOpen || opened) + return; + + if (!client_->d_func()->connection_->isConnected()) + return; + + qDebug("Open channel #%d", number); + QAMQP::Frame::Method frame(QAMQP::Frame::fcChannel, miOpen); + frame.setChannel(number); + QByteArray arguments_; + arguments_.resize(1); + arguments_[0] = 0; + frame.setArguments(arguments_); + sendFrame(frame); +} + +void ChannelPrivate::flow() +{ +} + +void ChannelPrivate::flow(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame); +} + +void ChannelPrivate::flowOk() +{ +} + +void ChannelPrivate::flowOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame); +} + +void ChannelPrivate::close(int code, const QString &text, int classId, int methodId) +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcChannel, miClose); + QByteArray arguments_; + QDataStream stream(&arguments_, QIODevice::WriteOnly); + + QAMQP::Frame::writeField('s',stream, client_->virtualHost()); + + stream << qint16(code); + QAMQP::Frame::writeField('s', stream, text); + stream << qint16(classId); + stream << qint16(methodId); + + frame.setArguments(arguments_); + client_->d_func()->network_->sendFrame(frame); +} + +void ChannelPrivate::close(const QAMQP::Frame::Method &frame) +{ + Q_Q(QAMQP::Channel); + q->stateChanged(csClosed); + + qDebug(">> CLOSE"); + QByteArray data = frame.arguments(); + QDataStream stream(&data, QIODevice::ReadOnly); + qint16 code_ = 0, classId, methodId; + stream >> code_; + QString text(QAMQP::Frame::readField('s', stream).toString()); + stream >> classId; + stream >> methodId; + + qDebug(">> code: %d", code_); + qDebug(">> text: %s", qPrintable(text)); + qDebug(">> class-id: %d", classId); + qDebug(">> method-id: %d", methodId); +} + +void ChannelPrivate::closeOk() +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcChannel, miCloseOk); + sendFrame(frame); +} + +void ChannelPrivate::closeOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Channel); + + q->stateChanged(csClosed); + q->onClose(); + opened = false; +} + +void ChannelPrivate::openOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Channel); + + qDebug(">> OpenOK"); + opened = true; + q->stateChanged(csOpened); + q->onOpen(); +} + +void ChannelPrivate::setQOS(qint32 prefetchSize, quint16 prefetchCount) +{ + client_->d_func()->connection_->d_func()->setQOS(prefetchSize, prefetchCount, number, false); +} + +void ChannelPrivate::_q_disconnected() +{ + nextChannelNumber_ = 0; + opened = false; +} + +#include "moc_amqp_channel.cpp" diff --git a/src/qamqp/amqp_channel.h b/src/qamqp/amqp_channel.h index f30ad9b..2a2ecc6 100644 --- a/src/qamqp/amqp_channel.h +++ b/src/qamqp/amqp_channel.h @@ -1,60 +1,58 @@ -#ifndef amqp_channel_h__ -#define amqp_channel_h__ - -#include -#include "amqp_global.h" -#include "amqp_frame.h" - -namespace QAMQP -{ - class ChannelPrivate; - class Client; - class Channel : public QObject, public Frame::MethodHandler - { - Q_OBJECT - - Q_PROPERTY(int number READ channelNumber); - Q_PROPERTY(QString name READ name WRITE setName); - - P_DECLARE_PRIVATE(QAMQP::Channel) - Q_DISABLE_COPY(Channel) - public: - ~Channel(); - - void closeChannel(); - void reopen(); - - QString name(); - int channelNumber(); - - void setName(const QString &name); - void setQOS(qint32 prefetchSize, quint16 prefetchCount); - bool isOpened() const; - - signals: - void opened(); - void closed(); - void flowChanged(bool enabled); - - protected: - Channel(int channelNumber = -1, Client * parent = 0); - Channel(ChannelPrivate * d); - virtual void onOpen(); - virtual void onClose(); - - ChannelPrivate * const pd_ptr; - - private: - void stateChanged(int state); - friend class ClientPrivate; - void _q_method(const QAMQP::Frame::Method & frame); - - Q_PRIVATE_SLOT(pd_func(), void _q_open()) - Q_PRIVATE_SLOT(pd_func(), void _q_disconnected()) - }; -} - -#ifdef QAMQP_P_INCLUDE -# include "amqp_channel_p.h" -#endif -#endif // amqp_channel_h__ +#ifndef amqp_channel_h__ +#define amqp_channel_h__ + +#include +#include "amqp_global.h" +#include "amqp_frame.h" + +namespace QAMQP +{ + +class Client; +class ChannelPrivate; +class Channel : public QObject, public Frame::MethodHandler +{ + Q_OBJECT + Q_PROPERTY(int number READ channelNumber) + Q_PROPERTY(QString name READ name WRITE setName) + +public: + ~Channel(); + + void closeChannel(); + void reopen(); + + QString name() const; + int channelNumber() const; + + void setName(const QString &name); + void setQOS(qint32 prefetchSize, quint16 prefetchCount); + bool isOpened() const; + +signals: + void opened(); + void closed(); + void flowChanged(bool enabled); + +protected: + Q_DISABLE_COPY(Channel) + Q_DECLARE_PRIVATE(QAMQP::Channel) + + Channel(int channelNumber = -1, Client *parent = 0); + Channel(ChannelPrivate *dd, Client *parent = 0); + QScopedPointer d_ptr; + + Q_PRIVATE_SLOT(d_func(), void _q_open()) + Q_PRIVATE_SLOT(d_func(), void _q_disconnected()) + + virtual void onOpen(); + virtual void onClose(); + void stateChanged(int state); + void _q_method(const QAMQP::Frame::Method &frame); + + friend class ClientPrivate; +}; + +} + +#endif diff --git a/src/qamqp/amqp_channel_p.h b/src/qamqp/amqp_channel_p.h index 0450fdf..b719f47 100644 --- a/src/qamqp/amqp_channel_p.h +++ b/src/qamqp/amqp_channel_p.h @@ -1,85 +1,85 @@ -#ifndef amqp_channel_p_h__ -#define amqp_channel_p_h__ - -#include "amqp_global.h" -#include - -#define METHOD_ID_ENUM(name, id) name = id, name ## Ok - -namespace QAMQP -{ - class Client; - class ClientPrivate; - class ChannelPrivate - { - P_DECLARE_PUBLIC(QAMQP::Channel) - public: - enum MethodId - { - METHOD_ID_ENUM(miOpen, 10), - METHOD_ID_ENUM(miFlow, 20), - METHOD_ID_ENUM(miClose, 40) - }; - - enum State { - csOpened, - csClosed, - csIdle, - csRunning - }; - - enum BasicMethod - { - METHOD_ID_ENUM(bmQos, 10), - METHOD_ID_ENUM(bmConsume, 20), - METHOD_ID_ENUM(bmCancel, 30), - bmPublish = 40, - bmReturn = 50, - bmDeliver = 60, - METHOD_ID_ENUM(bmGet, 70), - bmGetEmpty = 72, - bmAck = 80, - bmReject = 90, - bmRecoverAsync = 100, - METHOD_ID_ENUM(bmRecover, 110) - }; - - ChannelPrivate(Channel * q); - virtual ~ChannelPrivate(); - - void init(int channelNumber, Client * parent); - - void open(); - void flow(); - void flowOk(); - void close(int code, const QString & text, int classId, int methodId); - void closeOk(); - - ////////////////////////////////////////////////////////////////////////// - - void openOk(const QAMQP::Frame::Method & frame); - void flow(const QAMQP::Frame::Method & frame); - void flowOk(const QAMQP::Frame::Method & frame); - void close(const QAMQP::Frame::Method & frame); - void closeOk(const QAMQP::Frame::Method & frame); - - virtual bool _q_method(const QAMQP::Frame::Method & frame); - virtual void _q_disconnected(); - void _q_open(); - - void setQOS(qint32 prefetchSize, quint16 prefetchCount); - void sendFrame(const QAMQP::Frame::Base & frame); - - QPointer client_; - - QString name; - int number; - - static int nextChannelNumber_; - bool opened; - bool needOpen; - - Channel * const pq_ptr; - }; -} -#endif // amqp_channel_p_h__ \ No newline at end of file +#ifndef amqp_channel_p_h__ +#define amqp_channel_p_h__ + +#include "amqp_global.h" +#include + +#define METHOD_ID_ENUM(name, id) name = id, name ## Ok + +namespace QAMQP +{ +class Client; +class ClientPrivate; +class ChannelPrivate +{ +public: + enum MethodId { + METHOD_ID_ENUM(miOpen, 10), + METHOD_ID_ENUM(miFlow, 20), + METHOD_ID_ENUM(miClose, 40) + }; + + enum State { + csOpened, + csClosed, + csIdle, + csRunning + }; + + enum BasicMethod + { + METHOD_ID_ENUM(bmQos, 10), + METHOD_ID_ENUM(bmConsume, 20), + METHOD_ID_ENUM(bmCancel, 30), + bmPublish = 40, + bmReturn = 50, + bmDeliver = 60, + METHOD_ID_ENUM(bmGet, 70), + bmGetEmpty = 72, + bmAck = 80, + bmReject = 90, + bmRecoverAsync = 100, + METHOD_ID_ENUM(bmRecover, 110) + }; + + ChannelPrivate(Channel * q); + virtual ~ChannelPrivate(); + + void init(int channelNumber, Client *parent); + + void open(); + void flow(); + void flowOk(); + void close(int code, const QString &text, int classId, int methodId); + void closeOk(); + + ////////////////////////////////////////////////////////////////////////// + + void openOk(const QAMQP::Frame::Method &frame); + void flow(const QAMQP::Frame::Method &frame); + void flowOk(const QAMQP::Frame::Method &frame); + void close(const QAMQP::Frame::Method &frame); + void closeOk(const QAMQP::Frame::Method &frame); + + virtual bool _q_method(const QAMQP::Frame::Method &frame); + virtual void _q_disconnected(); + void _q_open(); + + void setQOS(qint32 prefetchSize, quint16 prefetchCount); + void sendFrame(const QAMQP::Frame::Base &frame); + + QPointer client_; + + QString name; + int number; + + static int nextChannelNumber_; + bool opened; + bool needOpen; + + Q_DECLARE_PUBLIC(QAMQP::Channel) + Channel * const q_ptr; +}; + +} +#endif // amqp_channel_p_h__ diff --git a/src/qamqp/amqp_connection.cpp b/src/qamqp/amqp_connection.cpp index 0301742..978379b 100644 --- a/src/qamqp/amqp_connection.cpp +++ b/src/qamqp/amqp_connection.cpp @@ -1,397 +1,369 @@ -#include "amqp_connection.h" -#include "amqp_connection_p.h" -#include "amqp.h" -#include "amqp_p.h" -#include "amqp_frame.h" - -#include -#include -#include -#include -#include - -using namespace QAMQP; - -namespace QAMQP -{ - struct ConnectionExceptionCleaner - { - /* this cleans up when the constructor throws an exception */ - static inline void cleanup(Connection *that, ConnectionPrivate *d) - { -#ifdef QT_NO_EXCEPTIONS - Q_UNUSED(that); - Q_UNUSED(d); -#else - Q_UNUSED(that); - Q_UNUSED(d); -#endif - } - }; - - - - -} -////////////////////////////////////////////////////////////////////////// - - -ConnectionPrivate::ConnectionPrivate( Connection * q) - : closed_(false) - , connected(false) - , pq_ptr(q) -{ - -} - -ConnectionPrivate::~ConnectionPrivate() -{ - -} - -void ConnectionPrivate::init(Client * parent) -{ - pq_func()->setParent(parent); - client_ = parent; - heartbeatTimer_ = new QTimer(parent); - QObject::connect(heartbeatTimer_, SIGNAL(timeout()), - pq_func(), SLOT(_q_heartbeat())); -} - -void ConnectionPrivate::startOk() -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miStartOk); - QByteArray arguments_; - QDataStream stream(&arguments_, QIODevice::WriteOnly); - - QAMQP::Frame::TableField clientProperties; - clientProperties["version"] = QString(QAMQP_VERSION); - clientProperties["platform"] = QString("Qt %1").arg(qVersion()); - clientProperties["product"] = QString("QAMQP"); - clientProperties.unite(customProperty); - QAMQP::Frame::serialize(stream, clientProperties); - - client_->pd_func()->auth_->write(stream); - - QAMQP::Frame::writeField('s', stream, "en_US"); - - frame.setArguments(arguments_); - - client_->pd_func()->network_->sendFrame(frame); -} - -void ConnectionPrivate::secureOk() -{ - - -} - -void ConnectionPrivate::tuneOk() -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miTuneOk); - QByteArray arguments_; - QDataStream stream(&arguments_, QIODevice::WriteOnly); - - stream << qint16(0); //channel_max - stream << qint32(FRAME_MAX); //frame_max - stream << qint16(heartbeatTimer_->interval() / 1000); //heartbeat - - frame.setArguments(arguments_); - client_->pd_func()->network_->sendFrame(frame); -} - -void ConnectionPrivate::open() -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miOpen); - QByteArray arguments_; - QDataStream stream(&arguments_, QIODevice::WriteOnly); - - QAMQP::Frame::writeField('s',stream, client_->virtualHost()); - - stream << qint8(0); - stream << qint8(0); - - frame.setArguments(arguments_); - client_->pd_func()->network_->sendFrame(frame); -} - -void ConnectionPrivate::start( const QAMQP::Frame::Method & frame ) -{ - qDebug(">> Start"); - QByteArray data = frame.arguments(); - QDataStream stream(&data, QIODevice::ReadOnly); - quint8 version_major = 0; - quint8 version_minor = 0; - - stream >> version_major >> version_minor; - - QAMQP::Frame::TableField table; - QAMQP::Frame::deserialize(stream, table); - - QString mechanisms = QAMQP::Frame::readField('S', stream).toString(); - QString locales = QAMQP::Frame::readField('S', stream).toString(); - - qDebug(">> version_major: %d", version_major); - qDebug(">> version_minor: %d", version_minor); - - QAMQP::Frame::print(table); - - qDebug(">> mechanisms: %s", qPrintable(mechanisms)); - qDebug(">> locales: %s", qPrintable(locales)); - - startOk(); -} - -void ConnectionPrivate::secure( const QAMQP::Frame::Method & frame ) -{ - Q_UNUSED(frame); -} - -void ConnectionPrivate::tune( const QAMQP::Frame::Method & frame ) -{ - qDebug(">> Tune"); - QByteArray data = frame.arguments(); - QDataStream stream(&data, QIODevice::ReadOnly); - - qint16 channel_max = 0, - heartbeat = 0; - qint32 frame_max = 0; - - stream >> channel_max; - stream >> frame_max; - stream >> heartbeat; - - qDebug(">> channel_max: %d", channel_max); - qDebug(">> frame_max: %d", frame_max); - qDebug(">> heartbeat: %d", heartbeat); - - if(heartbeatTimer_) - { - heartbeatTimer_->setInterval(heartbeat * 1000); - if(heartbeatTimer_->interval()) - { - heartbeatTimer_->start(); - } else { - heartbeatTimer_->stop(); - } - } - tuneOk(); - open(); -} - -void ConnectionPrivate::openOk( const QAMQP::Frame::Method & frame ) -{ - Q_UNUSED(frame); - qDebug(">> OpenOK"); - connected = true; - pq_func()->openOk(); -} - -void ConnectionPrivate::close( const QAMQP::Frame::Method & frame ) -{ - qDebug(">> CLOSE"); - QByteArray data = frame.arguments(); - QDataStream stream(&data, QIODevice::ReadOnly); - qint16 code_ = 0, classId, methodId; - stream >> code_; - QString text(QAMQP::Frame::readField('s', stream).toString()); - stream >> classId; - stream >> methodId; - - qDebug(">> code: %d", code_); - qDebug(">> text: %s", qPrintable(text)); - qDebug(">> class-id: %d", classId); - qDebug(">> method-id: %d", methodId); - connected = false; - client_->pd_func()->network_->error(QAbstractSocket::RemoteHostClosedError); - QMetaObject::invokeMethod(pq_func(), "disconnected"); -} - -void ConnectionPrivate::close(int code, const QString & text, int classId, int methodId) -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miClose); - QByteArray arguments_; - QDataStream stream(&arguments_, QIODevice::WriteOnly); - - QAMQP::Frame::writeField('s',stream, client_->virtualHost()); - - stream << qint16(code); - QAMQP::Frame::writeField('s', stream, text); - stream << qint16(classId); - stream << qint16(methodId); - - frame.setArguments(arguments_); - client_->pd_func()->network_->sendFrame(frame); -} - -void ConnectionPrivate::closeOk() -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miCloseOk); - connected = false; - client_->pd_func()->network_->sendFrame(frame); - -} - -void ConnectionPrivate::closeOk( const QAMQP::Frame::Method & ) -{ - connected = false; - QMetaObject::invokeMethod(pq_func(), "disconnected"); - if(heartbeatTimer_) - { - heartbeatTimer_->stop(); - } -} - - -void ConnectionPrivate::setQOS( qint32 prefetchSize, quint16 prefetchCount, int channel, bool global ) -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, 10); - frame.setChannel(channel); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - - out << prefetchSize; - out << prefetchCount; - out << qint8(global ? 1 : 0); - - frame.setArguments(arguments_); - client_->pd_func()->network_->sendFrame(frame); -} - -bool ConnectionPrivate::_q_method( const QAMQP::Frame::Method & frame ) -{ - Q_ASSERT(frame.methodClass() == QAMQP::Frame::fcConnection); - if(frame.methodClass() != QAMQP::Frame::fcConnection) - return true; - - qDebug() << "Connection:"; - - if (closed_) - { - if( frame.id() == miCloseOk) - closeOk(frame); - return true; - } - - switch(MethodId(frame.id())) - { - case miStart: - start(frame); - break; - case miSecure: - secure(frame); - break; - case miTune: - tune(frame); - break; - case miOpenOk: - openOk(frame); - break; - case miClose: - close(frame); - break; - case miCloseOk: - closeOk(frame); - break; - default: - qWarning("Unknown method-id %d", frame.id()); - return false; - } - return true; -} - -void ConnectionPrivate::_q_heartbeat() -{ - QAMQP::Frame::Heartbeat frame; - client_->pd_func()->network_->sendFrame(frame); -} - -////////////////////////////////////////////////////////////////////////// - -Connection::Connection( Client * parent /*= 0*/ ) - : pd_ptr(new ConnectionPrivate(this)) -{ - QT_TRY { - pd_func()->init(parent); - } QT_CATCH(...) { - ConnectionExceptionCleaner::cleanup(this, pd_func()); - QT_RETHROW; - } -} - -Connection::~Connection() -{ - QT_TRY { - QEvent e(QEvent::Destroy); - QCoreApplication::sendEvent(this, &e); - } QT_CATCH(const std::exception&) { - // if this fails we can't do anything about it but at least we are not allowed to throw. - } -} - -void Connection::startOk() -{ - pd_func()->startOk(); -} - -void Connection::secureOk() -{ - pd_func()->secureOk(); -} - -void Connection::tuneOk() -{ - pd_func()->tuneOk(); -} - -void Connection::open() -{ - pd_func()->open(); -} - -void Connection::close(int code, const QString & text, int classId , int methodId) -{ - pd_func()->close(code, text, classId, methodId); -} - -void Connection::closeOk() -{ - pd_func()->closeOk(); - emit disconnect(); -} - -void Connection::openOk() -{ - emit connected(); -} - -void Connection::_q_method(const QAMQP::Frame::Method & frame) -{ - pd_func()->_q_method(frame); -} - -bool Connection::isConnected() const -{ - return pd_func()->connected; -} - - -void Connection::setQOS( qint32 prefetchSize, quint16 prefetchCount ) -{ - pd_func()->setQOS(prefetchSize, prefetchCount, 0, true); -} - - -void Connection::addCustomProperty( const QString & name, const QString & value ) -{ - pd_func()->customProperty[name] = value; -} - -QString Connection::customProperty( const QString & name ) const -{ - if(pd_func()->customProperty.contains(name)) - { - return pd_func()->customProperty.value(name).toString(); - } - return QString(); -} +#include "amqp_connection.h" +#include "amqp_connection_p.h" +#include "amqp.h" +#include "amqp_p.h" +#include "amqp_frame.h" + +#include +#include +#include +#include +#include + +using namespace QAMQP; + +ConnectionPrivate::ConnectionPrivate(Connection * q) + : closed_(false), + connected(false), + q_ptr(q) +{ +} + +ConnectionPrivate::~ConnectionPrivate() +{ +} + +void ConnectionPrivate::init(Client * parent) +{ + Q_Q(QAMQP::Connection); + q->setParent(parent); + client_ = parent; + heartbeatTimer_ = new QTimer(parent); + QObject::connect(heartbeatTimer_, SIGNAL(timeout()), q, SLOT(_q_heartbeat())); +} + +void ConnectionPrivate::startOk() +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miStartOk); + QByteArray arguments_; + QDataStream stream(&arguments_, QIODevice::WriteOnly); + + QAMQP::Frame::TableField clientProperties; + clientProperties["version"] = QString(QAMQP_VERSION); + clientProperties["platform"] = QString("Qt %1").arg(qVersion()); + clientProperties["product"] = QString("QAMQP"); + clientProperties.unite(customProperty); + QAMQP::Frame::serialize(stream, clientProperties); + + client_->d_func()->auth_->write(stream); + QAMQP::Frame::writeField('s', stream, "en_US"); + frame.setArguments(arguments_); + client_->d_func()->network_->sendFrame(frame); +} + +void ConnectionPrivate::secureOk() +{ +} + +void ConnectionPrivate::tuneOk() +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miTuneOk); + QByteArray arguments_; + QDataStream stream(&arguments_, QIODevice::WriteOnly); + + stream << qint16(0); //channel_max + stream << qint32(FRAME_MAX); //frame_max + stream << qint16(heartbeatTimer_->interval() / 1000); //heartbeat + + frame.setArguments(arguments_); + client_->d_func()->network_->sendFrame(frame); +} + +void ConnectionPrivate::open() +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miOpen); + QByteArray arguments_; + QDataStream stream(&arguments_, QIODevice::WriteOnly); + + QAMQP::Frame::writeField('s',stream, client_->virtualHost()); + + stream << qint8(0); + stream << qint8(0); + + frame.setArguments(arguments_); + client_->d_func()->network_->sendFrame(frame); +} + +void ConnectionPrivate::start(const QAMQP::Frame::Method &frame) +{ + qDebug(">> Start"); + QByteArray data = frame.arguments(); + QDataStream stream(&data, QIODevice::ReadOnly); + quint8 version_major = 0; + quint8 version_minor = 0; + + stream >> version_major >> version_minor; + + QAMQP::Frame::TableField table; + QAMQP::Frame::deserialize(stream, table); + + QString mechanisms = QAMQP::Frame::readField('S', stream).toString(); + QString locales = QAMQP::Frame::readField('S', stream).toString(); + + qDebug(">> version_major: %d", version_major); + qDebug(">> version_minor: %d", version_minor); + + QAMQP::Frame::print(table); + + qDebug(">> mechanisms: %s", qPrintable(mechanisms)); + qDebug(">> locales: %s", qPrintable(locales)); + + startOk(); +} + +void ConnectionPrivate::secure(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) +} + +void ConnectionPrivate::tune(const QAMQP::Frame::Method &frame) +{ + qDebug(">> Tune"); + QByteArray data = frame.arguments(); + QDataStream stream(&data, QIODevice::ReadOnly); + + qint16 channel_max = 0, + heartbeat = 0; + qint32 frame_max = 0; + + stream >> channel_max; + stream >> frame_max; + stream >> heartbeat; + + qDebug(">> channel_max: %d", channel_max); + qDebug(">> frame_max: %d", frame_max); + qDebug(">> heartbeat: %d", heartbeat); + + if (heartbeatTimer_) { + heartbeatTimer_->setInterval(heartbeat * 1000); + if (heartbeatTimer_->interval()) + heartbeatTimer_->start(); + else + heartbeatTimer_->stop(); + } + + tuneOk(); + open(); +} + +void ConnectionPrivate::openOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Connection); + + qDebug(">> OpenOK"); + connected = true; + q->openOk(); +} + +void ConnectionPrivate::close(const QAMQP::Frame::Method &frame) +{ + Q_Q(QAMQP::Connection); + + qDebug(">> CLOSE"); + QByteArray data = frame.arguments(); + QDataStream stream(&data, QIODevice::ReadOnly); + qint16 code_ = 0, classId, methodId; + stream >> code_; + QString text(QAMQP::Frame::readField('s', stream).toString()); + stream >> classId; + stream >> methodId; + + qDebug(">> code: %d", code_); + qDebug(">> text: %s", qPrintable(text)); + qDebug(">> class-id: %d", classId); + qDebug(">> method-id: %d", methodId); + connected = false; + client_->d_func()->network_->error(QAbstractSocket::RemoteHostClosedError); + QMetaObject::invokeMethod(q, "disconnected"); +} + +void ConnectionPrivate::close(int code, const QString &text, int classId, int methodId) +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miClose); + QByteArray arguments_; + QDataStream stream(&arguments_, QIODevice::WriteOnly); + + QAMQP::Frame::writeField('s',stream, client_->virtualHost()); + + stream << qint16(code); + QAMQP::Frame::writeField('s', stream, text); + stream << qint16(classId); + stream << qint16(methodId); + + frame.setArguments(arguments_); + client_->d_func()->network_->sendFrame(frame); +} + +void ConnectionPrivate::closeOk() +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcConnection, miCloseOk); + connected = false; + client_->d_func()->network_->sendFrame(frame); + +} + +void ConnectionPrivate::closeOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Connection); + + connected = false; + QMetaObject::invokeMethod(q, "disconnected"); + if (heartbeatTimer_) + heartbeatTimer_->stop(); +} + + +void ConnectionPrivate::setQOS(qint32 prefetchSize, quint16 prefetchCount, int channel, bool global) +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, 10); + frame.setChannel(channel); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + + out << prefetchSize; + out << prefetchCount; + out << qint8(global ? 1 : 0); + + frame.setArguments(arguments_); + client_->d_func()->network_->sendFrame(frame); +} + +bool ConnectionPrivate::_q_method(const QAMQP::Frame::Method &frame) +{ + Q_ASSERT(frame.methodClass() == QAMQP::Frame::fcConnection); + if (frame.methodClass() != QAMQP::Frame::fcConnection) + return true; + + qDebug() << "Connection:"; + + if (closed_) { + if (frame.id() == miCloseOk) + closeOk(frame); + + return true; + } + + switch (MethodId(frame.id())) { + case miStart: + start(frame); + break; + case miSecure: + secure(frame); + break; + case miTune: + tune(frame); + break; + case miOpenOk: + openOk(frame); + break; + case miClose: + close(frame); + break; + case miCloseOk: + closeOk(frame); + break; + default: + qWarning("Unknown method-id %d", frame.id()); + return false; + } + + return true; +} + +void ConnectionPrivate::_q_heartbeat() +{ + QAMQP::Frame::Heartbeat frame; + client_->d_func()->network_->sendFrame(frame); +} + +////////////////////////////////////////////////////////////////////////// + +Connection::Connection(Client *parent) + : QObject(parent), + d_ptr(new ConnectionPrivate(this)) +{ + Q_D(QAMQP::Connection); + d->init(parent); +} + +Connection::~Connection() +{ +} + +void Connection::startOk() +{ + Q_D(QAMQP::Connection); + d->startOk(); +} + +void Connection::secureOk() +{ + Q_D(QAMQP::Connection); + d->secureOk(); +} + +void Connection::tuneOk() +{ + Q_D(QAMQP::Connection); + d->tuneOk(); +} + +void Connection::open() +{ + Q_D(QAMQP::Connection); + d->open(); +} + +void Connection::close(int code, const QString &text, int classId , int methodId) +{ + Q_D(QAMQP::Connection); + d->close(code, text, classId, methodId); +} + +void Connection::closeOk() +{ + Q_D(QAMQP::Connection); + d->closeOk(); + Q_EMIT disconnect(); +} + +void Connection::openOk() +{ + Q_EMIT connected(); +} + +void Connection::_q_method(const QAMQP::Frame::Method &frame) +{ + Q_D(QAMQP::Connection); + d->_q_method(frame); +} + +bool Connection::isConnected() const +{ + Q_D(const QAMQP::Connection); + return d->connected; +} + +void Connection::setQOS(qint32 prefetchSize, quint16 prefetchCount) +{ + Q_D(QAMQP::Connection); + d->setQOS(prefetchSize, prefetchCount, 0, true); +} + +void Connection::addCustomProperty(const QString &name, const QString &value) +{ + Q_D(QAMQP::Connection); + d->customProperty[name] = value; +} + +QString Connection::customProperty(const QString &name) const +{ + Q_D(const QAMQP::Connection); + if (d->customProperty.contains(name)) + return d->customProperty.value(name).toString(); + return QString(); +} + +#include "moc_amqp_connection.cpp" diff --git a/src/qamqp/amqp_connection.h b/src/qamqp/amqp_connection.h index 531a1be..a4a94f0 100644 --- a/src/qamqp/amqp_connection.h +++ b/src/qamqp/amqp_connection.h @@ -1,59 +1,56 @@ -#ifndef amqp_connection_h__ -#define amqp_connection_h__ - -#include -#include "amqp_frame.h" -#include "amqp_global.h" - -namespace QAMQP -{ - class ConnectionPrivate; - class ChannelPrivate; - class ClientPrivate; - class Client; - class Connection : public QObject, public Frame::MethodHandler - { - Q_OBJECT - P_DECLARE_PRIVATE(QAMQP::Connection) - Q_DISABLE_COPY(Connection) - Connection(Client * parent = 0); - public: - ~Connection(); - - - void addCustomProperty(const QString & name, const QString & value); - QString customProperty(const QString & name) const; - - void startOk(); - void secureOk(); - void tuneOk(); - void open(); - void close(int code, const QString & text, int classId = 0, int methodId = 0); - void closeOk(); - - bool isConnected() const; - - void setQOS(qint32 prefetchSize, quint16 prefetchCount); - - Q_SIGNALS: - void disconnected(); - void connected(); - protected: - ConnectionPrivate * const pd_ptr; - - private: - void openOk(); - friend class ClientPrivate; - friend class ChannelPrivate; - - void _q_method(const QAMQP::Frame::Method & frame); - Q_PRIVATE_SLOT(pd_func(), void _q_heartbeat()); - }; -} - -// Include private header so MOC won't complain -#ifdef QAMQP_P_INCLUDE -# include "amqp_connection_p.h" -#endif - -#endif // amqp_connection_h__ +#ifndef amqp_connection_h__ +#define amqp_connection_h__ + +#include +#include "amqp_frame.h" +#include "amqp_global.h" + +namespace QAMQP +{ + +class Client; +class ClientPrivate; +class ChannelPrivate; +class ConnectionPrivate; +class Connection : public QObject, public Frame::MethodHandler +{ + Q_OBJECT +public: + virtual ~Connection(); + + void addCustomProperty(const QString &name, const QString &value); + QString customProperty(const QString &name) const; + + void startOk(); + void secureOk(); + void tuneOk(); + void open(); + void close(int code, const QString &text, int classId = 0, int methodId = 0); + void closeOk(); + + bool isConnected() const; + + void setQOS(qint32 prefetchSize, quint16 prefetchCount); + +Q_SIGNALS: + void disconnected(); + void connected(); + +private: + Q_DISABLE_COPY(Connection) + Q_DECLARE_PRIVATE(Connection) + QScopedPointer d_ptr; + + Connection(Client * parent = 0); + + void openOk(); + friend class ClientPrivate; + friend class ChannelPrivate; + + void _q_method(const QAMQP::Frame::Method &frame); + Q_PRIVATE_SLOT(d_func(), void _q_heartbeat()) +}; + +} + +#endif // amqp_connection_h__ diff --git a/src/qamqp/amqp_connection_p.h b/src/qamqp/amqp_connection_p.h index cbf2032..a6df532 100644 --- a/src/qamqp/amqp_connection_p.h +++ b/src/qamqp/amqp_connection_p.h @@ -1,59 +1,62 @@ -#ifndef amqp_connection_p_h__ -#define amqp_connection_p_h__ - -#define METHOD_ID_ENUM(name, id) name = id, name ## Ok - -#include - -class QTimer; - -namespace QAMQP -{ - class Client; - class ClientPrivate; - class ConnectionPrivate - { - P_DECLARE_PUBLIC(QAMQP::Connection) - public: - enum MethodId - { - METHOD_ID_ENUM(miStart, 10), - METHOD_ID_ENUM(miSecure, 20), - METHOD_ID_ENUM(miTune, 30), - METHOD_ID_ENUM(miOpen, 40), - METHOD_ID_ENUM(miClose, 50) - }; - - ConnectionPrivate(Connection * q); - ~ConnectionPrivate(); - void init(Client * parent); - void startOk(); - void secureOk(); - void tuneOk(); - void open(); - void close(int code, const QString & text, int classId = 0, int methodId = 0); - void closeOk(); - - void start(const QAMQP::Frame::Method & frame); - void secure(const QAMQP::Frame::Method & frame); - void tune(const QAMQP::Frame::Method & frame); - void openOk(const QAMQP::Frame::Method & frame); - void close(const QAMQP::Frame::Method & frame); - void closeOk(const QAMQP::Frame::Method & frame); - bool _q_method(const QAMQP::Frame::Method & frame); - void _q_heartbeat(); - - void setQOS(qint32 prefetchSize, quint16 prefetchCount, int channel, bool global); - - QPointer client_; - bool closed_; - bool connected; - QPointer heartbeatTimer_; - - Connection * const pq_ptr; - - QAMQP::Frame::TableField customProperty; - - }; -} -#endif // amqp_connection_p_h__ +#ifndef amqp_connection_p_h__ +#define amqp_connection_p_h__ + +#define METHOD_ID_ENUM(name, id) name = id, name ## Ok + +#include + +class QTimer; + +namespace QAMQP +{ +class Client; +class ClientPrivate; +class Connection; +class ConnectionPrivate +{ +public: + enum MethodId { + METHOD_ID_ENUM(miStart, 10), + METHOD_ID_ENUM(miSecure, 20), + METHOD_ID_ENUM(miTune, 30), + METHOD_ID_ENUM(miOpen, 40), + METHOD_ID_ENUM(miClose, 50) + }; + + ConnectionPrivate(Connection *q); + ~ConnectionPrivate(); + + void init(Client *parent); + void startOk(); + void secureOk(); + void tuneOk(); + void open(); + void close(int code, const QString & text, int classId = 0, int methodId = 0); + void closeOk(); + + void start(const QAMQP::Frame::Method &frame); + void secure(const QAMQP::Frame::Method &frame); + void tune(const QAMQP::Frame::Method &frame); + void openOk(const QAMQP::Frame::Method &frame); + void close(const QAMQP::Frame::Method &frame); + void closeOk(const QAMQP::Frame::Method &frame); + + bool _q_method(const QAMQP::Frame::Method &frame); + void _q_heartbeat(); + + void setQOS(qint32 prefetchSize, quint16 prefetchCount, int channel, bool global); + + QPointer client_; + bool closed_; + bool connected; + QPointer heartbeatTimer_; + + QAMQP::Frame::TableField customProperty; + + Q_DECLARE_PUBLIC(QAMQP::Connection) + Connection * const q_ptr; +}; + +} + +#endif // amqp_connection_p_h__ diff --git a/src/qamqp/amqp_exchange.cpp b/src/qamqp/amqp_exchange.cpp index cbfd716..2f20a2b 100644 --- a/src/qamqp/amqp_exchange.cpp +++ b/src/qamqp/amqp_exchange.cpp @@ -1,276 +1,252 @@ -#include "amqp_exchange.h" -#include "amqp_exchange_p.h" -#include "amqp_queue.h" - -using namespace QAMQP; -using namespace QAMQP::Frame; - -#include -#include -#include - - -namespace QAMQP -{ - struct ExchangeExceptionCleaner - { - /* this cleans up when the constructor throws an exception */ - static inline void cleanup(Exchange *that, ExchangePrivate *d) - { -#ifdef QT_NO_EXCEPTIONS - Q_UNUSED(that); - Q_UNUSED(d); -#else - Q_UNUSED(that); - Q_UNUSED(d); -#endif - } - }; - - -} - -Exchange::Exchange(int channelNumber, Client * parent /*= 0*/ ) -: Channel(new ExchangePrivate(this)) -{ - QT_TRY { - pd_func()->init(channelNumber, parent); - } QT_CATCH(...) { - ExchangeExceptionCleaner::cleanup(this, pd_func()); - QT_RETHROW; - } -} - -Exchange::~Exchange() -{ - remove(); -} - -void Exchange::onOpen() -{ - P_D(Exchange); - if(d->delayedDeclare) - { - d->declare(); - } -} - -void Exchange::onClose() -{ - pd_func()->remove(true, true); -} - -Exchange::ExchangeOptions Exchange::option() const -{ - return pd_func()->options; -} - -QString Exchange::type() const -{ - return pd_func()->type; -} - - -void Exchange::declare(const QString &type, ExchangeOptions option , const TableField & arg) -{ - P_D(Exchange); - d->options = option; - d->type = type; - d->arguments = arg; - d->declare(); -} - -void Exchange::remove( bool ifUnused /*= true*/, bool noWait /*= true*/ ) -{ - pd_func()->remove(ifUnused, noWait); -} - - -void Exchange::bind( QAMQP::Queue * queue ) -{ - queue->bind(this, pd_func()->name); -} - -void Exchange::bind( const QString & queueName ) -{ - Q_UNUSED(queueName); - qWarning("Not implement"); -} - -void Exchange::bind( const QString & queueName, const QString &key ) -{ - Q_UNUSED(queueName); - Q_UNUSED(key); - qWarning("Not implement"); -} - -void Exchange::publish( const QString & message, const QString & key, const MessageProperties &prop ) -{ - pd_func()->publish(message.toUtf8(), key, QString::fromLatin1("text.plain"), QVariantHash(), prop); -} - - -void Exchange::publish( const QByteArray & message, const QString & key, const QString &mimeType, const MessageProperties &prop ) -{ - pd_func()->publish(message, key, mimeType, QVariantHash(), prop); -} - -void Exchange::publish( const QByteArray & message, const QString & key, const QVariantHash &headers, const QString &mimeType, const MessageProperties &prop ) -{ - pd_func()->publish(message, key, mimeType, headers, prop); -} - -////////////////////////////////////////////////////////////////////////// - - -ExchangePrivate::ExchangePrivate(Exchange * q) - :ChannelPrivate(q) - , delayedDeclare(false) - , declared(false) -{ -} - - -ExchangePrivate::~ExchangePrivate() -{ - -} - - -bool ExchangePrivate::_q_method( const QAMQP::Frame::Method & frame ) -{ - if(ChannelPrivate::_q_method(frame)) - return true; - - if(frame.methodClass() != QAMQP::Frame::fcExchange) - return false; - - switch(frame.id()) - { - case miDeclareOk: - declareOk(frame); - break; - case miDelete: - deleteOk(frame); - break; - default: - break; - } - return true; -} - -void ExchangePrivate::declareOk( const QAMQP::Frame::Method & ) -{ - qDebug() << "Declared exchange: " << name; - declared = true; - QMetaObject::invokeMethod(pq_func(), "declared"); -} - -void ExchangePrivate::deleteOk( const QAMQP::Frame::Method & ) -{ - qDebug() << "Deleted exchange: " << name; - declared = false; - QMetaObject::invokeMethod(pq_func(), "removed"); -} - -void ExchangePrivate::declare( ) -{ - if(!opened) - { - delayedDeclare = true; - return; - } - - if(name.isEmpty()) - return; - - QAMQP::Frame::Method frame(QAMQP::Frame::fcExchange, miDeclare); - frame.setChannel(number); - QByteArray arguments_; - QDataStream stream(&arguments_, QIODevice::WriteOnly); - - stream << qint16(0); //reserver 1 - writeField('s', stream, name); - writeField('s', stream, type); - stream << qint8(options); - writeField('F', stream, ExchangePrivate::arguments); - - frame.setArguments(arguments_); - sendFrame(frame); - delayedDeclare = false; -} - -void ExchangePrivate::remove( bool ifUnused /*= true*/, bool noWait /*= true*/ ) -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcExchange, miDelete); - frame.setChannel(number); - QByteArray arguments_; - QDataStream stream(&arguments_, QIODevice::WriteOnly); - - stream << qint16(0); //reserver 1 - writeField('s', stream, name); - - qint8 flag = 0; - - flag |= (ifUnused ? 0x1 : 0); - flag |= (noWait ? 0x2 : 0); - - stream << flag; //reserver 1 - - frame.setArguments(arguments_); - sendFrame(frame); -} - -void ExchangePrivate::publish( const QByteArray & message, const QString & key, const QString &mimeType /*= QString::fromLatin1("text/plain")*/, const QVariantHash & headers, const Exchange::MessageProperties & prop ) -{ - QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmPublish); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - - out << qint16(0); //reserver 1 - writeField('s', out, name); - writeField('s', out, key); - out << qint8(0); - - frame.setArguments(arguments_); - sendFrame(frame); - - - QAMQP::Frame::Content content(QAMQP::Frame::fcBasic); - content.setChannel(number); - content.setProperty(Content::cpContentType, mimeType); - content.setProperty(Content::cpContentEncoding, "utf-8"); - content.setProperty(Content::cpHeaders, headers); - content.setProperty(Content::cpMessageId, "0"); - - Exchange::MessageProperties::ConstIterator i; - - for(i = prop.begin(); i != prop.end(); ++i) - { - content.setProperty(i.key(), i.value()); - } - - content.setBody(message); - sendFrame(content); - - int fullSize = message.size(); - for (int sended_ = 0; sended_ < fullSize; sended_+= (FRAME_MAX - 7)) - { - QAMQP::Frame::ContentBody body; - QByteArray partition_ = message.mid(sended_, (FRAME_MAX - 7)); - body.setChannel(number); - body.setBody(partition_); - sendFrame(body); - } - -} - - -void ExchangePrivate::_q_disconnected() -{ - ChannelPrivate::_q_disconnected(); - qDebug() << "Exchange " << name << " disconnected"; - delayedDeclare = false; - declared = false; -} +#include "amqp_exchange.h" +#include "amqp_exchange_p.h" +#include "amqp_queue.h" + +using namespace QAMQP; +using namespace QAMQP::Frame; + +#include +#include +#include + +Exchange::Exchange(int channelNumber, Client *parent) + : Channel(new ExchangePrivate(this), parent) +{ + Q_D(QAMQP::Exchange); + d->init(channelNumber, parent); +} + +Exchange::~Exchange() +{ + remove(); +} + +void Exchange::onOpen() +{ + Q_D(QAMQP::Exchange); + if (d->delayedDeclare) + d->declare(); +} + +void Exchange::onClose() +{ + Q_D(QAMQP::Exchange); + d->remove(true, true); +} + +Exchange::ExchangeOptions Exchange::option() const +{ + Q_D(const QAMQP::Exchange); + return d->options; +} + +QString Exchange::type() const +{ + Q_D(const QAMQP::Exchange); + return d->type; +} + +void Exchange::declare(const QString &type, ExchangeOptions option , const TableField &arg) +{ + Q_D(QAMQP::Exchange); + d->options = option; + d->type = type; + d->arguments = arg; + d->declare(); +} + +void Exchange::remove(bool ifUnused, bool noWait) +{ + Q_D(QAMQP::Exchange); + d->remove(ifUnused, noWait); +} + +void Exchange::bind(QAMQP::Queue *queue) +{ + Q_D(QAMQP::Exchange); + queue->bind(this, d->name); +} + +void Exchange::bind(const QString &queueName) +{ + Q_UNUSED(queueName); + qWarning("Not implemented"); +} + +void Exchange::bind(const QString &queueName, const QString &key) +{ + Q_UNUSED(queueName); + Q_UNUSED(key); + qWarning("Not implemented"); +} + +void Exchange::publish(const QString &message, const QString &key, const MessageProperties &prop) +{ + Q_D(QAMQP::Exchange); + d->publish(message.toUtf8(), key, QLatin1String("text.plain"), QVariantHash(), prop); +} + +void Exchange::publish(const QByteArray &message, const QString &key, + const QString &mimeType, const MessageProperties &prop) +{ + Q_D(QAMQP::Exchange); + d->publish(message, key, mimeType, QVariantHash(), prop); +} + +void Exchange::publish(const QByteArray &message, const QString &key, + const QVariantHash &headers, const QString &mimeType, + const MessageProperties &prop) +{ + Q_D(QAMQP::Exchange); + d->publish(message, key, mimeType, headers, prop); +} + +////////////////////////////////////////////////////////////////////////// + +ExchangePrivate::ExchangePrivate(Exchange * q) + : ChannelPrivate(q), + delayedDeclare(false), + declared(false) +{ +} + +ExchangePrivate::~ExchangePrivate() +{ +} + +bool ExchangePrivate::_q_method(const QAMQP::Frame::Method &frame) +{ + if (ChannelPrivate::_q_method(frame)) + return true; + + if (frame.methodClass() != QAMQP::Frame::fcExchange) + return false; + + switch(frame.id()) { + case miDeclareOk: + declareOk(frame); + break; + case miDelete: + deleteOk(frame); + break; + default: + break; + } + + return true; +} + +void ExchangePrivate::declareOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Exchange); + qDebug() << "Declared exchange: " << name; + declared = true; + QMetaObject::invokeMethod(q, "declared"); +} + +void ExchangePrivate::deleteOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Exchange); + qDebug() << "Deleted exchange: " << name; + declared = false; + QMetaObject::invokeMethod(q, "removed"); +} + +void ExchangePrivate::declare() +{ + if (!opened) { + delayedDeclare = true; + return; + } + + if (name.isEmpty()) + return; + + QAMQP::Frame::Method frame(QAMQP::Frame::fcExchange, miDeclare); + frame.setChannel(number); + QByteArray arguments_; + QDataStream stream(&arguments_, QIODevice::WriteOnly); + + stream << qint16(0); //reserver 1 + writeField('s', stream, name); + writeField('s', stream, type); + stream << qint8(options); + writeField('F', stream, ExchangePrivate::arguments); + + frame.setArguments(arguments_); + sendFrame(frame); + delayedDeclare = false; +} + +void ExchangePrivate::remove(bool ifUnused, bool noWait) +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcExchange, miDelete); + frame.setChannel(number); + QByteArray arguments_; + QDataStream stream(&arguments_, QIODevice::WriteOnly); + + stream << qint16(0); //reserver 1 + writeField('s', stream, name); + + qint8 flag = 0; + + flag |= (ifUnused ? 0x1 : 0); + flag |= (noWait ? 0x2 : 0); + + stream << flag; //reserver 1 + + frame.setArguments(arguments_); + sendFrame(frame); +} + +void ExchangePrivate::publish(const QByteArray &message, const QString &key, + const QString &mimeType, const QVariantHash & headers, + const Exchange::MessageProperties &prop) +{ + QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmPublish); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + + out << qint16(0); //reserver 1 + writeField('s', out, name); + writeField('s', out, key); + out << qint8(0); + + frame.setArguments(arguments_); + sendFrame(frame); + + QAMQP::Frame::Content content(QAMQP::Frame::fcBasic); + content.setChannel(number); + content.setProperty(Content::cpContentType, mimeType); + content.setProperty(Content::cpContentEncoding, "utf-8"); + content.setProperty(Content::cpHeaders, headers); + content.setProperty(Content::cpMessageId, "0"); + + Exchange::MessageProperties::ConstIterator i; + + for (i = prop.begin(); i != prop.end(); ++i) + content.setProperty(i.key(), i.value()); + + content.setBody(message); + sendFrame(content); + + int fullSize = message.size(); + for (int sended_ = 0; sended_ < fullSize; sended_+= (FRAME_MAX - 7)) { + QAMQP::Frame::ContentBody body; + QByteArray partition_ = message.mid(sended_, (FRAME_MAX - 7)); + body.setChannel(number); + body.setBody(partition_); + sendFrame(body); + } +} + +void ExchangePrivate::_q_disconnected() +{ + ChannelPrivate::_q_disconnected(); + qDebug() << "Exchange " << name << " disconnected"; + delayedDeclare = false; + declared = false; +} diff --git a/src/qamqp/amqp_exchange.h b/src/qamqp/amqp_exchange.h index eb5a0f2..7ec1acd 100644 --- a/src/qamqp/amqp_exchange.h +++ b/src/qamqp/amqp_exchange.h @@ -1,64 +1,76 @@ -#ifndef amqp_exchange_h__ -#define amqp_exchange_h__ - -#include "amqp_channel.h" -namespace QAMQP -{ - class Client; - class Queue; - class ClientPrivate; - class ExchangePrivate; - - using namespace QAMQP::Frame; - class Exchange : public Channel - { - Q_OBJECT; - Exchange(int channelNumber = -1, Client * parent = 0); - - Q_PROPERTY(QString type READ type); - Q_PROPERTY(ExchangeOptions option READ option ); - - P_DECLARE_PRIVATE(QAMQP::Exchange) - Q_DISABLE_COPY(Exchange); - friend class ClientPrivate; - protected: - void onOpen(); - void onClose(); - - public: - - enum ExchangeOption { - NoOptions = 0x0, - Passive = 0x01, - Durable = 0x02, - AutoDelete = 0x4, - Internal = 0x8, - NoWait = 0x10 - }; - Q_DECLARE_FLAGS(ExchangeOptions, ExchangeOption) - - typedef QHash MessageProperties; - - ~Exchange(); - - QString type() const; - ExchangeOptions option() const; - - void declare(const QString &type = QString::fromLatin1("direct"), ExchangeOptions option = NoOptions, const TableField & arg = TableField()); - void remove(bool ifUnused = true, bool noWait = true); - - void bind(QAMQP::Queue * queue); - void bind(const QString & queueName); - void bind(const QString & queueName, const QString &key); - - void publish(const QString & message, const QString & key, const MessageProperties &property = MessageProperties() ); - void publish(const QByteArray & message, const QString & key, const QString &mimeType, const MessageProperties &property = MessageProperties()); - void publish(const QByteArray & message, const QString & key, const QVariantHash &headers, const QString &mimeType, const MessageProperties &property = MessageProperties()); - - Q_SIGNALS: - void declared(); - void removed(); - }; -} -Q_DECLARE_OPERATORS_FOR_FLAGS(QAMQP::Exchange::ExchangeOptions) -#endif // amqp_exchange_h__ +#ifndef amqp_exchange_h__ +#define amqp_exchange_h__ + +#include "amqp_channel.h" + +namespace QAMQP +{ + +using namespace QAMQP::Frame; + +class Client; +class Queue; +class ClientPrivate; +class ExchangePrivate; +class Exchange : public Channel +{ + Q_OBJECT + Q_PROPERTY(QString type READ type) + Q_PROPERTY(ExchangeOptions option READ option) + Q_ENUMS(ExchangeOption) + +public: + enum ExchangeOption { + NoOptions = 0x0, + Passive = 0x01, + Durable = 0x02, + AutoDelete = 0x4, + Internal = 0x8, + NoWait = 0x10 + }; + Q_DECLARE_FLAGS(ExchangeOptions, ExchangeOption) + + typedef QHash MessageProperties; + + virtual ~Exchange(); + + QString type() const; + ExchangeOptions option() const; + + void declare(const QString &type = QLatin1String("direct"), + ExchangeOptions option = NoOptions, + const TableField &arg = TableField()); + void remove(bool ifUnused = true, bool noWait = true); + + void bind(QAMQP::Queue *queue); + void bind(const QString &queueName); + void bind(const QString &queueName, const QString &key); + + void publish(const QString &message, const QString &key, + const MessageProperties &property = MessageProperties()); + void publish(const QByteArray &message, const QString &key, + const QString &mimeType, const MessageProperties &property = MessageProperties()); + void publish(const QByteArray &message, const QString &key, const QVariantHash &headers, + const QString &mimeType, const MessageProperties &property = MessageProperties()); + +Q_SIGNALS: + void declared(); + void removed(); + +protected: + void onOpen(); + void onClose(); + +private: + Q_DISABLE_COPY(Exchange) + Q_DECLARE_PRIVATE(QAMQP::Exchange) + Exchange(int channelNumber = -1, Client * parent = 0); + friend class ClientPrivate; + +}; + +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(QAMQP::Exchange::ExchangeOptions) + +#endif // amqp_exchange_h__ diff --git a/src/qamqp/amqp_exchange_p.h b/src/qamqp/amqp_exchange_p.h index cd1eea5..241ff04 100644 --- a/src/qamqp/amqp_exchange_p.h +++ b/src/qamqp/amqp_exchange_p.h @@ -1,40 +1,44 @@ -#include "amqp_channel_p.h" -#define METHOD_ID_ENUM(name, id) name = id, name ## Ok - -namespace QAMQP -{ - using namespace QAMQP::Frame; - class ExchangePrivate: public ChannelPrivate - { - P_DECLARE_PUBLIC(QAMQP::Exchange) - public: - - enum MethodId - { - METHOD_ID_ENUM(miDeclare, 10), - METHOD_ID_ENUM(miDelete, 20) - }; - - ExchangePrivate(Exchange * q); - ~ExchangePrivate(); - - void declare(); - void remove(bool ifUnused = true, bool noWait = true); - - void declareOk(const QAMQP::Frame::Method & frame); - void deleteOk(const QAMQP::Frame::Method & frame); - - void publish(const QByteArray & message, const QString & key, const QString &mimeType = QString::fromLatin1("text/plain"), const QVariantHash & headers = QVariantHash(), const Exchange::MessageProperties & properties = Exchange::MessageProperties()); - - QString type; - Exchange::ExchangeOptions options; - TableField arguments; - - bool _q_method(const QAMQP::Frame::Method & frame); - void _q_disconnected(); - - bool delayedDeclare; - bool declared; - - }; -} +#include "amqp_channel_p.h" + +#define METHOD_ID_ENUM(name, id) name = id, name ## Ok + +namespace QAMQP +{ + +using namespace QAMQP::Frame; +class ExchangePrivate: public ChannelPrivate +{ +public: + enum MethodId { + METHOD_ID_ENUM(miDeclare, 10), + METHOD_ID_ENUM(miDelete, 20) + }; + + ExchangePrivate(Exchange * q); + ~ExchangePrivate(); + + void declare(); + void remove(bool ifUnused = true, bool noWait = true); + + void declareOk(const QAMQP::Frame::Method &frame); + void deleteOk(const QAMQP::Frame::Method &frame); + + void publish(const QByteArray &message, const QString &key, + const QString &mimeType = QLatin1String("text/plain"), + const QVariantHash &headers = QVariantHash(), + const Exchange::MessageProperties &properties = Exchange::MessageProperties()); + + QString type; + Exchange::ExchangeOptions options; + TableField arguments; + + bool _q_method(const QAMQP::Frame::Method &frame); + void _q_disconnected(); + + bool delayedDeclare; + bool declared; + + Q_DECLARE_PUBLIC(QAMQP::Exchange) +}; + +} diff --git a/src/qamqp/amqp_frame.cpp b/src/qamqp/amqp_frame.cpp index 2cdbb8b..268859c 100644 --- a/src/qamqp/amqp_frame.cpp +++ b/src/qamqp/amqp_frame.cpp @@ -1,716 +1,693 @@ -#include "amqp_frame.h" - -#include -#include -#include -#include - -using namespace QAMQP::Frame; -Base::Base( Type type ) : size_(0), type_(type), channel_(0) {} - -Base::Base( QDataStream& raw ) -{ - readHeader(raw); -} - -Type Base::type() const -{ - return Type(type_); -} - -Base::~Base() -{} - -void Base::setChannel( qint16 channel ) -{ - channel_ = channel; -} - -qint16 Base::channel() const -{ - return channel_; -} - -qint32 Base::size() const -{ - return 0; -} - -void QAMQP::Frame::Base::writeHeader( QDataStream & stream ) const -{ - stream << type_; - stream << channel_; - stream << qint32(size()); - -} - -void QAMQP::Frame::Base::writeEnd( QDataStream & stream ) const -{ - stream << qint8(FRAME_END); -} - -void QAMQP::Frame::Base::writePayload( QDataStream & ) const{} - -void QAMQP::Frame::Base::readHeader( QDataStream & stream ) -{ - stream >> type_; - stream >> channel_; - stream >> size_; - -} - -void QAMQP::Frame::Base::readEnd( QDataStream & stream ) -{ - unsigned char end_ = 0; - stream.readRawData(reinterpret_cast(&end_), sizeof(end_)); - if(end_ != FRAME_END ) - { - qWarning("Wrong end of frame"); - } -} - -void QAMQP::Frame::Base::readPayload( QDataStream & stream ) -{ - stream.skipRawData(size_); -} - -void QAMQP::Frame::Base::toStream( QDataStream & stream ) const -{ - writeHeader(stream); - writePayload(stream); - writeEnd(stream); -} - -////////////////////////////////////////////////////////////////////////// - - -QAMQP::Frame::Method::Method( MethodClass methodClass, qint16 id ) -: Base(ftMethod), methodClass_(methodClass), id_(id) -{ - -} - -QAMQP::Frame::Method::Method( QDataStream& raw ) -: Base(raw) -{ - readPayload(raw); -} - -QAMQP::Frame::Method::Method(): Base(ftMethod) -{ - -} - -MethodClass QAMQP::Frame::Method::methodClass() const -{ - return MethodClass(methodClass_); -} - -qint16 QAMQP::Frame::Method::id() const -{ - return id_; -} - -qint32 QAMQP::Frame::Method::size() const -{ - return sizeof(id_) + sizeof(methodClass_) + arguments_.size(); -} - -void QAMQP::Frame::Method::setArguments( const QByteArray & data ) -{ - arguments_ = data; -} - -QByteArray QAMQP::Frame::Method::arguments() const -{ - return arguments_; -} - -void QAMQP::Frame::Method::readPayload( QDataStream & stream ) -{ - stream >> methodClass_; - stream >> id_; - - arguments_.resize(size_ - (sizeof(id_) + sizeof(methodClass_))); - stream.readRawData(arguments_.data(), arguments_.size()); -} - -void QAMQP::Frame::Method::writePayload( QDataStream & stream ) const -{ - stream << quint16(methodClass_); - stream << quint16(id_); - stream.writeRawData(arguments_.data(), arguments_.size()); -} - - -////////////////////////////////////////////////////////////////////////// - - -QVariant QAMQP::Frame::readField( qint8 valueType, QDataStream &s ) -{ - QVariant value; - QByteArray tmp; - qint8 nameSize_ = 0; - char octet = 0; - - switch(valueType) - { - case 't': - s.readRawData(&octet, sizeof(octet)); - value = QVariant::fromValue(octet > 0); - break; - case 'b': - s.readRawData(&octet, sizeof(octet)); - value = QVariant::fromValue(octet); - break; - case 'B': - s.readRawData(&octet, sizeof(octet)); - value = QVariant::fromValue(octet); - break; - case 'U': - { - qint16 tmp_value_ = 0; - s >> tmp_value_; - value = QVariant::fromValue(tmp_value_); - break; - } - case 'u': - { - quint16 tmp_value_ = 0; - s >> tmp_value_; - value = QVariant::fromValue(tmp_value_); - break; - } - case 'I': - { - qint32 tmp_value_ = 0; - s >> tmp_value_; - value = QVariant::fromValue(tmp_value_); - break; - } - case 'i': - { - quint32 tmp_value_ = 0; - s >> tmp_value_; - value = QVariant::fromValue(tmp_value_); - break; - } - case 'L': - { - qlonglong v = 0 ; - s >> v; - value = v; - } - - break; - case 'l': - { - qulonglong v = 0 ; - s >> v; - value = v; - } - - break; - case 'f': - { - float tmp_value_; - s >> tmp_value_; - value = QVariant::fromValue(tmp_value_); - break; - } - case 'd': - { - double tmp_value_; - s >> tmp_value_; - value = QVariant::fromValue(tmp_value_); - break; - } - case 'D': - { - QAMQP::Frame::decimal v; - s >> v.scale; - s >> v.value; - value = QVariant::fromValue(v); - } - break; - case 's': - s >> nameSize_; - tmp.resize(nameSize_); - s.readRawData(tmp.data(), tmp.size()); - #if QT_VERSION < 0x050000 - value = QString::fromAscii(tmp.data(), nameSize_); - #else // For Qt5 - value = QString::fromLatin1(tmp.data(), nameSize_); - #endif - break; - case 'S': - { - quint32 length_ = 0; - s >> length_; - nameSize_ = length_; - tmp.resize(length_); - } - s.readRawData(tmp.data(), tmp.size()); - #if QT_VERSION < 0x050000 - value = QString::fromAscii(tmp.data(), tmp.size()); - #else // For Qt5 - value = QString::fromLatin1(tmp.data(), tmp.size()); - #endif - break; - case 'A': - { - qint32 length_ = 0; - qint8 type = 0; - s >> length_; - QList array_; - for (int i =0; i < length_; ++i) - { - s >> type; - array_ << readField(type, s); - } - value = array_; - } - break; - case 'T': - { - qulonglong tmp_value_; - s >> tmp_value_; - value = QDateTime::fromMSecsSinceEpoch(tmp_value_); - break; - } - case 'F': - { - TableField table_; - deserialize(s, table_); - value = table_; - } - break; - case 'V': - break; - default: - qWarning("Unknown field type"); - } - return value; -} - -QDataStream & QAMQP::Frame::deserialize( QDataStream & stream, QAMQP::Frame::TableField & f ) -{ - QByteArray data; - stream >> data; - QDataStream s(&data, QIODevice::ReadOnly); - - while(!s.atEnd()) - { - qint8 valueType = 0; - - QString name = readField('s', s).toString(); - s >> valueType; - f[name] = readField(valueType, s); - } - - return stream; -} - -QDataStream & QAMQP::Frame::serialize( QDataStream & stream, const TableField & f ) -{ - QByteArray data; - QDataStream s(&data, QIODevice::WriteOnly); - TableField::ConstIterator i; - for(i = f.begin(); i != f.end(); ++i) - { - writeField('s', s, i.key()); - writeField(s, i.value()); - } - if(data.isEmpty()) - { - stream << qint32(0); - } else { - stream << data; - } - - return stream; -} - -void QAMQP::Frame::print( const TableField & f ) -{ - TableField::ConstIterator i; - for(i = f.begin(); i != f.end(); ++i) - { - switch(i.value().type()) - { - case QVariant::Hash: - qDebug() << "\t" << qPrintable(i.key()) << ": FIELD_TABLE"; - break; - case QVariant::List: - qDebug() << "\t" << qPrintable(i.key()) << ": ARRAY"; - break; - default: - qDebug() << "\t" << qPrintable(i.key()) << ": " << i.value(); - } - } -} - -void QAMQP::Frame::writeField( qint8 valueType, QDataStream &s, const QVariant & value, bool withType ) -{ - QByteArray tmp; - if(withType) - s << valueType; - - switch(valueType) - { - case 't': - s << (value.toBool() ? qint8(1) : qint8(0)); - break; - case 'b': - s << qint8(value.toInt()); - break; - case 'B': - s << quint8(value.toUInt()); - break; - case 'U': - s << qint16(value.toInt()); - break; - case 'u': - s << quint16(value.toUInt()); - break; - case 'I': - s << qint32(value.toInt()); - break; - case 'i': - s << quint32(value.toUInt()); - break; - case 'L': - s << qlonglong(value.toLongLong()); - break; - case 'l': - s << qulonglong(value.toULongLong()); - break; - case 'f': - s << value.toFloat(); - break; - case 'd': - s << value.toDouble(); - break; - case 'D': - { - QAMQP::Frame::decimal v(value.value()); - s << v.scale; - s << v.value; - } - break; - case 's': - { - QString str = value.toString(); - s << quint8(str.length()); - #if QT_VERSION < 0x050000 - s.writeRawData(str.toAscii().data(), str.length()); - #else // For Qt5 - s.writeRawData(str.toLatin1().data(), str.length()); - #endif - } - break; - case 'S': - { - QString str = value.toString(); - s << quint32(str.length()); - #if QT_VERSION < 0x050000 - s.writeRawData(str.toAscii().data(), str.length()); - #else // For Qt5 - s.writeRawData(str.toLatin1().data(), str.length()); - #endif - } - break; - case 'A': - { - QList array_(value.toList()); - s << quint32(array_.count()); - for (int i =0; i < array_.count(); ++i) - { - writeField(s, array_.at(i)); - } - } - break; - case 'T': - s << qulonglong(value.toDateTime().toMSecsSinceEpoch()); - break; - case 'F': - { - TableField table_(value.toHash()); - serialize(s, table_); - } - break; - case 'V': - break; - default: - qWarning("Unknown field type"); - } -} - -void QAMQP::Frame::writeField( QDataStream &s, const QVariant & value ) -{ - char type = 0; - switch(value.type()) - { - case QVariant::Bool: - type = 't'; - break; - case QVariant::ByteArray: - type = 'S'; - break; - case QVariant::Int: - { - int i = qAbs(value.toInt()); - if(i <= qint8(0xFF)) { - type = 'b'; - } else if(i <= qint16(0xFFFF)) { - type = 'U'; - } else if(i <= qint16(0xFFFFFFFF)) { - type = 'I'; - } - } - break; - case QVariant::UInt: - { - int i = value.toInt(); - if(i <= qint8(0xFF)) { - type = 'B'; - } else if(i <= qint16(0xFFFF)) { - type = 'u'; - } else if(i <= qint16(0xFFFFFFFF)) { - type = 'i'; - } - } - break; - case QVariant::LongLong: - type = 'L'; - break; - case QVariant::ULongLong: - type = 'l'; - break; - case QVariant::String: - type = 'S'; - break; - case QVariant::DateTime: - type = 'T'; - break; - case QVariant::Double: - type = value.toDouble() > FLT_MAX ? 'd' : 'f'; - break; - case QVariant::Hash: - type = 'F'; - break; - case QVariant::List: - type = 'A'; - break; - default:; - } - - if(type) - writeField(type, s, value, true); -} - -////////////////////////////////////////////////////////////////////////// - -QAMQP::Frame::Content::Content():Base(ftHeader) -{ - -} - -QAMQP::Frame::Content::Content( MethodClass methodClass ):Base(ftHeader) -{ - methodClass_ = methodClass; -} - -QAMQP::Frame::Content::Content( QDataStream& raw ): Base(raw) -{ - readPayload(raw); -} - -QAMQP::Frame::MethodClass QAMQP::Frame::Content::methodClass() const -{ - return MethodClass(methodClass_); -} - -qint32 QAMQP::Frame::Content::size() const -{ - QDataStream out(&buffer_, QIODevice::WriteOnly); - buffer_.clear(); - out << qint16(methodClass_); - out << qint16(0); //weight - out << qlonglong(body_.size()); - - qint16 prop_ = 0; - foreach (int p, properties_.keys()) - { - prop_ |= p; - } - - out << prop_; - - if(prop_ & cpContentType) - writeField('s', out, properties_[cpContentType]); - - if(prop_ & cpContentEncoding) - writeField('s', out, properties_[cpContentEncoding]); - - if(prop_ & cpHeaders) - writeField('F', out, properties_[cpHeaders]); - - if(prop_ & cpDeliveryMode) - writeField('b', out, properties_[cpDeliveryMode]); - - if(prop_ & cpPriority) - writeField('b', out, properties_[cpPriority]); - - if(prop_ & cpCorrelationId) - writeField('s', out, properties_[cpCorrelationId]); - - if(prop_ & cpReplyTo) - writeField('s', out, properties_[cpReplyTo]); - - if(prop_ & cpExpiration) - writeField('s', out, properties_[cpExpiration]); - - if(prop_ & cpMessageId) - writeField('s', out, properties_[cpMessageId]); - - if(prop_ & cpTimestamp) - writeField('T', out, properties_[cpTimestamp]); - - if(prop_ & cpType) - writeField('s', out, properties_[cpType]); - - if(prop_ & cpUserId) - writeField('s', out, properties_[cpUserId]); - - if(prop_ & cpAppId) - writeField('s', out, properties_[cpAppId]); - - if(prop_ & cpClusterID) - writeField('s', out, properties_[cpClusterID]); - - return buffer_.size(); -} - -void QAMQP::Frame::Content::setBody( const QByteArray & data ) -{ - body_ = data; -} - -QByteArray QAMQP::Frame::Content::body() const -{ - return body_; -} - -void QAMQP::Frame::Content::setProperty( Property prop, const QVariant & value ) -{ - properties_[prop] = value; -} - -QVariant QAMQP::Frame::Content::property( Property prop ) const -{ - return properties_.value(prop); -} - -void QAMQP::Frame::Content::writePayload( QDataStream & out ) const -{ - out.writeRawData(buffer_.data(), buffer_.size()); -} - -void QAMQP::Frame::Content::readPayload( QDataStream & in ) -{ - in >> methodClass_; - in.skipRawData(2); //weight - in >> bodySize_; - qint16 flags_ = 0; - in >> flags_; - if(flags_ & cpContentType) - properties_[cpContentType] = readField('s', in); - - if(flags_ & cpContentEncoding) - properties_[cpContentEncoding] = readField('s', in); - - if(flags_ & cpHeaders) - properties_[cpHeaders] = readField('F', in); - - if(flags_ & cpDeliveryMode) - properties_[cpDeliveryMode] = readField('b', in); - - if(flags_ & cpPriority) - properties_[cpPriority] = readField('b', in); - - if(flags_ & cpCorrelationId) - properties_[cpCorrelationId] = readField('s', in); - - if(flags_ & cpReplyTo) - properties_[cpReplyTo] = readField('s', in); - - if(flags_ & cpExpiration) - properties_[cpExpiration] = readField('s', in); - - if(flags_ & cpMessageId) - properties_[cpMessageId] = readField('s', in); - - if(flags_ & cpTimestamp) - properties_[cpTimestamp] = readField('T', in); - - if(flags_ & cpType) - properties_[cpType] = readField('s', in); - - if(flags_ & cpUserId) - properties_[cpUserId] = readField('s', in); - - if(flags_ & cpAppId) - properties_[cpAppId] = readField('s', in); - - if(flags_ & cpClusterID) - properties_[cpClusterID] = readField('s', in); -} - -qlonglong QAMQP::Frame::Content::bodySize() const -{ - return body_.isEmpty() ? bodySize_ : body_.size(); -} -////////////////////////////////////////////////////////////////////////// - -ContentBody::ContentBody() : Base(ftBody) -{} - -QAMQP::Frame::ContentBody::ContentBody( QDataStream& raw ): Base(raw) -{ - readPayload(raw); -} - -void QAMQP::Frame::ContentBody::setBody( const QByteArray & data ) -{ - body_ = data; -} - -QByteArray QAMQP::Frame::ContentBody::body() const -{ - return body_; -} - -void QAMQP::Frame::ContentBody::writePayload( QDataStream & out ) const -{ - out.writeRawData(body_.data(), body_.size()); -} - -void QAMQP::Frame::ContentBody::readPayload( QDataStream & in ) -{ - body_.resize(size_); - in.readRawData(body_.data(), body_.size()); -} - -qint32 QAMQP::Frame::ContentBody::size() const -{ - return body_.size(); -} - -////////////////////////////////////////////////////////////////////////// - -QAMQP::Frame::Heartbeat::Heartbeat() : Base(ftHeartbeat) {} - -void QAMQP::Frame::Heartbeat::readPayload(QDataStream & ) {} -void QAMQP::Frame::Heartbeat::writePayload(QDataStream & ) const {} - +#include "amqp_frame.h" + +#include + +#include +#include +#include + +using namespace QAMQP::Frame; +Base::Base(Type type) + : size_(0), + type_(type), + channel_(0) +{ +} + +Base::Base(QDataStream &raw) +{ + readHeader(raw); +} + +Type Base::type() const +{ + return Type(type_); +} + +Base::~Base() +{} + +void Base::setChannel(qint16 channel) +{ + channel_ = channel; +} + +qint16 Base::channel() const +{ + return channel_; +} + +qint32 Base::size() const +{ + return 0; +} + +void QAMQP::Frame::Base::writeHeader(QDataStream &stream) const +{ + stream << type_; + stream << channel_; + stream << qint32(size()); +} + +void QAMQP::Frame::Base::writeEnd(QDataStream &stream) const +{ + stream << qint8(FRAME_END); +} + +void QAMQP::Frame::Base::writePayload( QDataStream & ) const{} + +void QAMQP::Frame::Base::readHeader( QDataStream & stream ) +{ + stream >> type_; + stream >> channel_; + stream >> size_; +} + +void QAMQP::Frame::Base::readEnd(QDataStream &stream) +{ + unsigned char end_ = 0; + stream.readRawData(reinterpret_cast(&end_), sizeof(end_)); + if (end_ != FRAME_END) { + qWarning("Wrong end of frame"); + } +} + +void QAMQP::Frame::Base::readPayload(QDataStream &stream) +{ + stream.skipRawData(size_); +} + +void QAMQP::Frame::Base::toStream(QDataStream &stream) const +{ + writeHeader(stream); + writePayload(stream); + writeEnd(stream); +} + +////////////////////////////////////////////////////////////////////////// + +QAMQP::Frame::Method::Method(MethodClass methodClass, qint16 id) + : Base(ftMethod), methodClass_(methodClass), id_(id) +{ +} + +QAMQP::Frame::Method::Method(QDataStream &raw) + : Base(raw) +{ + readPayload(raw); +} + +QAMQP::Frame::Method::Method(): Base(ftMethod) +{ +} + +MethodClass QAMQP::Frame::Method::methodClass() const +{ + return MethodClass(methodClass_); +} + +qint16 QAMQP::Frame::Method::id() const +{ + return id_; +} + +qint32 QAMQP::Frame::Method::size() const +{ + return sizeof(id_) + sizeof(methodClass_) + arguments_.size(); +} + +void QAMQP::Frame::Method::setArguments(const QByteArray &data) +{ + arguments_ = data; +} + +QByteArray QAMQP::Frame::Method::arguments() const +{ + return arguments_; +} + +void QAMQP::Frame::Method::readPayload(QDataStream &stream) +{ + stream >> methodClass_; + stream >> id_; + + arguments_.resize(size_ - (sizeof(id_) + sizeof(methodClass_))); + stream.readRawData(arguments_.data(), arguments_.size()); +} + +void QAMQP::Frame::Method::writePayload(QDataStream &stream) const +{ + stream << quint16(methodClass_); + stream << quint16(id_); + stream.writeRawData(arguments_.data(), arguments_.size()); +} + +////////////////////////////////////////////////////////////////////////// + +QVariant QAMQP::Frame::readField(qint8 valueType, QDataStream &s) +{ + QVariant value; + QByteArray tmp; + qint8 nameSize_ = 0; + char octet = 0; + + switch(valueType) { + case 't': + s.readRawData(&octet, sizeof(octet)); + value = QVariant::fromValue(octet > 0); + break; + case 'b': + s.readRawData(&octet, sizeof(octet)); + value = QVariant::fromValue(octet); + break; + case 'B': + s.readRawData(&octet, sizeof(octet)); + value = QVariant::fromValue(octet); + break; + case 'U': + { + qint16 tmp_value_ = 0; + s >> tmp_value_; + value = QVariant::fromValue(tmp_value_); + break; + } + case 'u': + { + quint16 tmp_value_ = 0; + s >> tmp_value_; + value = QVariant::fromValue(tmp_value_); + break; + } + case 'I': + { + qint32 tmp_value_ = 0; + s >> tmp_value_; + value = QVariant::fromValue(tmp_value_); + break; + } + case 'i': + { + quint32 tmp_value_ = 0; + s >> tmp_value_; + value = QVariant::fromValue(tmp_value_); + break; + } + case 'L': + { + qlonglong v = 0 ; + s >> v; + value = v; + } + + break; + case 'l': + { + qulonglong v = 0 ; + s >> v; + value = v; + } + + break; + case 'f': + { + float tmp_value_; + s >> tmp_value_; + value = QVariant::fromValue(tmp_value_); + break; + } + case 'd': + { + double tmp_value_; + s >> tmp_value_; + value = QVariant::fromValue(tmp_value_); + break; + } + case 'D': + { + QAMQP::Frame::decimal v; + s >> v.scale; + s >> v.value; + value = QVariant::fromValue(v); + } + break; + case 's': + s >> nameSize_; + tmp.resize(nameSize_); + s.readRawData(tmp.data(), tmp.size()); + value = QString::fromLatin1(tmp.data(), nameSize_); + break; + case 'S': + { + quint32 length_ = 0; + s >> length_; + nameSize_ = length_; + tmp.resize(length_); + } + s.readRawData(tmp.data(), tmp.size()); + value = QString::fromLatin1(tmp.data(), tmp.size()); + break; + case 'A': + { + qint32 length_ = 0; + qint8 type = 0; + s >> length_; + QList array_; + for (int i =0; i < length_; ++i) { + s >> type; + array_ << readField(type, s); + } + value = array_; + } + break; + case 'T': + { + qulonglong tmp_value_; + s >> tmp_value_; + value = QDateTime::fromMSecsSinceEpoch(tmp_value_); + break; + } + case 'F': + { + TableField table_; + deserialize(s, table_); + value = table_; + } + break; + case 'V': + break; + default: + qWarning("Unknown field type"); + } + return value; +} + +QDataStream & QAMQP::Frame::deserialize(QDataStream &stream, QAMQP::Frame::TableField &f) +{ + QByteArray data; + stream >> data; + QDataStream s(&data, QIODevice::ReadOnly); + + while(!s.atEnd()) { + qint8 valueType = 0; + QString name = readField('s', s).toString(); + s >> valueType; + f[name] = readField(valueType, s); + } + + return stream; +} + +QDataStream & QAMQP::Frame::serialize(QDataStream &stream, const TableField &f) +{ + QByteArray data; + QDataStream s(&data, QIODevice::WriteOnly); + TableField::ConstIterator i; + for (i = f.begin(); i != f.end(); ++i) { + writeField('s', s, i.key()); + writeField(s, i.value()); + } + + if (data.isEmpty()) { + stream << qint32(0); + } else { + stream << data; + } + + return stream; +} + +void QAMQP::Frame::print(const TableField &f) +{ + TableField::ConstIterator i; + for (i = f.begin(); i != f.end(); ++i) { + switch(i.value().type()) { + case QVariant::Hash: + qDebug() << "\t" << qPrintable(i.key()) << ": FIELD_TABLE"; + break; + case QVariant::List: + qDebug() << "\t" << qPrintable(i.key()) << ": ARRAY"; + break; + default: + qDebug() << "\t" << qPrintable(i.key()) << ": " << i.value(); + } + } +} + +void QAMQP::Frame::writeField(qint8 valueType, QDataStream &s, const QVariant &value, bool withType) +{ + QByteArray tmp; + if (withType) + s << valueType; + + switch (valueType) { + case 't': + s << (value.toBool() ? qint8(1) : qint8(0)); + break; + case 'b': + s << qint8(value.toInt()); + break; + case 'B': + s << quint8(value.toUInt()); + break; + case 'U': + s << qint16(value.toInt()); + break; + case 'u': + s << quint16(value.toUInt()); + break; + case 'I': + s << qint32(value.toInt()); + break; + case 'i': + s << quint32(value.toUInt()); + break; + case 'L': + s << qlonglong(value.toLongLong()); + break; + case 'l': + s << qulonglong(value.toULongLong()); + break; + case 'f': + s << value.toFloat(); + break; + case 'd': + s << value.toDouble(); + break; + case 'D': + { + QAMQP::Frame::decimal v(value.value()); + s << v.scale; + s << v.value; + } + break; + case 's': + { + QString str = value.toString(); + s << quint8(str.length()); + s.writeRawData(str.toLatin1().data(), str.length()); + } + break; + case 'S': + { + QString str = value.toString(); + s << quint32(str.length()); + s.writeRawData(str.toLatin1().data(), str.length()); + } + break; + case 'A': + { + QList array_(value.toList()); + s << quint32(array_.count()); + for (int i =0; i < array_.count(); ++i) + writeField(s, array_.at(i)); + } + break; + case 'T': + s << qulonglong(value.toDateTime().toMSecsSinceEpoch()); + break; + case 'F': + { + TableField table_(value.toHash()); + serialize(s, table_); + } + break; + case 'V': + break; + default: + qWarning("Unknown field type"); + } +} + +void QAMQP::Frame::writeField(QDataStream &s, const QVariant &value) +{ + char type = 0; + switch (value.type()) { + case QVariant::Bool: + type = 't'; + break; + case QVariant::ByteArray: + type = 'S'; + break; + case QVariant::Int: + { + int i = qAbs(value.toInt()); + if (i <= qint8(0xFF)) { + type = 'b'; + } else if (i <= qint16(0xFFFF)) { + type = 'U'; + } else if (i <= qint16(0xFFFFFFFF)) { + type = 'I'; + } + } + break; + case QVariant::UInt: + { + int i = value.toInt(); + if (i <= qint8(0xFF)) { + type = 'B'; + } else if (i <= qint16(0xFFFF)) { + type = 'u'; + } else if (i <= qint16(0xFFFFFFFF)) { + type = 'i'; + } + } + break; + case QVariant::LongLong: + type = 'L'; + break; + case QVariant::ULongLong: + type = 'l'; + break; + case QVariant::String: + type = 'S'; + break; + case QVariant::DateTime: + type = 'T'; + break; + case QVariant::Double: + type = value.toDouble() > FLT_MAX ? 'd' : 'f'; + break; + case QVariant::Hash: + type = 'F'; + break; + case QVariant::List: + type = 'A'; + break; + + default: + qDebug() << Q_FUNC_INFO << "unhandled variant type: " << value.type(); + } + + if (type) + writeField(type, s, value, true); +} + +////////////////////////////////////////////////////////////////////////// + +QAMQP::Frame::Content::Content() + : Base(ftHeader) +{ +} + +QAMQP::Frame::Content::Content(MethodClass methodClass) + : Base(ftHeader) +{ + methodClass_ = methodClass; +} + +QAMQP::Frame::Content::Content(QDataStream &raw) + : Base(raw) +{ + readPayload(raw); +} + +QAMQP::Frame::MethodClass QAMQP::Frame::Content::methodClass() const +{ + return MethodClass(methodClass_); +} + +qint32 QAMQP::Frame::Content::size() const +{ + QDataStream out(&buffer_, QIODevice::WriteOnly); + buffer_.clear(); + out << qint16(methodClass_); + out << qint16(0); //weight + out << qlonglong(body_.size()); + + qint16 prop_ = 0; + foreach (int p, properties_.keys()) + prop_ |= p; + out << prop_; + + if (prop_ & cpContentType) + writeField('s', out, properties_[cpContentType]); + + if (prop_ & cpContentEncoding) + writeField('s', out, properties_[cpContentEncoding]); + + if (prop_ & cpHeaders) + writeField('F', out, properties_[cpHeaders]); + + if (prop_ & cpDeliveryMode) + writeField('b', out, properties_[cpDeliveryMode]); + + if (prop_ & cpPriority) + writeField('b', out, properties_[cpPriority]); + + if (prop_ & cpCorrelationId) + writeField('s', out, properties_[cpCorrelationId]); + + if (prop_ & cpReplyTo) + writeField('s', out, properties_[cpReplyTo]); + + if (prop_ & cpExpiration) + writeField('s', out, properties_[cpExpiration]); + + if (prop_ & cpMessageId) + writeField('s', out, properties_[cpMessageId]); + + if (prop_ & cpTimestamp) + writeField('T', out, properties_[cpTimestamp]); + + if (prop_ & cpType) + writeField('s', out, properties_[cpType]); + + if (prop_ & cpUserId) + writeField('s', out, properties_[cpUserId]); + + if (prop_ & cpAppId) + writeField('s', out, properties_[cpAppId]); + + if (prop_ & cpClusterID) + writeField('s', out, properties_[cpClusterID]); + + return buffer_.size(); +} + +void QAMQP::Frame::Content::setBody(const QByteArray &data) +{ + body_ = data; +} + +QByteArray QAMQP::Frame::Content::body() const +{ + return body_; +} + +void QAMQP::Frame::Content::setProperty(Property prop, const QVariant &value) +{ + properties_[prop] = value; +} + +QVariant QAMQP::Frame::Content::property(Property prop) const +{ + return properties_.value(prop); +} + +void QAMQP::Frame::Content::writePayload(QDataStream &out) const +{ + out.writeRawData(buffer_.data(), buffer_.size()); +} + +void QAMQP::Frame::Content::readPayload(QDataStream &in) +{ + in >> methodClass_; + in.skipRawData(2); //weight + in >> bodySize_; + qint16 flags_ = 0; + in >> flags_; + if (flags_ & cpContentType) + properties_[cpContentType] = readField('s', in); + + if (flags_ & cpContentEncoding) + properties_[cpContentEncoding] = readField('s', in); + + if (flags_ & cpHeaders) + properties_[cpHeaders] = readField('F', in); + + if (flags_ & cpDeliveryMode) + properties_[cpDeliveryMode] = readField('b', in); + + if (flags_ & cpPriority) + properties_[cpPriority] = readField('b', in); + + if (flags_ & cpCorrelationId) + properties_[cpCorrelationId] = readField('s', in); + + if (flags_ & cpReplyTo) + properties_[cpReplyTo] = readField('s', in); + + if (flags_ & cpExpiration) + properties_[cpExpiration] = readField('s', in); + + if (flags_ & cpMessageId) + properties_[cpMessageId] = readField('s', in); + + if (flags_ & cpTimestamp) + properties_[cpTimestamp] = readField('T', in); + + if (flags_ & cpType) + properties_[cpType] = readField('s', in); + + if (flags_ & cpUserId) + properties_[cpUserId] = readField('s', in); + + if (flags_ & cpAppId) + properties_[cpAppId] = readField('s', in); + + if (flags_ & cpClusterID) + properties_[cpClusterID] = readField('s', in); +} + +qlonglong QAMQP::Frame::Content::bodySize() const +{ + return body_.isEmpty() ? bodySize_ : body_.size(); +} +////////////////////////////////////////////////////////////////////////// + +ContentBody::ContentBody() + : Base(ftBody) +{ +} + +QAMQP::Frame::ContentBody::ContentBody(QDataStream &raw) + : Base(raw) +{ + readPayload(raw); +} + +void QAMQP::Frame::ContentBody::setBody(const QByteArray &data) +{ + body_ = data; +} + +QByteArray QAMQP::Frame::ContentBody::body() const +{ + return body_; +} + +void QAMQP::Frame::ContentBody::writePayload(QDataStream &out) const +{ + out.writeRawData(body_.data(), body_.size()); +} + +void QAMQP::Frame::ContentBody::readPayload(QDataStream &in) +{ + body_.resize(size_); + in.readRawData(body_.data(), body_.size()); +} + +qint32 QAMQP::Frame::ContentBody::size() const +{ + return body_.size(); +} + +////////////////////////////////////////////////////////////////////////// + +QAMQP::Frame::Heartbeat::Heartbeat() + : Base(ftHeartbeat) +{ +} + +void QAMQP::Frame::Heartbeat::readPayload(QDataStream &) {} +void QAMQP::Frame::Heartbeat::writePayload(QDataStream &) const {} diff --git a/src/qamqp/amqp_frame.h b/src/qamqp/amqp_frame.h index 8324d23..91dd85a 100644 --- a/src/qamqp/amqp_frame.h +++ b/src/qamqp/amqp_frame.h @@ -1,421 +1,421 @@ -#ifndef amqp_frame_h__ -#define amqp_frame_h__ - -#include -#include -#include - -#define AMQP_BASIC_CONTENT_TYPE_FLAG (1 << 15) -#define AMQP_BASIC_CONTENT_ENCODING_FLAG (1 << 7) -#define AMQP_BASIC_HEADERS_FLAG (1 << 13) -#define AMQP_BASIC_DELIVERY_MODE_FLAG (1 << 12) -#define AMQP_BASIC_PRIORITY_FLAG (1 << 11) -#define AMQP_BASIC_CORRELATION_ID_FLAG (1 << 10) -#define AMQP_BASIC_REPLY_TO_FLAG (1 << 9) -#define AMQP_BASIC_EXPIRATION_FLAG (1 << 8) -#define AMQP_BASIC_MESSAGE_ID_FLAG (1 << 14) -#define AMQP_BASIC_TIMESTAMP_FLAG (1 << 6) -#define AMQP_BASIC_TYPE_FLAG (1 << 5) -#define AMQP_BASIC_USER_ID_FLAG (1 << 4) -#define AMQP_BASIC_APP_ID_FLAG (1 << 3) -#define AMQP_BASIC_CLUSTER_ID_FLAG (1 << 2) - -/*! -Library namespace -@namespace QAMQP -*/ -namespace QAMQP -{ - class QueuePrivate; - /*! - Frame namespace - @namespace Frame - */ - namespace Frame - { - typedef quint16 channel_t; - /*! - @brief Header size in bytes - */ - static const qint64 HEADER_SIZE = 7; - /*! - @brief Frame end indicator size in bytes - */ - static const qint64 FRAME_END_SIZE = 1; - - /*! - @brief Frame end marker - */ - static const quint8 FRAME_END = 0xCE; - - /*! - @brief Frame type - */ - enum Type - { - ftMethod = 1, /*!< Used define method frame */ - ftHeader = 2, /*!< Used define content header frame */ - ftBody = 3, /*!< Used define content body frame */ - ftHeartbeat = 8 /*!< Used define heartbeat frame */ - }; - - /*! - @brief Frame method class - @enum MethodClass - */ - enum MethodClass - { - fcConnection = 10, /*!< Define class of methods related to connection */ - fcChannel = 20, /*!< Define class of methods related to channel */ - fcExchange = 40, /*!< Define class of methods related to exchange */ - fcQueue = 50, /*!< Define class of methods related to queue */ - fcBasic = 60, /*!< Define class of methods related to basic command */ - fcTx = 90, - }; - - struct decimal - { - qint8 scale; - quint32 value; - - }; - - /*! - @brief Definition implementation of TableField type - @detailed Define implementation TableField type in builtin Qt types. Key contains field name, value contains field data. - It can by any type witch support serialization in AMQP types. - */ - typedef QHash TableField; - - QDataStream & serialize( QDataStream & stream, const QAMQP::Frame::TableField & f ); - QDataStream & deserialize( QDataStream & stream, QAMQP::Frame::TableField & f ); - QVariant readField( qint8 valueType, QDataStream &s ); - void writeField( QDataStream &s, const QVariant & value ); - void writeField( qint8 valueType, QDataStream &s, const QVariant & value, bool withType = false ); - void print( const QAMQP::Frame::TableField & f ); - - /*! - @brief Base class for any frames. - @detailed Implement main methods for serialize and deserialize raw frame data. - All frames start with a 7-octet header composed of a type field (octet), a channel field (short integer) and a - size field (long integer): - @code Frame struct - 0 1 3 7 size+7 size+8 - +------+---------+---------+ +-------------+ +-----------+ - | type | channel | size | | payload | | frame-end | - +------+---------+---------+ +-------------+ +-----------+ - @endcode - octet short long 'size' octets octet - */ - class Base - { - public: - /*! - Base class constructor. - @detailed Construct frame class for sending. - @param type Define type of constructed frame. - */ - Base(Type type); - - /*! - Base class constructor. - @detailed Construct frame class from received raw data. - @param raw Data stream for reading source data. - */ - Base(QDataStream& raw); - - /*! - Base class virtual destructor - */ - virtual ~Base(); - - /*! - Frame type - @detailed Return type of current frame. - */ - Type type() const; - - /*! - Set number of associated channel. - @param channel Number of channel. - @sa channel() - */ - void setChannel(qint16 channel); - - /*! - Return number of associated channel. - @sa setChannel() - */ - qint16 channel() const; - - /*! - Return size of frame. - */ - virtual qint32 size() const; - - /*! - Output frame to stream. - @param stream Stream for serilize frame. - */ - void toStream(QDataStream & stream) const; - - protected: - void writeHeader(QDataStream & stream) const; - virtual void writePayload(QDataStream & stream) const; - void writeEnd(QDataStream & stream) const; - - void readHeader(QDataStream & stream); - virtual void readPayload(QDataStream & stream); - void readEnd(QDataStream & stream); - - qint32 size_; - private: - qint8 type_; - - qint16 channel_; - - }; - - /*! - @brief Class for working with method frames. - @detailed Implement main methods for serialize and deserialize raw method frame data. - Method frame bodies consist of an invariant list of data fields, called "arguments". All method bodies start - with identifier numbers for the class and method: - @code Frame struct - 0 2 4 - +----------+-----------+-------------- - - - | class-id | method-id | arguments... - +----------+-----------+-------------- - - - short short ... - @endcode - */ - class Method : public Base - { - public: - /*! - Method class constructor. - @detailed Construct frame class for sending. - */ - Method(); - - /*! - Method class constructor. - @detailed Construct frame class for sending. - @param methodClass Define method class id of constructed frame. - @param id Define method id of constructed frame. - */ - Method(MethodClass methodClass, qint16 id); - - /*! - Method class constructor. - @detailed Construct frame class from received raw data. - @param raw Data stream for reading source data. - */ - Method(QDataStream& raw); - - /*! - Method class type. - */ - MethodClass methodClass() const; - - /*! - Method id. - */ - qint16 id() const; - qint32 size() const; - - /*! - Set arguments for method. - @param data Serialized method arguments. - @sa arguments - */ - void setArguments(const QByteArray & data); - - /*! - Return arguments for method. - @sa setArguments - */ - QByteArray arguments() const; - - protected: - void writePayload(QDataStream & stream) const; - void readPayload(QDataStream & stream); - short methodClass_; - qint16 id_; - QByteArray arguments_; - }; - - - /*! - @brief Class for working with content frames. - @detailed Implement main methods for serialize and deserialize raw content frame data. - A content header payload has this format: - @code Frame struct - +----------+--------+-----------+----------------+------------- - - - | class-id | weight | body size | property flags | property list... - +----------+--------+-----------+----------------+------------- - - - short short long long short remainder... - @endcode - - | Property | Description | - | ---------- | ----------- | - |cpContentType | MIME content type | - | ocpContentEncoding | MIME content encoding | - | cpHeaders | message header field table | - | cpDeliveryMode| nonpersistent (1) or persistent (2) | - | cpPriority | message priority, 0 to 9 | - | cpCorrelationId | application correlation identifier | - | cpReplyTo | address to reply to | - | cpExpiration | message expiration specification | - | cpMessageId | application message identifier | - | cpTimestamp | message timestamp | - | cpType | message type name | - | cpUserId | creating user id | - | cpAppId | creating application id | - | cpClusterID| cluster ID | - - Default property: - @sa setProperty - @sa property - - */ - class Content : public Base - { - friend class QAMQP::QueuePrivate; - public: - - /*! Default content frame property - - */ - enum Property - { - cpContentType = AMQP_BASIC_CONTENT_TYPE_FLAG, - cpContentEncoding = AMQP_BASIC_CONTENT_ENCODING_FLAG, - cpHeaders = AMQP_BASIC_HEADERS_FLAG, - cpDeliveryMode = AMQP_BASIC_DELIVERY_MODE_FLAG, - cpPriority = AMQP_BASIC_PRIORITY_FLAG, - cpCorrelationId = AMQP_BASIC_CORRELATION_ID_FLAG, - cpReplyTo = AMQP_BASIC_REPLY_TO_FLAG, - cpExpiration = AMQP_BASIC_EXPIRATION_FLAG, - cpMessageId = AMQP_BASIC_MESSAGE_ID_FLAG, - cpTimestamp = AMQP_BASIC_TIMESTAMP_FLAG, - cpType = AMQP_BASIC_TYPE_FLAG, - cpUserId = AMQP_BASIC_USER_ID_FLAG, - cpAppId = AMQP_BASIC_APP_ID_FLAG, - cpClusterID = AMQP_BASIC_CLUSTER_ID_FLAG - }; - Q_DECLARE_FLAGS(Properties, Property); - - /*! - Content class constructor. - @detailed Construct frame content header class for sending. - */ - Content(); - - /*! - Content class constructor. - @detailed Construct frame content header class for sending. - @param methodClass Define method class id of constructed frame. - */ - Content(MethodClass methodClass); - - /*! - Content class constructor. - @detailed Construct frame content header class for sending. - @param raw Data stream for reading source data. - */ - Content(QDataStream& raw); - - /*! - Method class type. - */ - MethodClass methodClass() const; - qint32 size() const; - - /*! - Set default content header property - @param prop Any default content header property - @param value Associated data - */ - void setProperty(Property prop, const QVariant & value); - - /*! - Return associated with property value - @param prop Any default content header property - */ - QVariant property(Property prop) const; - - - void setBody(const QByteArray & data); - QByteArray body() const; - qlonglong bodySize() const; - - protected: - void writePayload(QDataStream & stream) const; - void readPayload(QDataStream & stream); - short methodClass_; - qint16 id_; - QByteArray body_; - mutable QByteArray buffer_; - QHash properties_; - qlonglong bodySize_; - }; - - class ContentBody : public Base - { - public: - ContentBody(); - ContentBody(QDataStream& raw); - void setBody(const QByteArray & data); - QByteArray body() const; - qint32 size() const; - protected: - void writePayload(QDataStream & stream) const; - void readPayload(QDataStream & stream); - - private: - QByteArray body_; - }; - - /*! - @brief Class for working with heartbeat frames. - @detailed Implement frame for heartbeat send. - */ - class Heartbeat : public Base - { - public: - /*! - Heartbeat class constructor. - @detailed Construct frame class for sending. - */ - Heartbeat(); - - protected: - void writePayload(QDataStream & stream) const; - void readPayload(QDataStream & stream); - }; - - class MethodHandler - { - public: - virtual void _q_method(const QAMQP::Frame::Method & frame) = 0; - }; - - class ContentHandler - { - public: - virtual void _q_content(const QAMQP::Frame::Content & frame) = 0; - }; - - class ContentBodyHandler - { - public: - virtual void _q_body(const QAMQP::Frame::ContentBody & frame) = 0; - }; - } -} - -Q_DECLARE_METATYPE(QAMQP::Frame::decimal); -Q_DECLARE_METATYPE(QAMQP::Frame::TableField); - -#endif // amqp_frame_h__ +#ifndef amqp_frame_h__ +#define amqp_frame_h__ + +#include +#include +#include + +#define AMQP_BASIC_CONTENT_TYPE_FLAG (1 << 15) +#define AMQP_BASIC_CONTENT_ENCODING_FLAG (1 << 7) +#define AMQP_BASIC_HEADERS_FLAG (1 << 13) +#define AMQP_BASIC_DELIVERY_MODE_FLAG (1 << 12) +#define AMQP_BASIC_PRIORITY_FLAG (1 << 11) +#define AMQP_BASIC_CORRELATION_ID_FLAG (1 << 10) +#define AMQP_BASIC_REPLY_TO_FLAG (1 << 9) +#define AMQP_BASIC_EXPIRATION_FLAG (1 << 8) +#define AMQP_BASIC_MESSAGE_ID_FLAG (1 << 14) +#define AMQP_BASIC_TIMESTAMP_FLAG (1 << 6) +#define AMQP_BASIC_TYPE_FLAG (1 << 5) +#define AMQP_BASIC_USER_ID_FLAG (1 << 4) +#define AMQP_BASIC_APP_ID_FLAG (1 << 3) +#define AMQP_BASIC_CLUSTER_ID_FLAG (1 << 2) + +/** + * Library namespace + * @namespace QAMQP + */ +namespace QAMQP +{ + +class QueuePrivate; + +namespace Frame +{ + typedef quint16 channel_t; + + /* + * @brief Header size in bytes + */ + static const qint64 HEADER_SIZE = 7; + + /* + * @brief Frame end indicator size in bytes + */ + static const qint64 FRAME_END_SIZE = 1; + + /* + * @brief Frame end marker + */ + static const quint8 FRAME_END = 0xCE; + + /* + * @brief Frame type + */ + enum Type + { + ftMethod = 1, /*!< Used define method frame */ + ftHeader = 2, /*!< Used define content header frame */ + ftBody = 3, /*!< Used define content body frame */ + ftHeartbeat = 8 /*!< Used define heartbeat frame */ + }; + + /* + * @brief Frame method class + * @enum MethodClass + */ + enum MethodClass + { + fcConnection = 10, // Define class of methods related to connection + fcChannel = 20, // Define class of methods related to channel + fcExchange = 40, // Define class of methods related to exchange + fcQueue = 50, // Define class of methods related to queue + fcBasic = 60, // Define class of methods related to basic command + fcTx = 90, + }; + + struct decimal + { + qint8 scale; + quint32 value; + }; + + /* + * @brief Definition implementation of TableField type + * @detailed Define implementation TableField type in builtin Qt types. Key contains field name, value contains field data. + * It can by any type witch support serialization in AMQP types. + */ + typedef QHash TableField; + + QDataStream & serialize( QDataStream & stream, const QAMQP::Frame::TableField & f ); + QDataStream & deserialize( QDataStream & stream, QAMQP::Frame::TableField & f ); + QVariant readField( qint8 valueType, QDataStream &s ); + void writeField( QDataStream &s, const QVariant & value ); + void writeField( qint8 valueType, QDataStream &s, const QVariant & value, bool withType = false ); + void print( const QAMQP::Frame::TableField & f ); + + /* + * @brief Base class for any frames. + * @detailed Implement main methods for serialize and deserialize raw frame data. + * All frames start with a 7-octet header composed of a type field (octet), a channel field (short integer) and a + * size field (long integer): + * @code Frame struct + * 0 1 3 7 size+7 size+8 + * +------+---------+---------+ +-------------+ +-----------+ + * | type | channel | size | | payload | | frame-end | + * +------+---------+---------+ +-------------+ +-----------+ + * @endcode + * octet short long 'size' octets octet + */ + class Base + { + public: + /* + * Base class constructor. + * @detailed Construct frame class for sending. + * @param type Define type of constructed frame. + */ + Base(Type type); + + /* + * Base class constructor. + * @detailed Construct frame class from received raw data. + * @param raw Data stream for reading source data. + */ + Base(QDataStream& raw); + + /* + * Base class virtual destructor + */ + virtual ~Base(); + + /* + * Frame type + * @detailed Return type of current frame. + */ + Type type() const; + + /* + * Set number of associated channel. + * @param channel Number of channel. + * @sa channel() + */ + void setChannel(qint16 channel); + + /* + * Return number of associated channel. + * @sa setChannel() + */ + qint16 channel() const; + + /* + * Return size of frame. + */ + virtual qint32 size() const; + + /* + * Output frame to stream. + * @param stream Stream for serilize frame. + */ + void toStream(QDataStream &stream) const; + + protected: + void writeHeader(QDataStream &stream) const; + virtual void writePayload(QDataStream &stream) const; + void writeEnd(QDataStream &stream) const; + + void readHeader(QDataStream &stream); + virtual void readPayload(QDataStream &stream); + void readEnd(QDataStream &stream); + + qint32 size_; + + private: + qint8 type_; + qint16 channel_; + + }; + + /* + * @brief Class for working with method frames. + * @detailed Implement main methods for serialize and deserialize raw method frame data. + * Method frame bodies consist of an invariant list of data fields, called "arguments". All method bodies start + * with identifier numbers for the class and method: + * @code Frame struct + * 0 2 4 + * +----------+-----------+-------------- - - + * | class-id | method-id | arguments... + * +----------+-----------+-------------- - - + * short short ... + * @endcode + */ + class Method : public Base + { + public: + /* + * Method class constructor. + * @detailed Construct frame class for sending. + */ + Method(); + + /* + * Method class constructor. + * @detailed Construct frame class for sending. + * @param methodClass Define method class id of constructed frame. + * @param id Define method id of constructed frame. + */ + Method(MethodClass methodClass, qint16 id); + + /* + * Method class constructor. + * @detailed Construct frame class from received raw data. + * @param raw Data stream for reading source data. + */ + Method(QDataStream &raw); + + /* + * Method class type. + */ + MethodClass methodClass() const; + + /* + * Method id. + */ + qint16 id() const; + qint32 size() const; + + /* + * Set arguments for method. + * @param data Serialized method arguments. + * @sa arguments + */ + void setArguments(const QByteArray &data); + + /* + * Return arguments for method. + * @sa setArguments + */ + QByteArray arguments() const; + + protected: + void writePayload(QDataStream & stream) const; + void readPayload(QDataStream & stream); + short methodClass_; + qint16 id_; + QByteArray arguments_; + + }; + + + /* + * @brief Class for working with content frames. + * @detailed Implement main methods for serialize and deserialize raw content frame data. + * A content header payload has this format: + * @code Frame struct + * +----------+--------+-----------+----------------+------------- - - + * | class-id | weight | body size | property flags | property list... + * +----------+--------+-----------+----------------+------------- - - + * short short long long short remainder... + * @endcode + * + * | Property | Description | + * | ---------- | ----------- | + * |cpContentType | MIME content type | + * | ocpContentEncoding | MIME content encoding | + * | cpHeaders | message header field table | + * | cpDeliveryMode| nonpersistent (1) or persistent (2) | + * | cpPriority | message priority, 0 to 9 | + * | cpCorrelationId | application correlation identifier | + * | cpReplyTo | address to reply to | + * | cpExpiration | message expiration specification | + * | cpMessageId | application message identifier | + * | cpTimestamp | message timestamp | + * | cpType | message type name | + * | cpUserId | creating user id | + * | cpAppId | creating application id | + * | cpClusterID| cluster ID | + * + * Default property: + * @sa setProperty + * @sa property + */ + class Content : public Base + { + friend class QAMQP::QueuePrivate; + + public: + /* + * Default content frame property + */ + enum Property + { + cpContentType = AMQP_BASIC_CONTENT_TYPE_FLAG, + cpContentEncoding = AMQP_BASIC_CONTENT_ENCODING_FLAG, + cpHeaders = AMQP_BASIC_HEADERS_FLAG, + cpDeliveryMode = AMQP_BASIC_DELIVERY_MODE_FLAG, + cpPriority = AMQP_BASIC_PRIORITY_FLAG, + cpCorrelationId = AMQP_BASIC_CORRELATION_ID_FLAG, + cpReplyTo = AMQP_BASIC_REPLY_TO_FLAG, + cpExpiration = AMQP_BASIC_EXPIRATION_FLAG, + cpMessageId = AMQP_BASIC_MESSAGE_ID_FLAG, + cpTimestamp = AMQP_BASIC_TIMESTAMP_FLAG, + cpType = AMQP_BASIC_TYPE_FLAG, + cpUserId = AMQP_BASIC_USER_ID_FLAG, + cpAppId = AMQP_BASIC_APP_ID_FLAG, + cpClusterID = AMQP_BASIC_CLUSTER_ID_FLAG + }; + Q_DECLARE_FLAGS(Properties, Property) + + /* + * Content class constructor. + * @detailed Construct frame content header class for sending. + */ + Content(); + + /* + * Content class constructor. + * @detailed Construct frame content header class for sending. + * @param methodClass Define method class id of constructed frame. + */ + Content(MethodClass methodClass); + + /* + * Content class constructor. + * @detailed Construct frame content header class for sending. + * @param raw Data stream for reading source data. + */ + Content(QDataStream &raw); + + /* + * Method class type. + */ + MethodClass methodClass() const; + qint32 size() const; + + /* + * Set default content header property + * @param prop Any default content header property + * @param value Associated data + */ + void setProperty(Property prop, const QVariant &value); + + /* + * Return associated with property value + * @param prop Any default content header property + */ + QVariant property(Property prop) const; + + void setBody(const QByteArray &data); + QByteArray body() const; + qlonglong bodySize() const; + + protected: + void writePayload(QDataStream &stream) const; + void readPayload(QDataStream &stream); + short methodClass_; + qint16 id_; + QByteArray body_; + mutable QByteArray buffer_; + QHash properties_; + qlonglong bodySize_; + }; + + class ContentBody : public Base + { + public: + ContentBody(); + ContentBody(QDataStream &raw); + + void setBody(const QByteArray &data); + QByteArray body() const; + + qint32 size() const; + protected: + void writePayload(QDataStream &stream) const; + void readPayload(QDataStream &stream); + + private: + QByteArray body_; + }; + + /* + * @brief Class for working with heartbeat frames. + * @detailed Implement frame for heartbeat send. + */ + class Heartbeat : public Base + { + public: + /* + * Heartbeat class constructor. + * @detailed Construct frame class for sending. + */ + Heartbeat(); + + protected: + void writePayload(QDataStream &stream) const; + void readPayload(QDataStream &stream); + }; + + class MethodHandler + { + public: + virtual void _q_method(const QAMQP::Frame::Method &frame) = 0; + }; + + class ContentHandler + { + public: + virtual void _q_content(const QAMQP::Frame::Content & frame) = 0; + }; + + class ContentBodyHandler + { + public: + virtual void _q_body(const QAMQP::Frame::ContentBody & frame) = 0; + }; +} +} + +Q_DECLARE_METATYPE(QAMQP::Frame::decimal) +Q_DECLARE_METATYPE(QAMQP::Frame::TableField) + +#endif // amqp_frame_h__ diff --git a/src/qamqp/amqp_global.h b/src/qamqp/amqp_global.h index 0bc9e3c..0684022 100644 --- a/src/qamqp/amqp_global.h +++ b/src/qamqp/amqp_global.h @@ -1,37 +1,18 @@ -#ifndef qamqp_global_h__ -#define qamqp_global_h__ - -#include - -#define QAMQP_P_INCLUDE -#define AMQPSCHEME "amqp" -#define AMQPSSCHEME "amqps" -#define AMQPPORT 5672 -#define AMQPHOST "localhost" -#define AMQPVHOST "/" -#define AMQPLOGIN "guest" -#define AMQPPSWD "guest" -#define FRAME_MAX 131072 - -#define QAMQP_VERSION "0.2.0" - - - -#define AMQP_CONNECTION_FORCED 320 - -#define P_DECLARE_PRIVATE(Class) \ - friend class Class##Private; \ - inline Class##Private* pd_func() { return reinterpret_cast(this->pd_ptr); } \ - inline const Class##Private* pd_func() const { return reinterpret_cast(this->pd_ptr); } - - -#define P_DECLARE_PUBLIC(Class) \ - inline Class* pq_func() { return static_cast(this->pq_ptr); } \ - inline const Class* pq_func() const { return static_cast(this->pq_ptr); } \ - friend class Class; - - -#define P_D(Class) Class##Private * const d = this->pd_func() -#define P_Q(Class) Class * const q = this->pq_func() - -#endif // qamqp_global_h__ +#ifndef qamqp_global_h__ +#define qamqp_global_h__ + +#define QAMQP_P_INCLUDE +#define AMQPSCHEME "amqp" +#define AMQPSSCHEME "amqps" +#define AMQPPORT 5672 +#define AMQPHOST "localhost" +#define AMQPVHOST "/" +#define AMQPLOGIN "guest" +#define AMQPPSWD "guest" +#define FRAME_MAX 131072 + +#define QAMQP_VERSION "0.2.0" + +#define AMQP_CONNECTION_FORCED 320 + +#endif // qamqp_global_h__ diff --git a/src/qamqp/amqp_message.cpp b/src/qamqp/amqp_message.cpp new file mode 100644 index 0000000..c9339a9 --- /dev/null +++ b/src/qamqp/amqp_message.cpp @@ -0,0 +1,15 @@ +#include "amqp_message.h" + +using namespace QAMQP; + +Message::Message() +{ + qDebug("Message create"); + leftSize = 0; + deliveryTag = 0; +} + +Message::~Message() +{ + qDebug("Message release"); +} diff --git a/src/qamqp/amqp_message.h b/src/qamqp/amqp_message.h index e71cb97..262c417 100644 --- a/src/qamqp/amqp_message.h +++ b/src/qamqp/amqp_message.h @@ -1,33 +1,28 @@ -#include "amqp_frame.h" -#include -#include -#include - -namespace QAMQP -{ - struct Message - { - Message() - { - qDebug("Message create"); - leftSize = 0; - deliveryTag = 0; - } - ~Message() - { - qDebug("Message release"); - } - typedef QAMQP::Frame::Content::Property MessageProperty; - Q_DECLARE_FLAGS(MessageProperties, MessageProperty); - - qlonglong deliveryTag; - QByteArray payload; - QHash property; - QAMQP::Frame::TableField headers; - QString routeKey; - QString exchangeName; - int leftSize; - }; - - typedef QSharedPointer MessagePtr; -} \ No newline at end of file +#include "amqp_frame.h" +#include +#include +#include + +namespace QAMQP +{ + +struct Message +{ + Message(); + virtual ~Message(); + + typedef QAMQP::Frame::Content::Property MessageProperty; + Q_DECLARE_FLAGS(MessageProperties, MessageProperty) + + qlonglong deliveryTag; + QByteArray payload; + QHash property; + QAMQP::Frame::TableField headers; + QString routeKey; + QString exchangeName; + int leftSize; +}; + +typedef QSharedPointer MessagePtr; + +} diff --git a/src/qamqp/amqp_network.cpp b/src/qamqp/amqp_network.cpp index cc3bea8..7d8ccf9 100644 --- a/src/qamqp/amqp_network.cpp +++ b/src/qamqp/amqp_network.cpp @@ -1,276 +1,243 @@ -#include "amqp_network.h" -#include -#include -#include - -QAMQP::Network::Network( QObject * parent /*= 0*/ ):QObject(parent) -{ - qRegisterMetaType("QAMQP::Frame::Method"); - - buffer_.reserve(Frame::HEADER_SIZE); - timeOut_ = 1000; - connect_ = false; - - initSocket(false); -} - -QAMQP::Network::~Network() -{ - disconnect(); -} - -void QAMQP::Network::connectTo( const QString & host, quint32 port ) -{ - if(!socket_) - { - qWarning("AMQP: Socket didn't create."); - return; - } - QString h(host); - int p(port); - connect_ = true; - if(host.isEmpty()) - h = lastHost_ ; - if(port == 0) - p = lastPort_; - - if (isSsl()) - { -#ifndef QT_NO_SSL - static_cast(socket_.data())->connectToHostEncrypted(h, p); -#else - qWarning("AMQP: You library has builded with QT_NO_SSL option."); -#endif - } else { - socket_->connectToHost(h, p); - } - - lastHost_ = h; - lastPort_ = p; -} - -void QAMQP::Network::disconnect() -{ - connect_ = false; - if(socket_) - socket_->close(); -} - -void QAMQP::Network::error( QAbstractSocket::SocketError socketError ) -{ - if(timeOut_ == 0) - { - timeOut_ = 1000; - } else { - if(timeOut_ < 120000) - { - timeOut_ *= 5; - } - } - - Q_UNUSED(socketError); - switch(socketError) - { - case QAbstractSocket::ConnectionRefusedError: - case QAbstractSocket::RemoteHostClosedError: - case QAbstractSocket::SocketTimeoutError: - case QAbstractSocket::NetworkError: - case QAbstractSocket::ProxyConnectionClosedError: - case QAbstractSocket::ProxyConnectionRefusedError: - case QAbstractSocket::ProxyConnectionTimeoutError: - - default: - qWarning() << "AMQP: Socket Error: " << socket_->errorString(); - break; - } - - if( autoReconnect_ && connect_ ) - { - QTimer::singleShot(timeOut_, this, SLOT(connectTo())); - } - -} - -void QAMQP::Network::readyRead() -{ - while(socket_->bytesAvailable() >= Frame::HEADER_SIZE) - { - char* headerData = buffer_.data(); - socket_->peek(headerData, Frame::HEADER_SIZE); - const quint32 payloadSize = qFromBigEndian(*(quint32*)&headerData[3]); - const qint64 readSize = Frame::HEADER_SIZE+payloadSize+Frame::FRAME_END_SIZE; - if(socket_->bytesAvailable() >= readSize) - { - buffer_.resize(readSize); - socket_->read(buffer_.data(), readSize); - const char* bufferData = buffer_.constData(); - const quint8 type = *(quint8*)&bufferData[0]; - const quint8 magic = *(quint8*)&bufferData[Frame::HEADER_SIZE+payloadSize]; - if(magic != QAMQP::Frame::FRAME_END) - { - qWarning() << "Wrong end frame"; - } - - QDataStream streamB(&buffer_, QIODevice::ReadOnly); - switch(QAMQP::Frame::Type(type)) - { - case QAMQP::Frame::ftMethod: - { - QAMQP::Frame::Method frame(streamB); - if(frame.methodClass() == QAMQP::Frame::fcConnection) - { - m_pMethodHandlerConnection->_q_method(frame); - } - else - { - foreach(Frame::MethodHandler* pMethodHandler, m_methodHandlersByChannel[frame.channel()]) - { - pMethodHandler->_q_method(frame); - } - } - } - break; - case QAMQP::Frame::ftHeader: - { - QAMQP::Frame::Content frame(streamB); - foreach(Frame::ContentHandler* pMethodHandler, m_contentHandlerByChannel[frame.channel()]) - { - pMethodHandler->_q_content(frame); - } - } - break; - case QAMQP::Frame::ftBody: - { - QAMQP::Frame::ContentBody frame(streamB); - foreach(Frame::ContentBodyHandler* pMethodHandler, m_bodyHandlersByChannel[frame.channel()]) - { - pMethodHandler->_q_body(frame); - } - } - break; - case QAMQP::Frame::ftHeartbeat: - { - qDebug("AMQP: Heartbeat"); - } - break; - default: - qWarning() << "AMQP: Unknown frame type: " << type; - } - } - else - { - break; - } - } -} - -void QAMQP::Network::sendFrame( const QAMQP::Frame::Base & frame ) -{ - if(socket_->state() == QAbstractSocket::ConnectedState) - { - QDataStream stream(socket_); - frame.toStream(stream); - } -} - -bool QAMQP::Network::isSsl() const -{ - if(socket_) - { - return QString(socket_->metaObject()->className()).compare( "QSslSocket", Qt::CaseInsensitive) == 0; - } - return false; -} - -void QAMQP::Network::setSsl( bool value ) -{ - initSocket(value); -} - -void QAMQP::Network::initSocket( bool ssl /*= false*/ ) -{ - if(socket_) - delete socket_; - - if(ssl) - { -#ifndef QT_NO_SSL - socket_ = new QSslSocket(this); - QSslSocket * ssl_= static_cast (socket_.data()); - ssl_->setProtocol(QSsl::AnyProtocol); - connect(socket_, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors())); - - connect(socket_, SIGNAL(connected()), this, SLOT(conectionReady())); -#else - qWarning("AMQP: You library has builded with QT_NO_SSL option."); -#endif - } else { - socket_ = new QTcpSocket(this); - connect(socket_, SIGNAL(connected()), this, SLOT(conectionReady())); - } - - if(socket_) - { - connect(socket_, SIGNAL(disconnected()), this, SIGNAL(disconnected())); - connect(socket_, SIGNAL(readyRead()), this, SLOT(readyRead())); - connect(socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError))); - } -} - - -void QAMQP::Network::sslErrors( ) -{ - #ifndef QT_NO_SSL - static_cast(socket_.data())->ignoreSslErrors(); - #endif -} - - -void QAMQP::Network::conectionReady() -{ - emit connected(); - timeOut_ = 0; - char header_[8] = {'A', 'M', 'Q', 'P', 0,0,9,1}; - socket_->write(header_, 8); -} - -bool QAMQP::Network::autoReconnect() const -{ - return autoReconnect_; -} - -void QAMQP::Network::setAutoReconnect( bool value ) -{ - autoReconnect_ = value; -} - -QAbstractSocket::SocketState QAMQP::Network::state() const -{ - if(socket_) - { - return socket_->state(); - } else { - return QAbstractSocket::UnconnectedState; - } - -} - -void QAMQP::Network::setMethodHandlerConnection(Frame::MethodHandler* pMethodHandlerConnection) -{ - m_pMethodHandlerConnection = pMethodHandlerConnection; -} - -void QAMQP::Network::addMethodHandlerForChannel(Channel channel, Frame::MethodHandler* pHandler) -{ - m_methodHandlersByChannel[channel].append(pHandler); -} - -void QAMQP::Network::addContentHandlerForChannel(Channel channel, Frame::ContentHandler* pHandler) -{ - m_contentHandlerByChannel[channel].append(pHandler); -} - -void QAMQP::Network::addContentBodyHandlerForChannel(Channel channel, Frame::ContentBodyHandler* pHandler) -{ - m_bodyHandlersByChannel[channel].append(pHandler); -} +#include "amqp_network.h" +#include +#include +#include + +QAMQP::Network::Network( QObject * parent) + : QObject(parent) +{ + qRegisterMetaType("QAMQP::Frame::Method"); + + buffer_.reserve(Frame::HEADER_SIZE); + timeOut_ = 1000; + connect_ = false; + + initSocket(false); +} + +QAMQP::Network::~Network() +{ + disconnect(); +} + +void QAMQP::Network::connectTo(const QString & host, quint16 port) +{ + if(!socket_) { + qWarning("AMQP: Socket didn't create."); + return; + } + + QString h(host); + int p(port); + connect_ = true; + if (host.isEmpty()) + h = lastHost_ ; + if (port == 0) + p = lastPort_; + + if (isSsl()) { +#ifndef QT_NO_SSL + static_cast(socket_.data())->connectToHostEncrypted(h, p); +#else + qWarning("AMQP: You library has builded with QT_NO_SSL option."); +#endif + } else { + socket_->connectToHost(h, p); + } + + lastHost_ = h; + lastPort_ = p; +} + +void QAMQP::Network::disconnect() +{ + connect_ = false; + if (socket_) + socket_->close(); +} + +void QAMQP::Network::error(QAbstractSocket::SocketError socketError) +{ + if (timeOut_ == 0) { + timeOut_ = 1000; + } else { + if (timeOut_ < 120000) + timeOut_ *= 5; + } + + switch(socketError) { + case QAbstractSocket::ConnectionRefusedError: + case QAbstractSocket::RemoteHostClosedError: + case QAbstractSocket::SocketTimeoutError: + case QAbstractSocket::NetworkError: + case QAbstractSocket::ProxyConnectionClosedError: + case QAbstractSocket::ProxyConnectionRefusedError: + case QAbstractSocket::ProxyConnectionTimeoutError: + + default: + qWarning() << "AMQP: Socket Error: " << socket_->errorString(); + break; + } + + if (autoReconnect_ && connect_) + QTimer::singleShot(timeOut_, this, SLOT(connectTo())); +} + +void QAMQP::Network::readyRead() +{ + while (socket_->bytesAvailable() >= Frame::HEADER_SIZE) { + char *headerData = buffer_.data(); + socket_->peek(headerData, Frame::HEADER_SIZE); + const quint32 payloadSize = qFromBigEndian(*(quint32*)&headerData[3]); + const qint64 readSize = Frame::HEADER_SIZE+payloadSize+Frame::FRAME_END_SIZE; + + if (socket_->bytesAvailable() >= readSize) { + buffer_.resize(readSize); + socket_->read(buffer_.data(), readSize); + const char* bufferData = buffer_.constData(); + const quint8 type = *(quint8*)&bufferData[0]; + const quint8 magic = *(quint8*)&bufferData[Frame::HEADER_SIZE+payloadSize]; + if (magic != QAMQP::Frame::FRAME_END) + qWarning() << "Wrong end frame"; + + QDataStream streamB(&buffer_, QIODevice::ReadOnly); + switch(QAMQP::Frame::Type(type)) { + case QAMQP::Frame::ftMethod: + { + QAMQP::Frame::Method frame(streamB); + if (frame.methodClass() == QAMQP::Frame::fcConnection) { + m_pMethodHandlerConnection->_q_method(frame); + } else { + foreach(Frame::MethodHandler* pMethodHandler, m_methodHandlersByChannel[frame.channel()]) + pMethodHandler->_q_method(frame); + } + } + break; + case QAMQP::Frame::ftHeader: + { + QAMQP::Frame::Content frame(streamB); + foreach(Frame::ContentHandler* pMethodHandler, m_contentHandlerByChannel[frame.channel()]) + pMethodHandler->_q_content(frame); + } + break; + case QAMQP::Frame::ftBody: + { + QAMQP::Frame::ContentBody frame(streamB); + foreach(Frame::ContentBodyHandler* pMethodHandler, m_bodyHandlersByChannel[frame.channel()]) + pMethodHandler->_q_body(frame); + } + break; + case QAMQP::Frame::ftHeartbeat: + qDebug("AMQP: Heartbeat"); + break; + default: + qWarning() << "AMQP: Unknown frame type: " << type; + } + } else { + break; + } + } +} + +void QAMQP::Network::sendFrame(const QAMQP::Frame::Base &frame) +{ + if (socket_->state() == QAbstractSocket::ConnectedState) { + QDataStream stream(socket_); + frame.toStream(stream); + } +} + +bool QAMQP::Network::isSsl() const +{ + if (socket_) + return QString(socket_->metaObject()->className()).compare("QSslSocket", Qt::CaseInsensitive) == 0; + return false; +} + +void QAMQP::Network::setSsl(bool value) +{ + initSocket(value); +} + +void QAMQP::Network::initSocket(bool ssl) +{ + if (socket_) { + socket_->deleteLater(); + socket_ = 0; + } + + if (ssl) { +#ifndef QT_NO_SSL + socket_ = new QSslSocket(this); + QSslSocket * ssl_= static_cast (socket_.data()); + ssl_->setProtocol(QSsl::AnyProtocol); + connect(socket_, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors())); + connect(socket_, SIGNAL(connected()), this, SLOT(conectionReady())); +#else + qWarning("AMQP: You library has builded with QT_NO_SSL option."); +#endif + } else { + socket_ = new QTcpSocket(this); + connect(socket_, SIGNAL(connected()), this, SLOT(conectionReady())); + } + + if (socket_) { + connect(socket_, SIGNAL(disconnected()), this, SIGNAL(disconnected())); + connect(socket_, SIGNAL(readyRead()), this, SLOT(readyRead())); + connect(socket_, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(error(QAbstractSocket::SocketError))); + } +} + +void QAMQP::Network::sslErrors() +{ +#ifndef QT_NO_SSL + static_cast(socket_.data())->ignoreSslErrors(); +#endif +} + +void QAMQP::Network::conectionReady() +{ + Q_EMIT connected(); + timeOut_ = 0; + + char header_[8] = {'A', 'M', 'Q', 'P', 0,0,9,1}; + socket_->write(header_, 8); +} + +bool QAMQP::Network::autoReconnect() const +{ + return autoReconnect_; +} + +void QAMQP::Network::setAutoReconnect(bool value) +{ + autoReconnect_ = value; +} + +QAbstractSocket::SocketState QAMQP::Network::state() const +{ + if (socket_) + return socket_->state(); + return QAbstractSocket::UnconnectedState; +} + +void QAMQP::Network::setMethodHandlerConnection(Frame::MethodHandler *pMethodHandlerConnection) +{ + m_pMethodHandlerConnection = pMethodHandlerConnection; +} + +void QAMQP::Network::addMethodHandlerForChannel(Channel channel, Frame::MethodHandler *pHandler) +{ + m_methodHandlersByChannel[channel].append(pHandler); +} + +void QAMQP::Network::addContentHandlerForChannel(Channel channel, Frame::ContentHandler *pHandler) +{ + m_contentHandlerByChannel[channel].append(pHandler); +} + +void QAMQP::Network::addContentBodyHandlerForChannel(Channel channel, Frame::ContentBodyHandler *pHandler) +{ + m_bodyHandlersByChannel[channel].append(pHandler); +} diff --git a/src/qamqp/amqp_network.h b/src/qamqp/amqp_network.h index 9dd6f41..089932c 100644 --- a/src/qamqp/amqp_network.h +++ b/src/qamqp/amqp_network.h @@ -1,77 +1,76 @@ -#ifndef amqp_network_h__ -#define amqp_network_h__ - -#include -#include -#ifndef QT_NO_SSL -#include -#endif -#include -#include - -#include "amqp_frame.h" - -namespace QAMQP -{ - class Network : public QObject - { - Q_OBJECT - Q_DISABLE_COPY(Network) - public: - typedef qint16 Channel; - - Network(QObject * parent = 0); - ~Network(); - - void disconnect(); - void sendFrame(); - - void sendFrame(const QAMQP::Frame::Base & frame); - - bool isSsl() const; - void setSsl(bool value); - - bool autoReconnect() const; - void setAutoReconnect(bool value); - - QAbstractSocket::SocketState state() const; - - void setMethodHandlerConnection(Frame::MethodHandler* pMethodHandlerConnection); - void addMethodHandlerForChannel(Channel channel, Frame::MethodHandler* pHandler); - void addContentHandlerForChannel(Channel channel, Frame::ContentHandler* pHandler); - void addContentBodyHandlerForChannel(Channel channel, Frame::ContentBodyHandler* pHandler); - - public slots: - void connectTo(const QString & host = QString(), quint32 port = 0); - void error( QAbstractSocket::SocketError socketError ); - - signals: - void connected(); - void disconnected(); - - private slots: - void readyRead(); - - void sslErrors ( ); - - - void conectionReady(); - - private: - void initSocket(bool ssl = false); - QPointer socket_; - QByteArray buffer_; - QString lastHost_; - int lastPort_; - bool autoReconnect_; - int timeOut_; - bool connect_; - - Frame::MethodHandler* m_pMethodHandlerConnection; - - QHash > m_methodHandlersByChannel; - QHash > m_contentHandlerByChannel; - QHash > m_bodyHandlersByChannel; - }; -} -#endif // amqp_network_h__ +#ifndef amqp_network_h__ +#define amqp_network_h__ + +#include +#include +#ifndef QT_NO_SSL +# include +#endif +#include +#include + +#include "amqp_frame.h" + +namespace QAMQP +{ + +class Network : public QObject +{ + Q_OBJECT +public: + Network(QObject *parent = 0); + ~Network(); + + void disconnect(); + void sendFrame(); + + void sendFrame(const QAMQP::Frame::Base &frame); + + bool isSsl() const; + void setSsl(bool value); + + bool autoReconnect() const; + void setAutoReconnect(bool value); + + QAbstractSocket::SocketState state() const; + + typedef qint16 Channel; + void setMethodHandlerConnection(Frame::MethodHandler *pMethodHandlerConnection); + void addMethodHandlerForChannel(Channel channel, Frame::MethodHandler *pHandler); + void addContentHandlerForChannel(Channel channel, Frame::ContentHandler *pHandler); + void addContentBodyHandlerForChannel(Channel channel, Frame::ContentBodyHandler *pHandler); + +public slots: + void connectTo(const QString &host = QString(), quint16 port = 0); + void error(QAbstractSocket::SocketError socketError); + +Q_SIGNALS: + void connected(); + void disconnected(); + +private Q_SLOTS: + void readyRead(); + void sslErrors(); + void conectionReady(); + +private: + Q_DISABLE_COPY(Network) + + void initSocket(bool ssl = false); + QPointer socket_; + QByteArray buffer_; + QString lastHost_; + int lastPort_; + bool autoReconnect_; + int timeOut_; + bool connect_; + + Frame::MethodHandler *m_pMethodHandlerConnection; + + QHash > m_methodHandlersByChannel; + QHash > m_contentHandlerByChannel; + QHash > m_bodyHandlersByChannel; +}; + +} +#endif // amqp_network_h__ diff --git a/src/qamqp/amqp_p.h b/src/qamqp/amqp_p.h index b68dc15..362e16c 100644 --- a/src/qamqp/amqp_p.h +++ b/src/qamqp/amqp_p.h @@ -1,51 +1,51 @@ -#ifndef qamqp_amqp_p_h__ -#define qamqp_amqp_p_h__ - -#include - -#include "amqp_global.h" -#include "amqp_network.h" -#include "amqp_connection.h" -#include "amqp_authenticator.h" - -namespace QAMQP -{ - class ClientPrivate - { - P_DECLARE_PUBLIC(QAMQP::Client) - - public: - ClientPrivate(Client * q ) ; - ~ClientPrivate(); - - - void init(QObject * parent); - void init(QObject * parent, const QUrl & connectionString); - void printConnect() const; - void connect(); - void disconnect(); - void parseCnnString( const QUrl & connectionString); - void sockConnect(); - void login(); - void setAuth(Authenticator* auth); - Exchange * createExchange(int channelNumber, const QString &name); - Queue * createQueue(int channelNumber, const QString &name); - - quint32 port; - QString host; - QString virtualHost; - - QPointer network_; - QPointer connection_; - QSharedPointer auth_; - - bool isSSl() const; - - - - Client * const pq_ptr; - - }; - -} -#endif // amqp_p_h__ +#ifndef QAMQP_P_H +#define QAMQP_P_H + +#include + +#include "amqp_global.h" +#include "amqp_network.h" +#include "amqp_connection.h" +#include "amqp_authenticator.h" + +namespace QAMQP +{ + +class Queue; +class Exchange; +class ClientPrivate +{ +public: + ClientPrivate(Client *q); + ~ClientPrivate(); + + void init(QObject *parent); + void init(QObject *parent, const QUrl &connectionString); + + void printConnect() const; + void connect(); + void disconnect(); + void parseConnectionString( const QUrl &connectionString); + void sockConnect(); + void login(); + void setAuth(Authenticator* auth); + Exchange *createExchange(int channelNumber, const QString &name); + Queue *createQueue(int channelNumber, const QString &name); + + quint32 port; + QString host; + QString virtualHost; + + QPointer network_; + QPointer connection_; + QSharedPointer auth_; + + bool isSSl() const; + + Client * const q_ptr; + Q_DECLARE_PUBLIC(QAMQP::Client) + +}; + +} +#endif // amqp_p_h__ diff --git a/src/qamqp/amqp_queue.cpp b/src/qamqp/amqp_queue.cpp index 7d39e31..aab0786 100644 --- a/src/qamqp/amqp_queue.cpp +++ b/src/qamqp/amqp_queue.cpp @@ -1,578 +1,534 @@ -#include "amqp_queue.h" -#include "amqp_queue_p.h" -#include "amqp_exchange.h" - -using namespace QAMQP; -using namespace QAMQP::Frame; - -#include -#include -#include -#include - -namespace QAMQP -{ - struct QueueExceptionCleaner - { - /* this cleans up when the constructor throws an exception */ - static inline void cleanup(Queue *that, QueuePrivate *d) - { -#ifdef QT_NO_EXCEPTIONS - Q_UNUSED(that); - Q_UNUSED(d); -#else - Q_UNUSED(that); - Q_UNUSED(d); -#endif - } - }; - -} - -Queue::Queue( int channelNumber, Client * parent /*= 0*/ ) -: Channel(new QueuePrivate(this)) -{ - QT_TRY { - pd_func()->init(channelNumber, parent); - } QT_CATCH(...) { - QueueExceptionCleaner::cleanup(this, pd_func()); - QT_RETHROW; - } -} - -Queue::~Queue() -{ - remove(); -} - -void Queue::onOpen() -{ - P_D(Queue); - if(d->delayedDeclare) - { - d->declare(); - } - if(!d->delayedBindings.isEmpty()) - { - typedef QPair BindingPair; - foreach(BindingPair binding, d->delayedBindings) - { - d->bind(binding.first, binding.second); - } - d->delayedBindings.clear(); - } -} - -void Queue::onClose() -{ - pd_func()->remove(true, true); -} - -Queue::QueueOptions Queue::option() const -{ - return pd_func()->options; -} - -void Queue::setNoAck( bool noAck ) -{ - pd_func()->noAck = noAck; -} - -bool Queue::noAck() const -{ - return pd_func()->noAck; -} - -void Queue::declare() -{ - P_D(Queue); - declare(d->name, QueueOptions(Durable | AutoDelete)); -} - -void Queue::declare( const QString &name, QueueOptions options ) -{ - P_D(Queue); - setName(name); - d->options = options; - d->declare(); -} - -void Queue::remove( bool ifUnused /*= true*/, bool ifEmpty /*= true*/, bool noWait /*= true*/ ) -{ - pd_func()->remove(ifUnused, ifEmpty, noWait); -} - -void Queue::purge() -{ - pd_func()->purge(); -} - -void Queue::bind( const QString & exchangeName, const QString & key ) -{ - pd_func()->bind(exchangeName, key); -} - -void Queue::bind( Exchange * exchange, const QString & key ) -{ - if(exchange) - pd_func()->bind(exchange->name(), key); -} - -void Queue::unbind( const QString & exchangeName, const QString & key ) -{ - pd_func()->unbind(exchangeName, key); -} - -void Queue::unbind( Exchange * exchange, const QString & key ) -{ - if(exchange) - pd_func()->unbind(exchange->name(), key); -} - -void Queue::_q_content(const Content &frame) -{ - pd_func()->_q_content(frame); -} - -void Queue::_q_body(const ContentBody &frame) -{ - pd_func()->_q_body(frame); -} - -QAMQP::MessagePtr Queue::getMessage() -{ - return pd_func()->messages_.dequeue(); -} - -bool Queue::hasMessage() const -{ - - if(pd_func()->messages_.isEmpty()) - { - return false; - } - const MessagePtr &q = pd_func()->messages_.head(); - return q->leftSize == 0; -} - -void Queue::consume(ConsumeOptions options) -{ - pd_func()->consume(options); -} - -void Queue::setConsumerTag( const QString &consumerTag ) -{ - pd_func()->consumerTag = consumerTag; -} - -QString Queue::consumerTag() const -{ - return pd_func()->consumerTag; -} - - -void Queue::get() -{ - pd_func()->get(); -} - - -void Queue::ack( const MessagePtr & message ) -{ - pd_func()->ack(message); -} - -////////////////////////////////////////////////////////////////////////// - - -QueuePrivate::QueuePrivate(Queue * q) - :ChannelPrivate(q) - , delayedDeclare(false) - , declared(false) - , noAck(true) - , recievingMessage(false) -{ - -} - -QueuePrivate::~QueuePrivate() -{ - -} - - -bool QueuePrivate::_q_method( const QAMQP::Frame::Method & frame ) -{ - if(ChannelPrivate::_q_method(frame)) - return true; - - if(frame.methodClass() == QAMQP::Frame::fcQueue) - { - switch(frame.id()) - { - case miDeclareOk: - declareOk(frame); - break; - case miDelete: - deleteOk(frame); - break; - case miBindOk: - bindOk(frame); - break; - case miUnbindOk: - unbindOk(frame); - break; - case miPurgeOk: - deleteOk(frame); - break; - default: - break; - } - return true; - } - - if(frame.methodClass() == QAMQP::Frame::fcBasic) - { - switch(frame.id()) - { - case bmConsumeOk: - consumeOk(frame); - break; - case bmDeliver: - deliver(frame); - break; - case bmGetOk: - getOk(frame); - break; - case bmGetEmpty: - QMetaObject::invokeMethod(pq_func(), "empty"); - break; - default: - break; - } - return true; - } - - - - return false; -} - -void QueuePrivate::declareOk( const QAMQP::Frame::Method & frame ) -{ - - qDebug() << "Declared queue: " << name; - declared = true; - - QByteArray data = frame.arguments(); - QDataStream stream(&data, QIODevice::ReadOnly); - - name = readField('s', stream).toString(); - qint32 messageCount = 0, consumerCount = 0; - stream >> messageCount >> consumerCount; - qDebug("Message count %d\nConsumer count: %d", messageCount, consumerCount); - - QMetaObject::invokeMethod(pq_func(), "declared"); -} - -void QueuePrivate::deleteOk( const QAMQP::Frame::Method & frame ) -{ - qDebug() << "Deleted or purged queue: " << name; - declared = false; - - QByteArray data = frame.arguments(); - QDataStream stream(&data, QIODevice::ReadOnly); - qint32 messageCount = 0; - stream >> messageCount; - qDebug("Message count %d", messageCount); - QMetaObject::invokeMethod(pq_func(), "removed"); -} - - -void QueuePrivate::bindOk( const QAMQP::Frame::Method & ) -{ - qDebug() << "Binded to queue: " << name; - QMetaObject::invokeMethod(pq_func(), "binded", Q_ARG(bool, true)); -} - -void QueuePrivate::unbindOk( const QAMQP::Frame::Method & ) -{ - qDebug() << "Unbinded queue: " << name; - QMetaObject::invokeMethod(pq_func(), "binded", Q_ARG(bool, false)); -} - -void QueuePrivate::declare() -{ - if(!opened) - { - delayedDeclare = true; - return; - } - - QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miDeclare); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - out << qint16(0); //reserver 1 - writeField('s', out, name); - out << qint8(options); - writeField('F', out, TableField()); - - frame.setArguments(arguments_); - sendFrame(frame); - delayedDeclare = false; - - -} - -void QueuePrivate::remove( bool ifUnused /*= true*/, bool ifEmpty /*= true*/, bool noWait /*= true*/ ) -{ - if(!declared) - return; - - QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miDelete); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - - out << qint16(0); //reserver 1 - writeField('s', out, name); - - qint8 flag = 0; - - flag |= (ifUnused ? 0x1 : 0); - flag |= (ifEmpty ? 0x2 : 0); - flag |= (noWait ? 0x4 : 0); - - out << flag; - - frame.setArguments(arguments_); - sendFrame(frame); - -} - -void QueuePrivate::purge() -{ - if(!opened) - { - return; - } - - QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miPurge); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - out << qint16(0); //reserver 1 - writeField('s', out, name); - out << qint8(0); // no-wait - frame.setArguments(arguments_); - sendFrame(frame); - -} - -void QueuePrivate::bind( const QString & exchangeName, const QString & key ) -{ - if(!opened) - { - delayedBindings.append(QPair(exchangeName, key)); - return; - } - - QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miBind); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - out << qint16(0); //reserver 1 - writeField('s', out, name); - writeField('s', out, exchangeName); - writeField('s', out, key); - out << qint8(0); // no-wait - writeField('F', out, TableField()); - - frame.setArguments(arguments_); - sendFrame(frame); - -} - -void QueuePrivate::unbind( const QString & exchangeName, const QString & key ) -{ - if(!opened) - { - return; - } - - QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miUnbind); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - out << qint16(0); //reserver 1 - writeField('s', out, name); - writeField('s', out, exchangeName); - writeField('s', out, key); - writeField('F', out, TableField()); - - frame.setArguments(arguments_); - sendFrame(frame); - -} - - -void QueuePrivate::get() -{ - if(!opened) - { - return; - } - - QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmGet); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - out << qint16(0); //reserver 1 - writeField('s', out, name); - out << qint8(noAck ? 1 : 0); // noAck - - frame.setArguments(arguments_); - sendFrame(frame); -} - - -void QueuePrivate::getOk( const QAMQP::Frame::Method & frame ) -{ - QByteArray data = frame.arguments(); - QDataStream in(&data, QIODevice::ReadOnly); - - qlonglong deliveryTag = readField('L',in).toLongLong(); - bool redelivered = readField('t',in).toBool(); - QString exchangeName = readField('s',in).toString(); - QString routingKey = readField('s',in).toString(); - - Q_UNUSED(redelivered) - - MessagePtr newMessage = MessagePtr(new Message); - newMessage->routeKey = routingKey; - newMessage->exchangeName = exchangeName; - newMessage->deliveryTag = deliveryTag; - messages_.enqueue(newMessage); -} - - -void QueuePrivate::ack( const MessagePtr & Message ) -{ - if(!opened) - { - return; - } - - QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmAck); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - out << Message->deliveryTag; //reserver 1 - out << qint8(0); // noAck - - frame.setArguments(arguments_); - sendFrame(frame); -} - -void QueuePrivate::consume( Queue::ConsumeOptions options ) -{ - if(!opened) - { - return; - } - - QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmConsume); - frame.setChannel(number); - QByteArray arguments_; - QDataStream out(&arguments_, QIODevice::WriteOnly); - out << qint16(0); //reserver 1 - writeField('s', out, name); - writeField('s', out, consumerTag); - out << qint8(options); // no-wait - writeField('F', out, TableField()); - - frame.setArguments(arguments_); - sendFrame(frame); - -} - - -void QueuePrivate::consumeOk( const QAMQP::Frame::Method & frame ) -{ - - qDebug() << "Consume ok: " << name; - declared = false; - - QByteArray data = frame.arguments(); - QDataStream stream(&data, QIODevice::ReadOnly); - consumerTag = readField('s',stream).toString(); - qDebug("Consumer tag = %s", qPrintable(consumerTag)); -} - - -void QueuePrivate::deliver( const QAMQP::Frame::Method & frame ) -{ - - QByteArray data = frame.arguments(); - QDataStream in(&data, QIODevice::ReadOnly); - QString consumer_ = readField('s',in).toString(); - if(consumer_ != consumerTag) - { - return; - } - - qlonglong deliveryTag = readField('L',in).toLongLong(); - bool redelivered = readField('t',in).toBool(); - QString exchangeName = readField('s',in).toString(); - QString routingKey = readField('s',in).toString(); - - Q_UNUSED(redelivered) - - MessagePtr newMessage = MessagePtr(new Message); - newMessage->routeKey = routingKey; - newMessage->exchangeName = exchangeName; - newMessage->deliveryTag = deliveryTag; - messages_.enqueue(newMessage); - -} - -void QueuePrivate::_q_content( const QAMQP::Frame::Content & frame ) -{ - Q_ASSERT(frame.channel() == number); - if(frame.channel() != number) - return; - if(messages_.isEmpty()) - { - qErrnoWarning("Received content-header without method frame before"); - return; - } - MessagePtr &message = messages_.last(); - message->leftSize = frame.bodySize(); - QHash::ConstIterator i; - for (i = frame.properties_.begin(); i != frame.properties_.end(); ++i) - { - message->property[Message::MessageProperty(i.key())]= i.value(); - } -} - -void QueuePrivate::_q_body(const QAMQP::Frame::ContentBody & frame) -{ - Q_ASSERT(frame.channel() == number); - if(frame.channel() != number) - return; - - if(messages_.isEmpty()) - { - qErrnoWarning("Received content-body without method frame before"); - return; - } - MessagePtr &message = messages_.last(); - message->payload.append(frame.body()); - message->leftSize -= frame.body().size(); - - if(message->leftSize == 0 && messages_.size() == 1) - { - emit pq_func()->messageReceived(pq_func()); - } -} +#include "amqp_queue.h" +#include "amqp_queue_p.h" +#include "amqp_exchange.h" + +using namespace QAMQP; +using namespace QAMQP::Frame; + +#include +#include +#include +#include + +Queue::Queue(int channelNumber, Client *parent) + : Channel(new QueuePrivate(this), parent) +{ + Q_D(QAMQP::Queue); + d->init(channelNumber, parent); +} + +Queue::~Queue() +{ + remove(); +} + +void Queue::onOpen() +{ + Q_D(QAMQP::Queue); + if (d->delayedDeclare) + d->declare(); + + if (!d->delayedBindings.isEmpty()) { + typedef QPair BindingPair; + foreach(BindingPair binding, d->delayedBindings) + d->bind(binding.first, binding.second); + d->delayedBindings.clear(); + } +} + +void Queue::onClose() +{ + Q_D(QAMQP::Queue); + d->remove(true, true); +} + +Queue::QueueOptions Queue::option() const +{ + Q_D(const QAMQP::Queue); + return d->options; +} + +void Queue::setNoAck(bool noAck) +{ + Q_D(QAMQP::Queue); + d->noAck = noAck; +} + +bool Queue::noAck() const +{ + Q_D(const QAMQP::Queue); + return d->noAck; +} + +void Queue::declare() +{ + Q_D(QAMQP::Queue); + declare(d->name, QueueOptions(Durable | AutoDelete)); +} + +void Queue::declare(const QString &name, QueueOptions options) +{ + Q_D(QAMQP::Queue); + setName(name); + d->options = options; + d->declare(); +} + +void Queue::remove(bool ifUnused, bool ifEmpty, bool noWait) +{ + Q_D(QAMQP::Queue); + d->remove(ifUnused, ifEmpty, noWait); +} + +void Queue::purge() +{ + Q_D(QAMQP::Queue); + d->purge(); +} + +void Queue::bind(const QString &exchangeName, const QString &key) +{ + Q_D(QAMQP::Queue); + d->bind(exchangeName, key); +} + +void Queue::bind(Exchange *exchange, const QString &key) +{ + Q_D(QAMQP::Queue); + if (exchange) + d->bind(exchange->name(), key); +} + +void Queue::unbind(const QString &exchangeName, const QString &key) +{ + Q_D(QAMQP::Queue); + d->unbind(exchangeName, key); +} + +void Queue::unbind(Exchange *exchange, const QString &key) +{ + Q_D(QAMQP::Queue); + if (exchange) + d->unbind(exchange->name(), key); +} + +void Queue::_q_content(const Content &frame) +{ + Q_D(QAMQP::Queue); + d->_q_content(frame); +} + +void Queue::_q_body(const ContentBody &frame) +{ + Q_D(QAMQP::Queue); + d->_q_body(frame); +} + +QAMQP::MessagePtr Queue::getMessage() +{ + Q_D(QAMQP::Queue); + return d->messages_.dequeue(); +} + +bool Queue::hasMessage() const +{ + Q_D(const QAMQP::Queue); + if (d->messages_.isEmpty()) + return false; + + const MessagePtr &q = d->messages_.head(); + return q->leftSize == 0; +} + +void Queue::consume(ConsumeOptions options) +{ + Q_D(QAMQP::Queue); + d->consume(options); +} + +void Queue::setConsumerTag(const QString &consumerTag) +{ + Q_D(QAMQP::Queue); + d->consumerTag = consumerTag; +} + +QString Queue::consumerTag() const +{ + Q_D(const QAMQP::Queue); + return d->consumerTag; +} + +void Queue::get() +{ + Q_D(QAMQP::Queue); + d->get(); +} + +void Queue::ack(const MessagePtr &message) +{ + Q_D(QAMQP::Queue); + d->ack(message); +} + +////////////////////////////////////////////////////////////////////////// + + +QueuePrivate::QueuePrivate(Queue * q) + : ChannelPrivate(q), + delayedDeclare(false), + declared(false), + noAck(true), + recievingMessage(false) +{ +} + +QueuePrivate::~QueuePrivate() +{ +} + +bool QueuePrivate::_q_method(const QAMQP::Frame::Method &frame) +{ + Q_Q(QAMQP::Queue); + if (ChannelPrivate::_q_method(frame)) + return true; + + if (frame.methodClass() == QAMQP::Frame::fcQueue) { + switch (frame.id()) { + case miDeclareOk: + declareOk(frame); + break; + case miDelete: + deleteOk(frame); + break; + case miBindOk: + bindOk(frame); + break; + case miUnbindOk: + unbindOk(frame); + break; + case miPurgeOk: + deleteOk(frame); + break; + default: + break; + } + + return true; + } + + if (frame.methodClass() == QAMQP::Frame::fcBasic) { + switch(frame.id()) { + case bmConsumeOk: + consumeOk(frame); + break; + case bmDeliver: + deliver(frame); + break; + case bmGetOk: + getOk(frame); + break; + case bmGetEmpty: + QMetaObject::invokeMethod(q, "empty"); + break; + default: + break; + } + return true; + } + + return false; +} + +void QueuePrivate::declareOk(const QAMQP::Frame::Method &frame) +{ + Q_Q(QAMQP::Queue); + qDebug() << "Declared queue: " << name; + declared = true; + + QByteArray data = frame.arguments(); + QDataStream stream(&data, QIODevice::ReadOnly); + + name = readField('s', stream).toString(); + qint32 messageCount = 0, consumerCount = 0; + stream >> messageCount >> consumerCount; + qDebug("Message count %d\nConsumer count: %d", messageCount, consumerCount); + + QMetaObject::invokeMethod(q, "declared"); +} + +void QueuePrivate::deleteOk(const QAMQP::Frame::Method &frame) +{ + Q_Q(QAMQP::Queue); + qDebug() << "Deleted or purged queue: " << name; + declared = false; + + QByteArray data = frame.arguments(); + QDataStream stream(&data, QIODevice::ReadOnly); + qint32 messageCount = 0; + stream >> messageCount; + qDebug("Message count %d", messageCount); + QMetaObject::invokeMethod(q, "removed"); +} + +void QueuePrivate::bindOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Queue); + + qDebug() << "Binded to queue: " << name; + QMetaObject::invokeMethod(q, "binded", Q_ARG(bool, true)); +} + +void QueuePrivate::unbindOk(const QAMQP::Frame::Method &frame) +{ + Q_UNUSED(frame) + Q_Q(QAMQP::Queue); + + qDebug() << "Unbinded queue: " << name; + QMetaObject::invokeMethod(q, "binded", Q_ARG(bool, false)); +} + +void QueuePrivate::declare() +{ + if (!opened) { + delayedDeclare = true; + return; + } + + QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miDeclare); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + out << qint16(0); //reserver 1 + writeField('s', out, name); + out << qint8(options); + writeField('F', out, TableField()); + + frame.setArguments(arguments_); + sendFrame(frame); + delayedDeclare = false; +} + +void QueuePrivate::remove(bool ifUnused, bool ifEmpty, bool noWait) +{ + if (!declared) + return; + + QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miDelete); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + + out << qint16(0); //reserver 1 + writeField('s', out, name); + + qint8 flag = 0; + + flag |= (ifUnused ? 0x1 : 0); + flag |= (ifEmpty ? 0x2 : 0); + flag |= (noWait ? 0x4 : 0); + + out << flag; + + frame.setArguments(arguments_); + sendFrame(frame); +} + +void QueuePrivate::purge() +{ + if (!opened) + return; + + QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miPurge); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + out << qint16(0); //reserver 1 + writeField('s', out, name); + out << qint8(0); // no-wait + frame.setArguments(arguments_); + sendFrame(frame); +} + +void QueuePrivate::bind(const QString & exchangeName, const QString &key) +{ + if (!opened) { + delayedBindings.append(QPair(exchangeName, key)); + return; + } + + QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miBind); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + out << qint16(0); //reserver 1 + writeField('s', out, name); + writeField('s', out, exchangeName); + writeField('s', out, key); + out << qint8(0); // no-wait + writeField('F', out, TableField()); + + frame.setArguments(arguments_); + sendFrame(frame); +} + +void QueuePrivate::unbind(const QString &exchangeName, const QString &key) +{ + if (!opened) + return; + + QAMQP::Frame::Method frame(QAMQP::Frame::fcQueue, miUnbind); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + out << qint16(0); //reserver 1 + writeField('s', out, name); + writeField('s', out, exchangeName); + writeField('s', out, key); + writeField('F', out, TableField()); + + frame.setArguments(arguments_); + sendFrame(frame); +} + +void QueuePrivate::get() +{ + if (!opened) + return; + + QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmGet); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + out << qint16(0); //reserver 1 + writeField('s', out, name); + out << qint8(noAck ? 1 : 0); // noAck + + frame.setArguments(arguments_); + sendFrame(frame); +} + +void QueuePrivate::getOk(const QAMQP::Frame::Method &frame) +{ + QByteArray data = frame.arguments(); + QDataStream in(&data, QIODevice::ReadOnly); + + qlonglong deliveryTag = readField('L',in).toLongLong(); + bool redelivered = readField('t',in).toBool(); + QString exchangeName = readField('s',in).toString(); + QString routingKey = readField('s',in).toString(); + + Q_UNUSED(redelivered) + + MessagePtr newMessage = MessagePtr(new Message); + newMessage->routeKey = routingKey; + newMessage->exchangeName = exchangeName; + newMessage->deliveryTag = deliveryTag; + messages_.enqueue(newMessage); +} + +void QueuePrivate::ack(const MessagePtr &Message) +{ + if (!opened) + return; + + QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmAck); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + out << Message->deliveryTag; //reserver 1 + out << qint8(0); // noAck + + frame.setArguments(arguments_); + sendFrame(frame); +} + +void QueuePrivate::consume(Queue::ConsumeOptions options) +{ + if (!opened) + return; + + QAMQP::Frame::Method frame(QAMQP::Frame::fcBasic, bmConsume); + frame.setChannel(number); + QByteArray arguments_; + QDataStream out(&arguments_, QIODevice::WriteOnly); + out << qint16(0); //reserver 1 + writeField('s', out, name); + writeField('s', out, consumerTag); + out << qint8(options); // no-wait + writeField('F', out, TableField()); + + frame.setArguments(arguments_); + sendFrame(frame); +} + +void QueuePrivate::consumeOk(const QAMQP::Frame::Method &frame) +{ + qDebug() << "Consume ok: " << name; + declared = false; + + QByteArray data = frame.arguments(); + QDataStream stream(&data, QIODevice::ReadOnly); + consumerTag = readField('s',stream).toString(); + qDebug("Consumer tag = %s", qPrintable(consumerTag)); +} + +void QueuePrivate::deliver(const QAMQP::Frame::Method &frame) +{ + QByteArray data = frame.arguments(); + QDataStream in(&data, QIODevice::ReadOnly); + QString consumer_ = readField('s',in).toString(); + if (consumer_ != consumerTag) + return; + + qlonglong deliveryTag = readField('L',in).toLongLong(); + bool redelivered = readField('t',in).toBool(); + QString exchangeName = readField('s',in).toString(); + QString routingKey = readField('s',in).toString(); + + Q_UNUSED(redelivered) + + MessagePtr newMessage = MessagePtr(new Message); + newMessage->routeKey = routingKey; + newMessage->exchangeName = exchangeName; + newMessage->deliveryTag = deliveryTag; + messages_.enqueue(newMessage); +} + +void QueuePrivate::_q_content(const QAMQP::Frame::Content &frame) +{ + Q_ASSERT(frame.channel() == number); + if (frame.channel() != number) + return; + + if (messages_.isEmpty()) { + qErrnoWarning("Received content-header without method frame before"); + return; + } + + MessagePtr &message = messages_.last(); + message->leftSize = frame.bodySize(); + QHash::ConstIterator i; + for (i = frame.properties_.begin(); i != frame.properties_.end(); ++i) + message->property[Message::MessageProperty(i.key())]= i.value(); +} + +void QueuePrivate::_q_body(const QAMQP::Frame::ContentBody &frame) +{ + Q_Q(QAMQP::Queue); + Q_ASSERT(frame.channel() == number); + if (frame.channel() != number) + return; + + if (messages_.isEmpty()) { + qErrnoWarning("Received content-body without method frame before"); + return; + } + + MessagePtr &message = messages_.last(); + message->payload.append(frame.body()); + message->leftSize -= frame.body().size(); + + if (message->leftSize == 0 && messages_.size() == 1) + Q_EMIT q->messageReceived(q); +} diff --git a/src/qamqp/amqp_queue.h b/src/qamqp/amqp_queue.h index baeab12..84b03c9 100644 --- a/src/qamqp/amqp_queue.h +++ b/src/qamqp/amqp_queue.h @@ -1,91 +1,95 @@ -#ifndef amqp_queue_h__ -#define amqp_queue_h__ - -#include "amqp_channel.h" -#include "amqp_message.h" - -namespace QAMQP -{ - class Client; - class ClientPrivate; - class Exchange; - class QueuePrivate; - class Queue : public Channel, public Frame::ContentHandler, public Frame::ContentBodyHandler - { - Q_OBJECT - Queue(int channelNumber = -1, Client * parent = 0); - - Q_PROPERTY(QueueOptions option READ option ); - Q_PROPERTY(QString consumerTag READ consumerTag WRITE setConsumerTag) - Q_PROPERTY(bool noAck READ noAck WRITE setNoAck) - - P_DECLARE_PRIVATE(QAMQP::Queue) - Q_DISABLE_COPY(Queue); - friend class ClientPrivate; - - protected: - void onOpen(); - void onClose(); - - public: - enum QueueOption { - NoOptions = 0x0, - Passive = 0x01, - Durable = 0x02, - Exclusive = 0x4, - AutoDelete = 0x8, - NoWait = 0x10 - }; - Q_DECLARE_FLAGS(QueueOptions, QueueOption) - - enum ConsumeOption { - coNoLocal = 0x1, - coNoAck = 0x02, - coExclusive = 0x04, - coNoWait = 0x8 - }; - Q_DECLARE_FLAGS(ConsumeOptions, ConsumeOption) - - ~Queue(); - - QueueOptions option() const; - - void declare(); - void declare(const QString &name, QueueOptions options); - void remove(bool ifUnused = true, bool ifEmpty = true, bool noWait = true); - - void purge(); - - void bind(const QString & exchangeName, const QString & key); - void bind(Exchange * exchange, const QString & key); - - void unbind(const QString & exchangeName, const QString & key); - void unbind(Exchange * exchange, const QString & key); - - MessagePtr getMessage(); - void get(); - void ack(const MessagePtr & message); - bool hasMessage() const; - void consume(ConsumeOptions options = ConsumeOptions(NoOptions)); - void setConsumerTag(const QString &consumerTag); - QString consumerTag() const; - - void setNoAck(bool noAck); - bool noAck() const; - - Q_SIGNALS: - void declared(); - void binded(bool); - void removed(); - void messageReceived(QAMQP::Queue* pQueue); - void empty(); - - private: - void _q_content(const QAMQP::Frame::Content & frame); - void _q_body(const QAMQP::Frame::ContentBody & frame); - }; -} -#ifdef QAMQP_P_INCLUDE -# include "amqp_queue_p.h" -#endif -#endif // amqp_queue_h__ +#ifndef amqp_queue_h__ +#define amqp_queue_h__ + +#include "amqp_channel.h" +#include "amqp_message.h" + +namespace QAMQP +{ + +class Client; +class ClientPrivate; +class Exchange; +class QueuePrivate; +class Queue : public Channel, public Frame::ContentHandler, public Frame::ContentBodyHandler +{ + Q_OBJECT + Q_ENUMS(QueueOptions) + Q_PROPERTY(QueueOptions option READ option) + Q_PROPERTY(QString consumerTag READ consumerTag WRITE setConsumerTag) + Q_PROPERTY(bool noAck READ noAck WRITE setNoAck) + +public: + enum QueueOption { + NoOptions = 0x0, + Passive = 0x01, + Durable = 0x02, + Exclusive = 0x4, + AutoDelete = 0x8, + NoWait = 0x10 + }; + Q_DECLARE_FLAGS(QueueOptions, QueueOption) + + enum ConsumeOption { + coNoLocal = 0x1, + coNoAck = 0x02, + coExclusive = 0x04, + coNoWait = 0x8 + }; + Q_DECLARE_FLAGS(ConsumeOptions, ConsumeOption) + + ~Queue(); + QueueOptions option() const; + + void declare(); + void declare(const QString &name, QueueOptions options); + void remove(bool ifUnused = true, bool ifEmpty = true, bool noWait = true); + + void purge(); + + void bind(const QString & exchangeName, const QString & key); + void bind(Exchange * exchange, const QString & key); + + void unbind(const QString & exchangeName, const QString & key); + void unbind(Exchange * exchange, const QString & key); + + MessagePtr getMessage(); + void get(); + void ack(const MessagePtr & message); + bool hasMessage() const; + void consume(ConsumeOptions options = ConsumeOptions(NoOptions)); + void setConsumerTag(const QString &consumerTag); + QString consumerTag() const; + + void setNoAck(bool noAck); + bool noAck() const; + +Q_SIGNALS: + void declared(); + void binded(bool); + void removed(); + void messageReceived(QAMQP::Queue *pQueue); + void empty(); + +protected: + void onOpen(); + void onClose(); + +private: + Queue(int channelNumber = -1, Client * parent = 0); + + void _q_content(const QAMQP::Frame::Content & frame); + void _q_body(const QAMQP::Frame::ContentBody & frame); + + Q_DISABLE_COPY(Queue) + Q_DECLARE_PRIVATE(QAMQP::Queue) + + friend class ClientPrivate; + +}; + +} +#ifdef QAMQP_P_INCLUDE +# include "amqp_queue_p.h" +#endif +#endif // amqp_queue_h__ diff --git a/src/qamqp/amqp_queue_p.h b/src/qamqp/amqp_queue_p.h index 79f9321..2733e2e 100644 --- a/src/qamqp/amqp_queue_p.h +++ b/src/qamqp/amqp_queue_p.h @@ -1,70 +1,73 @@ -#ifndef amqp_queue_p_h__ -#define amqp_queue_p_h__ - -#include "amqp_channel_p.h" -#define METHOD_ID_ENUM(name, id) name = id, name ## Ok -#include - -namespace QAMQP -{ - using namespace QAMQP::Frame; - class QueuePrivate: public ChannelPrivate - { - P_DECLARE_PUBLIC(QAMQP::Queue) - public: - - enum MethodId - { - METHOD_ID_ENUM(miDeclare, 10), - METHOD_ID_ENUM(miBind, 20), - METHOD_ID_ENUM(miUnbind, 50), - METHOD_ID_ENUM(miPurge, 30), - METHOD_ID_ENUM(miDelete, 40) - }; - - QueuePrivate(Queue * q); - ~QueuePrivate(); - - void declare(); - void remove(bool ifUnused = true, bool ifEmpty = true, bool noWait = true); - void purge(); - void bind(const QString & exchangeName, const QString & key); - void unbind(const QString & exchangeName, const QString & key); - - void declareOk(const QAMQP::Frame::Method & frame); - void deleteOk(const QAMQP::Frame::Method & frame); - void bindOk(const QAMQP::Frame::Method & frame); - void unbindOk(const QAMQP::Frame::Method & frame); - - /************************************************************************/ - /* CLASS BASIC METHODS */ - /************************************************************************/ - - void consume(Queue::ConsumeOptions options); - void consumeOk(const QAMQP::Frame::Method & frame); - void deliver(const QAMQP::Frame::Method & frame); - - void get(); - void getOk(const QAMQP::Frame::Method & frame); - void ack(const MessagePtr & Message); - - QString type; - Queue::QueueOptions options; - - bool _q_method(const QAMQP::Frame::Method & frame); - - bool delayedDeclare; - bool declared; - bool noAck; - QString consumerTag; - - QQueue > delayedBindings; - QQueue messages_; - - bool recievingMessage; - - void _q_content(const QAMQP::Frame::Content & frame); - void _q_body(const QAMQP::Frame::ContentBody & frame); - }; -} -#endif // amqp_queue_p_h__ +#ifndef amqp_queue_p_h__ +#define amqp_queue_p_h__ + +#include "amqp_channel_p.h" +#define METHOD_ID_ENUM(name, id) name = id, name ## Ok +#include + +namespace QAMQP +{ + +using namespace QAMQP::Frame; + +class QueuePrivate: public ChannelPrivate +{ +public: + enum MethodId { + METHOD_ID_ENUM(miDeclare, 10), + METHOD_ID_ENUM(miBind, 20), + METHOD_ID_ENUM(miUnbind, 50), + METHOD_ID_ENUM(miPurge, 30), + METHOD_ID_ENUM(miDelete, 40) + }; + + QueuePrivate(Queue *q); + ~QueuePrivate(); + + void declare(); + void remove(bool ifUnused = true, bool ifEmpty = true, bool noWait = true); + void purge(); + void bind(const QString &exchangeName, const QString &key); + void unbind(const QString &exchangeName, const QString &key); + + void declareOk(const QAMQP::Frame::Method &frame); + void deleteOk(const QAMQP::Frame::Method &frame); + void bindOk(const QAMQP::Frame::Method &frame); + void unbindOk(const QAMQP::Frame::Method &frame); + + /************************************************************************/ + /* CLASS BASIC METHODS */ + /************************************************************************/ + + void consume(Queue::ConsumeOptions options); + void consumeOk(const QAMQP::Frame::Method &frame); + void deliver(const QAMQP::Frame::Method &frame); + + void get(); + void getOk(const QAMQP::Frame::Method &frame); + void ack(const MessagePtr &Message); + + QString type; + Queue::QueueOptions options; + + bool _q_method(const QAMQP::Frame::Method &frame); + + bool delayedDeclare; + bool declared; + bool noAck; + QString consumerTag; + + QQueue > delayedBindings; + QQueue messages_; + + bool recievingMessage; + + void _q_content(const QAMQP::Frame::Content &frame); + void _q_body(const QAMQP::Frame::ContentBody &frame); + + Q_DECLARE_PUBLIC(QAMQP::Queue) + +}; + +} +#endif // amqp_queue_p_h__ diff --git a/src/qamqp/qamqp.pri b/src/qamqp/qamqp.pri index 86db087..1992c80 100644 --- a/src/qamqp/qamqp.pri +++ b/src/qamqp/qamqp.pri @@ -1,28 +1,29 @@ -QT += network - -DEPENDPATH += $$PWD - -HEADERS += $$PWD/amqp.h \ - $$PWD/amqp_authenticator.h \ - $$PWD/amqp_channel.h \ - $$PWD/amqp_channel_p.h \ - $$PWD/amqp_connection.h \ - $$PWD/amqp_connection_p.h \ - $$PWD/amqp_exchange.h \ - $$PWD/amqp_exchange_p.h \ - $$PWD/amqp_frame.h \ - $$PWD/amqp_message.h \ - $$PWD/amqp_network.h \ - $$PWD/amqp_p.h \ - $$PWD/amqp_queue.h \ - $$PWD/amqp_queue_p.h \ - $$PWD/amqp_global.h \ - -SOURCES += $$PWD/amqp.cpp \ - $$PWD/amqp_authenticator.cpp \ - $$PWD/amqp_channel.cpp \ - $$PWD/amqp_connection.cpp \ - $$PWD/amqp_exchange.cpp \ - $$PWD/amqp_frame.cpp \ - $$PWD/amqp_network.cpp \ - $$PWD/amqp_queue.cpp \ \ No newline at end of file +QT += network + +DEPENDPATH += $$PWD + +HEADERS += $$PWD/amqp.h \ + $$PWD/amqp_authenticator.h \ + $$PWD/amqp_channel.h \ + $$PWD/amqp_channel_p.h \ + $$PWD/amqp_connection.h \ + $$PWD/amqp_connection_p.h \ + $$PWD/amqp_exchange.h \ + $$PWD/amqp_exchange_p.h \ + $$PWD/amqp_frame.h \ + $$PWD/amqp_message.h \ + $$PWD/amqp_network.h \ + $$PWD/amqp_p.h \ + $$PWD/amqp_queue.h \ + $$PWD/amqp_queue_p.h \ + $$PWD/amqp_global.h \ + +SOURCES += $$PWD/amqp.cpp \ + $$PWD/amqp_authenticator.cpp \ + $$PWD/amqp_channel.cpp \ + $$PWD/amqp_connection.cpp \ + $$PWD/amqp_exchange.cpp \ + $$PWD/amqp_frame.cpp \ + $$PWD/amqp_message.cpp \ + $$PWD/amqp_network.cpp \ + $$PWD/amqp_queue.cpp \