diff --git a/include/receivedframe.h b/include/receivedframe.h index 7c1e1d5..98b9272 100644 --- a/include/receivedframe.h +++ b/include/receivedframe.h @@ -111,6 +111,13 @@ private: */ bool processBasicFrame(ConnectionImpl *connection); + /** + * Process a confirm frame + * @param connection + * @return bool + */ + bool processConfirmFrame(ConnectionImpl *connection); + /** * Process a transaction frame * @param connection diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eae0c22..e06b204 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,8 @@ channelframe.h channelimpl.cpp channelopenframe.h channelopenokframe.h +confirmselectframe.h +confirmselectokframe.h connectioncloseframe.h connectioncloseokframe.h connectionframe.h diff --git a/src/confirmframe.h b/src/confirmframe.h new file mode 100644 index 0000000..02377f9 --- /dev/null +++ b/src/confirmframe.h @@ -0,0 +1,56 @@ +/** + * Class describing an AMQP confirm frame + * + * @author Marcin Gibula + * @copyright 2017 Copernica BV + */ + +/** + * Set up namespace + */ +namespace AMQP { + +/** + * Class implementation + */ +class ConfirmFrame : public MethodFrame +{ +protected: + /** + * Constructor + * @param channel channel identifier + * @param size frame size + */ + ConfirmFrame(uint16_t channel, uint32_t size) : + MethodFrame(channel, size) + {} + + /** + * Constructor based on incoming frame + * @param frame + */ + ConfirmFrame(ReceivedFrame &frame) : + MethodFrame(frame) + {} + +public: + /** + * Destructor + */ + virtual ~ConfirmFrame() {} + + /** + * Class id + * @return uint16_t + */ + virtual uint16_t classID() const override + { + return 85; + } +}; + +/** + * end namespace + */ +} + diff --git a/src/confirmselectframe.h b/src/confirmselectframe.h new file mode 100644 index 0000000..8a9f79d --- /dev/null +++ b/src/confirmselectframe.h @@ -0,0 +1,88 @@ +/** + * Class describing an AMQP confirm select frame + * + * @author Marcin Gibula + * @copyright 2017 Copernica BV + */ + +/** + * Set up namespace + */ +namespace AMQP { + +/** + * Class implementation + */ +class ConfirmSelectFrame : public ConfirmFrame +{ +private: + + /** + * 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 + ConfirmFrame::fill(buffer); + + // add boolean + _noWait.fill(buffer); + } + +public: + /** + * Decode a confirm select frame from a received frame + * + * @param frame received frame to decode + */ + ConfirmSelectFrame(ReceivedFrame& frame) : ConfirmFrame(frame), _noWait(frame) {} + + /** + * Construct a confirm select frame + * + * @param channel channel identifier + * @return newly created confirm select frame + */ + ConfirmSelectFrame(uint16_t channel, bool noWait = false) : + ConfirmFrame(channel, 0), + _noWait(noWait) + {} + + /** + * Destructor + */ + virtual ~ConfirmSelectFrame() {} + + /** + * return the method id + * @return uint16_t + */ + virtual uint16_t methodID() const override + { + return 10; + } + + /** + * Return whether to wait for a response + * @return boolean + */ + bool noWait() const + { + return _noWait.get(0); + } +}; + +/** + * end namespace + */ +} + diff --git a/src/confirmselectokframe.h b/src/confirmselectokframe.h new file mode 100644 index 0000000..4a20992 --- /dev/null +++ b/src/confirmselectokframe.h @@ -0,0 +1,89 @@ +/** + * Class describing an AMQP confirm select ok frame + * + * @author Marcin Gibula + * @copyright 2017 Copernica BV + */ + +/** + * Set up namespace + */ +namespace AMQP { + +/** + * Class implementation + */ +class ConfirmSelectOKFrame : public ConfirmFrame +{ +protected: + /** + * Encode a frame on a string buffer + * + * @param buffer buffer to write frame to + */ + virtual void fill(OutBuffer& buffer) const override + { + // call base + ConfirmFrame::fill(buffer); + } + +public: + /** + * Constructor for an incoming frame + * + * @param frame received frame to decode + */ + ConfirmSelectOKFrame(ReceivedFrame& frame) : + ConfirmFrame(frame) + {} + + /** + * Construct a confirm select ok frame + * + * @param channel channel identifier + * @return newly created confirm select ok frame + */ + ConfirmSelectOKFrame(uint16_t channel) : + ConfirmFrame(channel, 0) + {} + + /** + * Destructor + */ + virtual ~ConfirmSelectOKFrame() {} + + /** + * return 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 + { + // we need the appropriate channel + auto channel = connection->channel(this->channel()); + + // channel does not exist + if(!channel) return false; + + // report that the channel is open + if (channel->reportSuccess()) channel->onSynchronized(); + + // done + return true; + } +}; + +/** + * end namespace + */ +} + diff --git a/src/includes.h b/src/includes.h index 2a10061..b105932 100644 --- a/src/includes.h +++ b/src/includes.h @@ -90,6 +90,7 @@ #include "exchangeframe.h" #include "queueframe.h" #include "basicframe.h" +#include "confirmframe.h" #include "transactionframe.h" #include "addressinfo.h" diff --git a/src/receivedframe.cpp b/src/receivedframe.cpp index 31406f4..83b83aa 100644 --- a/src/receivedframe.cpp +++ b/src/receivedframe.cpp @@ -7,6 +7,8 @@ */ #include "includes.h" #include "heartbeatframe.h" +#include "confirmselectframe.h" +#include "confirmselectokframe.h" #include "connectionstartokframe.h" #include "connectionstartframe.h" #include "connectionsecureframe.h" @@ -336,6 +338,7 @@ bool ReceivedFrame::processMethodFrame(ConnectionImpl *connection) case 40: return processExchangeFrame(connection); case 50: return processQueueFrame(connection); case 60: return processBasicFrame(connection); + case 85: return processConfirmFrame(connection); case 90: return processTransactionFrame(connection); } @@ -493,6 +496,27 @@ bool ReceivedFrame::processBasicFrame(ConnectionImpl *connection) throw ProtocolException("unrecognized basic frame method " + std::to_string(methodID)); } +/** + * Process a confirm frame + * @param connection + * @return bool + */ +bool ReceivedFrame::processConfirmFrame(ConnectionImpl *connection) +{ + // read the method id + uint16_t methodID = nextUint16(); + + // construct frame based on method id + switch (methodID) + { + case 10: return ConfirmSelectFrame(*this).process(connection); + case 11: return ConfirmSelectOKFrame(*this).process(connection); + } + + // this is a problem + throw ProtocolException("unrecognized confirm frame method " + std::to_string(methodID)); +} + /** * Process a transaction frame * @param connection