2014-01-04 19:45:04 +08:00
|
|
|
/**
|
|
|
|
|
* Channel.cpp
|
|
|
|
|
*
|
|
|
|
|
* Implementation for a channel
|
|
|
|
|
*
|
|
|
|
|
* @copyright 2014 Copernica BV
|
|
|
|
|
*/
|
|
|
|
|
#include "includes.h"
|
2014-01-06 01:50:41 +08:00
|
|
|
#include "basicdeliverframe.h"
|
2014-01-06 22:49:31 +08:00
|
|
|
#include "basicreturnframe.h"
|
2014-01-06 01:50:41 +08:00
|
|
|
#include "messageimpl.h"
|
2014-01-06 22:49:31 +08:00
|
|
|
#include "consumedmessage.h"
|
|
|
|
|
#include "returnedmessage.h"
|
2014-01-04 19:45:04 +08:00
|
|
|
#include "channelopenframe.h"
|
|
|
|
|
#include "channelflowframe.h"
|
2014-01-06 01:50:41 +08:00
|
|
|
#include "channelcloseokframe.h"
|
2014-01-04 19:45:04 +08:00
|
|
|
#include "channelcloseframe.h"
|
|
|
|
|
#include "transactionselectframe.h"
|
|
|
|
|
#include "transactioncommitframe.h"
|
|
|
|
|
#include "transactionrollbackframe.h"
|
|
|
|
|
#include "exchangedeclareframe.h"
|
|
|
|
|
#include "exchangedeleteframe.h"
|
|
|
|
|
#include "exchangebindframe.h"
|
|
|
|
|
#include "exchangeunbindframe.h"
|
|
|
|
|
#include "queuedeclareframe.h"
|
|
|
|
|
#include "queuebindframe.h"
|
|
|
|
|
#include "queueunbindframe.h"
|
|
|
|
|
#include "queuepurgeframe.h"
|
|
|
|
|
#include "queuedeleteframe.h"
|
2014-01-05 20:08:35 +08:00
|
|
|
#include "basicpublishframe.h"
|
|
|
|
|
#include "basicheaderframe.h"
|
|
|
|
|
#include "bodyframe.h"
|
2014-01-05 21:19:35 +08:00
|
|
|
#include "basicqosframe.h"
|
2014-01-06 01:50:41 +08:00
|
|
|
#include "basicconsumeframe.h"
|
|
|
|
|
#include "basiccancelframe.h"
|
2014-01-06 04:21:09 +08:00
|
|
|
#include "basicackframe.h"
|
2014-01-06 21:28:58 +08:00
|
|
|
#include "basicnackframe.h"
|
2014-01-06 21:38:48 +08:00
|
|
|
#include "basicrecoverframe.h"
|
2014-01-04 19:45:04 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set up namespace
|
|
|
|
|
*/
|
|
|
|
|
namespace AMQP {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a channel object
|
|
|
|
|
* @param parent
|
|
|
|
|
* @param connection
|
|
|
|
|
* @param handler
|
|
|
|
|
*/
|
2014-04-10 18:51:04 +08:00
|
|
|
ChannelImpl::ChannelImpl(Channel *parent, Connection *connection) :
|
2014-01-04 19:45:04 +08:00
|
|
|
_parent(parent),
|
2014-04-10 18:51:04 +08:00
|
|
|
_connection(&connection->_implementation)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
|
|
|
|
// add the channel to the connection
|
2014-01-07 00:15:21 +08:00
|
|
|
_id = _connection->add(this);
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
// check if the id is valid
|
|
|
|
|
if (_id == 0)
|
|
|
|
|
{
|
|
|
|
|
// this is invalid
|
|
|
|
|
_state = state_closed;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// busy connecting
|
|
|
|
|
_state = state_connected;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
// valid id, send a channel open frame
|
|
|
|
|
send(ChannelOpenFrame(_id));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Destructor
|
|
|
|
|
*/
|
|
|
|
|
ChannelImpl::~ChannelImpl()
|
|
|
|
|
{
|
2014-04-08 20:42:07 +08:00
|
|
|
// remove incoming message
|
2014-01-06 01:50:41 +08:00
|
|
|
if (_message) delete _message;
|
|
|
|
|
_message = nullptr;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-07 00:15:21 +08:00
|
|
|
// remove this channel from the connection (but not if the connection is already destructed)
|
2014-01-07 05:34:54 +08:00
|
|
|
if (_connection) _connection->remove(this);
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
// close the channel now
|
|
|
|
|
close();
|
2014-04-15 16:43:33 +08:00
|
|
|
|
2014-04-15 18:25:56 +08:00
|
|
|
// destruct deferred results
|
|
|
|
|
while (_oldestCallback) _oldestCallback.reset(_oldestCallback->next());
|
2014-04-15 16:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Push a deferred result
|
|
|
|
|
* @param result The deferred object to push
|
|
|
|
|
* @param error Error message in case of error
|
|
|
|
|
*/
|
|
|
|
|
void ChannelImpl::push(Deferred *deferred, const char *error)
|
|
|
|
|
{
|
|
|
|
|
// do we already have an oldest?
|
2014-04-15 18:25:56 +08:00
|
|
|
if (!_oldestCallback) _oldestCallback.reset(deferred);
|
2014-04-15 16:43:33 +08:00
|
|
|
|
|
|
|
|
// do we already have a newest?
|
|
|
|
|
if (_newestCallback) _newestCallback->add(deferred);
|
|
|
|
|
|
|
|
|
|
// store newest callback
|
|
|
|
|
_newestCallback = deferred;
|
|
|
|
|
|
|
|
|
|
// @todo in case of error we have to report the error with a timeout
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Pause deliveries on a channel
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
2014-01-04 19:45:04 +08:00
|
|
|
* This will stop all incoming messages
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::pause()
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-08 20:42:07 +08:00
|
|
|
// send a channel flow frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(ChannelFlowFrame(_id, false), "Cannot send channel flow frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Resume a paused channel
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This will resume incoming messages
|
|
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::resume()
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-08 20:42:07 +08:00
|
|
|
// send a channel flow frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(ChannelFlowFrame(_id, true), "Cannot send channel flow frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Start a transaction
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::startTransaction()
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-08 20:42:07 +08:00
|
|
|
// send a transaction frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(TransactionSelectFrame(_id), "Cannot send transaction start frame");
|
2014-04-08 20:42:07 +08:00
|
|
|
}
|
2014-01-04 19:45:04 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Commit the current transaction
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::commitTransaction()
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-08 20:42:07 +08:00
|
|
|
// send a transaction frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(TransactionCommitFrame(_id), "Cannot send transaction commit frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Rollback the current transaction
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::rollbackTransaction()
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-08 20:42:07 +08:00
|
|
|
// send a transaction frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(TransactionRollbackFrame(_id), "Cannot send transaction commit frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Close the current channel
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::close()
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-01-07 00:15:21 +08:00
|
|
|
// channel could be dead after send operation, we need to monitor that
|
|
|
|
|
Monitor monitor(this);
|
|
|
|
|
|
2014-04-08 20:42:07 +08:00
|
|
|
// send a channel close frame
|
2014-04-15 16:43:33 +08:00
|
|
|
auto &handler = send(ChannelCloseFrame(_id), "Cannot send channel close frame");
|
2014-01-07 00:15:21 +08:00
|
|
|
|
2014-04-08 20:42:07 +08:00
|
|
|
// was the frame sent and are we still alive?
|
|
|
|
|
if (handler && monitor.valid()) _state = state_closing;
|
2014-01-04 19:45:04 +08:00
|
|
|
|
|
|
|
|
// done
|
2014-04-08 20:42:07 +08:00
|
|
|
return handler;
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* declare an exchange
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
* @param name name of the exchange to declare
|
|
|
|
|
* @param type type of exchange
|
|
|
|
|
* @param flags additional settings for the exchange
|
|
|
|
|
* @param arguments additional arguments
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::declareExchange(const std::string &name, ExchangeType type, int flags, const Table &arguments)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-01-07 00:15:21 +08:00
|
|
|
// convert exchange type
|
2014-01-04 19:45:04 +08:00
|
|
|
std::string exchangeType;
|
2014-01-07 00:15:21 +08:00
|
|
|
if (type == ExchangeType::fanout) exchangeType = "fanout";
|
|
|
|
|
if (type == ExchangeType::direct) exchangeType = "direct";
|
|
|
|
|
if (type == ExchangeType::topic) exchangeType = "topic";
|
|
|
|
|
if (type == ExchangeType::headers)exchangeType = "headers";
|
|
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
// send declare exchange frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(ExchangeDeclareFrame(_id, name, exchangeType, flags & passive, flags & durable, flags & nowait, arguments), "Cannot send exchange declare frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* bind an exchange
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
2014-01-04 19:45:04 +08:00
|
|
|
* @param source exchange which binds to target
|
|
|
|
|
* @param target exchange to bind to
|
|
|
|
|
* @param routingKey routing key
|
|
|
|
|
* @param flags additional flags
|
|
|
|
|
* @param arguments additional arguments for binding
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::bindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags, const Table &arguments)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
|
|
|
|
// send exchange bind frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(ExchangeBindFrame(_id, target, source, routingkey, flags & nowait, arguments), "Cannot send exchange bind frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* unbind two exchanges
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
2014-01-04 19:45:04 +08:00
|
|
|
* @param source the source exchange
|
|
|
|
|
* @param target the target exchange
|
|
|
|
|
* @param routingkey the routing key
|
|
|
|
|
* @param flags optional flags
|
|
|
|
|
* @param arguments additional unbind arguments
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::unbindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags, const Table &arguments)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
|
|
|
|
// send exchange unbind frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(ExchangeUnbindFrame(_id, target, source, routingkey, flags & nowait, arguments), "Cannot send exchange unbind frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* remove an exchange
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
2014-01-04 19:45:04 +08:00
|
|
|
* @param name name of the exchange to remove
|
|
|
|
|
* @param flags additional settings for deleting the exchange
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::removeExchange(const std::string &name, int flags)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
|
|
|
|
// send delete exchange frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(ExchangeDeleteFrame(_id, name, flags & ifunused, flags & nowait), "Cannot send exchange delete frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* declare a queue
|
|
|
|
|
* @param name queue name
|
|
|
|
|
* @param flags additional settings for the queue
|
|
|
|
|
* @param arguments additional arguments
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
DeferredQueue &ChannelImpl::declareQueue(const std::string &name, int flags, const Table &arguments)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-15 16:43:33 +08:00
|
|
|
// the frame to send
|
|
|
|
|
QueueDeclareFrame frame(_id, name, flags & passive, flags & durable, flags & exclusive, flags & autodelete, flags & nowait, arguments);
|
|
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
// send the queuedeclareframe
|
2014-04-15 16:43:33 +08:00
|
|
|
auto *result = new DeferredQueue(send(frame));
|
|
|
|
|
|
|
|
|
|
// add the deferred result
|
|
|
|
|
push(result, "Cannot send queue declare frame");
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
return *result;
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Bind a queue to an exchange
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
2014-01-04 19:45:04 +08:00
|
|
|
* @param exchangeName name of the exchange to bind to
|
|
|
|
|
* @param queueName name of the queue
|
|
|
|
|
* @param routingkey routingkey
|
|
|
|
|
* @param flags additional flags
|
|
|
|
|
* @param arguments additional arguments
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::bindQueue(const std::string &exchangeName, const std::string &queueName, const std::string &routingkey, int flags, const Table &arguments)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
|
|
|
|
// send the bind queue frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(QueueBindFrame(_id, queueName, exchangeName, routingkey, flags & nowait, arguments), "Cannot send queue bind frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unbind a queue from an exchange
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
2014-01-04 19:45:04 +08:00
|
|
|
* @param exchange the source exchange
|
|
|
|
|
* @param queue the target queue
|
|
|
|
|
* @param routingkey the routing key
|
|
|
|
|
* @param arguments additional bind arguments
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::unbindQueue(const std::string &exchange, const std::string &queue, const std::string &routingkey, const Table &arguments)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
|
|
|
|
// send the unbind queue frame
|
2014-04-15 16:43:33 +08:00
|
|
|
return send(QueueUnbindFrame(_id, queue, exchange, routingkey, arguments), "Cannot send queue unbind frame");
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Purge a queue
|
|
|
|
|
* @param queue queue to purge
|
|
|
|
|
* @param flags additional flags
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
|
|
|
|
*
|
|
|
|
|
* The onSuccess() callback that you can install should have the following signature:
|
|
|
|
|
*
|
|
|
|
|
* void myCallback(AMQP::Channel *channel, uint32_t messageCount);
|
|
|
|
|
*
|
|
|
|
|
* For example: channel.declareQueue("myqueue").onSuccess([](AMQP::Channel *channel, uint32_t messageCount) {
|
|
|
|
|
*
|
|
|
|
|
* std::cout << "Queue purged, all " << messageCount << " messages removed" << std::endl;
|
|
|
|
|
*
|
|
|
|
|
* });
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
DeferredDelete &ChannelImpl::purgeQueue(const std::string &name, int flags)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-15 16:43:33 +08:00
|
|
|
// the frame to send
|
|
|
|
|
QueuePurgeFrame frame(_id, name, flags & nowait);
|
|
|
|
|
|
|
|
|
|
// send the frame, and create deferred object
|
|
|
|
|
auto *deferred = new DeferredDelete(send(frame));
|
|
|
|
|
|
|
|
|
|
// push to list
|
|
|
|
|
push(deferred, "Cannot send queue purge frame");
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
return *deferred;
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Remove a queue
|
|
|
|
|
* @param queue queue to remove
|
|
|
|
|
* @param flags additional flags
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
|
|
|
|
*
|
|
|
|
|
* The onSuccess() callback that you can install should have the following signature:
|
|
|
|
|
*
|
|
|
|
|
* void myCallback(AMQP::Channel *channel, uint32_t messageCount);
|
|
|
|
|
*
|
|
|
|
|
* For example: channel.declareQueue("myqueue").onSuccess([](AMQP::Channel *channel, uint32_t messageCount) {
|
|
|
|
|
*
|
|
|
|
|
* std::cout << "Queue deleted, along with " << messageCount << " messages" << std::endl;
|
|
|
|
|
*
|
|
|
|
|
* });
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
DeferredDelete &ChannelImpl::removeQueue(const std::string &name, int flags)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-04-15 16:43:33 +08:00
|
|
|
// the frame to send
|
|
|
|
|
QueueDeleteFrame frame(_id, name, flags & ifunused, flags & ifempty, flags & nowait);
|
|
|
|
|
|
|
|
|
|
// send the frame, and create deferred object
|
|
|
|
|
auto *deferred = new DeferredDelete(send(frame));
|
|
|
|
|
|
|
|
|
|
// push to list
|
|
|
|
|
push(deferred, "Cannot send remove queue frame");
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
return *deferred;
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
2014-01-05 20:08:35 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Publish a message to an exchange
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
2014-01-05 20:08:35 +08:00
|
|
|
* @param exchange the exchange to publish to
|
|
|
|
|
* @param routingkey the routing key
|
|
|
|
|
* @param envelope the full envelope to send
|
|
|
|
|
* @param message the message to send
|
|
|
|
|
* @param size size of the message
|
|
|
|
|
*/
|
2014-04-10 18:51:04 +08:00
|
|
|
bool ChannelImpl::publish(const std::string &exchange, const std::string &routingKey, const Envelope &envelope)
|
2014-01-05 20:08:35 +08:00
|
|
|
{
|
2014-01-07 00:15:21 +08:00
|
|
|
// we are going to send out multiple frames, each one will trigger a call to the handler,
|
|
|
|
|
// which in turn could destruct the channel object, we need to monitor that
|
|
|
|
|
Monitor monitor(this);
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
// @todo do not copy the entire buffer to individual frames
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-05 20:08:35 +08:00
|
|
|
// send the publish frame
|
2014-04-10 18:51:04 +08:00
|
|
|
if (!send(BasicPublishFrame(_id, exchange, routingKey))) return false;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-07 00:15:21 +08:00
|
|
|
// channel still valid?
|
|
|
|
|
if (!monitor.valid()) return false;
|
2014-01-05 20:08:35 +08:00
|
|
|
|
|
|
|
|
// send header
|
2014-01-07 00:15:21 +08:00
|
|
|
if (!send(BasicHeaderFrame(_id, envelope))) return false;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-07 00:15:21 +08:00
|
|
|
// channel and connection still valid?
|
2014-01-07 05:34:54 +08:00
|
|
|
if (!monitor.valid() || !_connection) return false;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-05 20:08:35 +08:00
|
|
|
// the max payload size is the max frame size minus the bytes for headers and trailer
|
2014-01-07 00:15:21 +08:00
|
|
|
uint32_t maxpayload = _connection->maxPayload();
|
2014-01-05 20:08:35 +08:00
|
|
|
uint32_t bytessent = 0;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-05 20:08:35 +08:00
|
|
|
// the buffer
|
|
|
|
|
const char *data = envelope.body();
|
|
|
|
|
uint32_t bytesleft = envelope.bodySize();
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-05 20:08:35 +08:00
|
|
|
// split up the body in multiple frames depending on the max frame size
|
|
|
|
|
while (bytesleft > 0)
|
|
|
|
|
{
|
|
|
|
|
// size of this chunk
|
|
|
|
|
uint32_t chunksize = std::min(maxpayload, bytesleft);
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-05 20:08:35 +08:00
|
|
|
// send out a body frame
|
2014-01-07 00:15:21 +08:00
|
|
|
if (!send(BodyFrame(_id, data + bytessent, chunksize))) return false;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-07 00:15:21 +08:00
|
|
|
// channel still valid?
|
|
|
|
|
if (!monitor.valid()) return false;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-05 20:08:35 +08:00
|
|
|
// update counters
|
|
|
|
|
bytessent += chunksize;
|
|
|
|
|
bytesleft -= chunksize;
|
|
|
|
|
}
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-05 20:08:35 +08:00
|
|
|
// done
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-01-04 19:45:04 +08:00
|
|
|
|
2014-01-05 21:19:35 +08:00
|
|
|
/**
|
|
|
|
|
* Set the Quality of Service (QOS) for this channel
|
|
|
|
|
* @param prefetchCount maximum number of messages to prefetch
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-05 21:19:35 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::setQos(uint16_t prefetchCount)
|
2014-01-05 21:19:35 +08:00
|
|
|
{
|
2014-01-06 01:50:41 +08:00
|
|
|
// send a qos frame
|
2014-04-08 20:42:07 +08:00
|
|
|
return send(BasicQosFrame(_id, prefetchCount, false), "Cannot send basic QOS frame");
|
2014-01-05 21:19:35 +08:00
|
|
|
}
|
|
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
|
|
|
|
* Tell the RabbitMQ server that we're ready to consume messages
|
|
|
|
|
* @param queue the queue from which you want to consume
|
|
|
|
|
* @param tag a consumer tag that will be associated with this consume operation
|
|
|
|
|
* @param flags additional flags
|
|
|
|
|
* @param arguments additional arguments
|
2014-04-10 18:51:04 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
|
|
|
|
*
|
|
|
|
|
* The onSuccess() callback that you can install should have the following signature:
|
|
|
|
|
*
|
|
|
|
|
* void myCallback(AMQP::Channel *channel, const std::string& tag);
|
|
|
|
|
*
|
|
|
|
|
* For example: channel.declareQueue("myqueue").onSuccess([](AMQP::Channel *channel, const std::string& tag) {
|
|
|
|
|
*
|
|
|
|
|
* std::cout << "Started consuming under tag " << tag << std::endl;
|
|
|
|
|
*
|
|
|
|
|
* });
|
2014-01-06 01:50:41 +08:00
|
|
|
*/
|
2014-04-10 18:51:04 +08:00
|
|
|
DeferredConsumer& ChannelImpl::consume(const std::string &queue, const std::string &tag, int flags, const Table &arguments)
|
2014-01-06 01:50:41 +08:00
|
|
|
{
|
2014-04-15 17:39:52 +08:00
|
|
|
// the frame to send
|
|
|
|
|
BasicConsumeFrame frame(_id, queue, tag, flags & nolocal, flags & noack, flags & exclusive, flags & nowait, arguments);
|
|
|
|
|
|
|
|
|
|
// send the frame, and create deferred object
|
|
|
|
|
auto *deferred = new DeferredConsumer(this, send(frame));
|
|
|
|
|
|
|
|
|
|
// push to list
|
|
|
|
|
push(deferred, "Cannot send basic consume frame");
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
return *deferred;
|
2014-01-06 01:50:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Cancel a running consumer
|
|
|
|
|
* @param tag the consumer tag
|
|
|
|
|
* @param flags optional flags
|
2014-04-10 18:51:04 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
|
|
|
|
*
|
|
|
|
|
* The onSuccess() callback that you can install should have the following signature:
|
|
|
|
|
*
|
|
|
|
|
* void myCallback(AMQP::Channel *channel, const std::string& tag);
|
|
|
|
|
*
|
|
|
|
|
* For example: channel.declareQueue("myqueue").onSuccess([](AMQP::Channel *channel, const std::string& tag) {
|
|
|
|
|
*
|
|
|
|
|
* std::cout << "Started consuming under tag " << tag << std::endl;
|
|
|
|
|
*
|
|
|
|
|
* });
|
2014-01-06 01:50:41 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
DeferredCancel &ChannelImpl::cancel(const std::string &tag, int flags)
|
2014-01-06 01:50:41 +08:00
|
|
|
{
|
2014-04-15 16:43:33 +08:00
|
|
|
// the cancel frame to send
|
|
|
|
|
BasicCancelFrame frame(_id, tag, flags & nowait);
|
|
|
|
|
|
|
|
|
|
// send the frame, and create deferred object
|
2014-04-15 18:36:11 +08:00
|
|
|
auto *deferred = new DeferredCancel(this, send(frame));
|
2014-04-15 16:43:33 +08:00
|
|
|
|
|
|
|
|
// push to list
|
|
|
|
|
push(deferred, "Cannot send basic cancel frame");
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
return *deferred;
|
2014-01-06 01:50:41 +08:00
|
|
|
}
|
|
|
|
|
|
2014-01-06 04:21:09 +08:00
|
|
|
/**
|
2014-04-10 18:51:04 +08:00
|
|
|
* Acknowledge a message
|
2014-01-06 04:21:09 +08:00
|
|
|
* @param deliveryTag the delivery tag
|
|
|
|
|
* @param flags optional flags
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
bool ChannelImpl::ack(uint64_t deliveryTag, int flags)
|
|
|
|
|
{
|
|
|
|
|
// send an ack frame
|
2014-01-07 00:15:21 +08:00
|
|
|
return send(BasicAckFrame(_id, deliveryTag, flags & multiple));
|
2014-01-06 04:21:09 +08:00
|
|
|
}
|
|
|
|
|
|
2014-01-06 21:28:58 +08:00
|
|
|
/**
|
|
|
|
|
* Reject a message
|
|
|
|
|
* @param deliveryTag the delivery tag
|
|
|
|
|
* @param flags optional flags
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
bool ChannelImpl::reject(uint64_t deliveryTag, int flags)
|
|
|
|
|
{
|
|
|
|
|
// send a nack frame
|
2014-01-07 00:15:21 +08:00
|
|
|
return send(BasicNackFrame(_id, deliveryTag, flags & multiple, flags & requeue));
|
2014-01-06 21:28:58 +08:00
|
|
|
}
|
|
|
|
|
|
2014-01-06 21:38:48 +08:00
|
|
|
/**
|
|
|
|
|
* Recover un-acked messages
|
|
|
|
|
* @param flags optional flags
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* This function returns a deferred handler. Callbacks can be installed
|
|
|
|
|
* using onSuccess(), onError() and onFinalize() methods.
|
2014-01-06 21:38:48 +08:00
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::recover(int flags)
|
2014-01-06 21:38:48 +08:00
|
|
|
{
|
|
|
|
|
// send a nack frame
|
2014-04-08 20:42:07 +08:00
|
|
|
return send(BasicRecoverFrame(_id, flags & requeue), "Cannot send basic recover frame");
|
2014-01-06 21:38:48 +08:00
|
|
|
}
|
|
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
/**
|
|
|
|
|
* Send a frame over the channel
|
|
|
|
|
* @param frame frame to send
|
2014-01-07 00:15:21 +08:00
|
|
|
* @return bool was the frame sent?
|
2014-01-04 19:45:04 +08:00
|
|
|
*/
|
2014-01-07 00:15:21 +08:00
|
|
|
bool ChannelImpl::send(const Frame &frame)
|
2014-01-04 19:45:04 +08:00
|
|
|
{
|
2014-01-07 00:15:21 +08:00
|
|
|
// skip if channel is not connected
|
2014-01-07 05:34:54 +08:00
|
|
|
if (_state != state_connected || !_connection) return false;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-07 05:34:54 +08:00
|
|
|
// send to tcp connection
|
|
|
|
|
return _connection->send(frame);
|
2014-01-04 19:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
2014-04-08 20:42:07 +08:00
|
|
|
/**
|
2014-04-08 22:12:04 +08:00
|
|
|
* Send a frame over the channel and get a deferred handler for it.
|
2014-04-08 20:42:07 +08:00
|
|
|
*
|
|
|
|
|
* @param frame frame to send
|
|
|
|
|
* @param message the message to trigger if the frame cannot be send at all
|
|
|
|
|
*/
|
2014-04-15 16:43:33 +08:00
|
|
|
Deferred &ChannelImpl::send(const Frame &frame, const char *message)
|
2014-04-08 20:42:07 +08:00
|
|
|
{
|
2014-04-15 16:43:33 +08:00
|
|
|
// send the frame, and create deferred object
|
|
|
|
|
auto *deferred = new Deferred(send(frame));
|
|
|
|
|
|
|
|
|
|
// push to list
|
|
|
|
|
push(deferred, message);
|
|
|
|
|
|
|
|
|
|
// done
|
|
|
|
|
return *deferred;
|
2014-04-08 20:42:07 +08:00
|
|
|
}
|
|
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
/**
|
2014-01-06 04:21:09 +08:00
|
|
|
* Report the received message
|
2014-01-06 01:50:41 +08:00
|
|
|
*/
|
2014-01-06 22:49:31 +08:00
|
|
|
void ChannelImpl::reportMessage()
|
2014-01-06 01:50:41 +08:00
|
|
|
{
|
2014-01-06 22:49:31 +08:00
|
|
|
// skip if there is no message
|
|
|
|
|
if (!_message) return;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-04-15 17:39:52 +08:00
|
|
|
// look for the consumer
|
|
|
|
|
auto iter = _consumers.find(_message->consumer());
|
|
|
|
|
if (iter == _consumers.end()) return;
|
|
|
|
|
|
|
|
|
|
// is this a valid callback method
|
|
|
|
|
if (!iter->second) return;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-04-15 17:39:52 +08:00
|
|
|
// after the report the channel may be destructed, monitor that
|
|
|
|
|
Monitor monitor(this);
|
|
|
|
|
|
|
|
|
|
// call the callback
|
|
|
|
|
_message->report(iter->second);
|
|
|
|
|
|
|
|
|
|
// skip if channel was destructed
|
|
|
|
|
if (!monitor.valid()) return;
|
2014-04-08 20:42:07 +08:00
|
|
|
|
2014-01-06 22:49:31 +08:00
|
|
|
// no longer need the message
|
2014-04-15 17:39:52 +08:00
|
|
|
delete _message; _message = nullptr;
|
2014-01-06 01:50:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create an incoming message
|
|
|
|
|
* @param frame
|
2014-04-15 17:39:52 +08:00
|
|
|
* @return ConsumedMessage
|
2014-01-06 01:50:41 +08:00
|
|
|
*/
|
2014-04-15 17:39:52 +08:00
|
|
|
ConsumedMessage *ChannelImpl::message(const BasicDeliverFrame &frame)
|
2014-01-06 01:50:41 +08:00
|
|
|
{
|
2014-04-15 17:39:52 +08:00
|
|
|
// destruct if message is already set
|
2014-01-06 01:50:41 +08:00
|
|
|
if (_message) delete _message;
|
2014-04-15 17:39:52 +08:00
|
|
|
|
2014-01-06 01:50:41 +08:00
|
|
|
// construct a message
|
2014-01-06 22:49:31 +08:00
|
|
|
return _message = new ConsumedMessage(frame);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-04 19:45:04 +08:00
|
|
|
/**
|
|
|
|
|
* End of namespace
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|