2015-11-01 01:26:04 +08:00
|
|
|
/**
|
|
|
|
|
* TcpConnection.cpp
|
|
|
|
|
*
|
|
|
|
|
* Implementation file for the TCP connection
|
|
|
|
|
*
|
|
|
|
|
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
|
|
|
|
|
* @copyright 2015 Copernica BV
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Dependencies
|
|
|
|
|
*/
|
|
|
|
|
#include "includes.h"
|
|
|
|
|
#include "tcpresolver.h"
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set up namespace
|
|
|
|
|
*/
|
|
|
|
|
namespace AMQP {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor
|
|
|
|
|
* @param handler User implemented handler object
|
2015-11-01 04:13:41 +08:00
|
|
|
* @param hostname The address to connect to
|
2015-11-01 01:26:04 +08:00
|
|
|
*/
|
2015-11-01 04:13:41 +08:00
|
|
|
TcpConnection::TcpConnection(TcpHandler *handler, const Address &address) :
|
|
|
|
|
_state(new TcpResolver(this, address.hostname(), address.port(), handler)),
|
|
|
|
|
_connection(this, address.login(), address.vhost()) {}
|
|
|
|
|
|
2015-11-01 01:26:04 +08:00
|
|
|
/**
|
|
|
|
|
* Destructor
|
|
|
|
|
*/
|
|
|
|
|
TcpConnection::~TcpConnection()
|
|
|
|
|
{
|
|
|
|
|
// remove the state object
|
|
|
|
|
delete _state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Process the TCP connection
|
|
|
|
|
* This method should be called when the filedescriptor that is registered
|
|
|
|
|
* in the event loop becomes active. You should pass in a flag holding the
|
|
|
|
|
* flags AMQP::readable or AMQP::writable to indicate whether the descriptor
|
|
|
|
|
* was readable or writable, or bitwise-or if it was both
|
|
|
|
|
* @param fd The filedescriptor that became readable or writable
|
|
|
|
|
* @param events What sort of events occured?
|
|
|
|
|
*/
|
|
|
|
|
void TcpConnection::process(int fd, int flags)
|
|
|
|
|
{
|
|
|
|
|
// pass on the the state, that returns a new impl
|
|
|
|
|
auto *result = _state->process(fd, flags);
|
|
|
|
|
|
|
|
|
|
// skip if the same state is continued to be used
|
|
|
|
|
if (result == _state) return;
|
|
|
|
|
|
|
|
|
|
// remove old state
|
|
|
|
|
delete _state;
|
|
|
|
|
|
|
|
|
|
// replace it with the new implementation
|
|
|
|
|
_state = result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Method that is called by the connection when data needs to be sent over the network
|
|
|
|
|
* @param connection The connection that created this output
|
|
|
|
|
* @param buffer Data to send
|
|
|
|
|
* @param size Size of the buffer
|
|
|
|
|
*/
|
|
|
|
|
void TcpConnection::onData(Connection *connection, const char *buffer, size_t size)
|
|
|
|
|
{
|
|
|
|
|
// send the data over the connecction
|
|
|
|
|
_state->send(buffer, size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Method called when the connection ends up in an error state
|
|
|
|
|
* @param connection The connection that entered the error state
|
|
|
|
|
* @param message Error message
|
|
|
|
|
*/
|
|
|
|
|
void TcpConnection::onError(Connection *connection, const char *message)
|
|
|
|
|
{
|
|
|
|
|
// current object is going to be removed, wrap it in a unique pointer to enforce that
|
|
|
|
|
std::unique_ptr<TcpState> ptr(_state);
|
|
|
|
|
|
|
|
|
|
// object is now in a closed state
|
|
|
|
|
_state = new TcpClosed(_state);
|
|
|
|
|
|
|
|
|
|
// tell the implementation to report the error
|
|
|
|
|
ptr->reportError(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Method that is called when the connection is established
|
|
|
|
|
* @param connection The connection that can now be used
|
|
|
|
|
*/
|
|
|
|
|
void TcpConnection::onConnected(Connection *connection)
|
|
|
|
|
{
|
|
|
|
|
// tell the implementation to report the status
|
|
|
|
|
_state->reportConnected();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Method that is called when the connection was closed.
|
|
|
|
|
* @param connection The connection that was closed and that is now unusable
|
|
|
|
|
*/
|
|
|
|
|
void TcpConnection::onClosed(Connection *connection)
|
|
|
|
|
{
|
|
|
|
|
// current object is going to be removed, wrap it in a unique pointer to enforce that
|
|
|
|
|
std::unique_ptr<TcpState> ptr(_state);
|
|
|
|
|
|
|
|
|
|
// object is now in a closed state
|
|
|
|
|
_state = new TcpClosed(_state);
|
|
|
|
|
|
|
|
|
|
// tell the implementation to report the error
|
|
|
|
|
ptr->reportClosed();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* End of namespace
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|