support for amqps:// addresses in the AMQP::Address class (although it does not yet make a real secure connection)

This commit is contained in:
Tamas Elekes 2018-03-02 13:53:00 +01:00
parent ab817384b1
commit 342268e50a
3 changed files with 44 additions and 23 deletions

View File

@ -23,12 +23,11 @@ namespace AMQP {
class Address
{
private:
/**
* The auth method
* @var std::string
* @var bool
*/
std::string _authmethod;
bool _secure;
/**
* Login data (username + password)
@ -68,12 +67,12 @@ public:
const char *last = data + size;
// must start with amqp:// or ampqs://
if (strncmp(data, "amqps://", 8) == 0) _authmethod = std::string("amqps://");
else if (strncmp(data, "amqp://", 7) == 0) _authmethod = std::string("amqp://");
if (strncmp(data, "amqps://", 8) == 0) _secure = true;
else if (strncmp(data, "amqp://", 7) == 0) _secure = false;
else throw std::runtime_error("AMQP address should start with \"amqp://\" or \"amqps://\"");
// begin of the string was parsed
data += _authmethod.length();
data += _secure ? 8 : 7;
// do we have a '@' to split user-data and hostname?
const char *at = (const char *)memchr(data, '@', last - data);
@ -138,14 +137,14 @@ public:
/**
* Constructor based on already known properties
* @param authmethod
* @param host
* @param port
* @param login
* @param vhost
* @param secure
*/
Address(std::string authmethod, std::string host, uint16_t port, Login login, std::string vhost) :
_authmethod(std::move(authmethod)),
Address(std::string host, uint16_t port, Login login, std::string vhost, bool secure = false) :
_secure(secure),
_login(std::move(login)),
_hostname(std::move(host)),
_port(port),
@ -157,12 +156,12 @@ public:
virtual ~Address() = default;
/**
* Expose the login data
* @return Login
* Should we open a secure connection?
* @return bool
*/
const std::string &authmethod() const
bool secure() const
{
return _authmethod;
return _secure;
}
/**
@ -208,7 +207,7 @@ public:
operator std::string () const
{
// result object
std::string str(_authmethod);
std::string str(_secure ? "amqps://" : "amqp://");
// append login
str.append(_login.user()).append(":").append(_login.password()).append("@").append(_hostname);
@ -233,8 +232,8 @@ public:
*/
bool operator==(const Address &that) const
{
// auth method should match
if (_authmethod != that._authmethod) return false;
// security setting should match
if (_secure != that._secure) return false;
// logins must match
if (_login != that._login) return false;
@ -267,8 +266,8 @@ public:
*/
bool operator<(const Address &that) const
{
// compare auth methods
if (_authmethod != that._authmethod) return _authmethod < that._authmethod;
// compare auth methods (amqp comes before amqps)
if (_secure != that._secure) return !_secure;
// compare logins
if (_login != that._login) return _login < that._login;
@ -295,7 +294,7 @@ public:
friend std::ostream &operator<<(std::ostream &stream, const Address &address)
{
// start with the protocol and login
stream << address._authmethod << address._login;
stream << (address._secure ? "amqps://" : "amqp://");
// do we need a special portnumber?
if (address._port != 5672) stream << ":" << address._port;

View File

@ -24,7 +24,7 @@ namespace AMQP {
* @param hostname The address to connect to
*/
TcpConnection::TcpConnection(TcpHandler *handler, const Address &address) :
_state(new TcpResolver(this, address.hostname(), address.port(), handler)),
_state(new TcpResolver(this, address.hostname(), address.port(), address.secure(), handler)),
_connection(this, address.login(), address.vhost()) {}
/**

View File

@ -39,6 +39,12 @@ private:
*/
std::string _hostname;
/**
* Should we be using a secure connection?
* @var bool
*/
bool _secure;
/**
* The portnumber to connect to
* @var uint16_t
@ -142,11 +148,13 @@ public:
* @param connection Parent connection object
* @param hostname The hostname for the lookup
* @param portnumber The portnumber for the lookup
* @param secure Do we need a secure tls connection when ready?
* @param handler User implemented handler object
*/
TcpResolver(TcpConnection *connection, const std::string &hostname, uint16_t port, TcpHandler *handler) :
TcpResolver(TcpConnection *connection, const std::string &hostname, uint16_t port, bool secure, TcpHandler *handler) :
TcpState(connection, handler),
_hostname(hostname),
_secure(secure),
_port(port)
{
// tell the event loop to monitor the filedescriptor of the pipe
@ -183,7 +191,14 @@ public:
if (fd != _pipe.in() || !(flags & readable)) return this;
// do we have a valid socket?
if (_socket >= 0) return new TcpConnected(_connection, _socket, std::move(_buffer), _handler);
if (_socket >= 0)
{
// if we need a secure connection, we move to the tls handshake
//if (_secure) return new TcpSslHandshake(....);
// otherwise we have a valid regular tcp connection
return new TcpConnected(_connection, _socket, std::move(_buffer), _handler);
}
// report error
_handler->onError(_connection, _error.data());
@ -202,7 +217,14 @@ public:
_thread.join();
// do we have a valid socket?
if (_socket >= 0) return new TcpConnected(_connection, _socket, std::move(_buffer), _handler);
if (_socket >= 0)
{
// if we need a secure connection, we move to the tls handshake
//if (_secure) return new TcpSslHandshake(....);
// otherwise we have a valid regular tcp connection
return new TcpConnected(_connection, _socket, std::move(_buffer), _handler);
}
// report error
_handler->onError(_connection, _error.data());