diff --git a/libamqpprox/amqpprox_backend.cpp b/libamqpprox/amqpprox_backend.cpp index c2d8050..ffd566b 100644 --- a/libamqpprox/amqpprox_backend.cpp +++ b/libamqpprox/amqpprox_backend.cpp @@ -25,6 +25,7 @@ Backend::Backend(const std::string &name, const std::string &datacenterTag, const std::string &host, const std::string &ip, + const std::string &virtualHost, int port, bool proxyEnabled, bool tlsEnabled, @@ -33,6 +34,7 @@ Backend::Backend(const std::string &name, , d_datacenterTag(datacenterTag) , d_host(host) , d_ip(ip) +, d_virtualHost(virtualHost) , d_port(port) , d_proxyProtocolEnabled(proxyEnabled) , d_tlsEnabled(tlsEnabled) @@ -45,6 +47,7 @@ Backend::Backend() , d_datacenterTag("") , d_host("") , d_ip("") +, d_virtualHost("") , d_port(0) , d_proxyProtocolEnabled(false) , d_tlsEnabled(false) @@ -56,7 +59,7 @@ std::ostream &operator<<(std::ostream &os, const Backend &backend) { os << backend.name() << " (" << backend.datacenterTag() << "): " << backend.host() << " " << backend.ip() << ":" - << backend.port(); + << backend.port() << " <" << backend.virtualHost() << ">"; if (backend.proxyProtocolEnabled()) { os << " " << Constants::proxyProtocolV1Enabled(); } @@ -71,7 +74,7 @@ bool operator==(const Backend &lhs, const Backend &rhs) return (lhs.name() == rhs.name() && lhs.datacenterTag() == rhs.datacenterTag() && lhs.host() == rhs.host() && lhs.ip() == rhs.ip() && - lhs.port() == rhs.port() && + lhs.virtualHost() == rhs.virtualHost() && lhs.port() == rhs.port() && lhs.proxyProtocolEnabled() == rhs.proxyProtocolEnabled() && lhs.tlsEnabled() == rhs.tlsEnabled()); } diff --git a/libamqpprox/amqpprox_backend.h b/libamqpprox/amqpprox_backend.h index 86bf2c2..be4a8db 100644 --- a/libamqpprox/amqpprox_backend.h +++ b/libamqpprox/amqpprox_backend.h @@ -30,6 +30,7 @@ class Backend { std::string d_datacenterTag; std::string d_host; std::string d_ip; + std::string d_virtualHost; int d_port; bool d_proxyProtocolEnabled; bool d_tlsEnabled; @@ -40,14 +41,28 @@ class Backend { const std::string &datacenterTag, const std::string &host, const std::string &ip, + const std::string &virtualHost, int port, bool proxyProtocolEnabled = false, bool tlsEnabled = false, bool dnsBasedEntry = false); + Backend(const std::string &name, + const std::string &datacenterTag, + const std::string &host, + const std::string &ip, + int port, + bool proxyProtocolEnabled = false, + bool tlsEnabled = false, + bool dnsBasedEntry = false) + : Backend(name, datacenterTag, host, ip, "", port, proxyProtocolEnabled, tlsEnabled, dnsBasedEntry) + { + } + Backend(); inline const std::string &host() const; + inline const std::string &virtualHost() const; inline const std::string &ip() const; inline int port() const; inline const std::string &datacenterTag() const; @@ -62,6 +77,11 @@ inline const std::string &Backend::host() const return d_host; } +inline const std::string &Backend::virtualHost() const +{ + return d_virtualHost; +} + inline const std::string &Backend::ip() const { return d_ip; diff --git a/libamqpprox/amqpprox_backendcontrolcommand.cpp b/libamqpprox/amqpprox_backendcontrolcommand.cpp index ecec1d9..0a6dc47 100644 --- a/libamqpprox/amqpprox_backendcontrolcommand.cpp +++ b/libamqpprox/amqpprox_backendcontrolcommand.cpp @@ -40,8 +40,8 @@ std::string BackendControlCommand::commandVerb() const std::string BackendControlCommand::helpText() const { - return "(ADD name datacenter host port [SEND-PROXY] [TLS] | ADD_DNS name " - "datacenter address port [SEND-PROXY] [TLS] | DELETE name | " + return "(ADD name datacenter host[/vhost] port [SEND-PROXY] [TLS] | ADD_DNS name " + "datacenter address[/vhost] port [SEND-PROXY] [TLS] | DELETE name | " "PRINT) - Change backend servers"; } @@ -63,6 +63,7 @@ void BackendControlCommand::handleCommand(const std::string & /* command */, std::string name; std::string datacenter; std::string host; + std::string virtualHost; int port = 0; std::string arg1, arg2; iss >> name; @@ -75,6 +76,12 @@ void BackendControlCommand::handleCommand(const std::string & /* command */, boost::to_upper(arg2); if (!name.empty() && !datacenter.empty() && !host.empty() && port) { + std::string::size_type vhostPos = host.find("/"); + if (vhostPos != std::string::npos) { + virtualHost = host.substr(vhostPos + 1); + host = host.substr(0, vhostPos); + } + std::string ip; if (!isDns) { auto &ioContext = controlHandle->ioContext(); @@ -99,6 +106,7 @@ void BackendControlCommand::handleCommand(const std::string & /* command */, datacenter, host, ip, + virtualHost, port, isSendProxy, isSecure, diff --git a/libamqpprox/amqpprox_connector.cpp b/libamqpprox/amqpprox_connector.cpp index a2dea32..caac7b9 100644 --- a/libamqpprox/amqpprox_connector.cpp +++ b/libamqpprox/amqpprox_connector.cpp @@ -220,7 +220,11 @@ void Connector::receive(const Method &method, FlowType direction) LOG_TRACE << "Server Tune: " << d_receivedTune; sendResponse(d_tuneOk, false); - sendResponse(d_open, false); + + methods::Open openCopy = d_open; + openCopy.setVirtualHost(d_sessionState_p->getBackendVirtualHost()); + sendResponse(openCopy, false); + d_state = State::OPEN_SENT; } break; case State::OPEN_SENT: { diff --git a/libamqpprox/amqpprox_methods_open.h b/libamqpprox/amqpprox_methods_open.h index 786284c..cf7ba89 100644 --- a/libamqpprox/amqpprox_methods_open.h +++ b/libamqpprox/amqpprox_methods_open.h @@ -35,6 +35,10 @@ class Open { public: const std::string &virtualHost() const { return d_virtualHost; } + void setVirtualHost(const std::string& virtualHost) { + d_virtualHost = virtualHost; + } + /** * \brief Decode specified buffer and copy the data into open method */ diff --git a/libamqpprox/amqpprox_session.cpp b/libamqpprox/amqpprox_session.cpp index 6c0ec63..6a9db7b 100644 --- a/libamqpprox/amqpprox_session.cpp +++ b/libamqpprox/amqpprox_session.cpp @@ -249,6 +249,12 @@ void Session::attemptConnection( auto currentBackend = connectionManager->getConnection(d_egressRetryCounter); + if (currentBackend != nullptr) { + d_sessionState.setBackendVirtualHost(currentBackend->virtualHost()); + } else { + d_sessionState.setBackendVirtualHost(""); + } + // With Boost ASIO it sometimes on Linux returns a good error code, // but no items in the list. This catches this case as well as the // regular error return. @@ -550,7 +556,7 @@ void Session::establishConnection() // Initialize auth request data authproto::AuthRequest authRequestData; - authRequestData.set_vhostname(d_sessionState.getVirtualHost()); + authRequestData.set_vhostname(d_sessionState.getBackendVirtualHost()); authproto::SASL *saslPtr = authRequestData.mutable_authdata(); saslPtr->set_authmechanism(sasl.first); saslPtr->set_credentials(sasl.second); diff --git a/libamqpprox/amqpprox_sessionstate.cpp b/libamqpprox/amqpprox_sessionstate.cpp index 33c0465..fef3d34 100644 --- a/libamqpprox/amqpprox_sessionstate.cpp +++ b/libamqpprox/amqpprox_sessionstate.cpp @@ -214,6 +214,7 @@ std::ostream &operator<<(std::ostream &os, const SessionState &state) os << std::setw(7) << state.id() << ": " << "vhost=" << state.getVirtualHost() << " " + << "vhost-back=" << state.getBackendVirtualHost() << " " << ", " << (state.getDisconnectType() == SessionState::DisconnectType::NOT_DISCONNECTED diff --git a/libamqpprox/amqpprox_sessionstate.h b/libamqpprox/amqpprox_sessionstate.h index 683f589..88c8116 100644 --- a/libamqpprox/amqpprox_sessionstate.h +++ b/libamqpprox/amqpprox_sessionstate.h @@ -72,6 +72,7 @@ class SessionState { std::atomic d_ingressSecured; std::atomic d_limitedConnection; std::string d_virtualHost; + std::string d_backendVirtualHost; DisconnectType d_disconnectedStatus; uint64_t d_id; mutable std::mutex d_lock; @@ -209,6 +210,10 @@ class SessionState { */ inline const std::string &getVirtualHost() const; + inline void setBackendVirtualHost(const std::string& virtualHost); + + inline const std::string &getBackendVirtualHost() const; + /** * \return the state(paused/unpaused) of the virtual host */ @@ -280,6 +285,18 @@ inline const std::string &SessionState::getVirtualHost() const return d_virtualHost; } +inline void SessionState::setBackendVirtualHost(const std::string& virtualHost) +{ + std::lock_guard lg(d_lock); + d_backendVirtualHost = virtualHost; +} + +inline const std::string &SessionState::getBackendVirtualHost() const +{ + std::lock_guard lg(d_lock); + return d_backendVirtualHost.empty() ? d_virtualHost : d_backendVirtualHost; +} + inline bool SessionState::getPaused() const { return d_paused;