From 7a6527dddf6eeedd7f00b2f1bd9e1a20f35ddc05 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Sat, 4 Jan 2014 05:11:06 -0800 Subject: [PATCH] updated Makefile, removed vhost from Login object, now also the commit of the README file and the header files --- README.md | 67 +++++++++++++++++++++++++++++++++++++ include/channelhandler.h | 2 +- include/channelimpl.h | 2 +- include/connection.h | 24 ++++++++++--- include/connectionhandler.h | 6 ++-- include/connectionimpl.h | 46 ++++++++++--------------- include/login.h | 34 ++++--------------- tests/myconnection.cpp | 4 +-- tests/myconnection.h | 4 +-- 9 files changed, 118 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index b1d1858..b498201 100644 --- a/README.md +++ b/README.md @@ -74,4 +74,71 @@ class MyConnectionHandler : public AMQP::ConnectionHandler } }; ```` +After you've implemented the ConnectionHandler class, you can start using +the library by creating a Connection object, and one or more Channel objects: + +````c++ +// create an instance of your own connection handler +MyConnectionHandler myHandler; + +// create a AMQP connection object +AMQP::Connection connection(&myHandler, Login("guest","guest"), "/"); + +// and create a channel +AMQP::Channel channel(&connection); + +// use the channel object to call the AMQP method you like +channel.declareExchange("my-exchange", AMQP::fanout); +channel.declareQueue("my-queue"); +channel.bindQueue("my-exchange", "my-queue"); +```` + +A number of remarks about the above example. First you may have noticed that we've +created all objects on the stack. You are of course also free to create them +on the heap with the C++ operator 'new'. That works just as good. + +But more importantly, you see that in the example above we have created the +channel object directly after we created the connection object, and we did also +start declaring exchanges and queues right away. It would have been better to +first wait for the connection to be ready (and the onConnected() method is called +in your handler object), before you create channel objects and start calling +methods. But if you insist, you do not have to wait, and you are free to call +the additional methods right away. + +As we've explained above, the AMQP library does not do any IO by itself and when it +needs to send data to RabbitMQ, it will call the onData() method in your handler +object. But it is of course also not possible for the library to receive data from +the server. It is again up to you to to this. If, for example, you notice in your +event loop that the socket that is connected with the RabbitMQ server becomes +readable, you should read out that data (for example by calling the recv() system +call), and pass the received bytes to the AMQP library. This can be done by +calling the parse() method in the Connection object. + +The Connection::parse() method gets two parameters, a pointer to a buffer of +data received from RabbitMQ, and a parameter that holds the size of this buffer. +The code snippet below comes from the Connection.h C++ header file. + +````c++ +/** + * Parse data that was recevied from RabbitMQ + * + * Every time that data comes in from RabbitMQ, 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); +} +```` + diff --git a/include/channelhandler.h b/include/channelhandler.h index 93b6228..9e86f61 100644 --- a/include/channelhandler.h +++ b/include/channelhandler.h @@ -33,7 +33,7 @@ public: * @param channel * @param message */ - virtual void onChannelError(Channel *channel, const std::string &message) {} + virtual void onError(Channel *channel, const std::string &message) {} /** * Method that is called when the channel was paused diff --git a/include/channelimpl.h b/include/channelimpl.h index 42e494f..d9b8660 100644 --- a/include/channelimpl.h +++ b/include/channelimpl.h @@ -281,7 +281,7 @@ public: _state = state_closed; // inform handler - if (_handler) _handler->onChannelError(_parent, message); + if (_handler) _handler->onError(_parent, message); } /** diff --git a/include/connection.h b/include/connection.h index 85421c0..9a7af4f 100644 --- a/include/connection.h +++ b/include/connection.h @@ -30,14 +30,28 @@ public: * * @param handler Connection handler * @param login Login data + * @param vhost Vhost to use */ - Connection(ConnectionHandler *handler, const Login &login) : _implementation(this, handler, login) {} + Connection(ConnectionHandler *handler, const Login &login, const std::string &vhost) : _implementation(this, handler, login, vhost) {} /** - * Construct an AMQP object with default login data + * Construct with default vhost + * @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 and default vhost * @param handler Connection handler */ - Connection(ConnectionHandler *handler) : _implementation(this, handler) {} + Connection(ConnectionHandler *handler, const std::string &vhost) : _implementation(this, handler, Login(), vhost) {} + + /** + * Construct an AMQP object with default login data and default vhost + * @param handler Connection handler + */ + Connection(ConnectionHandler *handler) : _implementation(this, handler, Login(), "/") {} /** * Destructor @@ -45,9 +59,9 @@ public: virtual ~Connection() {} /** - * Parse the buffer into a recognized frame + * Parse data that was recevied from RabbitMQ * - * Every time that data comes in on the connection, you should call this method to parse + * Every time that data comes in from RabbitMQ, 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. * diff --git a/include/connectionhandler.h b/include/connectionhandler.h index 1eb6cad..ec3142a 100644 --- a/include/connectionhandler.h +++ b/include/connectionhandler.h @@ -38,14 +38,12 @@ public: * 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. + * state and can no longer be used. * - * @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; + virtual void onError(Connection *connection, const std::string &message) = 0; /** * Method that is called when the login attempt succeeded. After this method diff --git a/include/connectionimpl.h b/include/connectionimpl.h index 7873457..616713c 100644 --- a/include/connectionimpl.h +++ b/include/connectionimpl.h @@ -69,15 +69,17 @@ protected: uint32_t _maxFrame = 10000; /** - * The address of the server (vhost, login, password) - * @var Address + * The login for the server (login, password) + * @var Login */ Login _login; - + /** - * Initialize the connection + * Vhost to connect to + * @var string */ - void initialize(); + std::string _vhost; + private: /** @@ -93,28 +95,7 @@ private: * @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(); - } + ConnectionImpl(Connection *parent, ConnectionHandler *handler, const Login &login, const std::string &vhost); public: /** @@ -171,6 +152,15 @@ public: { return _login; } + + /** + * Retrieve the vhost + * @return string + */ + std::string &vhost() + { + return _vhost; + } /** * Store the max number of channels and max number of frames @@ -261,7 +251,7 @@ public: _state = state_closed; // inform handler - _handler->onConnectionError(_parent, message); + _handler->onError(_parent, message); // @Todo: notify all channels of closed connection } diff --git a/include/login.h b/include/login.h index 823ac94..9102329 100644 --- a/include/login.h +++ b/include/login.h @@ -17,47 +17,34 @@ namespace AMQP { 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) {} - + _user(user), _password(password) {} + /** * Constructor */ Login() : - _vhost("/"), _user("guest"), _password("guest") {} + _user("guest"), _password("guest") {} /** * Destructor @@ -76,15 +63,6 @@ public: // append other elements return result.append(_user).append("\0",1).append(_password); } - - /** - * Retrieve the vhost - * @return string - */ - std::string &vhost() - { - return _vhost; - } }; /** diff --git a/tests/myconnection.cpp b/tests/myconnection.cpp index 947b200..0b4dd69 100644 --- a/tests/myconnection.cpp +++ b/tests/myconnection.cpp @@ -171,7 +171,7 @@ void MyConnection::onData(AMQP::Connection *connection, const char *buffer, size * @param connection The connection that entered the error state * @param message Error message */ -void MyConnection::onConnectionError(AMQP::Connection *connection, const std::string &message) +void MyConnection::onError(AMQP::Connection *connection, const std::string &message) { // report error std::cout << "AMQP Connection error: " << message << std::endl; @@ -216,7 +216,7 @@ void MyConnection::onReady(AMQP::Channel *channel) * @param message */ -void MyConnection::onChannelError(AMQP::Channel *channel, const std::string &message) +void MyConnection::onError(AMQP::Channel *channel, const std::string &message) { // show std::cout << "AMQP channel error, id: " << (int) channel->id() << " - message: " << message << std::endl; diff --git a/tests/myconnection.h b/tests/myconnection.h index 58e03d3..11b7b33 100644 --- a/tests/myconnection.h +++ b/tests/myconnection.h @@ -95,7 +95,7 @@ private: * @param connection The connection that entered the error state * @param message Error message */ - virtual void onConnectionError(AMQP::Connection *connection, const std::string &message) override; + virtual void onError(AMQP::Connection *connection, const std::string &message) override; /** * Method that is called when the login attempt succeeded. After this method @@ -117,7 +117,7 @@ private: * @param channel * @param message */ - virtual void onChannelError(AMQP::Channel *channel, const std::string &message) override; + virtual void onError(AMQP::Channel *channel, const std::string &message) override; /** * Method that is called when the channel was paused