Initial commit with the implementation of all methods apart from the publish and consume methods
This commit is contained in:
parent
aa675084f1
commit
ea4f82ac8f
|
|
@ -0,0 +1,18 @@
|
|||
PREFIX = /usr
|
||||
INCLUDE_DIR = ${PREFIX}/include
|
||||
LIBRARY_DIR = ${PREFIX}/lib
|
||||
COPERNICA_INCLUDE_DIR = ${INCLUDE_DIR}/copernica
|
||||
|
||||
all:
|
||||
$(MAKE) -C src all
|
||||
|
||||
clean:
|
||||
$(MAKE) -C src clean
|
||||
|
||||
install:
|
||||
mkdir -p ${COPERNICA_INCLUDE_DIR}/amqp
|
||||
mkdir -p ${LIBRARY_DIR}
|
||||
cp -f amqp.h ${COPERNICA_INCLUDE_DIR}
|
||||
cp -f include/*.h ${COPERNICA_INCLUDE_DIR}/amqp
|
||||
cp -f src/libcopernica_amqp.so ${LIBRARY_DIR}
|
||||
cp -f src/libcopernica_amqp.a ${LIBRARY_DIR}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* AMQP.h
|
||||
*
|
||||
* Starting point for all includes of the Copernica AMQP library
|
||||
*
|
||||
* @documentation public
|
||||
*/
|
||||
|
||||
// base C++ include files
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
|
||||
// base C include files
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <endian.h>
|
||||
#include <string.h>
|
||||
|
||||
// other libraries
|
||||
#include <copernica/event.h>
|
||||
#include <copernica/network.h>
|
||||
|
||||
// forward declarations
|
||||
#include <copernica/amqp/classes.h>
|
||||
|
||||
// utility classes
|
||||
#include <copernica/amqp/receivedframe.h>
|
||||
#include <copernica/amqp/outbuffer.h>
|
||||
#include <copernica/amqp/watchable.h>
|
||||
#include <copernica/amqp/monitor.h>
|
||||
|
||||
// amqp types
|
||||
#include <copernica/amqp/field.h>
|
||||
#include <copernica/amqp/numericfield.h>
|
||||
#include <copernica/amqp/decimalfield.h>
|
||||
#include <copernica/amqp/stringfield.h>
|
||||
#include <copernica/amqp/booleanset.h>
|
||||
#include <copernica/amqp/fieldproxy.h>
|
||||
#include <copernica/amqp/table.h>
|
||||
#include <copernica/amqp/array.h>
|
||||
|
||||
// envelope for publishing and consuming
|
||||
#include <copernica/amqp/envelopefield.h>
|
||||
#include <copernica/amqp/envelope.h>
|
||||
|
||||
// mid level includes
|
||||
#include <copernica/amqp/exchangetype.h>
|
||||
#include <copernica/amqp/flags.h>
|
||||
#include <copernica/amqp/channelhandler.h>
|
||||
#include <copernica/amqp/channelimpl.h>
|
||||
#include <copernica/amqp/channel.h>
|
||||
#include <copernica/amqp/login.h>
|
||||
#include <copernica/amqp/connectionhandler.h>
|
||||
#include <copernica/amqp/connectionimpl.h>
|
||||
#include <copernica/amqp/connection.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/**
|
||||
* AMQP field array
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* AMQP field array
|
||||
*/
|
||||
class Array : public Field
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Definition of an array as a vector
|
||||
* @typedef
|
||||
*/
|
||||
typedef std::vector<std::shared_ptr<Field>> FieldArray;
|
||||
|
||||
/**
|
||||
* The actual fields
|
||||
* @var FieldArray
|
||||
*/
|
||||
FieldArray _fields;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor to construct an array from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
Array(ReceivedFrame &frame);
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
* @param array
|
||||
*/
|
||||
Array(const Array &array);
|
||||
|
||||
/**
|
||||
* Constructor for an empty Array
|
||||
*/
|
||||
Array() {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Array() {}
|
||||
|
||||
/**
|
||||
* Create a new instance of this object
|
||||
* @return Field*
|
||||
*/
|
||||
virtual Field *clone() const override
|
||||
{
|
||||
return new Array(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
* @return size_t
|
||||
*/
|
||||
virtual size_t size() const override;
|
||||
|
||||
/**
|
||||
* Set a field
|
||||
*
|
||||
* @param index field index
|
||||
* @param value field value
|
||||
* @return Array
|
||||
*/
|
||||
Array set(uint8_t index, const Field &value)
|
||||
{
|
||||
// copy to a new pointer and store it
|
||||
_fields[index] = std::shared_ptr<Field>(value.clone());
|
||||
|
||||
// allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a field
|
||||
*
|
||||
* If the field does not exist, an empty string is returned
|
||||
*
|
||||
* @param index field index
|
||||
* @return Field
|
||||
*/
|
||||
const Field &get(uint8_t index);
|
||||
|
||||
/**
|
||||
* Get a field
|
||||
*
|
||||
* @param index field index
|
||||
* @return ArrayFieldProxy
|
||||
*/
|
||||
ArrayFieldProxy operator[](uint8_t index)
|
||||
{
|
||||
return ArrayFieldProxy(this, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write encoded payload to the given buffer.
|
||||
* @param buffer
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override;
|
||||
|
||||
/**
|
||||
* Get the type ID that is used to identify this type of
|
||||
* field in a field table
|
||||
* @return char
|
||||
*/
|
||||
virtual char typeID() const override
|
||||
{
|
||||
return 'A';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* BooleanSet.h
|
||||
*
|
||||
* AMQP can store eight booleans in a single byte. This class
|
||||
* is a utility class for setting and getting the eight
|
||||
* booleans
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class BooleanSet : public Field
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The actual byte
|
||||
* @var uint8_t
|
||||
*/
|
||||
uint8_t _byte;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param first the first bool to set
|
||||
* @param second the second bool to set
|
||||
* @param third the third bool to set
|
||||
* @param fourth the fourth bool to set
|
||||
* @param fifth the fifth bool to set
|
||||
* @param sixth the sixth bool to set
|
||||
* @param seventh the seventh bool to set
|
||||
* @param eigth the eigth bool to set
|
||||
*/
|
||||
BooleanSet(bool first = false, bool second = false, bool third = false, bool fourth = false, bool fifth = false, bool sixth = false, bool seventh = false, bool eigth = false)
|
||||
{
|
||||
_byte = 0;
|
||||
set(0, first);
|
||||
set(1, second);
|
||||
set(2, third);
|
||||
set(3, fourth);
|
||||
set(4, fifth);
|
||||
set(5, sixth);
|
||||
set(6, seventh);
|
||||
set(7, eigth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
* @param frame
|
||||
*/
|
||||
BooleanSet(ReceivedFrame &frame)
|
||||
{
|
||||
_byte = frame.nextUint8();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
* @param that
|
||||
*/
|
||||
BooleanSet(const BooleanSet &that)
|
||||
{
|
||||
_byte = that._byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BooleanSet() {}
|
||||
|
||||
/**
|
||||
* Extending from field forces us to implement a clone function.
|
||||
* @return shared_ptr
|
||||
*/
|
||||
virtual Field *clone() const override
|
||||
{
|
||||
return new BooleanSet(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one of the booleans
|
||||
* @param index from 0 to 7, where 0 is rightmost bit
|
||||
* @return bool
|
||||
*/
|
||||
bool get(uint32_t index) const
|
||||
{
|
||||
// bigger than seven is not an option
|
||||
if (index > 7) return false;
|
||||
|
||||
// magic bit manipulation...
|
||||
return (bool)((1 << index) & _byte);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a boolean in the set
|
||||
* @param index
|
||||
* @param value
|
||||
*/
|
||||
void set(uint32_t index, bool value)
|
||||
{
|
||||
// index must be valid
|
||||
if (index > 7) return;
|
||||
|
||||
// are we setting or unsetting
|
||||
if (value)
|
||||
{
|
||||
// magic bit manipulation...
|
||||
_byte |= (1 << index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// magic bit manipulation...
|
||||
_byte &= ~(1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the buffer
|
||||
* @param buffer
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
buffer.add(_byte);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the byte value
|
||||
* @return value
|
||||
*/
|
||||
uint8_t value()
|
||||
{
|
||||
return _byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type ID
|
||||
* @return char
|
||||
*/
|
||||
virtual char typeID() const override
|
||||
{
|
||||
return 't';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
*/
|
||||
virtual size_t size() const override
|
||||
{
|
||||
// booleanset takes up a single byte.
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
/**
|
||||
* Class describing a (mid-level) AMQP channel implementation
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class Channel
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The implementation for the channel
|
||||
* @var ChannelImpl
|
||||
*/
|
||||
ChannelImpl _implementation;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a channel object
|
||||
* @param connection
|
||||
* @param handler
|
||||
*/
|
||||
Channel(Connection *connection, ChannelHandler *handler) : _implementation(this, connection, handler) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Channel() {}
|
||||
|
||||
/**
|
||||
* Pause deliveries on a channel
|
||||
*
|
||||
* This will stop all incoming messages
|
||||
*
|
||||
* This method returns true if the request to pause has been sent to the
|
||||
* broker. This does not necessarily mean that the channel is already
|
||||
* paused.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool pause()
|
||||
{
|
||||
return _implementation.pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume a paused channel
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool resume()
|
||||
{
|
||||
return _implementation.resume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the channel connected?
|
||||
* @return bool
|
||||
*/
|
||||
bool connected()
|
||||
{
|
||||
return _implementation.connected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool startTransaction()
|
||||
{
|
||||
return _implementation.startTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the current transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool commitTransaction()
|
||||
{
|
||||
return _implementation.commitTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the current transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool rollbackTransaction()
|
||||
{
|
||||
return _implementation.rollbackTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare an exchange
|
||||
*
|
||||
* If an empty name is supplied, a name will be assigned by the server.
|
||||
*
|
||||
* The following flags can be used for the exchange:
|
||||
*
|
||||
* - amqp_durable exchange survives a broker restart
|
||||
* - amqp_autodelete exchange is automatically removed when all connected queues are removed
|
||||
* - amqp_passive only check if the exchange exist
|
||||
*
|
||||
* @param name name of the exchange
|
||||
* @param type exchange type
|
||||
* @param flags exchange flags
|
||||
* @param arguments additional arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool declareExchange(const std::string &name, ExchangeType type, int flags, const Table &arguments) { return _implementation.declareExchange(name, type, flags, arguments); }
|
||||
bool declareExchange(const std::string &name, ExchangeType type, const Table &arguments) { return _implementation.declareExchange(name, type, 0, arguments); }
|
||||
bool declareExchange(const std::string &name, ExchangeType type = fanout, int flags = 0) { return _implementation.declareExchange(name, type, flags, Table()); }
|
||||
bool declareExchange(ExchangeType type, int flags, const Table &arguments) { return _implementation.declareExchange(std::string(), type, flags, arguments); }
|
||||
bool declareExchange(ExchangeType type, const Table &arguments) { return _implementation.declareExchange(std::string(), type, 0, arguments); }
|
||||
bool declareExchange(ExchangeType type = fanout, int flags = 0) { return _implementation.declareExchange(std::string(), type, flags, Table()); }
|
||||
|
||||
/**
|
||||
* Remove an exchange
|
||||
*
|
||||
* The following flags can be used for the exchange:
|
||||
*
|
||||
* - amqp_ifunused only delete if no queues are connected
|
||||
|
||||
* @param name name of the exchange to remove
|
||||
* @param flags optional flags
|
||||
* @return bool
|
||||
*/
|
||||
bool removeExchange(const std::string &name, int flags = 0) { return _implementation.removeExchange(name, flags); }
|
||||
|
||||
/**
|
||||
* Bind two exchanges to each other
|
||||
*
|
||||
* The following flags can be used for the exchange
|
||||
*
|
||||
* - amqp_nowait do not wait on response
|
||||
*
|
||||
* @param source the source exchange
|
||||
* @param target the target exchange
|
||||
* @param routingkey the routing key
|
||||
* @param flags optional flags
|
||||
* @param arguments additional bind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool bindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags, const Table &arguments) { return _implementation.bindExchange(source, target, routingkey, flags, arguments); }
|
||||
bool bindExchange(const std::string &source, const std::string &target, const std::string &routingkey, const Table &arguments) { return _implementation.bindExchange(source, target, routingkey, 0, arguments); }
|
||||
bool bindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags = 0) { return _implementation.bindExchange(source, target, routingkey, flags, Table()); }
|
||||
|
||||
/**
|
||||
* Unbind two exchanges from one another
|
||||
*
|
||||
* The following flags can be used for the exchange
|
||||
*
|
||||
* - amqp_nowait do not wait on response
|
||||
*
|
||||
* @param target the target exchange
|
||||
* @param source the source exchange
|
||||
* @param routingkey the routing key
|
||||
* @param flags optional flags
|
||||
* @param arguments additional unbind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool unbindExchange(const std::string &target, const std::string &source, const std::string &routingkey, int flags, const Table &arguments) { return _implementation.unbindExchange(target, source, routingkey, flags, arguments); }
|
||||
bool unbindExchange(const std::string &target, const std::string &source, const std::string &routingkey, const Table &arguments) { return _implementation.unbindExchange(target, source, routingkey, 0, arguments); }
|
||||
bool unbindExchange(const std::string &target, const std::string &source, const std::string &routingkey, int flags = 0) { return _implementation.unbindExchange(target, source, routingkey, flags, Table()); }
|
||||
|
||||
/**
|
||||
* Declare a queue
|
||||
*
|
||||
* If you do not supply a name, a name will be assigned by the server.
|
||||
*
|
||||
* The flags can be a combination of the following values:
|
||||
*
|
||||
* - amqp_durable queue survives a broker restart
|
||||
* - amqp_autodelete queue is automatically removed when all connected consumers are gone
|
||||
* - amqp_passive only check if the queue exist
|
||||
* - amqp_exclusive the queue only exists for this connection, and is automatically removed when connection is gone
|
||||
*
|
||||
* @param name name of the queue
|
||||
* @param flags combination of flags
|
||||
* @param arguments optional arguments
|
||||
*/
|
||||
bool declareQueue(const std::string &name, int flags, const Table &arguments) { return _implementation.declareQueue(name, flags, arguments); }
|
||||
bool declareQueue(const std::string &name, const Table &arguments) { return _implementation.declareQueue(name, 0, arguments); }
|
||||
bool declareQueue(const std::string &name, int flags = 0) { return _implementation.declareQueue(name, flags, Table()); }
|
||||
bool declareQueue(int flags, const Table &arguments) { return _implementation.declareQueue(std::string(), flags, arguments); }
|
||||
bool declareQueue(const Table &arguments) { return _implementation.declareQueue(std::string(), 0, arguments); }
|
||||
bool declareQueue(int flags = 0) { return _implementation.declareQueue(std::string(), flags, Table()); }
|
||||
|
||||
/**
|
||||
* Bind a queue to an exchange
|
||||
*
|
||||
* The following flags can be used for the exchange
|
||||
*
|
||||
* - amqp_noWait do not wait on response
|
||||
*
|
||||
* @param queue the target queue
|
||||
* @param exchange the source exchange
|
||||
* @param routingkey the routing key
|
||||
* @param flags additional flags
|
||||
* @param arguments additional bind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool bindQueue(const std::string &queue, const std::string &exchange, const std::string &routingkey, int flags, const Table &arguments) { return _implementation.bindQueue(exchange, queue, routingkey, flags, arguments); }
|
||||
bool bindQueue(const std::string &queue, const std::string &exchange, const std::string &routingkey, const Table &arguments) { return _implementation.bindQueue(exchange, queue, routingkey, 0, arguments); }
|
||||
bool bindQueue(const std::string &queue, const std::string &exchange, const std::string &routingkey, int flags = 0) { return _implementation.bindQueue(exchange, queue, routingkey, flags, Table()); }
|
||||
|
||||
/**
|
||||
* Unbind a queue from an exchange
|
||||
* @param queue the target queue
|
||||
* @param exchange the source exchange
|
||||
* @param routingkey the routing key
|
||||
* @param arguments additional bind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool unbindQueue(const std::string &queue, const std::string &exchange, const std::string &routingkey, const Table &arguments) { return _implementation.unbindQueue(exchange, queue, routingkey, arguments); }
|
||||
bool unbindQueue(const std::string &queue, const std::string &exchange, const std::string &routingkey) { return _implementation.unbindQueue(exchange, queue, routingkey, Table()); }
|
||||
|
||||
/**
|
||||
* Purge a queue
|
||||
*
|
||||
* The following flags can be used for the exchange
|
||||
*
|
||||
* - amqp_noWait do not wait on response
|
||||
*
|
||||
* @param name name of the queue
|
||||
* @param flags additional flags
|
||||
* @return bool
|
||||
*/
|
||||
bool purgeQueue(const std::string &name, int flags = 0){ return _implementation.purgeQueue(name, flags); }
|
||||
|
||||
/**
|
||||
* Remove a queue
|
||||
*
|
||||
* The following flags can be used for the exchange:
|
||||
*
|
||||
* - amqp_ifunused only delete if no consumers are connected
|
||||
* - amqp_ifempty only delete if the queue is empty
|
||||
*
|
||||
* @param name name of the queue to remove
|
||||
* @param flags optional flags
|
||||
* @return bool
|
||||
*/
|
||||
bool removeQueue(const std::string &name, int flags = 0) { return _implementation.removeQueue(name, flags); }
|
||||
|
||||
/**
|
||||
* Close the current channel
|
||||
* @return bool
|
||||
*/
|
||||
bool close()
|
||||
{
|
||||
return _implementation.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channel we're working on
|
||||
* @return uint16_t
|
||||
*/
|
||||
const uint16_t id() const
|
||||
{
|
||||
return _implementation.id();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* ChannelHandler.h
|
||||
*
|
||||
* Interface that should be implemented by a user of the AMQP library,
|
||||
* and that is passed to the Connection::createChannel() method.
|
||||
*
|
||||
* This interface contains a number of methods that are called when
|
||||
* the channel changes state.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ChannelHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Method that is called when the channel was succesfully created.
|
||||
* Only after the channel was created, you can use it for subsequent messages over it
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onReady(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* An error has occured on the channel
|
||||
* @param channel
|
||||
* @param message
|
||||
*/
|
||||
virtual void onChannelError(Channel *channel, const std::string &message) {}
|
||||
|
||||
/**
|
||||
* Method that is called when the channel was paused
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onPaused(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when the channel was resumed
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onResumed(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a channel is closed
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onClosed(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a transaction was started
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onTransactionStarted(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a transaction was committed
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onTransactionCommitted(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a transaction was rolled back
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onTransactionRolledBack(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when an exchange is bound
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onExchangeBound(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when an exchange is unbound
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onExchangeUnbound(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when an exchange is deleted
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onExchangeDeleted(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Mehod that is called when an exchange is declared
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onExchangeDeclared(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a queue is declared
|
||||
* @param channel
|
||||
* @param name name of the queue
|
||||
* @param messageCount number of messages in queue
|
||||
* @param consumerCount number of active consumers
|
||||
*/
|
||||
virtual void onQueueDeclared(Channel *channel, const std::string &name, uint32_t messageCount, uint32_t consumerCount) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a queue is bound
|
||||
* @param channel
|
||||
* @param
|
||||
*/
|
||||
virtual void onQueueBound(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a queue is deleted
|
||||
* @param channel
|
||||
* @param messageCount number of messages deleted along with the queue
|
||||
*/
|
||||
virtual void onQueueDeleted(Channel *channel, uint32_t messageCount) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a queue is unbound
|
||||
* @param channel
|
||||
*/
|
||||
virtual void onQueueUnbound(Channel *channel) {}
|
||||
|
||||
/**
|
||||
* Method that is called when a queue is purged
|
||||
* @param messageCount number of message purged
|
||||
*/
|
||||
virtual void onQueuePurged(Channel *channel, uint32_t messageCount) {}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,375 @@
|
|||
/**
|
||||
* ChannelImpl.h
|
||||
*
|
||||
* Extended channel object that is used internally by the library, but
|
||||
* that has a private constructor so that it can not be used from outside
|
||||
* the AMQP library
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ChannelImpl
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The actual channel object
|
||||
* @var Channel
|
||||
*/
|
||||
Channel *_parent;
|
||||
|
||||
/**
|
||||
* Pointer to the connection
|
||||
* @var Connection
|
||||
*/
|
||||
Connection *_connection;
|
||||
|
||||
/**
|
||||
* The handler that is notified about events
|
||||
* @var MyChannelHandler
|
||||
*/
|
||||
ChannelHandler *_handler;
|
||||
|
||||
/**
|
||||
* The channel number
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _id;
|
||||
|
||||
/**
|
||||
* State of the channel object
|
||||
* @var enum
|
||||
*/
|
||||
enum {
|
||||
state_connected,
|
||||
state_closed
|
||||
} _state = state_connected;
|
||||
|
||||
/**
|
||||
* Is a transaction now active?
|
||||
* @var bool
|
||||
*/
|
||||
bool _transaction = false;
|
||||
|
||||
/**
|
||||
* Construct a channel object
|
||||
*
|
||||
* Note that the constructor is private, and that the Channel class is
|
||||
* a friend. By doing this we ensure that nobody can instantiate this
|
||||
* object, and that it can thus only be used inside the library.
|
||||
*
|
||||
* @param parent the public channel object
|
||||
* @param connection pointer to the connection
|
||||
* @param handler handler that is notified on events
|
||||
*/
|
||||
ChannelImpl(Channel *parent, Connection *connection, ChannelHandler *handler = nullptr);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelImpl();
|
||||
|
||||
/**
|
||||
* Pause deliveries on a channel
|
||||
*
|
||||
* This will stop all incoming messages
|
||||
*
|
||||
* This method returns true if the request to pause has been sent to the
|
||||
* broker. This does not necessarily mean that the channel is already
|
||||
* paused.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool pause();
|
||||
|
||||
/**
|
||||
* Resume a paused channel
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool resume();
|
||||
|
||||
/**
|
||||
* Is the channel connected?
|
||||
* @return bool
|
||||
*/
|
||||
bool connected()
|
||||
{
|
||||
return _state == state_connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool startTransaction();
|
||||
|
||||
/**
|
||||
* Commit the current transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool commitTransaction();
|
||||
|
||||
/**
|
||||
* Rollback the current transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool rollbackTransaction();
|
||||
|
||||
/**
|
||||
* declare an exchange
|
||||
* @param name name of the exchange to declare
|
||||
* @param type type of exchange
|
||||
* @param flags additional settings for the exchange
|
||||
* @param arguments additional arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool declareExchange(const std::string &name, ExchangeType type, int flags, const Table &arguments);
|
||||
|
||||
/**
|
||||
* bind two exchanges
|
||||
* @param source exchange which binds to target
|
||||
* @param target exchange to bind to
|
||||
* @param routingKey routing key
|
||||
* @param glags additional flags
|
||||
* @param arguments additional arguments for binding
|
||||
* @return bool
|
||||
*/
|
||||
bool bindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags, const Table &arguments);
|
||||
|
||||
/**
|
||||
* unbind two exchanges
|
||||
* @param source the source exchange
|
||||
* @param target the target exchange
|
||||
* @param routingkey the routing key
|
||||
* @param flags optional flags
|
||||
* @param arguments additional unbind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool unbindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags, const Table &arguments);
|
||||
|
||||
/**
|
||||
* remove an exchange
|
||||
* @param name name of the exchange to remove
|
||||
* @param flags additional settings for deleting the exchange
|
||||
* @return bool
|
||||
*/
|
||||
bool removeExchange(const std::string &name, int flags);
|
||||
|
||||
/**
|
||||
* declare a queue
|
||||
* @param name queue name
|
||||
* @param flags additional settings for the queue
|
||||
* @param arguments additional arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool declareQueue(const std::string &name, int flags, const Table &arguments);
|
||||
|
||||
/**
|
||||
* Bind a queue to an exchange
|
||||
* @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
|
||||
* @return bool
|
||||
*/
|
||||
bool bindQueue(const std::string &exchangeName, const std::string &queueName, const std::string &routingkey, int flags, const Table &arguments);
|
||||
|
||||
/**
|
||||
* Unbind a queue from an exchange
|
||||
* @param exchange the source exchange
|
||||
* @param queue the target queue
|
||||
* @param routingkey the routing key
|
||||
* @param arguments additional bind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool unbindQueue(const std::string &exchangeName, const std::string &queueName, const std::string &routingkey, const Table &arguments);
|
||||
|
||||
/**
|
||||
* Purge a queue
|
||||
* @param queue queue to purge
|
||||
* @param flags additional flags
|
||||
* @return bool
|
||||
*/
|
||||
bool purgeQueue(const std::string &name, int flags);
|
||||
|
||||
/**
|
||||
* Remove a queue
|
||||
* @param queue queue to remove
|
||||
* @param flags additional flags
|
||||
* @return bool
|
||||
*/
|
||||
bool removeQueue(const std::string &name, int flags);
|
||||
|
||||
/**
|
||||
* Close the current channel
|
||||
* @return bool
|
||||
*/
|
||||
bool close();
|
||||
|
||||
/**
|
||||
* Get the channel we're working on
|
||||
* @return uint16_t
|
||||
*/
|
||||
const uint16_t id() const
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a frame over the channel
|
||||
* @param frame frame to send
|
||||
* @return size_t number of bytes sent
|
||||
*/
|
||||
size_t send(const Frame &frame);
|
||||
|
||||
/**
|
||||
* Report to the handler that the channel is closed
|
||||
*/
|
||||
void reportClosed()
|
||||
{
|
||||
// change state
|
||||
_state = state_closed;
|
||||
|
||||
// inform handler
|
||||
if (_handler) _handler->onClosed(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report to the handler that the channel is paused
|
||||
*/
|
||||
void reportPaused()
|
||||
{
|
||||
// inform handler
|
||||
if (_handler) _handler->onPaused(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report to the handler that the channel is resumed
|
||||
*/
|
||||
void reportResumed()
|
||||
{
|
||||
// inform handler
|
||||
if (_handler) _handler->onResumed(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report to the handler that the channel is opened
|
||||
*/
|
||||
void reportReady()
|
||||
{
|
||||
// inform handler
|
||||
if (_handler) _handler->onReady(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an error message on a channel
|
||||
* @param message
|
||||
*/
|
||||
void reportChannelError(const std::string &message)
|
||||
{
|
||||
// change state
|
||||
_state = state_closed;
|
||||
|
||||
// inform handler
|
||||
if (_handler) _handler->onChannelError(_parent, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that the exchange is succesfully declared
|
||||
*/
|
||||
void reportExchangeDeclared()
|
||||
{
|
||||
if(_handler) _handler->onExchangeDeclared(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that the exchange is succesfully deleted
|
||||
*/
|
||||
void reportExchangeDeleted()
|
||||
{
|
||||
if(_handler) _handler->onExchangeDeleted(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that the exchange is bound
|
||||
*/
|
||||
void reportExchangeBound()
|
||||
{
|
||||
if(_handler) _handler->onExchangeBound(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that the exchange is unbound
|
||||
*/
|
||||
void reportExchangeUnbound()
|
||||
{
|
||||
if(_handler) _handler->onExchangeUnbound(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that the queue was succesfully declared
|
||||
* @param queueName name of the queue which was declared
|
||||
* @param messagecount number of messages currently in the queue
|
||||
* @param consumerCount number of active consumers in the queue
|
||||
*/
|
||||
void reportQueueDeclared(const std::string &queueName, uint32_t messageCount, uint32_t consumerCount)
|
||||
{
|
||||
if(_handler) _handler->onQueueDeclared(_parent, queueName, messageCount, consumerCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that a queue was succesfully bound
|
||||
*/
|
||||
void reportQueueBound()
|
||||
{
|
||||
if(_handler) _handler->onQueueBound(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that a queue was succesfully unbound
|
||||
*/
|
||||
void reportQueueUnbound()
|
||||
{
|
||||
if(_handler) _handler->onQueueUnbound(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that a queue was succesfully deleted
|
||||
* @param messageCount number of messages left in queue, now deleted
|
||||
*/
|
||||
void reportQueueDeleted(uint32_t messageCount)
|
||||
{
|
||||
if(_handler) _handler->onQueueDeleted(_parent, messageCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that a queue was succesfully purged
|
||||
* @param messageCount number of messages purged
|
||||
*/
|
||||
void reportQueuePurged(uint32_t messageCount)
|
||||
{
|
||||
if(_handler) _handler->onQueuePurged(_parent, messageCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel class is its friend, thus can it instantiate this object
|
||||
*/
|
||||
friend class Channel;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Classes.h
|
||||
*
|
||||
* List of all declared classes
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* All classes defined by this library
|
||||
*/
|
||||
class Array;
|
||||
class Channel;
|
||||
class Connection;
|
||||
class ConnectionHandler;
|
||||
class ConnectionImpl;
|
||||
class Exchange;
|
||||
class Frame;
|
||||
class Login;
|
||||
class Monitor;
|
||||
class OutBuffer;
|
||||
class ReceivedFrame;
|
||||
class Table;
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Class describing a mid-level Amqp connection
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class Connection
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The actual implementation
|
||||
* @var ConnectionImpl
|
||||
*/
|
||||
ConnectionImpl _implementation;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct an AMQP object based on full login data
|
||||
*
|
||||
* The first parameter is a handler object. This handler class is
|
||||
* an interface that should be implemented by the caller.
|
||||
*
|
||||
* @param handler Connection handler
|
||||
* @param login Login data
|
||||
*/
|
||||
Connection(ConnectionHandler *handler, const Login &login) : _implementation(this, handler, login) {}
|
||||
|
||||
/**
|
||||
* Construct an AMQP object with default login data
|
||||
* @param handler Connection handler
|
||||
*/
|
||||
Connection(ConnectionHandler *handler) : _implementation(this, handler) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Connection() {}
|
||||
|
||||
/**
|
||||
* Parse the buffer into a recognized frame
|
||||
*
|
||||
* Every time that data comes in on the connection, you should call this method to parse
|
||||
* the incoming data, and let it handle by the AMQP library. This method returns the number
|
||||
* of bytes that were processed.
|
||||
*
|
||||
* If not all bytes could be processed because it only contained a partial frame, you should
|
||||
* call this same method later on when more data is available. The AMQP library does not do
|
||||
* any buffering, so it is up to the caller to ensure that the old data is also passed in that
|
||||
* later call.
|
||||
*
|
||||
* @param buffer buffer to decode
|
||||
* @param size size of the buffer to decode
|
||||
* @return number of bytes that were processed
|
||||
*/
|
||||
size_t parse(char *buffer, size_t size)
|
||||
{
|
||||
return _implementation.parse(buffer, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the connection
|
||||
* This will close all channels
|
||||
* @return bool
|
||||
*/
|
||||
bool close()
|
||||
{
|
||||
return _implementation.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Quality of Service (QOS) of the entire connection
|
||||
* @param prefetchSize maximum size (in octets) of messages to be prefetched
|
||||
* @param prefetchCount maximum number of messages to prefetch
|
||||
* @return bool whether the Qos frame is sent.
|
||||
*/
|
||||
bool setQos(uint32_t prefetchSize, uint16_t prefetchCount)
|
||||
{
|
||||
return _implementation.setQos(prefetchSize, prefetchCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some classes have access to private properties
|
||||
*/
|
||||
friend class ChannelImpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* ConnectionHandler.h
|
||||
*
|
||||
* Interface that should be implemented by the caller of the library and
|
||||
* that is passed to the AMQP connection. This interface contains all sorts
|
||||
* of methods that are called when data needs to be sent, or when the
|
||||
* AMQP connection ends up in a broken state.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ConnectionHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Method that is called when data needs to be sent over the network
|
||||
*
|
||||
* Note that the AMQP library does no buffering by itself. This means
|
||||
* that this method should always send out all data or do the buffering
|
||||
* itself.
|
||||
*
|
||||
* @param connection The connection that created this output
|
||||
* @param buffer Data to send
|
||||
* @param size Size of the buffer
|
||||
*/
|
||||
virtual void onData(Connection *connection, const char *buffer, size_t size) = 0;
|
||||
|
||||
/**
|
||||
* When the connection ends up in an error state this method is called.
|
||||
* This happens when data comes in that does not match the AMQP protocol
|
||||
*
|
||||
* After this method is called, the connection no longer is in a valid
|
||||
* state and can be used. In normal circumstances this method is not called.
|
||||
*
|
||||
* @todo do we need this method, or only in the ChannelHandler class?
|
||||
*
|
||||
* @param connection The connection that entered the error state
|
||||
* @param message Error message
|
||||
*/
|
||||
virtual void onConnectionError(Connection *connection, const std::string &message) = 0;
|
||||
|
||||
/**
|
||||
* Method that is called when the login attempt succeeded. After this method
|
||||
* was called, the connection is ready to use
|
||||
*
|
||||
* @param connection The connection that can now be used
|
||||
*/
|
||||
virtual void onConnected(Connection *connection) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
/**
|
||||
* Connection implementation
|
||||
*
|
||||
* This is the implementation of the connection - a class that can only be
|
||||
* constructed by the connection class itselves and that has all sorts of
|
||||
* methods that are only useful inside the library
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ConnectionImpl : public Watchable
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* The parent connection object
|
||||
* @var Connection
|
||||
*/
|
||||
Connection *_parent;
|
||||
|
||||
/**
|
||||
* The connection handler
|
||||
* @var ConnectionHandler
|
||||
*/
|
||||
ConnectionHandler *_handler;
|
||||
|
||||
/**
|
||||
* State of the connection
|
||||
* The current state is the last frame sent to the server
|
||||
* @var enum
|
||||
*/
|
||||
enum {
|
||||
state_invalid, // object is in an invalid state
|
||||
state_protocol, // protocol headers are being passed
|
||||
state_handshake, // busy with the handshake to open the connection
|
||||
state_connected, // connection is set up and ready for communication
|
||||
state_closed // connection is closed
|
||||
} _state = state_protocol;
|
||||
|
||||
/**
|
||||
* All channels that are active
|
||||
* @var map
|
||||
*/
|
||||
std::map<uint16_t, ChannelImpl*> _channels;
|
||||
|
||||
/**
|
||||
* The last unused channel ID
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _nextFreeChannel = 1;
|
||||
|
||||
/**
|
||||
* Max number of channels (0 for unlimited)
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _maxChannels = 0;
|
||||
|
||||
/**
|
||||
* Max frame size
|
||||
* @var uint32_t
|
||||
*/
|
||||
uint32_t _maxFrame = 10000;
|
||||
|
||||
/**
|
||||
* The address of the server (vhost, login, password)
|
||||
* @var Address
|
||||
*/
|
||||
Login _login;
|
||||
|
||||
/**
|
||||
* Initialize the connection
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Construct an AMQP object based on full login data
|
||||
*
|
||||
* The first parameter is a handler object. This handler class is
|
||||
* an interface that should be implemented by the caller.
|
||||
*
|
||||
* Note that the constructor is private to ensure that nobody can construct
|
||||
* this class, only the real Connection class via a friend construct
|
||||
*
|
||||
* @param parent Parent connection object
|
||||
* @param handler Connection handler
|
||||
* @param login Login data
|
||||
*/
|
||||
ConnectionImpl(Connection *parent, ConnectionHandler *handler, const Login &login) :
|
||||
_parent(parent), _handler(handler), _login(login)
|
||||
{
|
||||
// initialize the connection
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an AMQP object with default login data
|
||||
*
|
||||
* Note that the constructor is private to ensure that nobody can construct
|
||||
* this class, only the real Connection class via a friend construct
|
||||
*
|
||||
* @param parent Parent connection object
|
||||
* @param handler Connection handler
|
||||
*/
|
||||
ConnectionImpl(Connection *parent, ConnectionHandler *handler) :
|
||||
_parent(parent), _handler(handler)
|
||||
{
|
||||
// initialize the connection
|
||||
initialize();
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionImpl();
|
||||
|
||||
/**
|
||||
* What is the state of the connection - is the protocol handshake completed?
|
||||
* @return bool
|
||||
*/
|
||||
bool protocolOk()
|
||||
{
|
||||
// must be busy doing the connection handshake, or already connected
|
||||
return _state == state_handshake || _state == state_connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the protocol as being ok
|
||||
*/
|
||||
void setProtocolOk()
|
||||
{
|
||||
// move on to handshake state
|
||||
if (_state == state_protocol) _state = state_handshake;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we fully connected?
|
||||
* @return bool
|
||||
*/
|
||||
bool connected()
|
||||
{
|
||||
// state must be connected
|
||||
return _state == state_connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the connection as connected
|
||||
*/
|
||||
void setConnected()
|
||||
{
|
||||
// store connected state
|
||||
_state = state_connected;
|
||||
|
||||
// inform handler
|
||||
_handler->onConnected(_parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the login data
|
||||
* @return Login
|
||||
*/
|
||||
Login &login()
|
||||
{
|
||||
return _login;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the max number of channels and max number of frames
|
||||
* @param channels max number of channels
|
||||
* @param size max frame size
|
||||
*/
|
||||
void setCapacity(uint16_t channels, uint32_t size)
|
||||
{
|
||||
_maxChannels = channels;
|
||||
_maxFrame = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a channel to the connection, and return the channel ID that it
|
||||
* is allowed to use, or 0 when no more ID's are available
|
||||
* @param channel
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t add(ChannelImpl *channel);
|
||||
|
||||
/**
|
||||
* Remove a channel
|
||||
* @param channel
|
||||
*/
|
||||
void remove(ChannelImpl *channel);
|
||||
|
||||
/**
|
||||
* Parse the buffer into a recognized frame
|
||||
*
|
||||
* Every time that data comes in on the connection, you should call this method to parse
|
||||
* the incoming data, and let it handle by the AMQP library. This method returns the number
|
||||
* of bytes that were processed.
|
||||
*
|
||||
* If not all bytes could be processed because it only contained a partial frame, you should
|
||||
* call this same method later on when more data is available. The AMQP library does not do
|
||||
* any buffering, so it is up to the caller to ensure that the old data is also passed in that
|
||||
* later call.
|
||||
*
|
||||
* @param buffer buffer to decode
|
||||
* @param size size of the buffer to decode
|
||||
* @return number of bytes that were processed
|
||||
*/
|
||||
size_t parse(char *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* Close the connection
|
||||
* This will close all channels
|
||||
* @return bool
|
||||
*/
|
||||
bool close();
|
||||
|
||||
/**
|
||||
* Send a frame over the connection
|
||||
*
|
||||
* This is an internal method that you normally do not have to call yourself
|
||||
*
|
||||
* @param frame the frame to send
|
||||
* @return number of bytes sent
|
||||
*/
|
||||
size_t send(const Frame &frame);
|
||||
|
||||
/**
|
||||
* Get a channel by its identifier
|
||||
*
|
||||
* This method only works if you had already created the channel before.
|
||||
* This is an internal method that you will not need if you cache the channel
|
||||
* object.
|
||||
*
|
||||
* @param number channel identifier
|
||||
* @return channel the channel object, or nullptr if not yet created
|
||||
*/
|
||||
ChannelImpl *channel(int number)
|
||||
{
|
||||
auto iter = _channels.find(number);
|
||||
return iter == _channels.end() ? nullptr : iter->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an error message
|
||||
* @param message
|
||||
*/
|
||||
void reportConnectionError(const std::string &message)
|
||||
{
|
||||
// close everything
|
||||
close();
|
||||
|
||||
// set connection state to closed
|
||||
_state = state_closed;
|
||||
|
||||
// inform handler
|
||||
_handler->onConnectionError(_parent, message);
|
||||
|
||||
// @Todo: notify all channels of closed connection
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Quality of Service (QOS) of the entire connection
|
||||
* @param prefetchSize maximum size (in octets) of messages to be prefetched
|
||||
* @param prefetchCount maximum number of messages to prefetch
|
||||
* @return bool whether the Qos frame is sent.
|
||||
*/
|
||||
bool setQos(uint32_t prefetchSize, uint16_t prefetchCount);
|
||||
|
||||
/**
|
||||
* The actual connection is a friend and can construct this class
|
||||
*/
|
||||
friend class Connection;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
/**
|
||||
* Decimal field type for AMQP
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class DecimalField : public Field
|
||||
{
|
||||
/**
|
||||
* To preserve precision the decision is made to work with the places and number.
|
||||
* These values are sent in the framedata, so no precision will be lost.
|
||||
* Other options, such as floats, doubles, Decimal32 etc result in loss of precision
|
||||
* and this is something which is not acceptable.
|
||||
*
|
||||
* Only (in)equality and assignment operators are implemented since the decimalfield
|
||||
* is not supposed to be altered.
|
||||
* e.q. ==, != and =
|
||||
*
|
||||
* When requesting the value of this object there are 3 choices;
|
||||
* float, double or DecimalField
|
||||
* e.g. valueFloat(), valueDouble() and value()
|
||||
*/
|
||||
private:
|
||||
/**
|
||||
* The number of places, which means the number of decimals
|
||||
* e.g. number = 1234, places = 2, true value is 12.34
|
||||
*/
|
||||
uint8_t _places;
|
||||
|
||||
/**
|
||||
* The number without the decimals
|
||||
*/
|
||||
uint32_t _number;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Write encoded payload to the given buffer.
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// encode fields
|
||||
buffer.add(_places);
|
||||
buffer.add(_number);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct decimal field
|
||||
*
|
||||
* @param places the number of places
|
||||
* @param number the integer number
|
||||
*/
|
||||
DecimalField(uint8_t places = 0, uint32_t number = 0) :
|
||||
_places(places),
|
||||
_number(number)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct based on incoming data
|
||||
* @param frame
|
||||
*/
|
||||
DecimalField(ReceivedFrame &frame)
|
||||
{
|
||||
_places = frame.nextUint8();
|
||||
_number = frame.nextUint32();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~DecimalField() {}
|
||||
|
||||
/**
|
||||
* Create a new identical instance of this object
|
||||
* @return Field*
|
||||
*/
|
||||
virtual Field *clone() const override
|
||||
{
|
||||
return new DecimalField(_places, _number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a new value
|
||||
*
|
||||
* @param value new value for field
|
||||
* @return DecimalField
|
||||
*/
|
||||
DecimalField& operator=(const DecimalField& value)
|
||||
{
|
||||
// if it's the same object, skip assignment and just return *this
|
||||
if (this == &value) return *this;
|
||||
|
||||
// not the same object, copy values to this object.
|
||||
_places = value._places;
|
||||
_number = value._number;
|
||||
|
||||
// allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts decimalfield to double
|
||||
* e.g. "double x = decimalfield" will work
|
||||
*
|
||||
* @return double value of decimalfield in double format
|
||||
*/
|
||||
operator double() const
|
||||
{
|
||||
return _number / pow(10, _places);
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts decimalfield to float
|
||||
* e.g. "float x = decimalfield" will work
|
||||
*
|
||||
* @return float value of decimalfield in float format
|
||||
*/
|
||||
operator float() const
|
||||
{
|
||||
return _number / pow(10, _places);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for equality between this and another DecimalField
|
||||
*
|
||||
* @param value value to be checked for equality
|
||||
* @return boolean whether values are equal
|
||||
*/
|
||||
bool operator==(const DecimalField& value) const
|
||||
{
|
||||
// check if everything is the same
|
||||
// precision is taken into account, e.q. 1.0 != 1.00
|
||||
// meaning number:10, places:1 is not equal to number:100, places:2
|
||||
return _number == value.number() && _places == value.places();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for inequality between this and another DecimalField
|
||||
*
|
||||
* @param value value to be checked for inequality
|
||||
* @return boolean whether values are inequal
|
||||
*/
|
||||
bool operator!=(const DecimalField& value) const
|
||||
{
|
||||
return !(*this == value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
*/
|
||||
virtual size_t size() const override
|
||||
{
|
||||
// the sum of all fields
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of places
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t places() const
|
||||
{
|
||||
return _places;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number without decimals
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t number() const
|
||||
{
|
||||
return _number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DecimalField
|
||||
* To preserve precision DecimalField is returned, containing the number and places.
|
||||
* @return return DecimalField
|
||||
*/
|
||||
DecimalField value() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type ID that is used to identify this type of
|
||||
* field in a field table
|
||||
*/
|
||||
virtual char typeID() const override
|
||||
{
|
||||
return 'D';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* EntityImpl.h
|
||||
*
|
||||
* Common base class for exchanges and queues.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class EntityImpl
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* The channel on which we communicate
|
||||
* @var Channel
|
||||
*/
|
||||
Channel *_channel;
|
||||
|
||||
/**
|
||||
* Name of the queue/exchange
|
||||
* @var string
|
||||
*/
|
||||
std::string _name;
|
||||
|
||||
/**
|
||||
* Is this a durable queue/exchange?
|
||||
* A durable queue/exchange survives a broker restart
|
||||
* @var bool
|
||||
*/
|
||||
bool _durable = false;
|
||||
|
||||
/**
|
||||
* Is this a passive queue/exchange?
|
||||
* If set, only check if the queue/exchange exists without actually creating it
|
||||
* @var bool
|
||||
*/
|
||||
bool _passive = false;
|
||||
|
||||
/**
|
||||
* Is this an auto-delete queue/exchange?
|
||||
* If set, the entity is removed when it is no longer used (for queues
|
||||
* when all consumers are gone, for exchanges when all queues are gone)
|
||||
* @var bool
|
||||
*/
|
||||
bool _autoDelete = false;
|
||||
|
||||
/**
|
||||
* Additional arguments
|
||||
* @var Table
|
||||
*/
|
||||
Table _arguments;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor is protected and can only be accessed by derived classes
|
||||
* @param channel
|
||||
*/
|
||||
EntityImpl(Channel *channel) : _channel(channel) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~EntityImpl();
|
||||
|
||||
/**
|
||||
* Retrieve the name
|
||||
* @return string
|
||||
*/
|
||||
std::string &name()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the name
|
||||
* You must declare the entity before this has effect
|
||||
* @param string
|
||||
*/
|
||||
void setName(const std::string &name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the queue or exchange durable
|
||||
* The entity survives a broker restart if it is durable
|
||||
* @return bool
|
||||
*/
|
||||
bool durable()
|
||||
{
|
||||
return _durable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the object as durable
|
||||
* @param bool
|
||||
*/
|
||||
void setDurable(bool durable)
|
||||
{
|
||||
_durable = durable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the passive bit set
|
||||
* If set, the declare method only checks if the queue/exchange exists without actually creating it
|
||||
* @return bool
|
||||
*/
|
||||
bool passive()
|
||||
{
|
||||
return _passive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the passive bit
|
||||
* @param bool
|
||||
*/
|
||||
void setPassive(bool passive)
|
||||
{
|
||||
_passive = passive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the auto-delete property set?
|
||||
* The entity is removed when the consumers and/or queues are unlinked from it
|
||||
* @return bool
|
||||
*/
|
||||
bool autoDelete()
|
||||
{
|
||||
return _autoDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the auto-delete bit
|
||||
* @param bool
|
||||
*/
|
||||
void setAutoDelete(bool autoDelete)
|
||||
{
|
||||
_autoDelete = autoDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom argument
|
||||
* @param name Name of the argument
|
||||
* @param value Value of the argument
|
||||
*/
|
||||
void setArgument(const std::string &name, const std::string &value)
|
||||
{
|
||||
_arguments[name] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a argument
|
||||
* @param name Name of the argument
|
||||
* @return The value of the argument
|
||||
*/
|
||||
std::string &argument(const std::string &name)
|
||||
{
|
||||
return _arguments[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to a different exchange
|
||||
* @param exchange The exchange to bind to
|
||||
* @param key The routing key
|
||||
* @return bool
|
||||
*/
|
||||
virtual bool bind(const std::string &exchange, const std::string &key) = 0;
|
||||
|
||||
/**
|
||||
* Unbind from an exchange
|
||||
* @param exchange Exchange to unbind from
|
||||
* @param key The routing key
|
||||
* @return bool
|
||||
*/
|
||||
virtual bool unbind(const std::string &exchange, const std::string &key) = 0;
|
||||
|
||||
/**
|
||||
* Declare the queue/exchange
|
||||
* @return bool
|
||||
*/
|
||||
virtual bool declare() = 0;
|
||||
|
||||
/**
|
||||
* Remove the queue/exchange
|
||||
* @return bool
|
||||
*/
|
||||
virtual bool remove() = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
/**
|
||||
* Envelope.h
|
||||
*
|
||||
* When you send or receive a message to the rabbitMQ server, it is encapsulated
|
||||
* in an envelope that contains additional meta information as well.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class Envelope
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Pointer to the body data (the memory buffer is not managed by the AMQP
|
||||
* library!)
|
||||
* @var const char *
|
||||
*/
|
||||
const char *_data;
|
||||
|
||||
/**
|
||||
* Size of the data
|
||||
* @var size_t
|
||||
*/
|
||||
size_t _size;
|
||||
|
||||
/**
|
||||
* The content type
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _contentType;
|
||||
|
||||
/**
|
||||
* The content encoding
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _contentEncoding;
|
||||
|
||||
/**
|
||||
* The priority
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<uint8_t> _priority;
|
||||
|
||||
/**
|
||||
* The delivery mode (1=non-persistent, 2=persistent)
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<uint8_t> _deliveryMode;
|
||||
|
||||
/**
|
||||
* The correlation ID
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _correlationID;
|
||||
|
||||
/**
|
||||
* Reply-to field
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _replyTo;
|
||||
|
||||
/**
|
||||
* Expiration value
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _expiration;
|
||||
|
||||
/**
|
||||
* The message id
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _messageID;
|
||||
|
||||
/**
|
||||
* Timestamp
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<uint64_t> _timestamp;
|
||||
|
||||
/**
|
||||
* The type name
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _typeName;
|
||||
|
||||
/**
|
||||
* The user ID
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _userID;
|
||||
|
||||
/**
|
||||
* The application ID
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<std::string> _appID;
|
||||
|
||||
/**
|
||||
* Additional custom headers
|
||||
* @var EnvelopeField
|
||||
*/
|
||||
EnvelopeField<Table> _headers;
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* The data buffer that you pass to this constructor must be valid during
|
||||
* the lifetime of the Envelope object.
|
||||
*
|
||||
* @param data
|
||||
* @param size
|
||||
*/
|
||||
Envelope(const char *data, size_t size) : _data(data), _size(size) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Envelope() {}
|
||||
|
||||
/**
|
||||
* Access to the full message data
|
||||
* @return buffer
|
||||
*/
|
||||
const char *body()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the body
|
||||
* @return size_t
|
||||
*/
|
||||
size_t size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a certain field is set
|
||||
* @return bool
|
||||
*/
|
||||
bool hasPriority () { return _priority.valid(); }
|
||||
bool hasDeliveryMode () { return _deliveryMode.valid(); }
|
||||
bool hasTimestamp () { return _timestamp.valid(); }
|
||||
bool hasContentType () { return _contentType.valid(); }
|
||||
bool hasContentEncoding () { return _contentEncoding.valid(); }
|
||||
bool hasCorrelationID () { return _correlationID.valid(); }
|
||||
bool hasReplyTo () { return _replyTo.valid(); }
|
||||
bool hasExpiration () { return _expiration.valid(); }
|
||||
bool hasMessageID () { return _messageID.valid(); }
|
||||
bool hasTypeName () { return _typeName.valid(); }
|
||||
bool hasUserID () { return _userID.valid(); }
|
||||
bool hasAppID () { return _appID.valid(); }
|
||||
bool hasHeaders () { return _headers.valid(); }
|
||||
|
||||
/**
|
||||
* Set the various supported fields
|
||||
* @param value
|
||||
*/
|
||||
void setPriority (uint8_t value) { _priority = value; }
|
||||
void setDeliveryMode (uint8_t value) { _deliveryMode = value; }
|
||||
void setTimestamp (uint64_t value) { _timestamp = value; }
|
||||
void setContentType (const std::string &value) { _contentType = value; }
|
||||
void setContentEncoding (const std::string &value) { _contentEncoding = value; }
|
||||
void setCorrelationID (const std::string &value) { _correlationID = value; }
|
||||
void setReplyTo (const std::string &value) { _replyTo = value; }
|
||||
void setExpiration (const std::string &value) { _expiration = value; }
|
||||
void setMessageID (const std::string &value) { _messageID = value; }
|
||||
void setTypeName (const std::string &value) { _typeName = value; }
|
||||
void setUserID (const std::string &value) { _userID = value; }
|
||||
void setAppID (const std::string &value) { _appID = value; }
|
||||
void setHeaders (const Table &value) { _headers = value; }
|
||||
|
||||
/**
|
||||
* Reset the various supported fields
|
||||
* @param value
|
||||
*/
|
||||
void setPriority (nullptr_t value = nullptr) { _priority = value; }
|
||||
void setDeliveryMode (nullptr_t value = nullptr) { _deliveryMode = value; }
|
||||
void setTimestamp (nullptr_t value = nullptr) { _timestamp = value; }
|
||||
void setContentType (nullptr_t value = nullptr) { _contentType = value; }
|
||||
void setContentEncoding (nullptr_t value = nullptr) { _contentEncoding = value; }
|
||||
void setCorrelationID (nullptr_t value = nullptr) { _correlationID = value; }
|
||||
void setReplyTo (nullptr_t value = nullptr) { _replyTo = value; }
|
||||
void setExpiration (nullptr_t value = nullptr) { _expiration = value; }
|
||||
void setMessageID (nullptr_t value = nullptr) { _messageID = value; }
|
||||
void setTypeName (nullptr_t value = nullptr) { _typeName = value; }
|
||||
void setUserID (nullptr_t value = nullptr) { _userID = value; }
|
||||
void setAppID (nullptr_t value = nullptr) { _appID = value; }
|
||||
void setHeaders (nullptr_t value = nullptr) { _headers = value; }
|
||||
|
||||
/**
|
||||
* Retrieve the fields
|
||||
* @return string
|
||||
*/
|
||||
uint8_t priority () { return _priority; }
|
||||
uint8_t deliveryMode () { return _deliveryMode; }
|
||||
uint64_t timestamp () { return _timestamp; }
|
||||
std::string &contentType () { return _contentType; }
|
||||
std::string &contentEncoding() { return _contentEncoding; }
|
||||
std::string &correlationID () { return _correlationID; }
|
||||
std::string &replyTo () { return _replyTo; }
|
||||
std::string &expiration () { return _expiration; }
|
||||
std::string &messageID () { return _messageID; }
|
||||
std::string &typeName () { return _typeName; }
|
||||
std::string &userID () { return _userID; }
|
||||
std::string &appID () { return _appID; }
|
||||
Table &headers () { return _headers; }
|
||||
|
||||
/**
|
||||
* Is this a message with persistent storage
|
||||
* This is an alias for retrieving the delivery mode and checking if it is set to 2
|
||||
* @return bool
|
||||
*/
|
||||
bool persistent()
|
||||
{
|
||||
return hasDeliveryMode() && deliveryMode() == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether storage should be persistent or not
|
||||
* @param bool
|
||||
*/
|
||||
void setPersistent(bool value = true)
|
||||
{
|
||||
if (value) setDeliveryMode(2);
|
||||
else setDeliveryMode(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* EnvelopeField.h
|
||||
*
|
||||
* An envelope field is a field that also keeps track whether it is set
|
||||
* or not. Used internally by the Envelope class.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
template <typename T>
|
||||
class EnvelopeField
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The actual value
|
||||
* @var T
|
||||
*/
|
||||
T _value;
|
||||
|
||||
/**
|
||||
* Is it set or not
|
||||
* @var bool
|
||||
*/
|
||||
bool _isset;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Empty constructor
|
||||
*/
|
||||
EnvelopeField() : _isset(false) {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param value
|
||||
* @param isset
|
||||
*/
|
||||
EnvelopeField(const T &value, bool isset = true) : _value(value), _isset(isset) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~EnvelopeField() {}
|
||||
|
||||
/**
|
||||
* Assign a new value
|
||||
* @param value
|
||||
* @return EnvelopeField
|
||||
*/
|
||||
EnvelopeField &operator=(const T &value)
|
||||
{
|
||||
_value = value;
|
||||
_isset = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the value
|
||||
* @param value
|
||||
* @return EnvelopeField
|
||||
*/
|
||||
EnvelopeField &operator=(nullptr_t value)
|
||||
{
|
||||
_value = T();
|
||||
_isset = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast to the set value
|
||||
* @return T
|
||||
*/
|
||||
operator T& ()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the value to not being set
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
_isset = false;
|
||||
_value = T();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it set?
|
||||
* @return bool
|
||||
*/
|
||||
bool valid()
|
||||
{
|
||||
return _isset;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* ExchangeType.h
|
||||
*
|
||||
* The various exchange types that are supported
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* The class
|
||||
*/
|
||||
enum ExchangeType
|
||||
{
|
||||
fanout,
|
||||
direct,
|
||||
topic,
|
||||
headers
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Available field types for AMQP
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Base field class
|
||||
*
|
||||
* This class cannot be constructed, but serves
|
||||
* as the base class for all AMQP field types
|
||||
*/
|
||||
class Field
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Decode a field by fetching a type and full field from a frame
|
||||
* The returned field is allocated on the heap!
|
||||
* @param frame
|
||||
* @return Field*
|
||||
*/
|
||||
static Field *decode(ReceivedFrame &frame);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Field() {}
|
||||
|
||||
/**
|
||||
* Create a new instance on the heap of this object, identical to the object passed
|
||||
* @return Field*
|
||||
*/
|
||||
virtual Field *clone() const = 0;
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
* @return size_t
|
||||
*/
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
/**
|
||||
* Write encoded payload to the given buffer.
|
||||
* @param buffer
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const = 0;
|
||||
|
||||
/**
|
||||
* Get the type ID that is used to identify this type of
|
||||
* field in a field table
|
||||
* @return char
|
||||
*
|
||||
* @todo check if all derived classes use the 'override' keyword
|
||||
*/
|
||||
virtual char typeID() const = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,402 @@
|
|||
/**
|
||||
* Field proxy. Returned by the table. Can be casted to the
|
||||
* relevant native type (std::string or numeric)
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
template <typename T, typename I>
|
||||
class FieldProxy
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The table or array possibly holding the requested field
|
||||
*/
|
||||
T *_source;
|
||||
|
||||
/**
|
||||
* The key in the table
|
||||
*/
|
||||
I _index;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct the field proxy
|
||||
*
|
||||
* @param table the table possibly holding the field
|
||||
* @oaram index key in table map
|
||||
*/
|
||||
FieldProxy(T *source, I index) :
|
||||
_source(source),
|
||||
_index(index)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Assign a boolean value
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
FieldProxy& operator=(bool value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, BooleanSet(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(uint8_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, UOctet(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(int8_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, Octet(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(uint16_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, UShort(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(int16_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, Short(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(uint32_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, ULong(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(int32_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, Long(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(uint64_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, ULongLong(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a numeric value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(int64_t value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, LongLong(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a decimal value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy& operator=(const DecimalField value)
|
||||
{
|
||||
// assign value and allow chaining
|
||||
_source->set(_index, DecimalField(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a string value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy &operator=(const std::string &value)
|
||||
{
|
||||
// in theory we should make a distinction between short and long string,
|
||||
// but in practive only long strings are accepted
|
||||
_source->set(_index, LongString(value));
|
||||
|
||||
// allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a string value
|
||||
*
|
||||
* @param value
|
||||
* @return FieldProxy
|
||||
*/
|
||||
FieldProxy &operator=(const char *value)
|
||||
{
|
||||
// cast to a string
|
||||
return operator=(std::string(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get boolean value
|
||||
* @return BooleanSet
|
||||
*/
|
||||
operator BooleanSet ()
|
||||
{
|
||||
// the value
|
||||
BooleanSet value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boolean
|
||||
* @return bool
|
||||
*/
|
||||
operator bool ()
|
||||
{
|
||||
// the value
|
||||
BooleanSet value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return int8_t
|
||||
*/
|
||||
operator int8_t ()
|
||||
{
|
||||
// the value
|
||||
Octet value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return uint8_t
|
||||
*/
|
||||
operator uint8_t ()
|
||||
{
|
||||
// the value
|
||||
UOctet value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return int16_t
|
||||
*/
|
||||
operator int16_t ()
|
||||
{
|
||||
// the value
|
||||
Short value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return uint16_t
|
||||
*/
|
||||
operator uint16_t ()
|
||||
{
|
||||
// the value
|
||||
UShort value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return int32_t
|
||||
*/
|
||||
operator int32_t ()
|
||||
{
|
||||
// the value
|
||||
Long value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return uint32_t
|
||||
*/
|
||||
operator uint32_t ()
|
||||
{
|
||||
// the value
|
||||
ULong value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return int64_t
|
||||
*/
|
||||
operator int64_t ()
|
||||
{
|
||||
// the value
|
||||
Long value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric value
|
||||
* @return uint64_t
|
||||
*/
|
||||
operator uint64_t ()
|
||||
{
|
||||
// the value
|
||||
ULong value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get decimal value
|
||||
* @return DecimalField
|
||||
*/
|
||||
operator DecimalField ()
|
||||
{
|
||||
// the value
|
||||
DecimalField value;
|
||||
|
||||
// retrieve the value
|
||||
_source->get(_index, value);
|
||||
|
||||
// return the result
|
||||
return value.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string value
|
||||
* @return string
|
||||
*/
|
||||
operator std::string ()
|
||||
{
|
||||
// it has to be either a short or a long string
|
||||
ShortString shortValue;
|
||||
LongString longValue;
|
||||
|
||||
// try to retrieve the value
|
||||
if (_source->get(_index, shortValue)) return shortValue.value();
|
||||
if (_source->get(_index, longValue)) return longValue.value();
|
||||
|
||||
// no valid string found
|
||||
return std::string("");
|
||||
}
|
||||
};
|
||||
|
||||
// define types for array- and table-based field proxy
|
||||
typedef FieldProxy<Table, std::string> AssociativeFieldProxy;
|
||||
typedef FieldProxy<Array, uint8_t> ArrayFieldProxy;
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* AmqpFlags.h
|
||||
*
|
||||
* The various flags that are supported
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* All bit flags
|
||||
* @var int
|
||||
*/
|
||||
extern const int durable;
|
||||
extern const int autodelete;
|
||||
extern const int active;
|
||||
extern const int passive;
|
||||
extern const int ifunused;
|
||||
extern const int ifempty;
|
||||
extern const int global;
|
||||
extern const int nolocal;
|
||||
extern const int noack;
|
||||
extern const int exclusive;
|
||||
extern const int nowait;
|
||||
extern const int mandatory;
|
||||
extern const int immediate;
|
||||
extern const int redelivered;
|
||||
extern const int multiple;
|
||||
extern const int requeue;
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* The login information to access a server
|
||||
*
|
||||
* This class combines login, password and vhost
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class Login
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The vhost
|
||||
* @var string
|
||||
*/
|
||||
std::string _vhost;
|
||||
|
||||
/**
|
||||
* The username
|
||||
* @var string
|
||||
*/
|
||||
std::string _user;
|
||||
|
||||
/**
|
||||
* The password
|
||||
* @var string
|
||||
*/
|
||||
std::string _password;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param vhost
|
||||
* @param user
|
||||
* @param password
|
||||
*/
|
||||
Login(const std::string &vhost, const std::string &user, const std::string &password) :
|
||||
_vhost(vhost), _user(user), _password(password) {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param user
|
||||
* @param password
|
||||
*/
|
||||
Login(const std::string &user, const std::string &password) :
|
||||
_vhost("/"), _user(user), _password(password) {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Login() :
|
||||
_vhost("/"), _user("guest"), _password("guest") {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Login() {}
|
||||
|
||||
/**
|
||||
* String representation in SASL PLAIN mode
|
||||
* @return string
|
||||
*/
|
||||
std::string saslPlain()
|
||||
{
|
||||
// we need an initial string
|
||||
std::string result("\0", 1);
|
||||
|
||||
// append other elements
|
||||
return result.append(_user).append("\0",1).append(_password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the vhost
|
||||
* @return string
|
||||
*/
|
||||
std::string &vhost()
|
||||
{
|
||||
return _vhost;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Monitor.h
|
||||
*
|
||||
* A monitor object monitors if the connection is still valid. When the
|
||||
* connection is parsing incoming data, it calls the user handler for each
|
||||
* incoming frame. However, it is unknown what this handler is going to do,
|
||||
* it could for example decide to destruct the connection object. In that
|
||||
* case the connection object should stop further handling the data. This
|
||||
* monitor class is used to check if the connection has been destructed.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class Monitor
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The object being watched
|
||||
* @var Watchable
|
||||
*/
|
||||
Watchable *_watchable;
|
||||
|
||||
/**
|
||||
* Invalidate the object
|
||||
*/
|
||||
void invalidate()
|
||||
{
|
||||
_watchable = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param watchable
|
||||
*/
|
||||
Monitor(Watchable *watchable) : _watchable(watchable)
|
||||
{
|
||||
// register with the watchable
|
||||
_watchable->add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Monitor()
|
||||
{
|
||||
// remove from watchable
|
||||
if (_watchable) _watchable->remove(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the object is valid
|
||||
* @return bool
|
||||
*/
|
||||
bool valid()
|
||||
{
|
||||
return _watchable != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* The watchable can access private data
|
||||
*/
|
||||
friend class Watchable;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
/**
|
||||
* Numeric field types for AMQP
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Template for numeric field types
|
||||
*/
|
||||
template<
|
||||
typename T,
|
||||
char F,
|
||||
typename = typename std::enable_if<std::is_arithmetic<T>::value, T>,
|
||||
typename = typename std::enable_if<std::is_integral<T>::value, T>
|
||||
>
|
||||
class NumericField : public Field
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Field value
|
||||
*/
|
||||
T _value;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor, assign 0
|
||||
*/
|
||||
NumericField() : _value(0) {}
|
||||
|
||||
/**
|
||||
* Construct numeric field from
|
||||
* one of numeric types
|
||||
*
|
||||
* @param value field value
|
||||
*/
|
||||
NumericField(T value) : _value(value) {}
|
||||
|
||||
/**
|
||||
* Parse based on incoming buffer
|
||||
* @param frame
|
||||
*/
|
||||
NumericField(ReceivedFrame &frame)
|
||||
{
|
||||
// copy the data from the buffer into the field
|
||||
if (!std::is_floating_point<T>::value)
|
||||
{
|
||||
// convert value based on internal storage size
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1: _value = frame.nextUint8(); break;
|
||||
case 2: _value = frame.nextUint16(); break;
|
||||
case 4: _value = frame.nextUint32(); break;
|
||||
case 8: _value = frame.nextUint64(); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 4: _value = frame.nextFloat(); break;
|
||||
case 8: _value = frame.nextDouble(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~NumericField() {}
|
||||
|
||||
/**
|
||||
* Create a new instance of this object
|
||||
* @return Field*
|
||||
*/
|
||||
virtual Field *clone() const override
|
||||
{
|
||||
// create a new copy of ourselves and return it
|
||||
return new NumericField(_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a new value
|
||||
*
|
||||
* @param value new value for field
|
||||
* @return NumericField
|
||||
*/
|
||||
NumericField& operator=(T value)
|
||||
{
|
||||
_value = value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the value
|
||||
* @return mixed
|
||||
*/
|
||||
operator T () const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value
|
||||
* @return mixed
|
||||
*/
|
||||
T value() const
|
||||
{
|
||||
// return internal value
|
||||
return _value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
* @return size_t
|
||||
*/
|
||||
virtual size_t size() const override
|
||||
{
|
||||
// numeric types have no extra storage requirements
|
||||
return sizeof(_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum allowed value for this field
|
||||
* @return mixed
|
||||
*/
|
||||
constexpr static T max()
|
||||
{
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write encoded payload to the given buffer.
|
||||
* @param buffer OutBuffer to write to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// store converted value
|
||||
T value = _value;
|
||||
|
||||
// write to buffer
|
||||
// adding a value takes care of host to network byte order
|
||||
buffer.add(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type ID that is used to identify this type of
|
||||
* field in a field table
|
||||
*/
|
||||
virtual char typeID() const override
|
||||
{
|
||||
return F;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Concrete numeric types for AMQP
|
||||
*/
|
||||
typedef NumericField<int8_t, 'b'> Octet;
|
||||
typedef NumericField<uint8_t, 'B'> UOctet;
|
||||
typedef NumericField<int16_t, 'U'> Short;
|
||||
typedef NumericField<uint16_t, 'u'> UShort;
|
||||
typedef NumericField<int32_t, 'I'> Long;
|
||||
typedef NumericField<uint32_t, 'i'> ULong;
|
||||
typedef NumericField<int64_t, 'L'> LongLong;
|
||||
typedef NumericField<uint64_t, 'l'> ULongLong;
|
||||
typedef NumericField<uint64_t, 'T'> Timestamp;
|
||||
|
||||
/**
|
||||
* Concrete floating-point types for AMQP
|
||||
*/
|
||||
typedef NumericField<float, 'f'> Float;
|
||||
typedef NumericField<double, 'd'> Double;
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
/**
|
||||
* OutBuffer.h
|
||||
*
|
||||
* This is a utility class for writing various data types to a binary
|
||||
* string, and converting the values to network byte order
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class OutBuffer
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Pointer to the beginning of the buffer
|
||||
* @var char*
|
||||
*/
|
||||
char *_buffer;
|
||||
|
||||
/**
|
||||
* Pointer to the buffer to be filled
|
||||
* @var char*
|
||||
*/
|
||||
char *_current;
|
||||
|
||||
/**
|
||||
* Current size of the buffer
|
||||
* @var size_t
|
||||
*/
|
||||
size_t _size;
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param capacity
|
||||
*/
|
||||
OutBuffer(uint32_t capacity)
|
||||
{
|
||||
_size = 0;
|
||||
_buffer = _current = new char[capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~OutBuffer()
|
||||
{
|
||||
delete[] _buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access to the internal buffer
|
||||
* @return const char*
|
||||
*/
|
||||
const char *data()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Current size of the output buffer
|
||||
* @return size_t
|
||||
*/
|
||||
size_t size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a binary buffer to the buffer
|
||||
* @param string char* to the string
|
||||
* @param size size of string
|
||||
*/
|
||||
void add(const char *string, uint32_t size)
|
||||
{
|
||||
memcpy(_current, string, size);
|
||||
_current += size;
|
||||
_size += size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a binary buffer to the buffer
|
||||
* @param string char* to the string
|
||||
* @param size size of string
|
||||
*/
|
||||
void add(const std::string &string)
|
||||
{
|
||||
add(string.c_str(), string.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* add a uint8_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(uint8_t value)
|
||||
{
|
||||
memcpy(_current, &value, sizeof(value));
|
||||
_current += sizeof(value);
|
||||
_size += sizeof(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a uint16_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(uint16_t value)
|
||||
{
|
||||
uint16_t v = htobe16(value);
|
||||
memcpy(_current, &v, sizeof(v));
|
||||
_current += sizeof(v);
|
||||
_size += sizeof(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a uint32_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(uint32_t value)
|
||||
{
|
||||
uint32_t v = htobe32(value);
|
||||
memcpy(_current, &v, sizeof(v));
|
||||
_current += sizeof(v);
|
||||
_size += sizeof(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a uint64_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(uint64_t value)
|
||||
{
|
||||
uint64_t v = htobe64(value);
|
||||
memcpy(_current, &v, sizeof(v));
|
||||
_current += sizeof(v);
|
||||
_size += sizeof(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a int8_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(int8_t value)
|
||||
{
|
||||
memcpy(_current, &value, sizeof(value));
|
||||
_current += sizeof(value);
|
||||
_size += sizeof(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a int16_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(int16_t value)
|
||||
{
|
||||
int16_t v = htobe16(value);
|
||||
memcpy(_current, &v, sizeof(v));
|
||||
_current += sizeof(v);
|
||||
_size += sizeof(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a int32_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(int32_t value)
|
||||
{
|
||||
int32_t v = htobe32(value);
|
||||
memcpy(_current, &v, sizeof(v));
|
||||
_current += sizeof(v);
|
||||
_size += sizeof(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a int64_t to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(int64_t value)
|
||||
{
|
||||
int64_t v = htobe64(value);
|
||||
memcpy(_current, &v, sizeof(v));
|
||||
_current += sizeof(v);
|
||||
_size += sizeof(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a float to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(float value)
|
||||
{
|
||||
memcpy(_current, &value, sizeof(value));
|
||||
_current += sizeof(value);
|
||||
_size += sizeof(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a double to the buffer
|
||||
* @param value value to add
|
||||
*/
|
||||
void add(double value)
|
||||
{
|
||||
memcpy(_current, &value, sizeof(value));
|
||||
_current += sizeof(value);
|
||||
_size += sizeof(value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
/**
|
||||
* ReceivedFrame.h
|
||||
*
|
||||
* The received frame class is a wrapper around a data buffer, it tries to
|
||||
* find out if the buffer is big enough to contain an entire frame, and
|
||||
* it will try to recognize the frame type in the buffer
|
||||
*
|
||||
* This is a class that is used internally by the AMQP library. As a used
|
||||
* of this library, you normally do not have to instantiate it.
|
||||
*
|
||||
* @documentation public
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ReceivedFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The buffer we are reading from
|
||||
* @var char*
|
||||
*/
|
||||
const char *_buffer = nullptr;
|
||||
|
||||
/**
|
||||
* Number of bytes left to retrieve
|
||||
* @var uint32_t
|
||||
*/
|
||||
uint32_t _left = 0;
|
||||
|
||||
/**
|
||||
* Type of frame
|
||||
* @var uint8_t
|
||||
*/
|
||||
uint8_t _type = 0;
|
||||
|
||||
/**
|
||||
* Channel identifier
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _channel = 0;
|
||||
|
||||
/**
|
||||
* The payload size
|
||||
* @var uint32_t
|
||||
*/
|
||||
uint32_t _payloadSize = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Process a method frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processMethodFrame(ConnectionImpl *connection);
|
||||
|
||||
/**
|
||||
* Process a connection frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processConnectionFrame(ConnectionImpl *connection);
|
||||
|
||||
/**
|
||||
* Process a channel frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processChannelFrame(ConnectionImpl *connection);
|
||||
|
||||
/**
|
||||
* Process an exchange frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processExchangeFrame(ConnectionImpl *connection);
|
||||
|
||||
/**
|
||||
* Process a queue frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processQueueFrame(ConnectionImpl *connection);
|
||||
|
||||
/**
|
||||
* Process a basic frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processBasicFrame(ConnectionImpl *connection);
|
||||
|
||||
/**
|
||||
* Process a transaction frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processTransactionFrame(ConnectionImpl *connection);
|
||||
|
||||
/**
|
||||
* Process a header frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
*/
|
||||
bool processHeaderFrame(ConnectionImpl *connection);
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param buffer Binary buffer
|
||||
* @param size Size of the buffer
|
||||
* @param max Max buffer size
|
||||
*/
|
||||
ReceivedFrame(const char *buffer, uint32_t size, uint32_t max);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ReceivedFrame() {}
|
||||
|
||||
/**
|
||||
* Is this a complete frame?
|
||||
* @return integer
|
||||
*/
|
||||
bool complete() const;
|
||||
|
||||
/**
|
||||
* Return the channel identifier
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t channel() const
|
||||
{
|
||||
return _channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Total size of the frame (headers + payload)
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint64_t totalSize() const
|
||||
{
|
||||
// payload size + size of headers and end of frame byte
|
||||
return _payloadSize + 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of the payload
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t payloadSize() const
|
||||
{
|
||||
return _payloadSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next uint8_t from the buffer
|
||||
*
|
||||
* @return uint8_t value read
|
||||
*/
|
||||
uint8_t nextUint8();
|
||||
|
||||
/**
|
||||
* Read the next int8_t from the buffer
|
||||
*
|
||||
* @return int8_t value read
|
||||
*/
|
||||
int8_t nextInt8();
|
||||
|
||||
/**
|
||||
* Read the next uint16_t from the buffer
|
||||
*
|
||||
* @return uint16_t value read
|
||||
*/
|
||||
uint16_t nextUint16();
|
||||
|
||||
/**
|
||||
* Read the next int16_t from the buffer
|
||||
*
|
||||
* @return int16_t value read
|
||||
*/
|
||||
int16_t nextInt16();
|
||||
|
||||
/**
|
||||
* Read the next uint32_t from the buffer
|
||||
*
|
||||
* @return uint32_t value read
|
||||
*/
|
||||
uint32_t nextUint32();
|
||||
|
||||
/**
|
||||
* Read the next int32_t from the buffer
|
||||
*
|
||||
* @return int32_t value read
|
||||
*/
|
||||
int32_t nextInt32();
|
||||
|
||||
/**
|
||||
* Read the next uint64_t from the buffer
|
||||
*
|
||||
* @return uint64_t value read
|
||||
*/
|
||||
uint64_t nextUint64();
|
||||
|
||||
/**
|
||||
* Read the next int64_t from the buffer
|
||||
*
|
||||
* @return int64_t value read
|
||||
*/
|
||||
int64_t nextInt64();
|
||||
|
||||
/**
|
||||
* Read a float from the buffer
|
||||
*
|
||||
* @return float float read from buffer.
|
||||
*/
|
||||
float nextFloat();
|
||||
|
||||
/**
|
||||
* Read a double from the buffer
|
||||
*
|
||||
* @return double double read from buffer
|
||||
*/
|
||||
double nextDouble();
|
||||
|
||||
/**
|
||||
* Get a pointer to the next binary buffer of a certain size
|
||||
* @param size
|
||||
* @return char*
|
||||
*/
|
||||
const char *nextData(uint32_t size);
|
||||
|
||||
/**
|
||||
* Process the received frame
|
||||
*
|
||||
* If this method returns false, it means that the frame was not processed,
|
||||
* because it was an unrecognized frame. This does not mean that the
|
||||
* connection is now in an invalid state however.
|
||||
*
|
||||
* @param connection the connection over which the data was received
|
||||
* @return bool was the frame fully processed
|
||||
* @internal
|
||||
*/
|
||||
bool process(ConnectionImpl *connection);
|
||||
|
||||
|
||||
/**
|
||||
* The checker may access private data
|
||||
*/
|
||||
friend class FrameCheck;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* String field types for amqp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Base class for string types
|
||||
*/
|
||||
template <typename T, char F>
|
||||
class StringField : public Field
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Pointer to string data
|
||||
* @var string
|
||||
*/
|
||||
std::string _data;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initialize empty string
|
||||
*/
|
||||
StringField() {}
|
||||
|
||||
/**
|
||||
* Construct based on a std::string
|
||||
*
|
||||
* @param value string value
|
||||
*/
|
||||
StringField(std::string value) : _data(value) {}
|
||||
|
||||
/**
|
||||
* Construct based on received data
|
||||
* @param frame
|
||||
*/
|
||||
StringField(ReceivedFrame &frame)
|
||||
{
|
||||
// get the size
|
||||
T size(frame);
|
||||
|
||||
// read data
|
||||
const char *data = frame.nextData(size.value());
|
||||
|
||||
// @todo what if this fails?
|
||||
|
||||
// allocate string
|
||||
_data = std::string((char*) data, (size_t) size.value());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up memory used
|
||||
*/
|
||||
virtual ~StringField() {}
|
||||
|
||||
/**
|
||||
* Create a new instance of this object
|
||||
* @return Field*
|
||||
*
|
||||
* @todo can this be protected?
|
||||
* @todo check if all clone methods have a override keyword
|
||||
*/
|
||||
virtual Field *clone() const override
|
||||
{
|
||||
// create a new copy of ourselves and return it
|
||||
return new StringField(_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a new value
|
||||
*
|
||||
* @param value new value
|
||||
*/
|
||||
StringField& operator=(const std::string& value)
|
||||
{
|
||||
// overwrite data
|
||||
_data = value;
|
||||
|
||||
// allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
*/
|
||||
virtual size_t size() const override
|
||||
{
|
||||
// find out size of the size parameter
|
||||
T size(_data.size());
|
||||
|
||||
// size of the uint8 or uint32 + the actual string size
|
||||
return size.size() + _data.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value
|
||||
* @return string
|
||||
*/
|
||||
operator const std::string& () const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value
|
||||
* @return string
|
||||
*/
|
||||
const std::string& value() const
|
||||
{
|
||||
// get data
|
||||
return _data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum allowed string length for this field
|
||||
* @return size_t
|
||||
*/
|
||||
constexpr static size_t maxLength()
|
||||
{
|
||||
return T::max();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write encoded payload to the given buffer.
|
||||
* @param buffer
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// create size
|
||||
T size(_data.size());
|
||||
|
||||
// first, write down the size of the string
|
||||
size.fill(buffer);
|
||||
|
||||
// write down the string content
|
||||
buffer.add(_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type ID that is used to identify this type of
|
||||
* field in a field table
|
||||
* @return char
|
||||
*/
|
||||
virtual char typeID() const override
|
||||
{
|
||||
return F;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Concrete string types for AMQP
|
||||
*/
|
||||
typedef StringField<UOctet, 's'> ShortString;
|
||||
typedef StringField<ULong, 'S'> LongString;
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* AMQP field table
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* AMQP field table
|
||||
*/
|
||||
class Table : public Field
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* We define a custom type for storing fields
|
||||
* @typedef FieldMap
|
||||
*/
|
||||
typedef std::map<std::string, std::shared_ptr<Field> > FieldMap;
|
||||
|
||||
/**
|
||||
* Store the fields
|
||||
* @var FieldMap
|
||||
*/
|
||||
FieldMap _fields;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor that creates an empty table
|
||||
*/
|
||||
Table() {}
|
||||
|
||||
/**
|
||||
* Decode the data from a received frame into a table
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
Table(ReceivedFrame &frame);
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
* @param table
|
||||
*/
|
||||
Table(const Table &table);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Table() {}
|
||||
|
||||
/**
|
||||
* Create a new instance on the heap of this object, identical to the object passed
|
||||
* @return Field*
|
||||
*/
|
||||
virtual Field *clone() const override
|
||||
{
|
||||
return new Table(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
*/
|
||||
virtual size_t size() const override;
|
||||
|
||||
/**
|
||||
* Set a field
|
||||
*
|
||||
* @param name field name
|
||||
* @param value field value
|
||||
*/
|
||||
Table set(const std::string& name, const Field &value)
|
||||
{
|
||||
// copy to a new pointer and store it
|
||||
_fields[name] = std::shared_ptr<Field>(value.clone());
|
||||
|
||||
// allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a field
|
||||
*
|
||||
* If the field does not exist, an empty string field is returned
|
||||
*
|
||||
* @param name field name
|
||||
* @return the field value
|
||||
*/
|
||||
const Field &get(const std::string &name);
|
||||
|
||||
/**
|
||||
* Get a field
|
||||
*
|
||||
* @param name field name
|
||||
*/
|
||||
AssociativeFieldProxy operator[](const std::string& name)
|
||||
{
|
||||
return AssociativeFieldProxy(this, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write encoded payload to the given buffer.
|
||||
* @param buffer
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override;
|
||||
|
||||
/**
|
||||
* Get the type ID that is used to identify this type of
|
||||
* field in a field table
|
||||
*/
|
||||
virtual char typeID() const override
|
||||
{
|
||||
return 'F';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Watchable.h
|
||||
*
|
||||
* Every class that overrides from the Watchable class can be monitored for
|
||||
* destruction by a Monitor object
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class Watchable
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The monitors
|
||||
* @var set
|
||||
*/
|
||||
std::set<Monitor*> _monitors;
|
||||
|
||||
/**
|
||||
* Add a monitor
|
||||
* @param monitor
|
||||
*/
|
||||
void add(Monitor *monitor)
|
||||
{
|
||||
_monitors.insert(monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a monitor
|
||||
* @param monitor
|
||||
*/
|
||||
void remove(Monitor *monitor)
|
||||
{
|
||||
_monitors.erase(monitor);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Watchable();
|
||||
|
||||
/**
|
||||
* Only a monitor has full access
|
||||
*/
|
||||
friend class Monitor;
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
CPP = g++-4.8
|
||||
RM = rm -f
|
||||
CPPFLAGS = -Wall -c -I. -O2 -flto -std=c++11 -g
|
||||
LD = g++
|
||||
LD_FLAGS = -Wall -shared -O2
|
||||
RESULT = libcopernica_amqp.so
|
||||
|
||||
STATIC = $(RESULT:%.so=%.a)
|
||||
SOURCES = $(wildcard *.cpp)
|
||||
OBJECTS = $(SOURCES:%.cpp=%.o)
|
||||
OBJECTS_STATIC = $(SOURCES:%.cpp=%.s.o)
|
||||
|
||||
all: ${OBJECTS} ${OBJECTS_STATIC} ${RESULT}
|
||||
$(MAKE) STATIC_LIB
|
||||
|
||||
${RESULT}: ${OBJECTS}
|
||||
${LD} ${LD_FLAGS} -o $@ ${OBJECTS}
|
||||
|
||||
clean:
|
||||
${RM} *.obj *~* ${OBJECTS} ${OBJECTS_STATIC} ${RESULT} ${STATIC}
|
||||
|
||||
${OBJECTS}:
|
||||
${CPP} ${CPPFLAGS} -fpic -o $@ ${@:%.o=%.cpp}
|
||||
|
||||
${OBJECTS_STATIC}:
|
||||
${CPP} ${CPPFLAGS} -o $@ ${@:%.s.o=%.cpp}
|
||||
|
||||
STATIC_LIB:
|
||||
ar rcs ${STATIC} ${OBJECTS_STATIC}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* Array.cpp
|
||||
*
|
||||
* Implementation of an array
|
||||
*
|
||||
*/
|
||||
#include "includes.h"
|
||||
|
||||
// we live in the copernica namespace
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Constructor based on incoming frame
|
||||
* @param frame
|
||||
*/
|
||||
Array::Array(ReceivedFrame &frame)
|
||||
{
|
||||
// use this to see if we've read too many bytes.
|
||||
uint32_t charsToRead = frame.nextUint32();
|
||||
|
||||
// keep going until all data is read
|
||||
while (charsToRead > 0)
|
||||
{
|
||||
// one byte less for the field type
|
||||
charsToRead -= 1;
|
||||
|
||||
// read the field type and construct the field
|
||||
Field *field = Field::decode(frame);
|
||||
if (!field) continue;
|
||||
|
||||
// less bytes to read
|
||||
charsToRead -= field->size();
|
||||
|
||||
// add the additional field
|
||||
_fields.push_back(std::shared_ptr<Field>(field));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
* @param array
|
||||
*/
|
||||
Array::Array(const Array &array)
|
||||
{
|
||||
// loop through the other array
|
||||
for (auto iter = array._fields.begin(); iter != array._fields.end(); iter++)
|
||||
{
|
||||
// add to this vector
|
||||
_fields.push_back(std::shared_ptr<Field>((*iter)->clone()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a field
|
||||
*
|
||||
* If the field does not exist, an empty string is returned
|
||||
*
|
||||
* @param index field index
|
||||
* @return Field
|
||||
*/
|
||||
const Field &Array::get(uint8_t index)
|
||||
{
|
||||
// used if index does not exist
|
||||
static ShortString empty;
|
||||
|
||||
// check whether we have that many elements
|
||||
if (index >= _fields.size()) return empty;
|
||||
|
||||
// get value
|
||||
return *_fields[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size this field will take when
|
||||
* encoded in the AMQP wire-frame format
|
||||
*/
|
||||
size_t Array::size() const
|
||||
{
|
||||
// store the size (four bytes for the initial size)
|
||||
size_t size = 4;
|
||||
|
||||
// iterate over all elements
|
||||
for (auto iter(_fields.begin()); iter != _fields.end(); ++iter)
|
||||
{
|
||||
// add the size of the field type and size of element
|
||||
size += sizeof((*iter)->typeID());
|
||||
size += (*iter)->size();
|
||||
}
|
||||
|
||||
// return the result
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write encoded payload to the given buffer.
|
||||
*/
|
||||
void Array::fill(OutBuffer& buffer) const
|
||||
{
|
||||
// iterate over all elements
|
||||
for (auto iter(_fields.begin()); iter != _fields.end(); ++iter)
|
||||
{
|
||||
// encode the element type and element
|
||||
buffer.add((*iter)->typeID());
|
||||
(*iter)->fill(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// end namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* Class describing a basic acknowledgement frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class defintion
|
||||
*/
|
||||
class BasicAckFrame : public BasicFrame {
|
||||
private:
|
||||
/**
|
||||
* server-assigned and channel specific delivery tag
|
||||
* @var uint64_t
|
||||
*/
|
||||
uint64_t _deliveryTag;
|
||||
|
||||
/**
|
||||
* if set, tag is treated as "up to and including", so client can acknowledge multiple messages with a single method
|
||||
* if not set, refers to single message
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _multiple;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
* @return pointer to object to allow for chaining
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// add the delivery tag
|
||||
buffer.add(_deliveryTag);
|
||||
|
||||
// add the booleans
|
||||
_multiple.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic acknowledgement frame
|
||||
*
|
||||
* @param channel Channel identifier
|
||||
* @param deliveryTag server-assigned and channel specific delivery tag
|
||||
* @param multiple acknowledge mutiple messages
|
||||
*/
|
||||
BasicAckFrame(uint16_t channel, uint64_t deliveryTag, bool multiple = false) :
|
||||
BasicFrame(channel, 9),
|
||||
_deliveryTag(deliveryTag),
|
||||
_multiple(multiple) {}
|
||||
|
||||
/**
|
||||
* Construct based on received frame
|
||||
* @param frame
|
||||
*/
|
||||
BasicAckFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_deliveryTag(frame.nextUint64()),
|
||||
_multiple(frame) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicAckFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server-assigned and channel specific delivery tag
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t deliveryTag() const
|
||||
{
|
||||
return _deliveryTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to acknowledgement multiple messages
|
||||
* @return bool
|
||||
*/
|
||||
bool multiple()
|
||||
{
|
||||
return _multiple.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* Class describing a basic cancel frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicCancelFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Holds the consumer tag specified by the client or provided by the server.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _consumerTag;
|
||||
|
||||
/**
|
||||
* whether to wait for a response
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _noWait;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// add consumer tag + booleans
|
||||
_consumerTag.fill(buffer);
|
||||
_noWait.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic cancel frame from a received frame
|
||||
*
|
||||
* @param frame received frame to parse
|
||||
*/
|
||||
BasicCancelFrame(ReceivedFrame &frame) : BasicFrame(frame), _consumerTag(frame), _noWait(frame) {}
|
||||
|
||||
/**
|
||||
* Construct a basic cancel frame
|
||||
*
|
||||
* @param channel Channel identifier
|
||||
* @param consumerTag consumertag specified by client of provided by server
|
||||
* @param noWait whether to wait for a response.
|
||||
*/
|
||||
BasicCancelFrame(uint16_t channel, const std::string& consumerTag, bool noWait = false) :
|
||||
BasicFrame(channel, consumerTag.size() + 2), // 1 for extra string size, 1 for bool
|
||||
_consumerTag(consumerTag),
|
||||
_noWait(noWait) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicCancelFrame() {}
|
||||
|
||||
/**
|
||||
* Return the consumertag, which is specified by the client or provided by the server
|
||||
* @return string
|
||||
*/
|
||||
const std::string& consumerTag() const
|
||||
{
|
||||
return _consumerTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to wait for a response
|
||||
* @return boolean
|
||||
*/
|
||||
const bool noWait()
|
||||
{
|
||||
return _noWait.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Class describing a basic cancel ok frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicCancelOKFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Holds the consumer tag specified by the client or provided by the server.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _consumerTag;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// add own information
|
||||
_consumerTag.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic cancel ok frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicCancelOKFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_consumerTag(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic cancel ok frame (client-side)
|
||||
* @param channel channel identifier
|
||||
* @param consumerTag holds the consumertag specified by client or server
|
||||
*/
|
||||
BasicCancelOKFrame(uint16_t channel, std::string& consumerTag) :
|
||||
BasicFrame(channel, consumerTag.length() + 1), // add 1 byte for encoding the size of consumer tag
|
||||
_consumerTag(consumerTag)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicCancelOKFrame() {}
|
||||
|
||||
/**
|
||||
* Return the consumertag, which is specified by the client or provided by the server
|
||||
* @return string
|
||||
*/
|
||||
const std::string& consumerTag() const
|
||||
{
|
||||
return _consumerTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*
|
||||
* @todo check if all other implementations use override keyword
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 31;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
/**
|
||||
* Class describing a basic consume frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicConsumeFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Field that is no longer used
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _deprecated;
|
||||
|
||||
/**
|
||||
* specifies the name of the queue to consume from
|
||||
* @var Table
|
||||
*/
|
||||
ShortString _queueName;
|
||||
|
||||
/**
|
||||
* specifies the identifier for the consumer tag.
|
||||
* This tag is local to a channel so two clients can use the same consumer tags.
|
||||
* If empty, the server generates a tag.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _consumerTag;
|
||||
|
||||
/**
|
||||
* Booleans sent in frame
|
||||
* 0: noLocal
|
||||
* 1: noAck
|
||||
* 2: exclusive
|
||||
* 3: noWait
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _bools;
|
||||
|
||||
/**
|
||||
* additional arguments, implementation dependent
|
||||
* @var Table
|
||||
*/
|
||||
Table _filter;
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// fill the buffer
|
||||
buffer.add((uint16_t) _deprecated);
|
||||
_queueName.fill(buffer);
|
||||
_consumerTag.fill(buffer);
|
||||
_bools.fill(buffer);
|
||||
_filter.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic consume frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param queueName name of the queue to consume from
|
||||
* @param consumerTag identifier for the consumer tag.
|
||||
* @param noLocal no-local
|
||||
* @param noAck no acknowledgements
|
||||
* @param exclusive exclusive channel
|
||||
* @param noWait don't wait for a response
|
||||
* @param filter additional arguments
|
||||
*/
|
||||
BasicConsumeFrame(uint16_t channel, const std::string& queueName, const std::string& consumerTag, bool noLocal = false, bool noAck = false, bool exclusive = false, bool noWait = false, const Table& filter = {}) :
|
||||
BasicFrame(channel, (queueName.length() + consumerTag.length() + 5 + filter.size())), // size of vars, +1 for each shortstring size, +1 for bools, +2 for deprecated value
|
||||
_queueName(queueName),
|
||||
_consumerTag(consumerTag),
|
||||
_bools(noLocal, noAck, exclusive, noWait),
|
||||
_filter(filter)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
* @param frame
|
||||
*/
|
||||
BasicConsumeFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_deprecated(frame.nextUint16()), // read deprecated info
|
||||
_queueName(frame),
|
||||
_consumerTag(frame),
|
||||
_bools(frame),
|
||||
_filter(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicConsumeFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the queue to consume from
|
||||
* @return string
|
||||
*/
|
||||
const std::string& queueName() const
|
||||
{
|
||||
return _queueName;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the identifier for the consumertag
|
||||
* @return string
|
||||
*/
|
||||
const std::string& consumerTag() const
|
||||
{
|
||||
return _consumerTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the value of the noLocal bool
|
||||
* @return bool
|
||||
*/
|
||||
bool noLocal() const
|
||||
{
|
||||
return _bools.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the value of the noAck bool
|
||||
* @return bool
|
||||
*/
|
||||
bool noAck() const
|
||||
{
|
||||
return _bools.get(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* return whether the queue is exclusive
|
||||
* @return bool
|
||||
*/
|
||||
bool exclusive() const
|
||||
{
|
||||
return _bools.get(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* return whether to wait for a response
|
||||
* @return bool
|
||||
*/
|
||||
bool noWait() const
|
||||
{
|
||||
return _bools.get(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the additional filter arguments
|
||||
* @return Table
|
||||
*/
|
||||
const Table& filter() const
|
||||
{
|
||||
return _filter;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Class describing a basic consume ok frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicConsumeOKFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Holds the consumer tag specified by the client or provided by the server.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _consumerTag;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// add payload
|
||||
_consumerTag.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic consume frame
|
||||
*
|
||||
* @param consumerTag consumertag specified by client of provided by server
|
||||
*/
|
||||
BasicConsumeOKFrame(uint16_t channel, const std::string& consumerTag) :
|
||||
BasicFrame(channel, consumerTag.length() + 1), // length of string + 1 for encoding of stringsize
|
||||
_consumerTag(consumerTag)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic consume ok frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicConsumeOKFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_consumerTag(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicConsumeOKFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 21;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the consumertag, which is specified by the client or provided by the server
|
||||
* @return std::string
|
||||
*/
|
||||
const std::string& consumerTag() const
|
||||
{
|
||||
return _consumerTag;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* Class describing a basic deliver frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicDeliverFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* identifier for the consumer, valid within current channel
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _consumerTag;
|
||||
|
||||
/**
|
||||
* server-assigned and channel specific delivery tag
|
||||
* @var uint64_t
|
||||
*/
|
||||
uint64_t _deliveryTag;
|
||||
|
||||
/**
|
||||
* indicates whether the message has been previously delivered to this (or another) client
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _redelivered;
|
||||
|
||||
/**
|
||||
* the name of the exchange to publish to. An empty exchange name means the default exchange.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _exchange;
|
||||
|
||||
/**
|
||||
* Message routing key
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _routingKey;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
_consumerTag.fill(buffer);
|
||||
buffer.add(_deliveryTag);
|
||||
_redelivered.fill(buffer);
|
||||
_exchange.fill(buffer);
|
||||
_routingKey.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic deliver frame (client side)
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param consumerTag identifier for the consumer, valid within current channel
|
||||
* @param deliveryTag server-assigned and channel specific delivery tag
|
||||
* @param redelivered indicates whether the message has been previously delivered to this (or another) client
|
||||
* @param exchange name of exchange to publish to
|
||||
* @param routingKey message routing key
|
||||
*/
|
||||
BasicDeliverFrame(uint16_t channel, const std::string& consumerTag, uint64_t deliveryTag, bool redelivered = false, const std::string& exchange = "", const std::string& routingKey = "") :
|
||||
BasicFrame(channel, (consumerTag.length() + exchange.length() + routingKey.length() + 12)),
|
||||
// length of strings + 1 byte per string for stringsize, 8 bytes for uint64_t and 1 for bools
|
||||
_consumerTag(consumerTag),
|
||||
_deliveryTag(deliveryTag),
|
||||
_redelivered(redelivered),
|
||||
_exchange(exchange),
|
||||
_routingKey(routingKey)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic deliver frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicDeliverFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_consumerTag(frame),
|
||||
_deliveryTag(frame.nextUint64()),
|
||||
_redelivered(frame),
|
||||
_exchange(frame),
|
||||
_routingKey(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicDeliverFrame() {}
|
||||
|
||||
/**
|
||||
* Return the name of the exchange to publish to
|
||||
* @return string
|
||||
*/
|
||||
const std::string& exchange() const
|
||||
{
|
||||
return _exchange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the routing key
|
||||
* @return string
|
||||
*/
|
||||
const std::string& routingKey() const
|
||||
{
|
||||
return _routingKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server-assigned and channel specific delivery tag
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t deliveryTag() const
|
||||
{
|
||||
return _deliveryTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier for the consumer (channel specific)
|
||||
* @return string
|
||||
*/
|
||||
const std::string& consumerTag() const
|
||||
{
|
||||
return _consumerTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the message has been previously delivered to (another) client
|
||||
* @return bool
|
||||
*/
|
||||
bool redelivered() const
|
||||
{
|
||||
return _redelivered.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Class describing an AMQP basic frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicFrame : public MethodFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
* @param channel The channel ID
|
||||
* @param size Payload size
|
||||
*/
|
||||
BasicFrame(uint16_t channel, uint32_t size) : MethodFrame(channel, size) {}
|
||||
|
||||
/**
|
||||
* Constructor based on a received frame
|
||||
* @param frame
|
||||
*/
|
||||
BasicFrame(ReceivedFrame &frame) : MethodFrame(frame) {}
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicFrame() {}
|
||||
|
||||
/**
|
||||
* Class id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t classID() const override
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Class describing a basic get empty frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicGetEmptyFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Field that is no longer used
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _deprecated;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// recreate deprecated field and encode
|
||||
_deprecated.fill(buffer);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic get empty frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
*/
|
||||
BasicGetEmptyFrame(uint16_t channel) :
|
||||
BasicFrame(channel, 1) // 1 for encoding the deprecated cluster id (shortstring)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor for incoming data
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicGetEmptyFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_deprecated(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicGetEmptyFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 72;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* Class describing a basic get frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicGetFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Deprecated field
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _deprecated;
|
||||
|
||||
/**
|
||||
* name of the queue to get a message from
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _queue;
|
||||
|
||||
/**
|
||||
* if set, server does not expect acknowledgement for messages. Server dequeues message after sending
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _noAck;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// encode other values
|
||||
buffer.add(_deprecated);
|
||||
_queue.fill(buffer);
|
||||
_noAck.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic get frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param queue name of the queue
|
||||
* @param noAck whether server expects acknowledgements for messages
|
||||
*/
|
||||
BasicGetFrame(uint16_t channel, const std::string& queue, bool noAck = false) :
|
||||
BasicFrame(channel, queue.length() + 4), // 1 for bool, 1 for string size, 2 for deprecated field
|
||||
_deprecated(0),
|
||||
_queue(queue),
|
||||
_noAck(noAck)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor based on incoming frame
|
||||
* @param frame
|
||||
*/
|
||||
BasicGetFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_deprecated(frame.nextUint16()),
|
||||
_queue(frame),
|
||||
_noAck(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicGetFrame() {}
|
||||
|
||||
/**
|
||||
* Return the name of the queue
|
||||
* @return string
|
||||
*/
|
||||
const std::string& queue() const
|
||||
{
|
||||
return _queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 70;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the server expects acknowledgements for messages
|
||||
* @return boolean
|
||||
*/
|
||||
bool noAck() const
|
||||
{
|
||||
return _noAck.get(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* Class describing a basic get ok frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicGetOKFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* server-assigned and channel specific delivery tag
|
||||
* @var uint64_t
|
||||
*/
|
||||
uint64_t _deliveryTag;
|
||||
|
||||
/**
|
||||
* indicates whether the message has been previously delivered to this (or another) client
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _redelivered;
|
||||
|
||||
/**
|
||||
* the name of the exchange to publish to. An empty exchange name means the default exchange.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _exchange;
|
||||
|
||||
/**
|
||||
* Message routing key
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _routingKey;
|
||||
|
||||
/**
|
||||
* number of messages in the queue
|
||||
* @var uint32_t
|
||||
*/
|
||||
uint32_t _messageCount;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// encode rest of the fields
|
||||
buffer.add(_deliveryTag);
|
||||
_redelivered.fill(buffer);
|
||||
_exchange.fill(buffer);
|
||||
_routingKey.fill(buffer);
|
||||
buffer.add(_messageCount);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic get ok frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param deliveryTag server-assigned and channel specific delivery tag
|
||||
* @param redelivered indicates whether the message has been previously delivered to this (or another) client
|
||||
* @param exchange name of exchange to publish to
|
||||
* @param routingKey message routing key
|
||||
* @param messageCount number of messages in the queue
|
||||
*/
|
||||
BasicGetOKFrame(uint16_t channel, uint64_t deliveryTag, bool redelivered, const std::string& exchange, const std::string& routingKey, uint32_t messageCount) :
|
||||
BasicFrame(channel, (exchange.length() + routingKey.length() + 15)), // string length, +1 for each shortsrting length + 8 (uint64_t) + 4 (uint32_t) + 1 (bool)
|
||||
_deliveryTag(deliveryTag),
|
||||
_redelivered(redelivered),
|
||||
_exchange(exchange),
|
||||
_routingKey(routingKey),
|
||||
_messageCount(messageCount)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic get ok frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicGetOKFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_deliveryTag(frame.nextUint64()),
|
||||
_redelivered(frame),
|
||||
_exchange(frame),
|
||||
_routingKey(frame),
|
||||
_messageCount(frame.nextUint32())
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicGetOKFrame() {}
|
||||
|
||||
/**
|
||||
* Return the name of the exchange to publish to
|
||||
* @return string
|
||||
*/
|
||||
const std::string& exchange() const
|
||||
{
|
||||
return _exchange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the routing key
|
||||
* @return string
|
||||
*/
|
||||
const std::string& routingKey() const
|
||||
{
|
||||
return _routingKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 71;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server-assigned and channel specific delivery tag
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t deliveryTag() const
|
||||
{
|
||||
return _deliveryTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of messages in the queue
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t messageCount() const
|
||||
{
|
||||
return _messageCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the message has been previously delivered to (another) client
|
||||
* @return bool
|
||||
*/
|
||||
bool redelivered() const
|
||||
{
|
||||
return _redelivered.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,716 @@
|
|||
/**
|
||||
* Class describing an AMQP basic header frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicHeaderFrame : public HeaderFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Weight field, unused but must be sent, always value 0;
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _weight;
|
||||
|
||||
/**
|
||||
* Body size, sum of the sizes of all body frames following the content header
|
||||
* @var uint64_t
|
||||
*/
|
||||
uint64_t _bodySize;
|
||||
|
||||
/**
|
||||
* First set of booleans
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _bools1;
|
||||
|
||||
/**
|
||||
* Second set of booleans
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _bools2;
|
||||
|
||||
/**
|
||||
* MIME content type
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _contentType;
|
||||
|
||||
/**
|
||||
* MIME content encoding
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _contentEncoding;
|
||||
|
||||
/**
|
||||
* message header field table
|
||||
* @var Table
|
||||
*/
|
||||
Table _headers;
|
||||
|
||||
/**
|
||||
* Delivery mode (non-persistent (1) or persistent (2))
|
||||
* @var uint8_t
|
||||
*/
|
||||
uint8_t _deliveryMode;
|
||||
|
||||
/**
|
||||
* boolean whether field was sent to us
|
||||
* @var uint8_t
|
||||
*/
|
||||
uint8_t _priority;
|
||||
|
||||
/**
|
||||
* application correlation identifier
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _correlationID;
|
||||
|
||||
/**
|
||||
* address to reply to
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _replyTo;
|
||||
|
||||
/**
|
||||
* message expiration identifier
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _expiration;
|
||||
|
||||
/**
|
||||
* application message identifier
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _messageID;
|
||||
|
||||
/**
|
||||
* message timestamp
|
||||
* @var Timestamp
|
||||
*/
|
||||
Timestamp _timestamp;
|
||||
|
||||
/**
|
||||
* message type name
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _typeName;
|
||||
|
||||
/**
|
||||
* creating user id
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _userID;
|
||||
|
||||
/**
|
||||
* creating application id
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _appID;
|
||||
|
||||
/**
|
||||
* Deprecated cluster ID
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _clusterID;
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a header frame to a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
HeaderFrame::fill(buffer);
|
||||
|
||||
// fill own fields.
|
||||
buffer.add(_weight);
|
||||
buffer.add(_bodySize);
|
||||
_bools1.fill(buffer);
|
||||
_bools2.fill(buffer);
|
||||
|
||||
if (contentTypeSent() ) { _contentType.fill(buffer); }
|
||||
if (contentEncodingSent() ) { _contentEncoding.fill(buffer); }
|
||||
if (headersSent() ) { _headers.fill(buffer); }
|
||||
if (deliveryModeSent() ) { buffer.add(_deliveryMode); }
|
||||
if (prioritySent() ) { buffer.add(_priority); }
|
||||
if (correlationIDSent() ) { _correlationID.fill(buffer); }
|
||||
if (replyToSent() ) { _replyTo.fill(buffer); }
|
||||
if (expirationSent() ) { _expiration.fill(buffer); }
|
||||
if (messageIDSent() ) { _messageID.fill(buffer); }
|
||||
if (timestampSent() ) { _timestamp.fill(buffer); }
|
||||
if (typeNameSent() ) { _typeName.fill(buffer); }
|
||||
if (userIDSent() ) { _userID.fill(buffer); }
|
||||
if (appIDSent() ) { _appID.fill(buffer); }
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct an empty basic header frame
|
||||
*
|
||||
* All options are set using setter functions.
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
*/
|
||||
BasicHeaderFrame(uint16_t channel, uint64_t bodySize) :
|
||||
HeaderFrame(channel, 12), // there are at least 12 bytes sent, weight (2), bodySize (8), property flags (2)
|
||||
_weight(0),
|
||||
_bodySize(bodySize),
|
||||
_deliveryMode(0),
|
||||
_priority(0)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor to parse incoming frame
|
||||
* @param frame
|
||||
*/
|
||||
BasicHeaderFrame(ReceivedFrame &frame) :
|
||||
HeaderFrame(frame),
|
||||
_weight(frame.nextUint16()),
|
||||
_bodySize(frame.nextUint64()),
|
||||
_bools1(frame),
|
||||
_bools2(frame),
|
||||
_deliveryMode(0),
|
||||
_priority(0)
|
||||
{
|
||||
if (contentTypeSent()) _contentType = ShortString(frame);
|
||||
if (contentEncodingSent()) _contentEncoding = ShortString(frame);
|
||||
if (headersSent()) _headers = Table(frame);
|
||||
if (deliveryModeSent()) _deliveryMode = frame.nextUint8();
|
||||
if (prioritySent()) _priority = frame.nextUint8();
|
||||
if (correlationIDSent()) _correlationID = ShortString(frame);
|
||||
if (replyToSent()) _replyTo = ShortString(frame);
|
||||
if (expirationSent()) _expiration = ShortString(frame);
|
||||
if (messageIDSent()) _messageID = ShortString(frame);
|
||||
if (timestampSent()) _timestamp = Timestamp(frame);
|
||||
if (typeNameSent()) _typeName = ShortString(frame);
|
||||
if (userIDSent()) _userID = ShortString(frame);
|
||||
if (appIDSent()) _appID = ShortString(frame);
|
||||
if (clusterIDSent()) _clusterID = ShortString(frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicHeaderFrame() {}
|
||||
|
||||
/**
|
||||
* Size of the body
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t bodySize() const
|
||||
{
|
||||
return _bodySize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The class ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t classID() const override
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the body size
|
||||
* @param uint64_t sum of all body-sizes sent after this headerframe
|
||||
*/
|
||||
void setBodySize(uint64_t size)
|
||||
{
|
||||
_bodySize = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the MIME content type
|
||||
* @return string
|
||||
*/
|
||||
const std::string& contentType() const
|
||||
{
|
||||
return _contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content type
|
||||
* @param string
|
||||
*/
|
||||
void setContentType(std::string& string)
|
||||
{
|
||||
// was there already a content type
|
||||
if (contentTypeSent()) modifySize(-_contentType.size());
|
||||
|
||||
// set the new content type
|
||||
setContentTypeSent(string.size() > 0);
|
||||
_contentType = ShortString(string);
|
||||
|
||||
// modify the size to include the new content type
|
||||
if (contentTypeSent()) modifySize(_contentType.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bool for content type sent
|
||||
* @param bool
|
||||
*/
|
||||
void setContentTypeSent(bool b)
|
||||
{
|
||||
_bools1.set(7, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the MIME content encoding
|
||||
* @return string
|
||||
*/
|
||||
const std::string& contentEncoding() const
|
||||
{
|
||||
return _contentEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set content encoding
|
||||
* @param string
|
||||
*/
|
||||
void setContentEncoding(std::string& string)
|
||||
{
|
||||
// was there already a content encoding?
|
||||
if(contentEncodingSent()) modifySize(-_contentEncoding.size());
|
||||
|
||||
// set new content encoding
|
||||
setContentEncodingSent(string.size() > 0);
|
||||
_contentEncoding = ShortString(string);
|
||||
|
||||
// modify size to include the new content type
|
||||
modifySize(_contentEncoding.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set contentencoding sent
|
||||
* @param bool
|
||||
*/
|
||||
void setContentEncodingSent(bool b)
|
||||
{
|
||||
_bools1.set(6, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the message header field table
|
||||
* @return Table
|
||||
*/
|
||||
const Table& headers() const
|
||||
{
|
||||
return _headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set headers
|
||||
* @param Table
|
||||
*/
|
||||
void setHeaders(Table& t)
|
||||
{
|
||||
// were the headers already set
|
||||
if(headersSent()) modifySize(-_headers.size());
|
||||
|
||||
// set new headers
|
||||
setHeadersSent(true);
|
||||
_headers = t;
|
||||
|
||||
// modify size to include the new headers
|
||||
modifySize(_headers.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set headers sent
|
||||
* @param bool
|
||||
*/
|
||||
void setHeadersSent(bool b)
|
||||
{
|
||||
_bools1.set(5, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return whether non-persistent (1) or persistent (2)
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t deliveryMode() const
|
||||
{
|
||||
return _deliveryMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set deliverymode
|
||||
* @param uint8_t
|
||||
*/
|
||||
void setDeliveryMode(uint8_t val)
|
||||
{
|
||||
// was the delivery mode already set
|
||||
if(deliveryModeSent()) modifySize(-1);
|
||||
|
||||
// set delivery mode
|
||||
setDeliverModeSent(true);
|
||||
_deliveryMode = Octet(val);
|
||||
|
||||
// add new size
|
||||
modifySize(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* set delivermode sent
|
||||
* @param bool
|
||||
*/
|
||||
void setDeliverModeSent(bool b)
|
||||
{
|
||||
_bools1.set(4, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the message priority (0-9)
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t priority() const
|
||||
{
|
||||
return _priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set priority
|
||||
* @param uint8_t
|
||||
*/
|
||||
void setPriority(uint8_t val)
|
||||
{
|
||||
// was the priority already sent
|
||||
if(prioritySent()) modifySize(-1);
|
||||
|
||||
// set priority
|
||||
setPrioritySent(true);
|
||||
_priority = Octet(val);
|
||||
|
||||
// add new size
|
||||
modifySize(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set priority sent
|
||||
* @param bool
|
||||
*/
|
||||
void setPrioritySent(bool b)
|
||||
{
|
||||
_bools1.set(3, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the application correlation identifier
|
||||
* @return string
|
||||
*/
|
||||
const std::string& correlationID() const
|
||||
{
|
||||
return _correlationID;
|
||||
}
|
||||
|
||||
/**
|
||||
* set correlation ID
|
||||
* @param string
|
||||
*/
|
||||
void setCorrelationID(std::string &s)
|
||||
{
|
||||
// was the correlation ID sent
|
||||
if(correlationIDSent()) modifySize(-_correlationID.size());
|
||||
|
||||
// set new correlation ID
|
||||
setCorrelationIDSent(true);
|
||||
_correlationID = ShortString(s);
|
||||
|
||||
// add new size
|
||||
modifySize(_correlationID.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set correlationIDSent
|
||||
* @param bool
|
||||
*/
|
||||
void setCorrelationIDSent(bool b)
|
||||
{
|
||||
_bools1.set(2, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the address to reply to
|
||||
* @return string
|
||||
*/
|
||||
const std::string& replyTo() const
|
||||
{
|
||||
return _replyTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set reply to
|
||||
* @param string
|
||||
*/
|
||||
void setReplyTo(std::string &s)
|
||||
{
|
||||
// was replyTo set?
|
||||
if(replyToSent()) modifySize(-_replyTo.size());
|
||||
|
||||
// add new replyTo
|
||||
setReplyToSent(true);
|
||||
_replyTo = ShortString(s);
|
||||
|
||||
modifySize(_replyTo.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set reply to sent
|
||||
* @param bool
|
||||
*/
|
||||
void setReplyToSent(bool b)
|
||||
{
|
||||
_bools1.set(1, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the message expiration identifier
|
||||
* @return string
|
||||
*/
|
||||
const std::string& expiration() const
|
||||
{
|
||||
return _expiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set expiration
|
||||
* @param string
|
||||
*/
|
||||
void setExpiration(std::string &s)
|
||||
{
|
||||
// was expiration set?
|
||||
if(expirationSent()) modifySize(-_expiration.size());
|
||||
|
||||
// set expiration
|
||||
setExpirationSent(true);
|
||||
_expiration = ShortString(s);
|
||||
|
||||
// add new size
|
||||
modifySize(_expiration.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set expiration sent
|
||||
* @param bool
|
||||
*/
|
||||
void setExpirationSent(bool b)
|
||||
{
|
||||
_bools1.set(0, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the application message identifier
|
||||
* @return string
|
||||
*/
|
||||
const std::string& messageID() const
|
||||
{
|
||||
return _messageID;
|
||||
}
|
||||
|
||||
/**
|
||||
* set message ID
|
||||
* @param string
|
||||
*/
|
||||
void setMessageID(std::string &s)
|
||||
{
|
||||
// was message ID sent?
|
||||
if(messageIDSent()) modifySize(-_messageID.size());
|
||||
|
||||
// set messageID
|
||||
setMessageIDSent(true);
|
||||
_messageID = ShortString(s);
|
||||
|
||||
// add size
|
||||
modifySize(_messageID.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set messageID sent
|
||||
* @param bool
|
||||
*/
|
||||
void setMessageIDSent(bool b)
|
||||
{
|
||||
_bools2.set(7, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the message timestamp
|
||||
* @return uint64_t
|
||||
*/
|
||||
Timestamp timestamp() const
|
||||
{
|
||||
return _timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* set timestamp
|
||||
* @param uint64_t
|
||||
*/
|
||||
void setTimestamp(uint64_t val)
|
||||
{
|
||||
// was timestamp sent?
|
||||
if(timestampSent()) modifySize(-_timestamp.size());
|
||||
|
||||
// set timestamp
|
||||
setTimestampSent(true);
|
||||
_timestamp = Timestamp(val);
|
||||
|
||||
// add new size
|
||||
modifySize(_timestamp.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set timestamp sent
|
||||
* @param bool
|
||||
*/
|
||||
void setTimestampSent(bool b)
|
||||
{
|
||||
_bools2.set(6, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the message type name
|
||||
* @return string
|
||||
*/
|
||||
const std::string& typeName() const
|
||||
{
|
||||
return _typeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* set typename
|
||||
* @param string
|
||||
*/
|
||||
void setTypeName(std::string &s)
|
||||
{
|
||||
// was typename sent?
|
||||
if(typeNameSent()) modifySize(-_typeName.size());
|
||||
|
||||
// add typename
|
||||
setTypeNameSent(true);
|
||||
_typeName = ShortString(s);
|
||||
|
||||
// add new size
|
||||
modifySize(_typeName.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set typename sent
|
||||
* @param bool
|
||||
*/
|
||||
void setTypeNameSent(bool b)
|
||||
{
|
||||
_bools2.set(5, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the creating user id
|
||||
* @return string
|
||||
*/
|
||||
const std::string& userID() const
|
||||
{
|
||||
return _userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* set User ID
|
||||
* @param string
|
||||
*/
|
||||
void setUserID(std::string &s)
|
||||
{
|
||||
// was user id sent?
|
||||
if(userIDSent()) modifySize(-_userID.size());
|
||||
|
||||
// set new userID
|
||||
setUserIDSent(true);
|
||||
_userID = ShortString(s);
|
||||
|
||||
// add size
|
||||
modifySize(_userID.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set user id sent
|
||||
* @param bool
|
||||
*/
|
||||
void setUserIDSent(bool b)
|
||||
{
|
||||
_bools2.set(4, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the application id
|
||||
* @return string
|
||||
*/
|
||||
const std::string& appID() const
|
||||
{
|
||||
return _appID;
|
||||
}
|
||||
|
||||
/**
|
||||
* set appID
|
||||
* @param string
|
||||
*/
|
||||
void setAppID(std::string &s)
|
||||
{
|
||||
// was app id sent?
|
||||
if(appIDSent()) modifySize(-_appID.size());
|
||||
|
||||
// add new app id
|
||||
setAppIDSent(true);
|
||||
_appID = ShortString(s);
|
||||
|
||||
// add size
|
||||
modifySize(_appID.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* set app id sent
|
||||
* @param bool
|
||||
*/
|
||||
void setAppIDSent(bool b)
|
||||
{
|
||||
_bools2.set(3, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a field was sent
|
||||
* @return bool
|
||||
*/
|
||||
bool expirationSent() const { return _bools1.get(0); }
|
||||
bool replyToSent() const { return _bools1.get(1); }
|
||||
bool correlationIDSent() const { return _bools1.get(2); }
|
||||
bool prioritySent() const { return _bools1.get(3); }
|
||||
bool deliveryModeSent() const { return _bools1.get(4); }
|
||||
bool headersSent() const { return _bools1.get(5); }
|
||||
bool contentEncodingSent() const { return _bools1.get(6); }
|
||||
bool contentTypeSent() const { return _bools1.get(7); }
|
||||
bool clusterIDSent() const { return _bools2.get(2); }
|
||||
bool appIDSent() const { return _bools2.get(3); }
|
||||
bool userIDSent() const { return _bools2.get(4); }
|
||||
bool typeNameSent() const { return _bools2.get(5); }
|
||||
bool timestampSent() const { return _bools2.get(6); }
|
||||
bool messageIDSent() const { return _bools2.get(7); }
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* Class describing a basic publish frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicPublishFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Variable that no longer is in use
|
||||
* @var int16_t
|
||||
*/
|
||||
int16_t _deprecated;
|
||||
|
||||
/**
|
||||
* the name of the exchange to publish to. An empty exchange name means the default exchange.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _exchange;
|
||||
|
||||
/**
|
||||
* Message routing key
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _routingKey;
|
||||
|
||||
/**
|
||||
* BooleanSet, contains:
|
||||
* 0: mandatory, indicate mandatory routing. If set, server will return unroutable message, otherwise server silently drops message
|
||||
* 1: immediate, Request immediate delivery, if set and cannot be routed, return unroutable message.
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _bools;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// encode fields
|
||||
buffer.add(_deprecated);
|
||||
_exchange.fill(buffer);
|
||||
_routingKey.fill(buffer);
|
||||
_bools.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic publish frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param exchange name of exchange to publish to @default = ""
|
||||
* @param routingKey message routing key @default = ""
|
||||
* @param mandatory indicate mandatory routing @default = false
|
||||
* @param immediate request immediate delivery @default = false
|
||||
*/
|
||||
BasicPublishFrame(uint16_t channel, const std::string& exchange = "", const std::string& routingKey = "", bool mandatory = false, bool immediate = false) :
|
||||
BasicFrame(channel, exchange.length() + routingKey.length() + 5), // 1 extra per string (for the size), 1 for bools, 2 for deprecated field
|
||||
_deprecated(0),
|
||||
_exchange(exchange),
|
||||
_routingKey(routingKey),
|
||||
_bools(mandatory, immediate)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic publish frame from a received frame
|
||||
*
|
||||
* @param frame received frame to parse
|
||||
*/
|
||||
BasicPublishFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_deprecated(frame.nextInt16()),
|
||||
_exchange(frame),
|
||||
_routingKey(frame),
|
||||
_bools(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicPublishFrame() {}
|
||||
|
||||
/**
|
||||
* Return the name of the exchange to publish to
|
||||
* @return string
|
||||
*/
|
||||
const std::string& exchange() const
|
||||
{
|
||||
return _exchange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the routing key
|
||||
* @return string
|
||||
*/
|
||||
const std::string& routingKey() const
|
||||
{
|
||||
return _routingKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mandatory routing indication
|
||||
* @return boolean
|
||||
*/
|
||||
bool mandatory() const
|
||||
{
|
||||
return _bools.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the request immediate delivery indication
|
||||
* @return boolean
|
||||
*/
|
||||
bool immediate() const
|
||||
{
|
||||
return _bools.get(1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* Class describing a basic QOS frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicQosFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* specifies the size of the prefetch window in octets
|
||||
* @var int32_t
|
||||
*/
|
||||
int32_t _prefetchSize;
|
||||
|
||||
/**
|
||||
* specifies a prefetch window in terms of whole messages
|
||||
* @var int16_t
|
||||
*/
|
||||
int16_t _prefetchCount;
|
||||
|
||||
/**
|
||||
* apply QoS settings to entire connection
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _global;
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_prefetchSize);
|
||||
buffer.add(_prefetchCount);
|
||||
_global.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicQosFrame() {}
|
||||
/**
|
||||
* Construct a basic qos frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param prefetchSize specifies the size of the prefetch window in octets
|
||||
* @param prefetchCount specifies a prefetch window in terms of whole messages
|
||||
* @param global apply QoS settings to entire connection
|
||||
* @default false
|
||||
*/
|
||||
BasicQosFrame(uint16_t channel, int32_t prefetchSize = 0, int16_t prefetchCount = 0, bool global = false) :
|
||||
BasicFrame(channel, 7), // 4 (int32) + 2 (int16) + 1 (bool)
|
||||
_prefetchSize(prefetchSize),
|
||||
_prefetchCount(prefetchCount),
|
||||
_global(global)
|
||||
{}
|
||||
|
||||
|
||||
BasicQosFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_prefetchSize(frame.nextInt32()),
|
||||
_prefetchCount(frame.nextInt16()),
|
||||
_global(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t methodID() const
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the prefetch count
|
||||
* @return int16_t
|
||||
*/
|
||||
int16_t prefetchCount() const
|
||||
{
|
||||
return _prefetchCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the value of global
|
||||
* @return boolean
|
||||
*/
|
||||
bool global() const
|
||||
{
|
||||
return _global.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the prefetch size
|
||||
* @return int32_t
|
||||
*/
|
||||
int32_t prefetchSize() const
|
||||
{
|
||||
return _prefetchSize;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Class describing a basic QOS frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicQosOKFrame : public BasicFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base, then done (no other params)
|
||||
BasicFrame::fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic qos ok frame
|
||||
* @param channel channel we're working on
|
||||
*/
|
||||
BasicQosOKFrame(uint16_t channel) : BasicFrame(channel, 0) {}
|
||||
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
* @param frame
|
||||
*/
|
||||
BasicQosOKFrame(ReceivedFrame &frame) : BasicFrame(frame) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicQosOKFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 11;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Class describing a basic recover-async frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class BasicRecoverAsyncFrame : public BasicFrame {
|
||||
private:
|
||||
/**
|
||||
* Server will try to requeue messages. If requeue is false or requeue attempt fails, messages are discarded or dead-lettered
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _requeue;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// encode fields
|
||||
_requeue.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic recover async frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicRecoverAsyncFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_requeue(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic recover-async frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param requeue whether to attempt to requeue messages
|
||||
*/
|
||||
BasicRecoverAsyncFrame(uint16_t channel, bool requeue = false) :
|
||||
BasicFrame(channel, 1), //sizeof bool
|
||||
_requeue(requeue)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicRecoverAsyncFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the server will try to requeue
|
||||
* @return bool
|
||||
*/
|
||||
bool requeue() const
|
||||
{
|
||||
return _requeue.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* Class describing a basic recover frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class BasicRecoverFrame : public BasicFrame {
|
||||
private:
|
||||
/**
|
||||
* Server will try to requeue messages. If requeue is false or requeue attempt fails, messages are discarded or dead-lettered
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _requeue;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// encode fields
|
||||
_requeue.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic recover frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicRecoverFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_requeue(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic recover frame
|
||||
*
|
||||
* @param channel channel ID
|
||||
* @param requeue whether to attempt to requeue messages
|
||||
*/
|
||||
BasicRecoverFrame(uint16_t channel, bool requeue = false) :
|
||||
BasicFrame(channel, 1), //sizeof bool
|
||||
_requeue(requeue)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicRecoverFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 110;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the server will try to requeue
|
||||
* @return bool
|
||||
*/
|
||||
bool requeue() const
|
||||
{
|
||||
return _requeue.get(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Class describing a basic recover-async frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class BasicRecoverOKFrame : public BasicFrame {
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base then done, no other fields to encode
|
||||
BasicFrame::fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic recover ok frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicRecoverOKFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic recover ok frame
|
||||
*
|
||||
* @param channel channel id
|
||||
*/
|
||||
BasicRecoverOKFrame(uint16_t channel) :
|
||||
BasicFrame(channel, 0)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicRecoverOKFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 111;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* Class describing a basic reject frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class BasicRejectFrame : public BasicFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* server-assigned and channel specific delivery tag
|
||||
* @var int64_t
|
||||
*/
|
||||
int64_t _deliveryTag;
|
||||
|
||||
/**
|
||||
* Server will try to requeue messages. If requeue is false or requeue attempt fails, messages are discarded or dead-lettered
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _requeue;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// encode fields
|
||||
buffer.add(_deliveryTag);
|
||||
_requeue.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* construct a basic reject frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
BasicRejectFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_deliveryTag(frame.nextInt64()),
|
||||
_requeue(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic reject frame
|
||||
*
|
||||
* @param channel channel id
|
||||
* @param deliveryTag server-assigned and channel specific delivery tag
|
||||
* @param requeue whether to attempt to requeue messages
|
||||
*/
|
||||
BasicRejectFrame(uint16_t channel, int64_t deliveryTag, bool requeue = true) :
|
||||
BasicFrame(channel, 9), // 8 for uint64_t, 1 for bool
|
||||
_deliveryTag(deliveryTag),
|
||||
_requeue(requeue)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicRejectFrame() {}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 90;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server-assigned and channel specific delivery tag
|
||||
* @return uint64_t
|
||||
*/
|
||||
int64_t deliveryTag() const
|
||||
{
|
||||
return _deliveryTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the server will try to requeue
|
||||
* @return bool
|
||||
*/
|
||||
bool requeue() const
|
||||
{
|
||||
return _requeue.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* Class describing a basic return frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BasicReturnFrame : public BasicFrame {
|
||||
private:
|
||||
/**
|
||||
* reply code
|
||||
* @var int16_t
|
||||
*/
|
||||
int16_t _replyCode;
|
||||
|
||||
/**
|
||||
* reply text
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _replyText;
|
||||
|
||||
/**
|
||||
* the name of the exchange to publish to. An empty exchange name means the default exchange.
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _exchange;
|
||||
|
||||
/**
|
||||
* Message routing key
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _routingKey;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
BasicFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_replyCode);
|
||||
_replyText.fill(buffer);
|
||||
_exchange.fill(buffer);
|
||||
_routingKey.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a basic return frame
|
||||
*
|
||||
* @param channel channel identifier
|
||||
* @param replyCode reply code
|
||||
* @param replyText reply text
|
||||
* @param exchange name of exchange to publish to
|
||||
* @param routingKey message routing key
|
||||
*/
|
||||
BasicReturnFrame(uint16_t channel, int16_t replyCode, const std::string& replyText = "", const std::string& exchange = "", const std::string& routingKey = "") :
|
||||
BasicFrame(channel, replyText.length() + exchange.length() + routingKey.length() + 5), // 3 for each string (extra size byte), 2 for uint16_t
|
||||
_replyCode(replyCode),
|
||||
_replyText(replyText),
|
||||
_exchange(exchange),
|
||||
_routingKey(routingKey)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a basic return frame from a received frame
|
||||
*
|
||||
* @param received frame
|
||||
*/
|
||||
BasicReturnFrame(ReceivedFrame &frame) :
|
||||
BasicFrame(frame),
|
||||
_replyCode(frame.nextInt16()),
|
||||
_replyText(frame),
|
||||
_exchange(frame),
|
||||
_routingKey(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BasicReturnFrame() {}
|
||||
|
||||
/**
|
||||
* Return the name of the exchange to publish to
|
||||
* @return string
|
||||
*/
|
||||
const std::string& exchange() const
|
||||
{
|
||||
return _exchange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the routing key
|
||||
* @return string
|
||||
*/
|
||||
const std::string& routingKey() const
|
||||
{
|
||||
return _routingKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method ID
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the reply text
|
||||
* @return string
|
||||
*/
|
||||
const std::string& replyText() const
|
||||
{
|
||||
return _replyText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the reply code
|
||||
* @return int16_t
|
||||
*/
|
||||
int16_t replyCode() const
|
||||
{
|
||||
return _replyCode;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Class describing an AMQP Body Frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class BodyFrame : public ExtFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Payload of the frame
|
||||
* Payload can be any number of octets
|
||||
* @var vector<uint8_t>
|
||||
*/
|
||||
std::string _payload;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a body frame to a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExtFrame::fill(buffer);
|
||||
|
||||
// add payload to buffer
|
||||
buffer.add(_payload);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a body frame
|
||||
*
|
||||
* @param channel channel identifier
|
||||
* @param payload payload of the body
|
||||
*/
|
||||
BodyFrame(uint16_t channel, const std::string &payload) :
|
||||
ExtFrame(channel, payload.size()),
|
||||
_payload(payload)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor for incoming data
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
* @return shared pointer to newly created frame
|
||||
*/
|
||||
BodyFrame(ReceivedFrame& frame) :
|
||||
ExtFrame(frame),
|
||||
_payload(frame.nextData(frame.payloadSize()), frame.payloadSize())
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~BodyFrame() {}
|
||||
|
||||
/**
|
||||
* Return the type of frame
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t type() const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the payload of the body
|
||||
* @return vector<UOctet>
|
||||
*/
|
||||
const std::string& payload() const
|
||||
{
|
||||
return _payload;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* ChannelCloseFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "channelcloseframe.h"
|
||||
#include "channelcloseokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ChannelCloseFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// check if we have a channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// send back an ok frame
|
||||
connection->send(ChannelCloseOKFrame(this->channel()));
|
||||
|
||||
// what if channel doesn't exist?
|
||||
if (!channel) return false;
|
||||
|
||||
// report to the handler
|
||||
channel->reportChannelError(text());
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* Class describing a channel close frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ChannelCloseFrame : public ChannelFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The reply code
|
||||
* @var int16_t
|
||||
*/
|
||||
int16_t _code;
|
||||
|
||||
/**
|
||||
* The reply text
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _text;
|
||||
|
||||
/**
|
||||
* The failing class id if applicable
|
||||
* @note: will be 0 if no error occured
|
||||
* @var int16_t
|
||||
*/
|
||||
int16_t _failingClass;
|
||||
|
||||
/**
|
||||
* The failing method id if applicable
|
||||
* @note: will be 0 if no error occured
|
||||
* @var int16_t
|
||||
*/
|
||||
int16_t _failingMethod;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ChannelFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_code);
|
||||
_text.fill(buffer);
|
||||
buffer.add(_failingClass);
|
||||
buffer.add(_failingMethod);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Construct a channel close frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ChannelCloseFrame(ReceivedFrame &frame) :
|
||||
ChannelFrame(frame),
|
||||
_code(frame.nextInt16()),
|
||||
_text(frame),
|
||||
_failingClass(frame.nextInt16()),
|
||||
_failingMethod(frame.nextInt16())
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a channel close frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param code reply code
|
||||
* @param text reply text
|
||||
* @param failingClass failing class id if applicable
|
||||
* @param failingMethod failing method id if applicable
|
||||
*/
|
||||
ChannelCloseFrame(uint16_t channel, uint16_t code = 0, const std::string& text = "", uint16_t failingClass = 0, uint16_t failingMethod = 0) :
|
||||
ChannelFrame(channel, (text.length() + 7)), // sizeof code, failingclass, failingmethod (2byte + 2byte + 2byte) + text length + text length byte
|
||||
_code(code),
|
||||
_text(text),
|
||||
_failingClass(failingClass),
|
||||
_failingMethod(failingMethod)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelCloseFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reply code
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t code() const
|
||||
{
|
||||
return _code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reply text
|
||||
* @return string
|
||||
*/
|
||||
const std::string& text() const
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failing class id if applicable
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t failingClass() const
|
||||
{
|
||||
return _failingClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failing method id if applicable
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t failingMethod() const
|
||||
{
|
||||
return _failingMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* ChannelCloseOkFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "channelcloseokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ChannelCloseOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// we need the appropriate channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// channel does not exist
|
||||
if(!channel) return false;
|
||||
|
||||
// report that the channel is closed
|
||||
channel->reportClosed();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Class describing a channel close acknowledgement frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ChannelCloseOKFrame : public ChannelFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ChannelFrame::fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a channel close ok frame
|
||||
* @param frame
|
||||
*/
|
||||
ChannelCloseOKFrame(ReceivedFrame &frame) :
|
||||
ChannelFrame(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a channel close ok frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
*/
|
||||
ChannelCloseOKFrame(uint16_t channel) :
|
||||
ChannelFrame(channel, 0)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelCloseOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 41;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* Class describing a channel flow frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ChannelFlowFrame : public ChannelFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Enable or disable the channel flow
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _active;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ChannelFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
_active.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a channel flow frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ChannelFlowFrame(ReceivedFrame &frame) :
|
||||
ChannelFrame(frame),
|
||||
_active(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a channel flow frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param active enable or disable channel flow
|
||||
*/
|
||||
ChannelFlowFrame(uint16_t channel, bool active) :
|
||||
ChannelFrame(channel, 1), //sizeof bool
|
||||
_active(active)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelFlowFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is channel flow active or not?
|
||||
* @return bool
|
||||
*/
|
||||
bool active() const
|
||||
{
|
||||
return _active.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* ChannelFlowOkFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "channelflowokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ChannelFlowOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// we need the appropriate channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// channel does not exist
|
||||
if(!channel) return false;
|
||||
|
||||
// is the flow active?
|
||||
if (active()) channel->reportResumed();
|
||||
else channel->reportPaused();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Class describing a channel flow acknowledgement frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ChannelFlowOKFrame : public ChannelFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Is the channel flow currently active?
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _active;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ChannelFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
_active.fill(buffer);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Construct a channel flow frame
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
ChannelFlowOKFrame(ReceivedFrame &frame) :
|
||||
ChannelFrame(frame),
|
||||
_active(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a channel flow frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param active enable or disable channel flow
|
||||
*/
|
||||
ChannelFlowOKFrame(uint16_t channel, bool active) :
|
||||
ChannelFrame(channel, 1), //sizeof bool
|
||||
_active(active)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelFlowOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 21;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is channel flow active?
|
||||
* @return bool
|
||||
*/
|
||||
bool active() const
|
||||
{
|
||||
return _active.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Class describing an AMQP channel frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ChannelFrame : public MethodFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Constructor for a channelFrame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param size size of the frame
|
||||
*/
|
||||
ChannelFrame(uint16_t channel, uint32_t size) : MethodFrame(channel, size) {}
|
||||
|
||||
/**
|
||||
* Constructor that parses an incoming frame
|
||||
* @param frame The received frame
|
||||
*/
|
||||
ChannelFrame(ReceivedFrame &frame) : MethodFrame(frame) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelFrame() {}
|
||||
|
||||
/**
|
||||
* Class id
|
||||
* @return uint16_t
|
||||
*
|
||||
* @todo check if override keyword is used in all places
|
||||
*/
|
||||
virtual uint16_t classID() const override
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,385 @@
|
|||
/**
|
||||
* Channel.cpp
|
||||
*
|
||||
* Implementation for a channel
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "channelopenframe.h"
|
||||
#include "channelflowframe.h"
|
||||
#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"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Construct a channel object
|
||||
* @param parent
|
||||
* @param connection
|
||||
* @param handler
|
||||
*/
|
||||
ChannelImpl::ChannelImpl(Channel *parent, Connection *connection, ChannelHandler *handler) :
|
||||
_parent(parent),
|
||||
_connection(connection),
|
||||
_handler(handler)
|
||||
{
|
||||
// add the channel to the connection
|
||||
_id = connection->_implementation.add(this);
|
||||
|
||||
// check if the id is valid
|
||||
if (_id == 0)
|
||||
{
|
||||
// this is invalid
|
||||
_state = state_closed;
|
||||
|
||||
// invalid id, this channel can not exist
|
||||
handler->onChannelError(_parent, "Max number of channels reached");
|
||||
}
|
||||
else
|
||||
{
|
||||
// busy connecting
|
||||
_state = state_connected;
|
||||
|
||||
// valid id, send a channel open frame
|
||||
send(ChannelOpenFrame(_id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
ChannelImpl::~ChannelImpl()
|
||||
{
|
||||
// remove this channel from the connection
|
||||
_connection->_implementation.remove(this);
|
||||
|
||||
// leap out if already disconnected
|
||||
if (!connected()) return;
|
||||
|
||||
// close the channel now
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause deliveries on a channel
|
||||
*
|
||||
* This will stop all incoming messages
|
||||
*
|
||||
* This method returns true if the request to pause has been sent to the
|
||||
* broker. This does not necessarily mean that the channel is already
|
||||
* paused.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::pause()
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send a flow frame
|
||||
send(ChannelFlowFrame(_id, false));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume a paused channel
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::resume()
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send a flow frame
|
||||
send(ChannelFlowFrame(_id, true));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::startTransaction()
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send a flow frame
|
||||
send(TransactionSelectFrame(_id));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the current transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::commitTransaction()
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send a flow frame
|
||||
send(TransactionCommitFrame(_id));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the current transaction
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::rollbackTransaction()
|
||||
{
|
||||
std::cout << "send rollback frame" << std::endl;
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send a flow frame
|
||||
send(TransactionRollbackFrame(_id));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current channel
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::close()
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send a flow frame
|
||||
send(ChannelCloseFrame(_id));
|
||||
|
||||
// now it is closed
|
||||
_state = state_closed;
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* declare an exchange
|
||||
* @param name name of the exchange to declare
|
||||
* @param type type of exchange
|
||||
* @param flags additional settings for the exchange
|
||||
* @param arguments additional arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::declareExchange(const std::string &name, ExchangeType type, int flags, const Table &arguments)
|
||||
{
|
||||
// must be connected
|
||||
if(!connected()) return false;
|
||||
|
||||
std::string exchangeType;
|
||||
if(type == ExchangeType::fanout) exchangeType = "fanout";
|
||||
if(type == ExchangeType::direct) exchangeType = "direct";
|
||||
if(type == ExchangeType::topic) exchangeType = "topic";
|
||||
if(type == ExchangeType::headers)exchangeType = "headers";
|
||||
// send declare exchange frame
|
||||
send(ExchangeDeclareFrame(_id, name, exchangeType, (flags & passive) != 0, (flags & durable) != 0, (flags & nowait) != 0, arguments));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* bind an exchange
|
||||
* @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
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::bindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags, const Table &arguments)
|
||||
{
|
||||
// must be connected
|
||||
if(!connected()) return false;
|
||||
|
||||
// send exchange bind frame
|
||||
send(ExchangeBindFrame(_id, target, source, routingkey, (flags & nowait) != 0, arguments));
|
||||
|
||||
//done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* unbind two exchanges
|
||||
* @param source the source exchange
|
||||
* @param target the target exchange
|
||||
* @param routingkey the routing key
|
||||
* @param flags optional flags
|
||||
* @param arguments additional unbind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::unbindExchange(const std::string &source, const std::string &target, const std::string &routingkey, int flags, const Table &arguments)
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send exchange unbind frame
|
||||
send(ExchangeUnbindFrame(_id, target, source, routingkey, (flags & nowait) != 0, arguments));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove an exchange
|
||||
* @param name name of the exchange to remove
|
||||
* @param flags additional settings for deleting the exchange
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::removeExchange(const std::string &name, int flags)
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send delete exchange frame
|
||||
send(ExchangeDeleteFrame(_id, name, (flags & ifunused) != 0, (flags & nowait) != 0));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* declare a queue
|
||||
* @param name queue name
|
||||
* @param flags additional settings for the queue
|
||||
* @param arguments additional arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::declareQueue(const std::string &name, int flags, const Table &arguments)
|
||||
{
|
||||
// must be connected
|
||||
if (!connected()) return false;
|
||||
|
||||
// send the queuedeclareframe
|
||||
send(QueueDeclareFrame(_id, name, (flags & passive) != 0, (flags & durable) != 0, (flags & durable) != 0, (flags & autodelete) != 0, (flags & nowait) != 0, arguments));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a queue to an exchange
|
||||
* @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
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::bindQueue(const std::string &exchangeName, const std::string &queueName, const std::string &routingkey, int flags, const Table &arguments)
|
||||
{
|
||||
// must be connected
|
||||
if(!connected()) return false;
|
||||
|
||||
// send the bind queue frame
|
||||
send(QueueBindFrame(_id, queueName, exchangeName, routingkey, (flags & nowait) != 0, arguments));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind a queue from an exchange
|
||||
* @param exchange the source exchange
|
||||
* @param queue the target queue
|
||||
* @param routingkey the routing key
|
||||
* @param arguments additional bind arguments
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::unbindQueue(const std::string &exchange, const std::string &queue, const std::string &routingkey, const Table &arguments)
|
||||
{
|
||||
// must be connected
|
||||
if(!connected()) return false;
|
||||
|
||||
// send the unbind queue frame
|
||||
send(QueueUnbindFrame(_id, queue, exchange, routingkey, arguments));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge a queue
|
||||
* @param queue queue to purge
|
||||
* @param flags additional flags
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::purgeQueue(const std::string &name, int flags)
|
||||
{
|
||||
// must be connected
|
||||
if(!connected()) return false;
|
||||
|
||||
// send the queue purge frame
|
||||
send(QueuePurgeFrame(_id, name, (flags & nowait) != 0));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a queue
|
||||
* @param queue queue to remove
|
||||
* @param flags additional flags
|
||||
* @return bool
|
||||
*/
|
||||
bool ChannelImpl::removeQueue(const std::string &name, int flags)
|
||||
{
|
||||
// must be connected
|
||||
if(!connected()) return false;
|
||||
|
||||
// send the remove queue frame
|
||||
send(QueueDeleteFrame(_id, name, (flags & ifunused) != 0,(flags & ifempty) != 0,(flags & nowait) != 0));
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a frame over the channel
|
||||
* @param frame frame to send
|
||||
* @return size_t number of bytes sent
|
||||
*/
|
||||
size_t ChannelImpl::send(const Frame &frame)
|
||||
{
|
||||
// send to tcp connection
|
||||
return _connection->_implementation.send(frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Class describing a channel open frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ChannelOpenFrame : public ChannelFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const
|
||||
{
|
||||
// call base
|
||||
ChannelFrame::fill(buffer);
|
||||
|
||||
// add deprecated data
|
||||
ShortString unused;
|
||||
|
||||
// add to the buffer
|
||||
unused.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor to create a channelOpenFrame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
*/
|
||||
ChannelOpenFrame(uint16_t channel) : ChannelFrame(channel, 1) {} // 1 for the deprecated shortstring size
|
||||
|
||||
/**
|
||||
* Construct to parse a received frame
|
||||
* @param frame
|
||||
*/
|
||||
ChannelOpenFrame(ReceivedFrame &frame) : ChannelFrame(frame)
|
||||
{
|
||||
// deprecated argument
|
||||
ShortString unused(frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelOpenFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* ChannelOpenOkFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "channelopenokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ChannelOpenOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// we need the appropriate channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// channel does not exist
|
||||
if(!channel) return false;
|
||||
|
||||
// report that the channel is open
|
||||
channel->reportReady();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Class describing a channel open acknowledgement frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ChannelOpenOKFrame : public ChannelFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ChannelFrame::fill(buffer);
|
||||
|
||||
// create and encode the silly deprecated argument
|
||||
LongString unused;
|
||||
|
||||
// add to the buffer
|
||||
unused.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor based on client information
|
||||
* @param channel Channel identifier
|
||||
*/
|
||||
ChannelOpenOKFrame(uint16_t channel) : ChannelFrame(channel, 4) {} // 4 for the longstring size value
|
||||
|
||||
/**
|
||||
* Constructor based on incoming frame
|
||||
* @param frame
|
||||
*/
|
||||
ChannelOpenOKFrame(ReceivedFrame &frame) : ChannelFrame(frame)
|
||||
{
|
||||
// read in a deprecated argument
|
||||
LongString unused(frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ChannelOpenOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 11;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* ConnectionCloseFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "connectioncloseframe.h"
|
||||
#include "connectioncloseokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ConnectionCloseFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// send back the ok frame
|
||||
connection->send(ConnectionCloseOKFrame());
|
||||
|
||||
// no need to check for a channel, the error is connection wide
|
||||
// report the error on the connection
|
||||
connection->reportConnectionError(text());
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* Class describing connection close frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionCloseFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The reply code
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _code;
|
||||
|
||||
/**
|
||||
* The reply text
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _text;
|
||||
|
||||
/**
|
||||
* Class id for failing class, if applicable
|
||||
* Will be 0 in absence of errors
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _failingClass;
|
||||
|
||||
/**
|
||||
* Method id for failinv class, if applicable
|
||||
* Will be 0 in absence of errors
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _failingMethod;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_code);
|
||||
_text.fill(buffer);
|
||||
buffer.add(_failingClass);
|
||||
buffer.add(_failingMethod);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a connection close frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionCloseFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_code(frame.nextUint16()),
|
||||
_text(frame),
|
||||
_failingClass(frame.nextUint16()),
|
||||
_failingMethod(frame.nextUint16())
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connection close frame
|
||||
*
|
||||
* @param code the reply code
|
||||
* @param text the reply text
|
||||
* @param failingClass id of the failing class if applicable
|
||||
* @param failingMethod id of the failing method if applicable
|
||||
*/
|
||||
ConnectionCloseFrame(uint16_t code, const std::string text, uint16_t failingClass = 0, uint16_t failingMethod = 0) :
|
||||
ConnectionFrame(text.length() + 7), // 1 for extra string byte, 2 for each uint16
|
||||
_code(code),
|
||||
_text(text),
|
||||
_failingClass(failingClass),
|
||||
_failingMethod(failingMethod)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionCloseFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t methodID() const
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reply code
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t code() const
|
||||
{
|
||||
return _code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reply text
|
||||
* @return string
|
||||
*/
|
||||
const std::string& text() const
|
||||
{
|
||||
return _text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failing class id if applicable
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t failingClass() const
|
||||
{
|
||||
return _failingClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the failing method id if applicable
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t failingMethod() const
|
||||
{
|
||||
return _failingMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Class describing connection close acknowledgement frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionCloseOKFrame : public ConnectionFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Constructor based on a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionCloseOKFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* construct a channelcloseokframe object
|
||||
*/
|
||||
ConnectionCloseOKFrame() :
|
||||
ConnectionFrame(0)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionCloseOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 51;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Class describing an AMQP connection frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionFrame : public MethodFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Constructor for a connectionFrame
|
||||
*
|
||||
* A connection frame never has a channel identifier, so this is passed
|
||||
* as zero to the base constructor
|
||||
*
|
||||
* @param size size of the frame
|
||||
*/
|
||||
ConnectionFrame(uint32_t size) : MethodFrame(0, size) {}
|
||||
|
||||
/**
|
||||
* Constructor based on a received frame
|
||||
* @param frame
|
||||
*/
|
||||
ConnectionFrame(ReceivedFrame &frame) : MethodFrame(frame) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionFrame() {}
|
||||
|
||||
/**
|
||||
* Class id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t classID() const override
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/**
|
||||
* ConnectionImpl.cpp
|
||||
*
|
||||
* Implementation of an AMQP connection
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "protocolheaderframe.h"
|
||||
#include "exception.h"
|
||||
#include "protocolexception.h"
|
||||
|
||||
/**
|
||||
* set namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
ConnectionImpl::~ConnectionImpl()
|
||||
{
|
||||
// still connected
|
||||
if (_state == state_invalid) return;
|
||||
|
||||
// still in a connected state - should we send the close frame?
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the connection
|
||||
*/
|
||||
void ConnectionImpl::initialize()
|
||||
{
|
||||
// we need a protocol header
|
||||
ProtocolHeaderFrame header;
|
||||
|
||||
// send out the protocol header
|
||||
send(header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a channel to the connection, and return the channel ID that it
|
||||
* is allowed to use, or 0 when no more ID's are available
|
||||
* @param channel
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t ConnectionImpl::add(ChannelImpl *channel)
|
||||
{
|
||||
// check if we have exceeded the limit already
|
||||
if (_maxChannels > 0 && _channels.size() >= _maxChannels) return 0;
|
||||
|
||||
// keep looping to find an id that is not in use
|
||||
while (true)
|
||||
{
|
||||
// is this id in use?
|
||||
if (_nextFreeChannel > 0 && _channels.find(_nextFreeChannel) == _channels.end()) break;
|
||||
|
||||
// id is in use, move on
|
||||
_nextFreeChannel++;
|
||||
}
|
||||
|
||||
// we have a new channel
|
||||
_channels[_nextFreeChannel] = channel;
|
||||
|
||||
// done
|
||||
return _nextFreeChannel++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a channel
|
||||
* @param channel
|
||||
*/
|
||||
void ConnectionImpl::remove(ChannelImpl *channel)
|
||||
{
|
||||
// skip zero channel
|
||||
if (channel->id() == 0) return;
|
||||
|
||||
// remove it
|
||||
_channels.erase(channel->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the buffer into a recognized frame
|
||||
*
|
||||
* Every time that data comes in on the connection, you should call this method to parse
|
||||
* the incoming data, and let it handle by the AMQP library. This method returns the number
|
||||
* of bytes that were processed.
|
||||
*
|
||||
* If not all bytes could be processed because it only contained a partial frame, you should
|
||||
* call this same method later on when more data is available. The AMQP library does not do
|
||||
* any buffering, so it is up to the caller to ensure that the old data is also passed in that
|
||||
* later call.
|
||||
*
|
||||
* @param buffer buffer to decode
|
||||
* @param size size of the buffer to decode
|
||||
* @return number of bytes that were processed
|
||||
*/
|
||||
size_t ConnectionImpl::parse(char *buffer, size_t size)
|
||||
{
|
||||
// number of bytes processed
|
||||
size_t processed = 0;
|
||||
|
||||
// create a monitor object that checks if the connection still exists
|
||||
Monitor monitor(this);
|
||||
|
||||
// keep looping until we have processed all bytes, and the monitor still
|
||||
// indicates that the connection is in a valid state
|
||||
while (size > 0 && monitor.valid())
|
||||
{
|
||||
// prevent protocol exceptions
|
||||
try
|
||||
{
|
||||
// try to recognize the frame
|
||||
ReceivedFrame receivedFrame(buffer, size, _maxFrame);
|
||||
if (!receivedFrame.complete()) return processed;
|
||||
|
||||
// process the frame
|
||||
receivedFrame.process(this);
|
||||
|
||||
// number of bytes processed
|
||||
size_t bytes = receivedFrame.totalSize();
|
||||
|
||||
// add bytes
|
||||
processed += bytes; size -= bytes; buffer += bytes;
|
||||
}
|
||||
catch (const ProtocolException &exception)
|
||||
{
|
||||
// something terrible happened on the protocol (like data out of range)
|
||||
reportConnectionError(exception.what());
|
||||
|
||||
// done
|
||||
return processed;
|
||||
}
|
||||
}
|
||||
|
||||
// done
|
||||
return processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the connection
|
||||
* This will close all channels
|
||||
* @return bool
|
||||
*/
|
||||
bool ConnectionImpl::close()
|
||||
{
|
||||
// leap out if not yet connected
|
||||
if (_state != state_connected) return false;
|
||||
|
||||
// loop over all channels
|
||||
for (auto iter = _channels.begin(); iter != _channels.end(); iter++)
|
||||
{
|
||||
// close the channel
|
||||
iter->second->close();
|
||||
}
|
||||
|
||||
// we're in a new state
|
||||
_state = state_invalid;
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a frame over the connection
|
||||
* @param frame The frame to send
|
||||
* @return size_t Number of bytes sent
|
||||
*/
|
||||
size_t ConnectionImpl::send(const Frame &frame)
|
||||
{
|
||||
std::cout << "send frame of " << frame.totalSize() << " bytes" << std::endl;
|
||||
|
||||
// we need an output buffer
|
||||
OutBuffer buffer(frame.totalSize());
|
||||
|
||||
// fill the buffer
|
||||
frame.fill(buffer);
|
||||
|
||||
// append an end of frame byte (but not when still negotiating the protocol)
|
||||
if (_state != state_protocol) buffer.add((uint8_t)206);
|
||||
|
||||
// send the buffer
|
||||
_handler->onData(_parent, buffer.data(), buffer.size());
|
||||
|
||||
// done
|
||||
return buffer.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Quality of Service (QOS) of the entire connection
|
||||
* @param prefetchSize maximum size (in octets) of messages to be prefetched
|
||||
* @param prefetchCount maximum number of messages to prefetch
|
||||
* @return bool whether the Qos frame is sent.
|
||||
*/
|
||||
//bool Connection::setQOS(uint32_t prefetchSize = 0, uint16_t prefetchCount = 0)
|
||||
//{
|
||||
// BasicQosFrame *frame = new BasicQosFrame(0, prefetchSize, prefetchCount, true);
|
||||
// if(_connection->send(frame->buffer(), frame->totalSize()) != frame->totalSize()) return false;
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* Class describing connection vhost open frame
|
||||
*
|
||||
* This frame is sent by the client after the connection is started and the
|
||||
* capacity has been tuned, to open the connection to a specific vhost.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionOpenFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Virtual host name
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _vhost;
|
||||
|
||||
/**
|
||||
* deprecated values, still need to read them somehow in the constructor
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _deprecatedCapabilities;
|
||||
|
||||
/**
|
||||
* More deprecated values
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _deprecatedInsist;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// encode fields
|
||||
_vhost.fill(buffer);
|
||||
_deprecatedCapabilities.fill(buffer);
|
||||
_deprecatedInsist.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Open a virtual host
|
||||
*
|
||||
* @param vhost name of virtual host to open
|
||||
*/
|
||||
ConnectionOpenFrame(const std::string &vhost) :
|
||||
ConnectionFrame(vhost.length() + 3), // length of vhost + byte to encode this length + deprecated shortstring size + deprecated bool
|
||||
_vhost(vhost),
|
||||
_deprecatedCapabilities(""),
|
||||
_deprecatedInsist()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor based on a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionOpenFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_vhost(frame),
|
||||
_deprecatedCapabilities(frame),
|
||||
_deprecatedInsist(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionOpenFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
*/
|
||||
uint16_t methodID() const
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the vhost name
|
||||
* @return string
|
||||
*/
|
||||
const std::string& vhost() const
|
||||
{
|
||||
return _vhost;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* ConnectionOpenOKFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "connectionopenokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ConnectionOpenOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// all is ok, mark the connection as connected
|
||||
connection->setConnected();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Class describing connection vhost open acknowledgement frame
|
||||
*
|
||||
* Message sent by the server to the client to confirm that a connection to
|
||||
* a vhost could be established
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionOpenOKFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Deprecated field we need to read
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _deprecatedKnownHosts;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// add deprecaed field
|
||||
_deprecatedKnownHosts.fill(buffer);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Construct a connectionopenokframe from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionOpenOKFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_deprecatedKnownHosts(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connectionopenokframe
|
||||
*
|
||||
*/
|
||||
ConnectionOpenOKFrame() :
|
||||
ConnectionFrame(1), // for the deprecated shortstring
|
||||
_deprecatedKnownHosts("")
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionOpenOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 41;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Class describing connection setup security challenge
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionSecureFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The security challenge
|
||||
* @var LongString
|
||||
*/
|
||||
LongString _challenge;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// encode fields
|
||||
_challenge.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a connection security challenge frame
|
||||
*
|
||||
* @param challenge the challenge
|
||||
*/
|
||||
ConnectionSecureFrame(const std::string& challenge) :
|
||||
ConnectionFrame(challenge.length() + 4), // 4 for the length of the challenge (uint32_t)
|
||||
_challenge(challenge)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connection secure frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionSecureFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_challenge(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionSecureFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the challenge
|
||||
* @return string
|
||||
*/
|
||||
const std::string& challenge() const
|
||||
{
|
||||
return _challenge;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Class describing connection setup security challenge response
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionSecureOKFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The security challenge response
|
||||
* @var LongString
|
||||
*/
|
||||
LongString _response;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
_response.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a connection security challenge response frame
|
||||
*
|
||||
* @param response the challenge response
|
||||
*/
|
||||
ConnectionSecureOKFrame(const std::string& response) :
|
||||
ConnectionFrame(response.length() + 4), //response length + uint32_t for encoding the length
|
||||
_response(response)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connection security challenge response frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionSecureOKFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_response(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionSecureOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 21;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the challenge response
|
||||
* @return string
|
||||
*/
|
||||
const std::string& response() const
|
||||
{
|
||||
return _response;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* ConnectionStartFrame.h
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "connectionstartframe.h"
|
||||
#include "connectionstartokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the connection start frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
* @internal
|
||||
*/
|
||||
bool ConnectionStartFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// @todo we must still be in protocol handshake mode
|
||||
|
||||
// move connection to handshake mode
|
||||
connection->setProtocolOk();
|
||||
|
||||
// the peer properties
|
||||
Table properties;
|
||||
|
||||
// fill the peer properties
|
||||
properties["product"] = "Copernica AMQP library";
|
||||
properties["version"] = "0.1";
|
||||
properties["platform"] = "Ubuntu";
|
||||
properties["copyright"] = "Copyright 2014 Copernica BV";
|
||||
properties["information"] = "";
|
||||
|
||||
// the start ok frame we'd like to send back
|
||||
ConnectionStartOKFrame frame(properties, "PLAIN", connection->login().saslPlain(), "en_US");
|
||||
|
||||
// send back a connection start ok frame
|
||||
connection->send(frame);
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* Class describing initial connection setup
|
||||
*
|
||||
* This frame is sent by the server to the client, right after the connection
|
||||
* is opened. It contains the initial connection properties, and the protocol
|
||||
* number.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionStartFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Major AMQP version number
|
||||
* @var uint8_t
|
||||
*/
|
||||
uint8_t _major;
|
||||
|
||||
/**
|
||||
* Minor AMQP version number
|
||||
* @var uint8_t
|
||||
*/
|
||||
uint8_t _minor;
|
||||
|
||||
/**
|
||||
* Additional server properties
|
||||
* @note: exact properties are not specified
|
||||
* and are implementation-dependent
|
||||
* @var Table
|
||||
*/
|
||||
Table _properties;
|
||||
|
||||
/**
|
||||
* Available security mechanisms
|
||||
* @var LongString
|
||||
*/
|
||||
LongString _mechanisms;
|
||||
|
||||
/**
|
||||
* Available message locales
|
||||
* @var LongString
|
||||
*/
|
||||
LongString _locales;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// encode all fields
|
||||
buffer.add(_major);
|
||||
buffer.add(_minor);
|
||||
_properties.fill(buffer);
|
||||
_mechanisms.fill(buffer);
|
||||
_locales.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Client-side constructer for a connection start frame
|
||||
*
|
||||
* @param major major protocol version
|
||||
* @param minor minor protocol version
|
||||
* @param properties server properties
|
||||
* @param mechanisms available security mechanisms
|
||||
* @param locales available locales
|
||||
*/
|
||||
ConnectionStartFrame(uint8_t major, uint8_t minor, const Table& properties, const std::string& mechanisms, const std::string& locales) :
|
||||
ConnectionFrame((properties.size() + mechanisms.length() + locales.length() + 10)), // 4 for each longstring (size-uint32), 2 major/minor
|
||||
_major(major),
|
||||
_minor(minor),
|
||||
_properties(properties),
|
||||
_mechanisms(mechanisms),
|
||||
_locales(locales)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connection start frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionStartFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_major(frame.nextUint8()),
|
||||
_minor(frame.nextUint8()),
|
||||
_properties(frame),
|
||||
_mechanisms(frame),
|
||||
_locales(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionStartFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Major AMQP version number
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t major() const
|
||||
{
|
||||
return _major;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minor AMQP version number
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t minor() const
|
||||
{
|
||||
return _minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional server properties
|
||||
* @note: exact properties are not specified
|
||||
* and are implementation-dependent
|
||||
*
|
||||
* @return Table
|
||||
*/
|
||||
const Table& properties() const
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Available security mechanisms
|
||||
* @return string
|
||||
*/
|
||||
const std::string &mechanisms() const
|
||||
{
|
||||
return _mechanisms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Available message locales
|
||||
* @return string
|
||||
*/
|
||||
const std::string &locales() const
|
||||
{
|
||||
return _locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the connection start frame
|
||||
* @param connection
|
||||
* @return bool
|
||||
* @internal
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* Class describing initial connection setup acknowledge frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionStartOKFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Additional client properties
|
||||
* @note: exact properties are not specified
|
||||
* and are implementation-dependent
|
||||
* @var Table
|
||||
*/
|
||||
Table _properties;
|
||||
|
||||
/**
|
||||
* The selected security mechanism
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _mechanism;
|
||||
|
||||
/**
|
||||
* The security response
|
||||
* @var LongString
|
||||
*/
|
||||
LongString _response;
|
||||
|
||||
/**
|
||||
* The selected locale
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _locale;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
_properties.fill(buffer);
|
||||
_mechanism.fill(buffer);
|
||||
_response.fill(buffer);
|
||||
_locale.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a connection start ok frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionStartOKFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_properties(frame),
|
||||
_mechanism(frame),
|
||||
_response(frame),
|
||||
_locale(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connection start ok frame
|
||||
*
|
||||
* @param properties client propertes
|
||||
* @param mechanism selected security mechanism
|
||||
* @param response security response data
|
||||
* @param locale selected locale.
|
||||
*/
|
||||
ConnectionStartOKFrame(const Table& properties, const std::string& mechanism, const std::string& response, const std::string& locale) :
|
||||
ConnectionFrame((properties.size() + mechanism.length() + response.length() + locale.length() + 6)), // 1 byte extra per shortstring, 4 per longstring
|
||||
_properties(properties),
|
||||
_mechanism(mechanism),
|
||||
_response(response),
|
||||
_locale(locale)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionStartOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
*/
|
||||
uint16_t methodID() const
|
||||
{
|
||||
return 11;
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional client properties
|
||||
* @note: exact properties are not specified
|
||||
* and are implementation-dependent
|
||||
* @return Table
|
||||
*/
|
||||
const Table& properties() const
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* The selected security mechanism
|
||||
* @return string
|
||||
*/
|
||||
const std::string& mechanism() const
|
||||
{
|
||||
return _mechanism;
|
||||
}
|
||||
|
||||
/**
|
||||
* The security response
|
||||
* @return string
|
||||
*/
|
||||
const std::string& response() const
|
||||
{
|
||||
return _response;
|
||||
}
|
||||
|
||||
/**
|
||||
* The selected locale
|
||||
* @return string
|
||||
*/
|
||||
const std::string locale() const
|
||||
{
|
||||
return _locale;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* ConnectionTuneFrame.cpp
|
||||
*
|
||||
* @copyright 2014
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "connectiontuneframe.h"
|
||||
#include "connectiontuneokframe.h"
|
||||
#include "connectionopenframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ConnectionTuneFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// @todo this is only allowed when the connection is set up
|
||||
|
||||
|
||||
// remember this in the connection
|
||||
connection->setCapacity(channelMax(), frameMax());
|
||||
|
||||
// send a tune-ok frame back
|
||||
ConnectionTuneOKFrame okframe(channelMax(), frameMax(), heartbeat());
|
||||
|
||||
// send it back
|
||||
connection->send(okframe);
|
||||
|
||||
// and finally we start to open the frame
|
||||
ConnectionOpenFrame openframe(connection->login().vhost());
|
||||
|
||||
// send the open frame
|
||||
connection->send(openframe);
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* Class describing connection tune frame
|
||||
*
|
||||
* A connection tune frame is sent by the server after the connection is
|
||||
* started to negotiate the max frame size, the max number of channels
|
||||
* and the heartbeat interval.
|
||||
*
|
||||
* When this frame is received, we should send back a tune-ok frame to
|
||||
* confirm that we have received this frame.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionTuneFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Proposed maximum number of channels
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _channels;
|
||||
|
||||
/**
|
||||
* Proposed maximum frame size
|
||||
* @var uint32_t
|
||||
*/
|
||||
uint32_t _frameMax;
|
||||
|
||||
/**
|
||||
* Desired heartbeat delay
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _heartbeat;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_channels);
|
||||
buffer.add(_frameMax);
|
||||
buffer.add(_heartbeat);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Construct a connection tuning frame
|
||||
*
|
||||
* @param channels proposed maximum number of channels
|
||||
* @param frameMax proposed maximum frame size
|
||||
* @param heartbeat desired heartbeat delay
|
||||
*/
|
||||
ConnectionTuneFrame(uint16_t channels, uint32_t frameMax, uint16_t heartbeat) :
|
||||
ConnectionFrame(8), // 2x uint16_t, 1x uint32_t
|
||||
_channels(channels),
|
||||
_frameMax(frameMax),
|
||||
_heartbeat(heartbeat)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connection tune frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionTuneFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_channels(frame.nextUint16()),
|
||||
_frameMax(frame.nextUint32()),
|
||||
_heartbeat(frame.nextUint16())
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionTuneFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proposed maximum number of channels
|
||||
* @return _uint16_t
|
||||
*/
|
||||
uint16_t channelMax() const
|
||||
{
|
||||
return _channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proposed maximum frame size
|
||||
* @return _uint32_t
|
||||
*/
|
||||
uint32_t frameMax() const
|
||||
{
|
||||
return _frameMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired heartbeat delay
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t heartbeat() const
|
||||
{
|
||||
return _heartbeat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* Class describing connection tune acknowledgement frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ConnectionTuneOKFrame : public ConnectionFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Proposed maximum number of channels
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _channels;
|
||||
|
||||
/**
|
||||
* Proposed maximum frame size
|
||||
* @var uint32_t
|
||||
*/
|
||||
uint32_t _frameMax;
|
||||
|
||||
/**
|
||||
* Desired heartbeat delay
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _heartbeat;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ConnectionFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_channels);
|
||||
buffer.add(_frameMax);
|
||||
buffer.add(_heartbeat);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Construct a connection tune frame from a received frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ConnectionTuneOKFrame(ReceivedFrame &frame) :
|
||||
ConnectionFrame(frame),
|
||||
_channels(frame.nextUint16()),
|
||||
_frameMax(frame.nextUint32()),
|
||||
_heartbeat(frame.nextUint16())
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct a connection tuning acknowledgement frame
|
||||
*
|
||||
* @param channels selected maximum number of channels
|
||||
* @param frame selected maximum frame size
|
||||
* @param heartbeat desired heartbeat delay
|
||||
*/
|
||||
ConnectionTuneOKFrame(uint16_t channels, uint32_t frameMax, uint16_t heartbeat) :
|
||||
ConnectionFrame(8), // 2x uint16_t, 1x uint32_t
|
||||
_channels(channels),
|
||||
_frameMax(frameMax),
|
||||
_heartbeat(heartbeat)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectionTuneOKFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t methodID() const
|
||||
{
|
||||
return 31;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proposed maximum number of channels
|
||||
* @return _uint16_t
|
||||
*/
|
||||
uint16_t channels() const
|
||||
{
|
||||
return _channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proposed maximum frame size
|
||||
* @return _uint32_t
|
||||
*/
|
||||
uint32_t frameMax() const
|
||||
{
|
||||
return _frameMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desired heartbeat delay
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t heartbeat() const
|
||||
{
|
||||
return _heartbeat;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
..
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Exception.h
|
||||
*
|
||||
* Base class for all AMQP exceptions
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Base exception class
|
||||
*/
|
||||
class Exception : public std::runtime_error
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
* @param what
|
||||
*/
|
||||
explicit Exception(const std::string &what) : runtime_error(what) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Exception() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* Exchangebindframe.h
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ExchangeBindFrame : public ExchangeFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* reserved byte
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _reserved;
|
||||
|
||||
/**
|
||||
* Exchange to bind to
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _destination;
|
||||
|
||||
/**
|
||||
* Exchange which is bound
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _source;
|
||||
|
||||
/**
|
||||
* Routing key
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _routingKey;
|
||||
|
||||
/**
|
||||
* contains: nowait do not wait on response
|
||||
* @var booleanset
|
||||
*/
|
||||
BooleanSet _bools;
|
||||
|
||||
/**
|
||||
* Additional arguments
|
||||
* @var Table
|
||||
*/
|
||||
Table _arguments;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer &buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
|
||||
buffer.add(_reserved);
|
||||
_destination.fill(buffer);
|
||||
_source.fill(buffer);
|
||||
_routingKey.fill(buffer);
|
||||
_bools.fill(buffer);
|
||||
_arguments.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
ExchangeBindFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame),
|
||||
_reserved(frame.nextUint16()),
|
||||
_destination(frame),
|
||||
_source(frame),
|
||||
_routingKey(frame),
|
||||
_bools(frame),
|
||||
_arguments(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor for an exchangebindframe
|
||||
* @param destination
|
||||
* @param source
|
||||
* @param routingkey
|
||||
* @param noWait
|
||||
* @param arguments
|
||||
*/
|
||||
ExchangeBindFrame(uint16_t channel, const std::string &destination, const std::string &source, const std::string &routingKey, bool noWait, const Table &arguments) :
|
||||
ExchangeFrame(channel, (destination.length() + source.length() + routingKey.length() + arguments.size() + 6)), // 1 for each string, 1 for booleanset, 2 for deprecated field
|
||||
_reserved(0),
|
||||
_destination(destination),
|
||||
_source(source),
|
||||
_routingKey(routingKey),
|
||||
_bools(noWait),
|
||||
_arguments(arguments)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Get the destination exchange
|
||||
* @return string
|
||||
*/
|
||||
const std::string& destination() const
|
||||
{
|
||||
return _destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source exchange
|
||||
* @return string
|
||||
*/
|
||||
const std::string& source() const
|
||||
{
|
||||
return _source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the routing key
|
||||
* @return string
|
||||
*/
|
||||
const std::string& routingkey() const
|
||||
{
|
||||
return _routingKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional arguments
|
||||
* @return Table
|
||||
*/
|
||||
const Table& arguments() const
|
||||
{
|
||||
return _arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nowait bool
|
||||
* @return bool
|
||||
*/
|
||||
bool noWait()
|
||||
{
|
||||
return _bools.get(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// end namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Exchangebindokframe.cpp
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "exchangebindokframe.h"
|
||||
|
||||
// setup namespace
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ExchangeBindOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// check if we have a channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// channel does not exist
|
||||
if(!channel) return false;
|
||||
|
||||
// report to handler
|
||||
channel->reportExchangeBound();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
// end namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Exchangebindokframe.h
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ExchangeBindOKFrame : public ExchangeFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
ExchangeBindOKFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor for an exchangebindframe
|
||||
* @param destination
|
||||
* @param source
|
||||
* @param routingkey
|
||||
* @param noWait
|
||||
* @param arguments
|
||||
*/
|
||||
ExchangeBindOKFrame(uint16_t channel) :
|
||||
ExchangeFrame(channel, 0)
|
||||
{}
|
||||
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 31;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
|
||||
};
|
||||
|
||||
// end namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/**
|
||||
* Class describing an AMQP exchange declare frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ExchangeDeclareFrame : public ExchangeFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Field that no longer is used
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _deprecated;
|
||||
|
||||
/**
|
||||
* The exchange name
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _name;
|
||||
|
||||
/**
|
||||
* The exchange type
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _type;
|
||||
|
||||
/**
|
||||
* The boolean set contains three settings:
|
||||
* 0: Passive declaration, do not create exchange if it does not exist
|
||||
* 1: Durable exchange
|
||||
* 4: Do not wait for a response
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _bools;
|
||||
|
||||
/**
|
||||
* Additional arguments. Implementation dependent.
|
||||
* @var Table
|
||||
*/
|
||||
Table _arguments;
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_deprecated);
|
||||
_name.fill(buffer);
|
||||
_type.fill(buffer);
|
||||
_bools.fill(buffer);
|
||||
_arguments.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a exchange declare frame (client side)
|
||||
*
|
||||
* @param channel channel we´re working on
|
||||
* @param name exchange name
|
||||
* @param type exchange type
|
||||
* @param passive do not create exchange if it does not exist
|
||||
* @param durable durable exchange
|
||||
* @param noWait do not wait on response
|
||||
* @param arguments additional arguments
|
||||
*/
|
||||
ExchangeDeclareFrame(uint16_t channel, const std::string& name, const std::string& type, bool passive, bool durable, bool noWait, const Table& arguments) :
|
||||
ExchangeFrame(channel, (name.length() + type.length() + arguments.size() + 5)), // size of name, type and arguments + 1 (all booleans are stored in 1 byte) + 2 (deprecated short) + 2 (string sizes)
|
||||
_deprecated(0),
|
||||
_name(name),
|
||||
_type(type),
|
||||
_bools(passive, durable, false, false, noWait),
|
||||
_arguments(arguments)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct parsing a declare frame from a received frame
|
||||
* @param frame The received frame
|
||||
*/
|
||||
ExchangeDeclareFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame),
|
||||
_deprecated(frame.nextUint16()),
|
||||
_name(frame),
|
||||
_type(frame),
|
||||
_bools(frame),
|
||||
_arguments(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ExchangeDeclareFrame() {}
|
||||
|
||||
/**
|
||||
* Method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t methodID() const
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* The exchange name
|
||||
* @return string
|
||||
*/
|
||||
const std::string& name()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The exchange type
|
||||
* @return string
|
||||
*/
|
||||
const std::string& type()
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passive declaration, do not create exchange if it does not exist
|
||||
* @return bool
|
||||
*/
|
||||
bool passive()
|
||||
{
|
||||
return _bools.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Durable exchange
|
||||
* @return bool
|
||||
*/
|
||||
bool durable()
|
||||
{
|
||||
return _bools.get(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not wait for a response
|
||||
* @return bool
|
||||
*/
|
||||
bool noWait()
|
||||
{
|
||||
return _bools.get(4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional arguments. Implementation dependent.
|
||||
* @return Table
|
||||
*/
|
||||
const Table& arguments()
|
||||
{
|
||||
return _arguments;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* ExchangeDeclareOKFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "exchangedeclareokframe.h"
|
||||
|
||||
// setup namespace
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ExchangeDeclareOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// we need the appropriate channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// channel does not exist
|
||||
if(!channel) return false;
|
||||
|
||||
// report exchange declare ok
|
||||
channel->reportExchangeDeclared();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
// end namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Class describing an AMQP exchange declare ok frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
namespace AMQP{
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ExchangeDeclareOKFrame : public ExchangeFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Construct an exchange declare ok frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
*/
|
||||
ExchangeDeclareOKFrame(uint16_t channel) : ExchangeFrame(channel, 0) {}
|
||||
|
||||
/**
|
||||
* Decode an exchange declare acknowledgement frame
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
ExchangeDeclareOKFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ExchangeDeclareOKFrame() {}
|
||||
|
||||
/**
|
||||
* returns the method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 11;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/**
|
||||
* Class describing an AMQP exchange delete frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* we live in the copernica namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ExchangeDeleteFrame : public ExchangeFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Field that is no longer in use
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _deprecated;
|
||||
|
||||
/**
|
||||
* The exchange name
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _name;
|
||||
|
||||
/**
|
||||
* booleanset, contains:
|
||||
* 0: ifUnused
|
||||
* 1: noWait
|
||||
* @var BooleanSet
|
||||
*/
|
||||
BooleanSet _bools;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
|
||||
// add fields
|
||||
buffer.add(_deprecated);
|
||||
_name.fill(buffer);
|
||||
_bools.fill(buffer);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* constructor based on incoming data
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ExchangeDeleteFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame),
|
||||
_deprecated(frame.nextUint16()),
|
||||
_name(frame),
|
||||
_bools(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* construct a exchangedeleteframe
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param String name Name of the exchange
|
||||
* @param bool ifUnused Delete only if frame is not used
|
||||
* @param bool noWait Do not wait for a response
|
||||
*/
|
||||
ExchangeDeleteFrame(uint16_t channel, const std::string& name, bool ifUnused = false, bool noWait = false) :
|
||||
ExchangeFrame(channel, name.length() + 4), // length of the name, 1 byte for encoding this length, 1 for bools, 2 for deprecated short
|
||||
_deprecated(0),
|
||||
_name(name),
|
||||
_bools(ifUnused, noWait)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ExchangeDeleteFrame() {}
|
||||
|
||||
/**
|
||||
* returns the method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
uint16_t methodID() const
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the exchange name
|
||||
* @return string
|
||||
*/
|
||||
const std::string& name()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns whether to delete if unused
|
||||
* @return bool
|
||||
*/
|
||||
bool ifUnused()
|
||||
{
|
||||
return _bools.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns whether to wait for a response
|
||||
* @return bool
|
||||
*/
|
||||
bool noWait()
|
||||
{
|
||||
return _bools.get(1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* ExchangeDeleteOKFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "exchangedeleteokframe.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ExchangeDeleteOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// check if we have a channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// channel does not exist
|
||||
if(!channel) return false;
|
||||
|
||||
// report to handler
|
||||
channel->reportExchangeDeleted();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Class describing an AMQP exchange delete ok frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ExchangeDeleteOKFrame : public ExchangeFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct an exchange delete ok frame
|
||||
*
|
||||
* @param frame received frame
|
||||
*/
|
||||
ExchangeDeleteOKFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Construct an exchange delete ok frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
*/
|
||||
ExchangeDeleteOKFrame(uint16_t channel) : ExchangeFrame(channel, 0) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ExchangeDeleteOKFrame() {}
|
||||
|
||||
/**
|
||||
* returns the method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 21;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Class describing an AMQP exchange frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class ExchangeFrame : public MethodFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
ExchangeFrame(ReceivedFrame &frame) : MethodFrame(frame) {}
|
||||
|
||||
/**
|
||||
* Constructor for an exchange frame
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param size size of the payload
|
||||
*/
|
||||
ExchangeFrame(uint16_t channel, uint32_t size) : MethodFrame(channel, size) {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ExchangeFrame() {}
|
||||
|
||||
/**
|
||||
* Class id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t classID() const override
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* Exchangeunbindframe.h
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ExchangeUnbindFrame : public ExchangeFrame
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* reserved byte
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _reserved;
|
||||
|
||||
/**
|
||||
* Exchange to bind to
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _destination;
|
||||
|
||||
/**
|
||||
* Exchange which is bound
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _source;
|
||||
|
||||
/**
|
||||
* Routing key
|
||||
* @var ShortString
|
||||
*/
|
||||
ShortString _routingKey;
|
||||
|
||||
/**
|
||||
* contains: nowait do not wait on response
|
||||
* @var booleanset
|
||||
*/
|
||||
BooleanSet _bools;
|
||||
|
||||
/**
|
||||
* Additional arguments
|
||||
* @var Table
|
||||
*/
|
||||
Table _arguments;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
|
||||
buffer.add(_reserved);
|
||||
_destination.fill(buffer);
|
||||
_source.fill(buffer);
|
||||
_routingKey.fill(buffer);
|
||||
_bools.fill(buffer);
|
||||
_arguments.fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
ExchangeUnbindFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame),
|
||||
_reserved(frame.nextUint16()),
|
||||
_destination(frame),
|
||||
_source(frame),
|
||||
_routingKey(frame),
|
||||
_bools(frame),
|
||||
_arguments(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor for an exchangebindframe
|
||||
* @param destination
|
||||
* @param source
|
||||
* @param routingkey
|
||||
* @param noWait
|
||||
* @param arguments
|
||||
*/
|
||||
ExchangeUnbindFrame(uint16_t channel, const std::string &destination, const std::string &source, const std::string &routingKey, bool noWait, const Table &arguments) :
|
||||
ExchangeFrame(channel, (destination.length() + source.length() + routingKey.length() + arguments.size() + 6)), // 1 for each string, 1 for booleanset, 2 for deprecated field
|
||||
_reserved(0),
|
||||
_destination(destination),
|
||||
_source(source),
|
||||
_routingKey(routingKey),
|
||||
_bools(noWait),
|
||||
_arguments(arguments)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Get the destination exchange
|
||||
* @return string
|
||||
*/
|
||||
const std::string& destination() const
|
||||
{
|
||||
return _destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source exchange
|
||||
* @return string
|
||||
*/
|
||||
const std::string& source() const
|
||||
{
|
||||
return _source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the routing key
|
||||
* @return string
|
||||
*/
|
||||
const std::string& routingkey() const
|
||||
{
|
||||
return _routingKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the method id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional arguments
|
||||
* @return Table
|
||||
*/
|
||||
const Table& arguments() const
|
||||
{
|
||||
return _arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nowait bool
|
||||
* @return bool
|
||||
*/
|
||||
bool noWait()
|
||||
{
|
||||
return _bools.get(0);
|
||||
}
|
||||
|
||||
};
|
||||
// leave namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* QueuePurgeOKFrame.cpp
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "exchangeunbindokframe.h"
|
||||
|
||||
// setup namespace
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool ExchangeUnbindOKFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// check if we have a channel
|
||||
ChannelImpl *channel = connection->channel(this->channel());
|
||||
|
||||
// channel does not exist
|
||||
if(!channel) return false;
|
||||
|
||||
// report to handler
|
||||
channel->reportExchangeUnbound();
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
// end namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Exchangeunbindokframe.h
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class ExchangeUnbindOKFrame : public ExchangeFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Encode a frame on a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const override
|
||||
{
|
||||
// call base
|
||||
ExchangeFrame::fill(buffer);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor based on incoming data
|
||||
*
|
||||
* @param frame received frame to decode
|
||||
*/
|
||||
ExchangeUnbindOKFrame(ReceivedFrame &frame) :
|
||||
ExchangeFrame(frame)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor for an exchangebindframe
|
||||
* @param destination
|
||||
* @param source
|
||||
* @param routingkey
|
||||
* @param noWait
|
||||
* @param arguments
|
||||
*/
|
||||
ExchangeUnbindOKFrame(uint16_t channel) :
|
||||
ExchangeFrame(channel, 0)
|
||||
{}
|
||||
|
||||
virtual uint16_t methodID() const override
|
||||
{
|
||||
return 51;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection) override;
|
||||
};
|
||||
|
||||
// end namespace
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* ExtFrame.h
|
||||
*
|
||||
* Class describing an AMQP frame. A frame can be encoded into the AMQP
|
||||
* wireframe format, so that it can be sent over an open socket, or it can be
|
||||
* constructed from a buffer containing AMQP wireframe format.
|
||||
*
|
||||
* The ExtFrame is the base class for all other frames, apart from the
|
||||
* protocol-header-frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Base frame class for all frames apart from the protocol header frame
|
||||
*/
|
||||
class ExtFrame : public Frame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* The AMQP channel
|
||||
* @var uint16_t
|
||||
*/
|
||||
uint16_t _channel;
|
||||
|
||||
/**
|
||||
* The payload size of the frame
|
||||
* @var uint32_t
|
||||
*/
|
||||
uint32_t _size;
|
||||
|
||||
/**
|
||||
* Constructor for an AMQP Frame
|
||||
*
|
||||
* The constructor is protected as you're not supposed
|
||||
*
|
||||
* @param channel channel we're working on
|
||||
* @param size size of the payload
|
||||
*/
|
||||
ExtFrame(uint16_t channel, uint32_t size) : _channel(channel), _size(size) {}
|
||||
|
||||
/**
|
||||
* Constructor based on a received not-yet-recognized frame
|
||||
* @param frame the received frame
|
||||
*/
|
||||
ExtFrame(ReceivedFrame &frame) : _channel(frame.channel()), _size(frame.payloadSize()) {}
|
||||
|
||||
/**
|
||||
* Modify the size of the frame
|
||||
* This method is called from derived classes when properties in it are
|
||||
* changed that force the frame to get a different size
|
||||
* @param change change in size
|
||||
*/
|
||||
void modifySize(int32_t change)
|
||||
{
|
||||
// change payload size
|
||||
_size += change;
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual method that must be implemented by sub classes to fill the output buffer
|
||||
* @param buffer
|
||||
*/
|
||||
virtual void fill(OutBuffer &buffer) const override
|
||||
{
|
||||
// add type, channel id and size
|
||||
buffer.add(type());
|
||||
buffer.add(_channel);
|
||||
buffer.add(_size);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destruct frame
|
||||
*/
|
||||
virtual ~ExtFrame() {}
|
||||
|
||||
/**
|
||||
* The channel this message was sent on
|
||||
*/
|
||||
uint16_t channel() const
|
||||
{
|
||||
return _channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the header
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t headerSize() const
|
||||
{
|
||||
// 1 byte for type, 2 bytes for channel, 4 bytes for payload
|
||||
return 7;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the trailer
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t trailerSize() const
|
||||
{
|
||||
// 1 byte for end-of-frame
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the total size of the frame
|
||||
* @return uint32_t
|
||||
*/
|
||||
virtual uint32_t totalSize() const override
|
||||
{
|
||||
// payload size + size of header and trailer
|
||||
return _size + headerSize() + trailerSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of the payload
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t payloadSize() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message type
|
||||
*/
|
||||
virtual uint8_t type() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Field.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Decode a field by fetching a type and full field from a frame
|
||||
* The returned field is allocated on the heap!
|
||||
* @param frame
|
||||
* @return Field*
|
||||
*/
|
||||
Field *Field::decode(ReceivedFrame &frame)
|
||||
{
|
||||
// get the type
|
||||
uint8_t type = frame.nextUint8();
|
||||
|
||||
// create field based on type
|
||||
switch (type)
|
||||
{
|
||||
case 't': return new BooleanSet(frame);
|
||||
case 'b': return new Octet(frame);
|
||||
case 'B': return new UOctet(frame);
|
||||
case 'U': return new Short(frame);
|
||||
case 'u': return new UShort(frame);
|
||||
case 'I': return new Long(frame);
|
||||
case 'i': return new ULong(frame);
|
||||
case 'L': return new LongLong(frame);
|
||||
case 'l': return new ULongLong(frame);
|
||||
case 'f': return new Float(frame);
|
||||
case 'd': return new Double(frame);
|
||||
case 'D': return new DecimalField(frame);
|
||||
case 's': return new ShortString(frame);
|
||||
case 'S': return new LongString(frame);
|
||||
case 'A': return new Array(frame);
|
||||
case 'T': return new Timestamp(frame);
|
||||
case 'F': return new Table(frame);
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Flags.cpp
|
||||
*
|
||||
* The various flags that are supported
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* All bit flags
|
||||
* @var int
|
||||
*/
|
||||
const int durable = 0x1;
|
||||
const int autodelete = 0x2;
|
||||
const int active = 0x4;
|
||||
const int passive = 0x8;
|
||||
const int ifunused = 0x10;
|
||||
const int ifempty = 0x20;
|
||||
const int global = 0x40;
|
||||
const int nolocal = 0x80;
|
||||
const int noack = 0x100;
|
||||
const int exclusive = 0x200;
|
||||
const int nowait = 0x400;
|
||||
const int mandatory = 0x800;
|
||||
const int immediate = 0x1000;
|
||||
const int redelivered = 0x2000;
|
||||
const int multiple = 0x4000;
|
||||
const int requeue = 0x8000;
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Frame.h
|
||||
*
|
||||
* Base class for frames. This base class can not be constructed from outside
|
||||
* the library, and is only used internally.
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class definition
|
||||
*/
|
||||
class Frame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Protected constructor to ensure that no objects are created from
|
||||
* outside the library
|
||||
*/
|
||||
Frame() {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Frame() {}
|
||||
|
||||
/**
|
||||
* return the total size of the frame
|
||||
* @return uint32_t
|
||||
*/
|
||||
virtual uint32_t totalSize() const = 0;
|
||||
|
||||
/**
|
||||
* Fill an output buffer
|
||||
* @param buffer
|
||||
*/
|
||||
virtual void fill(OutBuffer &buffer) const = 0;
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
virtual bool process(ConnectionImpl *connection)
|
||||
{
|
||||
// no process was implemented
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End of namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* FrameCheck.h
|
||||
*
|
||||
* Class that checks incoming frames for their size
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Internal helper class that checks if there is enough room left in the frame
|
||||
*/
|
||||
class FrameCheck
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The frame
|
||||
* @var ReceivedFrame
|
||||
*/
|
||||
ReceivedFrame *_frame;
|
||||
|
||||
/**
|
||||
* The size that is checked
|
||||
* @var size_t
|
||||
*/
|
||||
size_t _size;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param frame
|
||||
* @param size
|
||||
*/
|
||||
FrameCheck(ReceivedFrame *frame, size_t size) : _frame(frame), _size(size)
|
||||
{
|
||||
// no problem is there are still enough bytes left
|
||||
if (frame->_left >= size) return;
|
||||
|
||||
// frame buffer is too small
|
||||
throw ProtocolException("frame out of range");
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~FrameCheck()
|
||||
{
|
||||
// update the buffer and the number of bytes left
|
||||
_frame->_buffer += _size;
|
||||
_frame->_left -= _size;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* End namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Class describing an AMQP header frame
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set up namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Class implementation
|
||||
*/
|
||||
class HeaderFrame : public ExtFrame
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Construct a header frame
|
||||
* @param channel Channel ID
|
||||
* @param size Payload size
|
||||
*/
|
||||
HeaderFrame(uint16_t channel, uint32_t size) : ExtFrame(channel, size + 2) {} // + size of classID (2bytes)
|
||||
|
||||
/**
|
||||
* Construct based on incoming data
|
||||
* @param frame Incoming frame
|
||||
*/
|
||||
HeaderFrame(ReceivedFrame &frame) : ExtFrame(frame) {}
|
||||
|
||||
/**
|
||||
* Encode a header frame to a string buffer
|
||||
*
|
||||
* @param buffer buffer to write frame to
|
||||
*/
|
||||
virtual void fill(OutBuffer& buffer) const
|
||||
{
|
||||
ExtFrame::fill(buffer);
|
||||
|
||||
// add type
|
||||
buffer.add(classID());
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~HeaderFrame() {}
|
||||
|
||||
/**
|
||||
* Get the message type
|
||||
* @return uint8_t
|
||||
*/
|
||||
virtual uint8_t type() const override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class id
|
||||
* @return uint16_t
|
||||
*/
|
||||
virtual uint16_t classID() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* end namespace
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* HeartbeatFrame.cpp
|
||||
*
|
||||
* @copyright 2014 Copernica BV
|
||||
*/
|
||||
#include "includes.h"
|
||||
#include "heartbeatframe.h"
|
||||
|
||||
/**
|
||||
* Namespace
|
||||
*/
|
||||
namespace AMQP {
|
||||
|
||||
/**
|
||||
* Process the frame
|
||||
* @param connection The connection over which it was received
|
||||
* @return bool Was it succesfully processed?
|
||||
*/
|
||||
bool HeartbeatFrame::process(ConnectionImpl *connection)
|
||||
{
|
||||
// send back the same frame
|
||||
connection->send(*this);
|
||||
|
||||
// done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* End namespace
|
||||
*/
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue