diff options
author | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
---|---|---|
committer | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
commit | 66765100f4257159622cefe57bed50125a5ad017 (patch) | |
tree | a88ee23bb194eb91f0ebb2d9b23ff423e3ea8e37 /cpp/src/qpid/client | |
parent | 1aeaa7b16e5ce54f10c901d75c4d40f9f88b9db6 (diff) | |
parent | 88b98b2f4152ef59a671fad55a0d08338b6b78ca (diff) | |
download | qpid-python-rajith_jms_client.tar.gz |
Creating a branch for experimenting with some ideas for JMS client.rajith_jms_client
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/rajith_jms_client@1128369 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/client')
76 files changed, 0 insertions, 11458 deletions
diff --git a/cpp/src/qpid/client/Bounds.cpp b/cpp/src/qpid/client/Bounds.cpp deleted file mode 100644 index cc2577d5fc..0000000000 --- a/cpp/src/qpid/client/Bounds.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Bounds.h" - -#include "qpid/log/Statement.h" -#include "qpid/sys/Waitable.h" - -namespace qpid { -namespace client { - -using sys::Waitable; - -Bounds::Bounds(size_t maxSize) : max(maxSize), current(0) {} - -bool Bounds::expand(size_t sizeRequired, bool block) { - if (!max) return true; - Waitable::ScopedLock l(lock); - if (block) { - Waitable::ScopedWait w(lock); - while (current + sizeRequired > max) - lock.wait(); - } - current += sizeRequired; - return current <= max; -} - -void Bounds::reduce(size_t size) { - if (!max || size == 0) return; - Waitable::ScopedLock l(lock); - assert(current >= size); - current -= std::min(size, current); - if (current < max && lock.hasWaiters()) { - lock.notifyAll(); - } -} - -size_t Bounds::getCurrentSize() { - Waitable::ScopedLock l(lock); - return current; -} - -std::ostream& operator<<(std::ostream& out, const Bounds& bounds) { - out << "current=" << bounds.current << ", max=" << bounds.max << " [" << &bounds << "]"; - return out; -} - -void Bounds::setException(const sys::ExceptionHolder& e) { - Waitable::ScopedLock l(lock); - lock.setException(e); - lock.waitWaiters(); // Wait for waiting threads to exit. -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Bounds.h b/cpp/src/qpid/client/Bounds.h deleted file mode 100644 index 838fcb8368..0000000000 --- a/cpp/src/qpid/client/Bounds.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef QPID_CLIENT_BOUNDSCHECKING_H -#define QPID_CLIENT_BOUNDSCHECKING_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Waitable.h" - -namespace qpid{ -namespace client{ - -class Bounds -{ - public: - Bounds(size_t maxSize); - bool expand(size_t, bool block); - void reduce(size_t); - size_t getCurrentSize(); - void setException(const sys::ExceptionHolder&); - - private: - friend std::ostream& operator<<(std::ostream&, const Bounds&); - sys::Waitable lock; - const size_t max; - size_t current; -}; - -std::ostream& operator<<(std::ostream&, const Bounds&); - - -}} - -#endif diff --git a/cpp/src/qpid/client/ChainableFrameHandler.h b/cpp/src/qpid/client/ChainableFrameHandler.h deleted file mode 100644 index 29e16d53dc..0000000000 --- a/cpp/src/qpid/client/ChainableFrameHandler.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _ChainableFrameHandler_ -#define _ChainableFrameHandler_ - -#include <boost/function.hpp> -#include "qpid/framing/AMQFrame.h" - -namespace qpid { -namespace client { - -struct ChainableFrameHandler -{ - typedef boost::function<void(framing::AMQFrame&)> FrameDelegate; - - FrameDelegate in; - FrameDelegate out; - - ChainableFrameHandler() {} - ChainableFrameHandler(FrameDelegate i, FrameDelegate o): in(i), out(o) {} - virtual ~ChainableFrameHandler() {} -}; - -}} - - - -#endif diff --git a/cpp/src/qpid/client/Completion.cpp b/cpp/src/qpid/client/Completion.cpp deleted file mode 100644 index a97c8c3534..0000000000 --- a/cpp/src/qpid/client/Completion.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Completion.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/PrivateImplRef.h" - -namespace qpid { -namespace client { - -typedef PrivateImplRef<Completion> PI; -Completion::Completion(CompletionImpl* p) { PI::ctor(*this, p); } -Completion::Completion(const Completion& c) : Handle<CompletionImpl>() { PI::copy(*this, c); } -Completion::~Completion() { PI::dtor(*this); } -Completion& Completion::operator=(const Completion& c) { return PI::assign(*this, c); } - - -void Completion::wait() { impl->wait(); } -bool Completion::isComplete() { return impl->isComplete(); } -std::string Completion::getResult() { return impl->getResult(); } - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/CompletionImpl.h b/cpp/src/qpid/client/CompletionImpl.h deleted file mode 100644 index f180708316..0000000000 --- a/cpp/src/qpid/client/CompletionImpl.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_CLIENT_COMPLETIONIMPL_H -#define QPID_CLIENT_COMPLETIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qpid/client/Future.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace client { - -///@internal -class CompletionImpl : public RefCounted -{ -public: - CompletionImpl() {} - CompletionImpl(Future f, boost::shared_ptr<SessionImpl> s) : future(f), session(s) {} - - bool isComplete() { return future.isComplete(*session); } - void wait() { future.wait(*session); } - std::string getResult() { return future.getResult(*session); } - -protected: - Future future; - boost::shared_ptr<SessionImpl> session; -}; - -}} // namespace qpid::client - - -#endif /*!QPID_CLIENT_COMPLETIONIMPL_H*/ diff --git a/cpp/src/qpid/client/Connection.cpp b/cpp/src/qpid/client/Connection.cpp deleted file mode 100644 index 2882ef5d42..0000000000 --- a/cpp/src/qpid/client/Connection.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/Message.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/Url.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/AMQP_HighestVersion.h" - -#include <algorithm> -#include <iostream> -#include <sstream> -#include <functional> -#include <boost/format.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> - -using namespace qpid::framing; -using namespace qpid::sys; - - -namespace qpid { -namespace client { - -Connection::Connection() : version(framing::highestProtocolVersion) -{ - ConnectionImpl::init(); -} - -Connection::~Connection() {} - -void Connection::open( - const Url& url, - const std::string& uid, const std::string& pwd, - const std::string& vhost, - uint16_t maxFrameSize) -{ - ConnectionSettings settings; - settings.username = uid; - settings.password = pwd; - settings.virtualhost = vhost; - settings.maxFrameSize = maxFrameSize; - open(url, settings); -} - -void Connection::open(const Url& url, const ConnectionSettings& settings) { - if (url.empty()) - throw Exception(QPID_MSG("Attempt to open URL with no addresses.")); - Url::const_iterator i = url.begin(); - do { - const Address& addr = *i; - i++; - try { - ConnectionSettings cs(settings); - cs.protocol = addr.protocol; - cs.host = addr.host; - cs.port = addr.port; - open(cs); - break; - } - catch (const Exception& /*e*/) { - if (i == url.end()) throw; - } - } while (i != url.end()); -} - -void Connection::open( - const std::string& host, int port, - const std::string& uid, const std::string& pwd, - const std::string& vhost, - uint16_t maxFrameSize) -{ - ConnectionSettings settings; - settings.host = host; - settings.port = port; - settings.username = uid; - settings.password = pwd; - settings.virtualhost = vhost; - settings.maxFrameSize = maxFrameSize; - open(settings); -} - -bool Connection::isOpen() const { - return impl && impl->isOpen(); -} - -void -Connection::registerFailureCallback ( boost::function<void ()> fn ) { - failureCallback = fn; - if ( impl ) - impl->registerFailureCallback ( fn ); -} - - - -void Connection::open(const ConnectionSettings& settings) -{ - if (isOpen()) - throw Exception(QPID_MSG("Connection::open() was already called")); - - impl = ConnectionImpl::create(version, settings); - impl->open(); - if ( failureCallback ) - impl->registerFailureCallback ( failureCallback ); -} - -const ConnectionSettings& Connection::getNegotiatedSettings() -{ - if (!isOpen()) - throw Exception(QPID_MSG("Connection is not open.")); - return impl->getNegotiatedSettings(); -} - -Session Connection::newSession(const std::string& name, uint32_t timeout) { - if (!isOpen()) - throw Exception(QPID_MSG("Connection has not yet been opened")); - Session s; - SessionBase_0_10Access(s).set(impl->newSession(name, timeout)); - return s; -} - -void Connection::resume(Session& session) { - if (!isOpen()) - throw Exception(QPID_MSG("Connection is not open.")); - impl->addSession(session.impl); - session.impl->resume(impl); -} - -void Connection::close() { - if ( impl ) - impl->close(); -} - -std::vector<Url> Connection::getInitialBrokers() { - return impl ? impl->getInitialBrokers() : std::vector<Url>(); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/ConnectionAccess.h b/cpp/src/qpid/client/ConnectionAccess.h deleted file mode 100644 index 3a763f692f..0000000000 --- a/cpp/src/qpid/client/ConnectionAccess.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_CONNECTIONACCESS_H -#define QPID_CLIENT_CONNECTIONACCESS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Connection.h" - -/**@file @internal Internal use only */ - -namespace qpid { -namespace client { - - - -struct ConnectionAccess { - static void setVersion(Connection& c, const framing::ProtocolVersion& v) { c.version = v; } - static boost::shared_ptr<ConnectionImpl> getImpl(Connection& c) { return c.impl; } - static void setImpl(Connection& c, boost::shared_ptr<ConnectionImpl> i) { c.impl = i; } -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_CONNECTIONACCESS_H*/ diff --git a/cpp/src/qpid/client/ConnectionHandler.cpp b/cpp/src/qpid/client/ConnectionHandler.cpp deleted file mode 100644 index 4fbf55aa60..0000000000 --- a/cpp/src/qpid/client/ConnectionHandler.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ConnectionHandler.h" - -#include "qpid/SaslFactory.h" -#include "qpid/StringUtils.h" -#include "qpid/client/Bounds.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/ClientInvoker.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Helpers.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SystemInfo.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::framing::connection; -using qpid::sys::SecurityLayer; -using qpid::sys::Duration; -using qpid::sys::TimerTask; -using qpid::sys::Timer; -using qpid::sys::AbsTime; -using qpid::sys::TIME_SEC; -using qpid::sys::ScopedLock; -using qpid::sys::Mutex; - -namespace { -const std::string OK("OK"); -const std::string PLAIN("PLAIN"); -const std::string en_US("en_US"); - -const std::string INVALID_STATE_START("start received in invalid state"); -const std::string INVALID_STATE_TUNE("tune received in invalid state"); -const std::string INVALID_STATE_OPEN_OK("open-ok received in invalid state"); -const std::string INVALID_STATE_CLOSE_OK("close-ok received in invalid state"); - -const std::string SESSION_FLOW_CONTROL("qpid.session_flow"); -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -const int SESSION_FLOW_CONTROL_VER = 1; -} - -CloseCode ConnectionHandler::convert(uint16_t replyCode) -{ - switch (replyCode) { - case 200: return CLOSE_CODE_NORMAL; - case 320: return CLOSE_CODE_CONNECTION_FORCED; - case 402: return CLOSE_CODE_INVALID_PATH; - case 501: default: - return CLOSE_CODE_FRAMING_ERROR; - } -} - -ConnectionHandler::Adapter::Adapter(ConnectionHandler& h, Bounds& b) : handler(h), bounds(b) {} -void ConnectionHandler::Adapter::handle(qpid::framing::AMQFrame& f) -{ - bounds.expand(f.encodedSize(), false); - handler.out(f); -} - -ConnectionHandler::ConnectionHandler(const ConnectionSettings& s, ProtocolVersion& v, Bounds& b) - : StateManager(NOT_STARTED), ConnectionSettings(s), outHandler(*this, b), proxy(outHandler), - errorCode(CLOSE_CODE_NORMAL), version(v) -{ - insist = true; - - ESTABLISHED.insert(FAILED); - ESTABLISHED.insert(CLOSED); - ESTABLISHED.insert(OPEN); - - FINISHED.insert(FAILED); - FINISHED.insert(CLOSED); - - properties.setInt(SESSION_FLOW_CONTROL, SESSION_FLOW_CONTROL_VER); - properties.setString(CLIENT_PROCESS_NAME, sys::SystemInfo::getProcessName()); - properties.setInt(CLIENT_PID, sys::SystemInfo::getProcessId()); - properties.setInt(CLIENT_PPID, sys::SystemInfo::getParentProcessId()); -} - -void ConnectionHandler::incoming(AMQFrame& frame) -{ - if (getState() == CLOSED) { - throw Exception("Received frame on closed connection"); - } - - if (rcvTimeoutTask) { - // Received frame on connection so delay timeout - rcvTimeoutTask->restart(); - } - - AMQBody* body = frame.getBody(); - try { - if (frame.getChannel() != 0 || !invoke(static_cast<ConnectionOperations&>(*this), *body)) { - switch(getState()) { - case OPEN: - in(frame); - break; - case CLOSING: - QPID_LOG(warning, "Ignoring frame while closing connection: " << frame); - break; - default: - throw Exception("Cannot receive frames on non-zero channel until connection is established."); - } - } - }catch(std::exception& e){ - QPID_LOG(warning, "Closing connection due to " << e.what()); - setState(CLOSING); - errorCode = CLOSE_CODE_FRAMING_ERROR; - errorText = e.what(); - proxy.close(501, e.what()); - } -} - -void ConnectionHandler::outgoing(AMQFrame& frame) -{ - if (getState() == OPEN) - out(frame); - else - throw TransportFailure(errorText.empty() ? "Connection is not open." : errorText); -} - -void ConnectionHandler::waitForOpen() -{ - waitFor(ESTABLISHED); - if (getState() == FAILED || getState() == CLOSED) { - throw ConnectionException(errorCode, errorText); - } -} - -void ConnectionHandler::close() -{ - switch (getState()) { - case NEGOTIATING: - case OPENING: - fail("Connection closed before it was established"); - break; - case OPEN: - if (setState(CLOSING, OPEN)) { - proxy.close(200, OK); - if (ConnectionSettings::heartbeat) { - //heartbeat timer is turned off at this stage, so don't wait indefinately - if (!waitFor(FINISHED, qpid::sys::Duration(ConnectionSettings::heartbeat * qpid::sys::TIME_SEC))) { - QPID_LOG(warning, "Connection close timed out"); - } - } else { - waitFor(FINISHED);//FINISHED = CLOSED or FAILED - } - } - //else, state was changed from open after we checked, can only - //change to failed or closed, so nothing to do - break; - - // Nothing to do if already CLOSING, CLOSED, FAILED or if NOT_STARTED - } -} - -void ConnectionHandler::heartbeat() -{ - // Do nothing - the purpose of heartbeats is just to make sure that there is some - // traffic on the connection within the heart beat interval, we check for the - // traffic and don't need to do anything in response to heartbeats - - // Although the above is still true we're now using a received heartbeat as a trigger - // to send out our own heartbeat - proxy.heartbeat(); -} - -void ConnectionHandler::checkState(STATES s, const std::string& msg) -{ - if (getState() != s) { - throw CommandInvalidException(msg); - } -} - -void ConnectionHandler::fail(const std::string& message) -{ - errorCode = CLOSE_CODE_FRAMING_ERROR; - errorText = message; - QPID_LOG(warning, message); - setState(FAILED); -} - -namespace { -std::string SPACE(" "); - -std::string join(const std::vector<std::string>& in) -{ - std::string result; - for (std::vector<std::string>::const_iterator i = in.begin(); i != in.end(); ++i) { - if (result.size()) result += SPACE; - result += *i; - } - return result; -} - -void intersection(const std::vector<std::string>& a, const std::vector<std::string>& b, std::vector<std::string>& results) -{ - for (std::vector<std::string>::const_iterator i = a.begin(); i != a.end(); ++i) { - if (std::find(b.begin(), b.end(), *i) != b.end()) results.push_back(*i); - } -} - -} - -void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& mechanisms, const Array& /*locales*/) -{ - checkState(NOT_STARTED, INVALID_STATE_START); - setState(NEGOTIATING); - sasl = SaslFactory::getInstance().create( username, - password, - service, - host, - minSsf, - maxSsf - ); - - std::vector<std::string> mechlist; - if (mechanism.empty()) { - //mechlist is simply what the server offers - mechanisms.collect(mechlist); - } else { - //mechlist is the intersection of those indicated by user and - //those supported by server, in the order listed by user - std::vector<std::string> allowed = split(mechanism, " "); - std::vector<std::string> supported; - mechanisms.collect(supported); - intersection(allowed, supported, mechlist); - if (mechlist.empty()) { - throw Exception(QPID_MSG("Desired mechanism(s) not valid: " << mechanism << " (supported: " << join(supported) << ")")); - } - } - - if (sasl.get()) { - string response = sasl->start(join(mechlist), getSecuritySettings ? getSecuritySettings() : 0); - proxy.startOk(properties, sasl->getMechanism(), response, locale); - } else { - //TODO: verify that desired mechanism and locale are supported - string response = ((char)0) + username + ((char)0) + password; - proxy.startOk(properties, mechanism, response, locale); - } -} - -void ConnectionHandler::secure(const std::string& challenge) -{ - if (sasl.get()) { - string response = sasl->step(challenge); - proxy.secureOk(response); - } else { - throw NotImplementedException("Challenge-response cycle not yet implemented in client"); - } -} - -void ConnectionHandler::tune(uint16_t maxChannelsProposed, uint16_t maxFrameSizeProposed, - uint16_t heartbeatMin, uint16_t heartbeatMax) -{ - checkState(NEGOTIATING, INVALID_STATE_TUNE); - maxChannels = std::min(maxChannels, maxChannelsProposed); - maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed); - // Clip the requested heartbeat to the maximum/minimum offered - uint16_t heartbeat = ConnectionSettings::heartbeat; - heartbeat = heartbeat < heartbeatMin ? heartbeatMin : - heartbeat > heartbeatMax ? heartbeatMax : - heartbeat; - ConnectionSettings::heartbeat = heartbeat; - proxy.tuneOk(maxChannels, maxFrameSize, heartbeat); - setState(OPENING); - proxy.open(virtualhost, capabilities, insist); -} - -void ConnectionHandler::openOk ( const Array& knownBrokers ) -{ - checkState(OPENING, INVALID_STATE_OPEN_OK); - knownBrokersUrls.clear(); - framing::Array::ValueVector::const_iterator i; - for ( i = knownBrokers.begin(); i != knownBrokers.end(); ++i ) - knownBrokersUrls.push_back(Url((*i)->get<std::string>())); - if (sasl.get()) { - securityLayer = sasl->getSecurityLayer(maxFrameSize); - operUserId = sasl->getUserId(); - } - setState(OPEN); - QPID_LOG(debug, "Known-brokers for connection: " << log::formatList(knownBrokersUrls)); -} - - -void ConnectionHandler::redirect(const std::string& /*host*/, const Array& /*knownHosts*/) -{ - throw NotImplementedException("Redirection received from broker; not yet implemented in client"); -} - -void ConnectionHandler::close(uint16_t replyCode, const std::string& replyText) -{ - proxy.closeOk(); - errorCode = convert(replyCode); - errorText = replyText; - setState(CLOSED); - QPID_LOG(warning, "Broker closed connection: " << replyCode << ", " << replyText); - if (onError) { - onError(replyCode, replyText); - } -} - -void ConnectionHandler::closeOk() -{ - checkState(CLOSING, INVALID_STATE_CLOSE_OK); - if (onError && errorCode != CLOSE_CODE_NORMAL) { - onError(errorCode, errorText); - } else if (onClose) { - onClose(); - } - setState(CLOSED); -} - -bool ConnectionHandler::isOpen() const -{ - return getState() == OPEN; -} - -bool ConnectionHandler::isClosed() const -{ - int s = getState(); - return s == CLOSED || s == FAILED; -} - -bool ConnectionHandler::isClosing() const { return getState() == CLOSING; } - -std::auto_ptr<qpid::sys::SecurityLayer> ConnectionHandler::getSecurityLayer() -{ - return securityLayer; -} - -void ConnectionHandler::setRcvTimeoutTask(boost::intrusive_ptr<qpid::sys::TimerTask> t) -{ - rcvTimeoutTask = t; -} diff --git a/cpp/src/qpid/client/ConnectionHandler.h b/cpp/src/qpid/client/ConnectionHandler.h deleted file mode 100644 index 6af2e987fb..0000000000 --- a/cpp/src/qpid/client/ConnectionHandler.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionHandler_ -#define _ConnectionHandler_ - -#include "qpid/client/ChainableFrameHandler.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Sasl.h" -#include "qpid/client/StateManager.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/AMQP_ClientOperations.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/InputHandler.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/Timer.h" -#include "qpid/Url.h" -#include <memory> - -namespace qpid { - -namespace sys { -struct SecuritySettings; -} - -namespace client { - -class Bounds; - -class ConnectionHandler : private StateManager, - public ConnectionSettings, - public ChainableFrameHandler, - public framing::InputHandler, - private framing::AMQP_ClientOperations::ConnectionHandler -{ - typedef framing::AMQP_ClientOperations::ConnectionHandler ConnectionOperations; - enum STATES {NOT_STARTED, NEGOTIATING, OPENING, OPEN, CLOSING, CLOSED, FAILED}; - std::set<int> ESTABLISHED, FINISHED; - - class Adapter : public framing::FrameHandler - { - ConnectionHandler& handler; - Bounds& bounds; - public: - Adapter(ConnectionHandler& h, Bounds& bounds); - void handle(framing::AMQFrame& f); - }; - - Adapter outHandler; - framing::AMQP_ServerProxy::Connection proxy; - framing::connection::CloseCode errorCode; - std::string errorText; - bool insist; - framing::ProtocolVersion version; - framing::Array capabilities; - framing::FieldTable properties; - std::auto_ptr<Sasl> sasl; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - boost::intrusive_ptr<qpid::sys::TimerTask> rcvTimeoutTask; - std::string operUserId; - - void checkState(STATES s, const std::string& msg); - - //methods corresponding to connection controls: - void start(const framing::FieldTable& serverProperties, - const framing::Array& mechanisms, - const framing::Array& locales); - void secure(const std::string& challenge); - void tune(uint16_t channelMax, - uint16_t frameMax, - uint16_t heartbeatMin, - uint16_t heartbeatMax); - void openOk(const framing::Array& knownHosts); - void redirect(const std::string& host, - const framing::Array& knownHosts); - void close(uint16_t replyCode, const std::string& replyText); - void closeOk(); - void heartbeat(); - -public: - using InputHandler::handle; - typedef boost::function<void()> CloseListener; - typedef boost::function<void(uint16_t, const std::string&)> ErrorListener; - typedef boost::function<const qpid::sys::SecuritySettings*()> GetSecuritySettings; - - ConnectionHandler(const ConnectionSettings&, framing::ProtocolVersion&, Bounds&); - - void received(framing::AMQFrame& f) { incoming(f); } - - void incoming(framing::AMQFrame& frame); - void outgoing(framing::AMQFrame& frame); - - void waitForOpen(); - void close(); - void fail(const std::string& message); - - // Note that open and closed aren't related by open = !closed - bool isOpen() const; - bool isClosed() const; - bool isClosing() const; - - std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(); - void setRcvTimeoutTask(boost::intrusive_ptr<qpid::sys::TimerTask>); - - CloseListener onClose; - ErrorListener onError; - - std::vector<Url> knownBrokersUrls; - - static framing::connection::CloseCode convert(uint16_t replyCode); - const std::string& getUserId() const { return operUserId; } - GetSecuritySettings getSecuritySettings; /** query the transport for its security details */ -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/ConnectionImpl.cpp b/cpp/src/qpid/client/ConnectionImpl.cpp deleted file mode 100644 index 40c004f166..0000000000 --- a/cpp/src/qpid/client/ConnectionImpl.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ConnectionImpl.h" - -#include "qpid/client/LoadPlugins.h" -#include "qpid/client/Connector.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/SessionImpl.h" - -#include "qpid/log/Statement.h" -#include "qpid/Url.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/Options.h" - -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/shared_ptr.hpp> - -#include <limits> -#include <vector> - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -namespace qpid { -namespace client { - -using namespace qpid::framing; -using namespace qpid::framing::connection; -using namespace qpid::sys; -using namespace qpid::framing::connection;//for connection error codes - -namespace { -// Maybe should amalgamate the singletons into a single client singleton - -// Get timer singleton -Timer& theTimer() { - static Mutex timerInitLock; - ScopedLock<Mutex> l(timerInitLock); - - static qpid::sys::Timer t; - return t; -} - -struct IOThreadOptions : public qpid::Options { - int maxIOThreads; - - IOThreadOptions(int c) : - Options("IO threading options"), - maxIOThreads(c) - { - addOptions() - ("max-iothreads", optValue(maxIOThreads, "N"), "Maximum number of io threads to use"); - } -}; - -// IO threads -class IOThread { - int maxIOThreads; - int ioThreads; - int connections; - Mutex threadLock; - std::vector<Thread> t; - Poller::shared_ptr poller_; - -public: - void add() { - ScopedLock<Mutex> l(threadLock); - ++connections; - if (!poller_) - poller_.reset(new Poller); - if (ioThreads < connections && ioThreads < maxIOThreads) { - QPID_LOG(debug, "Created IO thread: " << ioThreads); - ++ioThreads; - t.push_back( Thread(poller_.get()) ); - } - } - - void sub() { - ScopedLock<Mutex> l(threadLock); - --connections; - } - - Poller::shared_ptr poller() const { - assert(poller_); - return poller_; - } - - // Here is where the maximum number of threads is set - IOThread(int c) : - ioThreads(0), - connections(0) - { - IOThreadOptions options(c); - options.parse(0, 0, QPIDC_CONF_FILE, true); - maxIOThreads = (options.maxIOThreads != -1) ? - options.maxIOThreads : 1; - } - - // We can't destroy threads one-by-one as the only - // control we have is to shutdown the whole lot - // and we can't do that before we're unloaded as we can't - // restart the Poller after shutting it down - ~IOThread() { - std::vector<Thread> threads; - { - ScopedLock<Mutex> l(threadLock); - if (poller_) - poller_->shutdown(); - t.swap(threads); - } - for (std::vector<Thread>::iterator i = threads.begin(); i != threads.end(); ++i) { - i->join(); - } - } -}; - -IOThread& theIO() { - static IOThread io(SystemInfo::concurrency()); - return io; -} - -class HeartbeatTask : public TimerTask { - TimeoutHandler& timeout; - - void fire() { - // If we ever get here then we have timed out - QPID_LOG(debug, "Traffic timeout"); - timeout.idleIn(); - } - -public: - HeartbeatTask(Duration p, TimeoutHandler& t) : - TimerTask(p,"Heartbeat"), - timeout(t) - {} -}; - -} - -void ConnectionImpl::init() { - // Ensure that the plugin modules have been loaded - // This will make sure that any plugin protocols are available - theModuleLoader(); - - // Ensure the IO threads exist: - // This needs to be called in the Connection constructor - // so that they will still exist at last connection destruction - (void) theIO(); -} - -boost::shared_ptr<ConnectionImpl> ConnectionImpl::create(framing::ProtocolVersion version, const ConnectionSettings& settings) -{ - boost::shared_ptr<ConnectionImpl> instance(new ConnectionImpl(version, settings), boost::bind(&ConnectionImpl::release, _1)); - return instance; -} - -ConnectionImpl::ConnectionImpl(framing::ProtocolVersion v, const ConnectionSettings& settings) - : Bounds(settings.maxFrameSize * settings.bounds), - handler(settings, v, *this), - version(v), - nextChannel(1), - shutdownComplete(false), - released(false) -{ - handler.in = boost::bind(&ConnectionImpl::incoming, this, _1); - handler.out = boost::bind(&Connector::send, boost::ref(connector), _1); - handler.onClose = boost::bind(&ConnectionImpl::closed, this, - CLOSE_CODE_NORMAL, std::string()); - //only set error handler once open - handler.onError = boost::bind(&ConnectionImpl::closed, this, _1, _2); - handler.getSecuritySettings = boost::bind(&Connector::getSecuritySettings, boost::ref(connector)); -} - -const uint16_t ConnectionImpl::NEXT_CHANNEL = std::numeric_limits<uint16_t>::max(); - -ConnectionImpl::~ConnectionImpl() { - if (heartbeatTask) heartbeatTask->cancel(); - theIO().sub(); -} - -void ConnectionImpl::addSession(const boost::shared_ptr<SessionImpl>& session, uint16_t channel) -{ - Mutex::ScopedLock l(lock); - for (uint16_t i = 0; i < NEXT_CHANNEL; i++) { //will at most search through channels once - uint16_t c = channel == NEXT_CHANNEL ? nextChannel++ : channel; - boost::weak_ptr<SessionImpl>& s = sessions[c]; - boost::shared_ptr<SessionImpl> ss = s.lock(); - if (!ss) { - //channel is free, we can assign it to this session - session->setChannel(c); - s = session; - return; - } else if (channel != NEXT_CHANNEL) { - //channel is taken and was requested explicitly so don't look for another - throw SessionBusyException(QPID_MSG("Channel " << ss->getChannel() << " attached to " << ss->getId())); - } //else channel is busy, but we can keep looking for a free one - } - // If we get here, we didn't find any available channel. - throw ResourceLimitExceededException("There are no channels available"); -} - -void ConnectionImpl::handle(framing::AMQFrame& frame) -{ - handler.outgoing(frame); -} - -void ConnectionImpl::incoming(framing::AMQFrame& frame) -{ - boost::shared_ptr<SessionImpl> s; - { - Mutex::ScopedLock l(lock); - s = sessions[frame.getChannel()].lock(); - } - if (!s) { - QPID_LOG(info, *this << " dropping frame received on invalid channel: " << frame); - } else { - s->in(frame); - } -} - -bool ConnectionImpl::isOpen() const -{ - return handler.isOpen(); -} - -void ConnectionImpl::open() -{ - const std::string& protocol = handler.protocol; - const std::string& host = handler.host; - int port = handler.port; - - theIO().add(); - connector.reset(Connector::create(protocol, theIO().poller(), version, handler, this)); - connector->setInputHandler(&handler); - connector->setShutdownHandler(this); - try { - connector->connect(host, port); - - } catch (const std::exception& e) { - QPID_LOG(debug, "Failed to connect to " << protocol << ":" << host << ":" << port << " " << e.what()); - connector.reset(); - throw; - } - connector->init(); - QPID_LOG(info, *this << " connected to " << protocol << ":" << host << ":" << port); - - // Enable heartbeat if requested - uint16_t heartbeat = static_cast<ConnectionSettings&>(handler).heartbeat; - if (heartbeat) { - // Set connection timeout to be 2x heart beat interval and setup timer - heartbeatTask = new HeartbeatTask(heartbeat * 2 * TIME_SEC, *this); - handler.setRcvTimeoutTask(heartbeatTask); - theTimer().add(heartbeatTask); - } - - // If the connect fails then the connector is cleaned up either when we try to connect again - // - in that case in connector.reset() above; - // - or when we are deleted - handler.waitForOpen(); - - // If the SASL layer has provided an "operational" userId for the connection, - // put it in the negotiated settings. - const std::string& userId(handler.getUserId()); - if (!userId.empty()) - handler.username = userId; - - //enable security layer if one has been negotiated: - std::auto_ptr<SecurityLayer> securityLayer = handler.getSecurityLayer(); - if (securityLayer.get()) { - QPID_LOG(debug, *this << " activating security layer"); - connector->activateSecurityLayer(securityLayer); - } else { - QPID_LOG(debug, *this << " no security layer in place"); - } -} - -void ConnectionImpl::idleIn() -{ - connector->abort(); -} - -void ConnectionImpl::idleOut() -{ - AMQFrame frame((AMQHeartbeatBody())); - connector->send(frame); -} - -void ConnectionImpl::close() -{ - if (heartbeatTask) - heartbeatTask->cancel(); - // close() must be idempotent and no-throw as it will often be called in destructors. - if (handler.isOpen()) { - try { - handler.close(); - closed(CLOSE_CODE_NORMAL, "Closed by client"); - } catch (...) {} - } - assert(!handler.isOpen()); -} - - -template <class F> void ConnectionImpl::closeInternal(const F& f) { - if (heartbeatTask) { - heartbeatTask->cancel(); - } - { - Mutex::ScopedUnlock u(lock); - connector->close(); - } - //notifying sessions of failure can result in those session being - //deleted which in turn results in a call to erase(); this can - //even happen on this thread, when 's' goes out of scope - //below. Using a copy prevents the map being modified as we - //iterate through. - SessionMap copy; - sessions.swap(copy); - for (SessionMap::iterator i = copy.begin(); i != copy.end(); ++i) { - boost::shared_ptr<SessionImpl> s = i->second.lock(); - if (s) f(s); - } -} - -void ConnectionImpl::closed(uint16_t code, const std::string& text) { - Mutex::ScopedLock l(lock); - setException(new ConnectionException(ConnectionHandler::convert(code), text)); - closeInternal(boost::bind(&SessionImpl::connectionClosed, _1, code, text)); -} - -void ConnectionImpl::shutdown() { - if (!handler.isClosed()) { - failedConnection(); - } - bool canDelete; - { - Mutex::ScopedLock l(lock); - //association with IO thread is now ended - shutdownComplete = true; - //If we have already been released, we can now delete ourselves - canDelete = released; - } - if (canDelete) delete this; -} - -void ConnectionImpl::release() { - bool isActive; - { - Mutex::ScopedLock l(lock); - isActive = connector && !shutdownComplete; - } - //If we are still active - i.e. associated with an IO thread - - //then we cannot delete ourselves yet, but must wait for the - //shutdown callback which we can trigger by calling - //connector.close() - if (isActive) { - connector->close(); - bool canDelete; - { - Mutex::ScopedLock l(lock); - released = true; - canDelete = shutdownComplete; - } - if (canDelete) delete this; - } else { - delete this; - } -} - -static const std::string CONN_CLOSED("Connection closed"); - -void ConnectionImpl::failedConnection() { - if ( failureCallback ) - failureCallback(); - - if (handler.isClosed()) return; - - bool isClosing = handler.isClosing(); - bool isOpen = handler.isOpen(); - - std::ostringstream msg; - msg << *this << " closed"; - - // FIXME aconway 2008-06-06: exception use, amqp0-10 does not seem to have - // an appropriate close-code. connection-forced is not right. - handler.fail(msg.str());//ensure connection is marked as failed before notifying sessions - - // At this point if the object isn't open and isn't closing it must have failed to open - // so we can't do the rest of the cleanup - if (!isClosing && !isOpen) return; - - Mutex::ScopedLock l(lock); - closeInternal(boost::bind(&SessionImpl::connectionBroke, _1, msg.str())); - setException(new TransportFailure(msg.str())); -} - -void ConnectionImpl::erase(uint16_t ch) { - Mutex::ScopedLock l(lock); - sessions.erase(ch); -} - -const ConnectionSettings& ConnectionImpl::getNegotiatedSettings() -{ - return handler; -} - -std::vector<qpid::Url> ConnectionImpl::getInitialBrokers() { - return handler.knownBrokersUrls; -} - -boost::shared_ptr<SessionImpl> ConnectionImpl::newSession(const std::string& name, uint32_t timeout, uint16_t channel) { - boost::shared_ptr<SessionImpl> simpl(new SessionImpl(name, shared_from_this())); - addSession(simpl, channel); - simpl->open(timeout); - return simpl; -} - -std::ostream& operator<<(std::ostream& o, const ConnectionImpl& c) { - if (c.connector) - return o << "Connection " << c.connector->getIdentifier(); - else - return o << "Connection <not connected>"; -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/ConnectionImpl.h b/cpp/src/qpid/client/ConnectionImpl.h deleted file mode 100644 index cc81500b18..0000000000 --- a/cpp/src/qpid/client/ConnectionImpl.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _ConnectionImpl_ -#define _ConnectionImpl_ - -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionHandler.h" - -#include "qpid/framing/FrameHandler.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/ShutdownHandler.h" -#include "qpid/sys/TimeoutHandler.h" - -#include <map> -#include <iosfwd> -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include <boost/scoped_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> - -namespace qpid { -namespace client { - -class Connector; -struct ConnectionSettings; -class SessionImpl; - -class ConnectionImpl : public Bounds, - public framing::FrameHandler, - public sys::TimeoutHandler, - public sys::ShutdownHandler, - public boost::enable_shared_from_this<ConnectionImpl> -{ - typedef std::map<uint16_t, boost::weak_ptr<SessionImpl> > SessionMap; - - static const uint16_t NEXT_CHANNEL; - - SessionMap sessions; - ConnectionHandler handler; - boost::scoped_ptr<Connector> connector; - framing::ProtocolVersion version; - uint16_t nextChannel; - sys::Mutex lock; - bool shutdownComplete; - bool released; - - boost::intrusive_ptr<qpid::sys::TimerTask> heartbeatTask; - - template <class F> void closeInternal(const F&); - - void incoming(framing::AMQFrame& frame); - void closed(uint16_t, const std::string&); - void idleOut(); - void idleIn(); - void shutdown(); - void failedConnection(); - void release(); - ConnectionImpl(framing::ProtocolVersion version, const ConnectionSettings& settings); - - boost::function<void ()> failureCallback; - - public: - static void init(); - static boost::shared_ptr<ConnectionImpl> create(framing::ProtocolVersion version, const ConnectionSettings& settings); - ~ConnectionImpl(); - - void open(); - bool isOpen() const; - - boost::shared_ptr<SessionImpl> newSession(const std::string& name, uint32_t timeout, uint16_t channel=NEXT_CHANNEL); - void addSession(const boost::shared_ptr<SessionImpl>&, uint16_t channel=NEXT_CHANNEL); - - void close(); - void handle(framing::AMQFrame& frame); - void erase(uint16_t channel); - const ConnectionSettings& getNegotiatedSettings(); - - std::vector<Url> getInitialBrokers(); - void registerFailureCallback ( boost::function<void ()> fn ) { failureCallback = fn; } - framing::ProtocolVersion getVersion() { return version; } - - friend std::ostream& operator<<(std::ostream&, const ConnectionImpl&); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/client/ConnectionSettings.cpp b/cpp/src/qpid/client/ConnectionSettings.cpp deleted file mode 100644 index 822e4af269..0000000000 --- a/cpp/src/qpid/client/ConnectionSettings.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/ConnectionSettings.h" - -#include "qpid/log/Logger.h" -#include "qpid/sys/Socket.h" -#include "qpid/Url.h" -#include "qpid/Version.h" - -namespace qpid { -namespace client { - -ConnectionSettings::ConnectionSettings() : - protocol("tcp"), - host("localhost"), - port(5672), - locale("en_US"), - heartbeat(0), - maxChannels(32767), - maxFrameSize(65535), - bounds(2), - tcpNoDelay(false), - service(qpid::saslName), - minSsf(0), - maxSsf(256), - sslCertName("") -{} - -ConnectionSettings::~ConnectionSettings() {} - -void ConnectionSettings::configureSocket(qpid::sys::Socket& socket) const -{ - if (tcpNoDelay) { - socket.setTcpNoDelay(); - QPID_LOG(info, "Set TCP_NODELAY"); - } -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Connector.cpp b/cpp/src/qpid/client/Connector.cpp deleted file mode 100644 index c71dd9ecb6..0000000000 --- a/cpp/src/qpid/client/Connector.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Connector.h" -#include "qpid/Url.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SecurityLayer.h" - -#include <map> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; - -namespace { - typedef std::map<std::string, Connector::Factory*> ProtocolRegistry; - - ProtocolRegistry& theProtocolRegistry() { - static ProtocolRegistry protocolRegistry; - - return protocolRegistry; - } -} - -Connector* Connector::create(const std::string& proto, - boost::shared_ptr<Poller> p, - framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) -{ - ProtocolRegistry::const_iterator i = theProtocolRegistry().find(proto); - if (i==theProtocolRegistry().end()) { - throw Exception(QPID_MSG("Unknown protocol: " << proto)); - } - return (i->second)(p, v, s, c); -} - -void Connector::registerFactory(const std::string& proto, Factory* connectorFactory) -{ - ProtocolRegistry::const_iterator i = theProtocolRegistry().find(proto); - if (i!=theProtocolRegistry().end()) { - QPID_LOG(error, "Tried to register protocol: " << proto << " more than once"); - } - theProtocolRegistry()[proto] = connectorFactory; - Url::addProtocol(proto); -} - -void Connector::activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>) -{ -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Connector.h b/cpp/src/qpid/client/Connector.h deleted file mode 100644 index 586012f9d6..0000000000 --- a/cpp/src/qpid/client/Connector.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Connector_ -#define _Connector_ - - -#include "qpid/framing/OutputHandler.h" -#include "qpid/framing/ProtocolVersion.h" - -#include <boost/shared_ptr.hpp> - -#include <string> - -namespace qpid { - -namespace sys { -class ShutdownHandler; -class SecurityLayer; -class Poller; -struct SecuritySettings; -} - -namespace framing { -class InputHandler; -class AMQFrame; -} - -namespace client { - -struct ConnectionSettings; -class ConnectionImpl; - -///@internal -class Connector : public framing::OutputHandler -{ - public: - // Protocol connector factory related stuff (it might be better to separate this code from the TCP Connector in the future) - typedef Connector* Factory(boost::shared_ptr<qpid::sys::Poller>, - framing::ProtocolVersion, const ConnectionSettings&, ConnectionImpl*); - static Connector* create(const std::string& proto, - boost::shared_ptr<qpid::sys::Poller>, - framing::ProtocolVersion, const ConnectionSettings&, ConnectionImpl*); - static void registerFactory(const std::string& proto, Factory* connectorFactory); - - virtual ~Connector() {}; - virtual void connect(const std::string& host, int port) = 0; - virtual void init() {}; - virtual void close() = 0; - virtual void send(framing::AMQFrame& frame) = 0; - virtual void abort() = 0; - - virtual void setInputHandler(framing::InputHandler* handler) = 0; - virtual void setShutdownHandler(sys::ShutdownHandler* handler) = 0; - virtual sys::ShutdownHandler* getShutdownHandler() const = 0; - virtual framing::OutputHandler* getOutputHandler() = 0; - virtual const std::string& getIdentifier() const = 0; - - virtual void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); - - virtual const qpid::sys::SecuritySettings* getSecuritySettings() = 0; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/client/Demux.cpp b/cpp/src/qpid/client/Demux.cpp deleted file mode 100644 index abc23c75df..0000000000 --- a/cpp/src/qpid/client/Demux.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Demux.h" -#include "qpid/Exception.h" -#include "qpid/framing/MessageTransferBody.h" - -#include <iostream> - -namespace qpid { -namespace client { - -ByTransferDest::ByTransferDest(const std::string& d) : dest(d) {} -bool ByTransferDest::operator()(const framing::FrameSet& frameset) const -{ - return frameset.isA<framing::MessageTransferBody>() && - frameset.as<framing::MessageTransferBody>()->getDestination() == dest; -} - -ScopedDivert::ScopedDivert(const std::string& _dest, Demux& _demuxer) : dest(_dest), demuxer(_demuxer) -{ - queue = demuxer.add(dest, ByTransferDest(dest)); -} - -ScopedDivert::~ScopedDivert() -{ - demuxer.remove(dest); -} - -Demux::Demux() : defaultQueue(new Queue()) {} - -Demux::~Demux() { close(sys::ExceptionHolder(new ClosedException())); } - -Demux::QueuePtr ScopedDivert::getQueue() -{ - return queue; -} - -void Demux::handle(framing::FrameSet::shared_ptr frameset) -{ - sys::Mutex::ScopedLock l(lock); - bool matched = false; - for (iterator i = records.begin(); i != records.end() && !matched; i++) { - if (i->condition && i->condition(*frameset)) { - matched = true; - i->queue->push(frameset); - } - } - if (!matched) { - defaultQueue->push(frameset); - } -} - -void Demux::close(const sys::ExceptionHolder& ex) -{ - sys::Mutex::ScopedLock l(lock); - for (iterator i = records.begin(); i != records.end(); i++) { - i->queue->close(ex); - } - defaultQueue->close(ex); -} - -void Demux::open() -{ - sys::Mutex::ScopedLock l(lock); - for (iterator i = records.begin(); i != records.end(); i++) { - i->queue->open(); - } - defaultQueue->open(); -} - -Demux::QueuePtr Demux::add(const std::string& name, Condition condition) -{ - sys::Mutex::ScopedLock l(lock); - iterator i = std::find_if(records.begin(), records.end(), Find(name)); - if (i == records.end()) { - Record r(name, condition); - records.push_back(r); - return r.queue; - } else { - throw Exception("Queue already exists for " + name); - } -} - -void Demux::remove(const std::string& name) -{ - sys::Mutex::ScopedLock l(lock); - records.remove_if(Find(name)); -} - -Demux::QueuePtr Demux::get(const std::string& name) -{ - sys::Mutex::ScopedLock l(lock); - iterator i = std::find_if(records.begin(), records.end(), Find(name)); - if (i == records.end()) { - throw Exception("No queue for " + name); - } - return i->queue; -} - -Demux::QueuePtr Demux::getDefault() -{ - return defaultQueue; -} - -Demux::Find::Find(const std::string& n) : name(n) {} - -bool Demux::Find::operator()(const Record& record) const -{ - return record.name == name; -} - -}} - diff --git a/cpp/src/qpid/client/Demux.h b/cpp/src/qpid/client/Demux.h deleted file mode 100644 index 31dc3f9c06..0000000000 --- a/cpp/src/qpid/client/Demux.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <list> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include "qpid/framing/FrameSet.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/ClientImportExport.h" - -#ifndef _Demux_ -#define _Demux_ - -namespace qpid { -namespace client { - -///@internal -class ByTransferDest -{ - const std::string dest; -public: - ByTransferDest(const std::string& dest); - bool operator()(const framing::FrameSet& frameset) const; -}; - -///@internal -class Demux -{ -public: - typedef boost::function<bool(const framing::FrameSet&)> Condition; - typedef sys::BlockingQueue<framing::FrameSet::shared_ptr> Queue; - typedef boost::shared_ptr<Queue> QueuePtr; - - QPID_CLIENT_EXTERN Demux(); - QPID_CLIENT_EXTERN ~Demux(); - - QPID_CLIENT_EXTERN void handle(framing::FrameSet::shared_ptr); - QPID_CLIENT_EXTERN void close(const sys::ExceptionHolder& ex); - QPID_CLIENT_EXTERN void open(); - - QPID_CLIENT_EXTERN QueuePtr add(const std::string& name, Condition); - QPID_CLIENT_EXTERN void remove(const std::string& name); - QPID_CLIENT_EXTERN QueuePtr get(const std::string& name); - QPID_CLIENT_EXTERN QueuePtr getDefault(); - -private: - struct Record - { - const std::string name; - Condition condition; - QueuePtr queue; - - Record(const std::string& n, Condition c) : name(n), condition(c), queue(new Queue()) {} - }; - - sys::Mutex lock; - std::list<Record> records; - QueuePtr defaultQueue; - - typedef std::list<Record>::iterator iterator; - - struct Find - { - const std::string name; - Find(const std::string& name); - bool operator()(const Record& record) const; - }; -}; - -class ScopedDivert -{ - const std::string dest; - Demux& demuxer; - Demux::QueuePtr queue; -public: - ScopedDivert(const std::string& dest, Demux& demuxer); - ~ScopedDivert(); - Demux::QueuePtr getQueue(); -}; - -}} // namespace qpid::client - - -#endif diff --git a/cpp/src/qpid/client/Dispatcher.cpp b/cpp/src/qpid/client/Dispatcher.cpp deleted file mode 100644 index a715c623bf..0000000000 --- a/cpp/src/qpid/client/Dispatcher.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Dispatcher.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/SessionImpl.h" - -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/Message.h" -#include "qpid/client/MessageImpl.h" - -#include <boost/version.hpp> -#if (BOOST_VERSION >= 104000) -# include <boost/serialization/state_saver.hpp> - using boost::serialization::state_saver; -#else -# include <boost/state_saver.hpp> - using boost::state_saver; -#endif /* BOOST_VERSION */ - -using qpid::framing::FrameSet; -using qpid::framing::MessageTransferBody; -using qpid::sys::Mutex; -using qpid::sys::ScopedLock; -using qpid::sys::Thread; - -namespace qpid { -namespace client { - -Dispatcher::Dispatcher(const Session& s, const std::string& q) - : session(s), - running(false), - autoStop(true), - failoverHandler(0) -{ - Demux& demux = SessionBase_0_10Access(session).get()->getDemux(); - queue = q.empty() ? demux.getDefault() : demux.get(q); -} - -void Dispatcher::start() -{ - worker = Thread(this); -} - -void Dispatcher::wait() -{ - worker.join(); -} - -void Dispatcher::run() -{ - Mutex::ScopedLock l(lock); - if (running) - throw Exception("Dispatcher is already running."); - state_saver<bool> reset(running); // Reset to false on exit. - running = true; - try { - while (!queue->isClosed()) { - Mutex::ScopedUnlock u(lock); - FrameSet::shared_ptr content = queue->pop(); - if (content->isA<MessageTransferBody>()) { - Message msg(new MessageImpl(*content)); - boost::intrusive_ptr<SubscriptionImpl> listener = find(msg.getDestination()); - if (!listener) { - QPID_LOG(error, "No listener found for destination " << msg.getDestination()); - } else { - assert(listener); - listener->received(msg); - } - } else { - if (handler.get()) { - handler->handle(*content); - } else { - QPID_LOG(warning, "No handler found for " << *(content->getMethod())); - } - } - } - session.sync(); // Make sure all our acks are received before returning. - } - catch (const ClosedException&) { - QPID_LOG(debug, QPID_MSG(session.getId() << ": closed by peer")); - } - catch (const TransportFailure&) { - QPID_LOG(info, QPID_MSG(session.getId() << ": transport failure")); - throw; - } - catch (const std::exception& e) { - if ( failoverHandler ) { - QPID_LOG(debug, QPID_MSG(session.getId() << " failover: " << e.what())); - failoverHandler(); - } else { - QPID_LOG(error, session.getId() << " error: " << e.what()); - throw; - } - } -} - -void Dispatcher::stop() -{ - ScopedLock<Mutex> l(lock); - queue->close(); // Will interrupt thread blocked in pop() -} - -void Dispatcher::setAutoStop(bool b) -{ - ScopedLock<Mutex> l(lock); - autoStop = b; -} - -boost::intrusive_ptr<SubscriptionImpl> Dispatcher::find(const std::string& name) -{ - ScopedLock<Mutex> l(lock); - Listeners::iterator i = listeners.find(name); - if (i == listeners.end()) { - return defaultListener; - } - return i->second; -} - -void Dispatcher::listen(const boost::intrusive_ptr<SubscriptionImpl>& subscription) { - ScopedLock<Mutex> l(lock); - listeners[subscription->getName()] = subscription; -} - -void Dispatcher::cancel(const std::string& destination) { - ScopedLock<Mutex> l(lock); - if (listeners.erase(destination) && running && autoStop && listeners.empty()) - queue->close(); -} - -}} diff --git a/cpp/src/qpid/client/Dispatcher.h b/cpp/src/qpid/client/Dispatcher.h deleted file mode 100644 index 74fdb90103..0000000000 --- a/cpp/src/qpid/client/Dispatcher.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Dispatcher_ -#define _Dispatcher_ - -#include <map> -#include <memory> -#include <string> -#include <boost/shared_ptr.hpp> -#include "qpid/client/Session.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/client/ClientImportExport.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/SubscriptionImpl.h" - -namespace qpid { -namespace client { - -class SubscriptionImpl; - -///@internal -typedef framing::Handler<framing::FrameSet> FrameSetHandler; - -///@internal -class Dispatcher : public sys::Runnable -{ - typedef std::map<std::string, boost::intrusive_ptr<SubscriptionImpl> >Listeners; - sys::Mutex lock; - sys::Thread worker; - Session session; - Demux::QueuePtr queue; - bool running; - bool autoStop; - Listeners listeners; - boost::intrusive_ptr<SubscriptionImpl> defaultListener; - std::auto_ptr<FrameSetHandler> handler; - - boost::intrusive_ptr<SubscriptionImpl> find(const std::string& name); - bool isStopped(); - - boost::function<void ()> failoverHandler; - -public: - Dispatcher(const Session& session, const std::string& queue = ""); - ~Dispatcher() {} - - void start(); - void wait(); - // As this class is marked 'internal', no extern should be made here; - // however, some test programs rely on it. - QPID_CLIENT_EXTERN void run(); - void stop(); - void setAutoStop(bool b); - - void registerFailoverHandler ( boost::function<void ()> fh ) - { - failoverHandler = fh; - } - - void listen(const boost::intrusive_ptr<SubscriptionImpl>& subscription); - void cancel(const std::string& destination); -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/Execution.h b/cpp/src/qpid/client/Execution.h deleted file mode 100644 index ad622af9c1..0000000000 --- a/cpp/src/qpid/client/Execution.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Execution_ -#define _Execution_ - -#include "qpid/framing/SequenceNumber.h" -#include "qpid/client/Demux.h" - -namespace qpid { -namespace client { - -/**@internal - * - * Provides access to more detailed aspects of the session - * implementation. - */ -class Execution -{ -public: - virtual ~Execution() {} - /** - * Provides access to the demultiplexing function within the - * session implementation - */ - virtual Demux& getDemux() = 0; - /** - * Wait until notification has been received of completion of the - * outgoing command with the specified id. - */ - void waitForCompletion(const framing::SequenceNumber& id); -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/FailoverListener.cpp b/cpp/src/qpid/client/FailoverListener.cpp deleted file mode 100644 index bf4fa91d49..0000000000 --- a/cpp/src/qpid/client/FailoverListener.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/FailoverListener.h" -#include "qpid/client/Session.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include "qpid/log/Helpers.h" - -namespace qpid { -namespace client { - -const std::string FailoverListener::AMQ_FAILOVER("amq.failover"); - -FailoverListener::FailoverListener(Connection c) : - connection(c), - session(c.newSession(AMQ_FAILOVER+"."+framing::Uuid(true).str())), - subscriptions(session) -{ init(true); } - -FailoverListener::FailoverListener(Connection c, bool useInitial) : - connection(c), - session(c.newSession(AMQ_FAILOVER+"."+framing::Uuid(true).str())), - subscriptions(session) -{ init(useInitial); } - -void FailoverListener::init(bool useInitial) { - if (useInitial) knownBrokers = connection.getInitialBrokers(); - if (session.exchangeQuery(arg::name=AMQ_FAILOVER).getNotFound()) { - session.close(); - return; - } - std::string qname=session.getId().getName(); - session.queueDeclare(arg::queue=qname, arg::exclusive=true, arg::autoDelete=true); - session.exchangeBind(arg::queue=qname, arg::exchange=AMQ_FAILOVER); - subscriptions.subscribe(*this, qname, SubscriptionSettings(FlowControl::unlimited(), - ACCEPT_MODE_NONE)); - thread = sys::Thread(*this); -} - -void FailoverListener::run() { - try { - subscriptions.run(); - } catch(...) {} -} - -FailoverListener::~FailoverListener() { - try { - subscriptions.stop(); - thread.join(); - if (connection.isOpen()) { - session.sync(); - session.close(); - } - } catch (...) {} -} - -void FailoverListener::received(Message& msg) { - sys::Mutex::ScopedLock l(lock); - knownBrokers = getKnownBrokers(msg); -} - -std::vector<Url> FailoverListener::getKnownBrokers() const { - sys::Mutex::ScopedLock l(lock); - return knownBrokers; -} - -std::vector<Url> FailoverListener::getKnownBrokers(const Message& msg) { - std::vector<Url> knownBrokers; - framing::Array urlArray; - msg.getHeaders().getArray("amq.failover", urlArray); - for (framing::Array::ValueVector::const_iterator i = urlArray.begin(); - i != urlArray.end(); - ++i ) - knownBrokers.push_back(Url((*i)->get<std::string>())); - return knownBrokers; -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/FailoverManager.cpp b/cpp/src/qpid/client/FailoverManager.cpp deleted file mode 100644 index 9405765b47..0000000000 --- a/cpp/src/qpid/client/FailoverManager.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/FailoverManager.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" - - -namespace qpid { -namespace client { - -using qpid::sys::Monitor; -using qpid::sys::AbsTime; -using qpid::sys::Duration; - -FailoverManager::FailoverManager(const ConnectionSettings& s, - ReconnectionStrategy* rs) : settings(s), strategy(rs), state(IDLE) {} - -void FailoverManager::execute(Command& c) -{ - bool retry = false; - bool completed = false; - AbsTime failed; - while (!completed) { - try { - AsyncSession session = connect().newSession(); - if (retry) { - Duration failoverTime(failed, AbsTime::now()); - QPID_LOG(info, "Failed over for " << &c << " in " << (failoverTime/qpid::sys::TIME_MSEC) << " milliseconds"); - } - c.execute(session, retry); - session.sync();//TODO: shouldn't be required - session.close(); - completed = true; - } catch(const TransportFailure&) { - retry = true; - failed = AbsTime::now(); - } - } -} - -void FailoverManager::close() -{ - Monitor::ScopedLock l(lock); - connection.close(); -} - -Connection& FailoverManager::connect(std::vector<Url> brokers) -{ - Monitor::ScopedLock l(lock); - if (state == CANT_CONNECT) { - state = IDLE;//retry - } - while (!connection.isOpen()) { - if (state == CONNECTING) { - lock.wait(); - } else if (state == CANT_CONNECT) { - throw CannotConnectException("Cannot establish a connection"); - } else { - state = CONNECTING; - Connection c; - if (brokers.empty() && failoverListener.get()) - brokers = failoverListener->getKnownBrokers(); - attempt(c, settings, brokers); - if (c.isOpen()) state = IDLE; - else state = CANT_CONNECT; - connection = c; - lock.notifyAll(); - } - } - return connection; -} - -Connection& FailoverManager::getConnection() -{ - Monitor::ScopedLock l(lock); - return connection; -} - -void FailoverManager::attempt(Connection& c, ConnectionSettings s, std::vector<Url> urls) -{ - Monitor::ScopedUnlock u(lock); - if (strategy) strategy->editUrlList(urls); - if (urls.empty()) { - attempt(c, s); - } else { - for (std::vector<Url>::const_iterator i = urls.begin(); i != urls.end() && !c.isOpen(); ++i) { - for (Url::const_iterator j = i->begin(); j != i->end() && !c.isOpen(); ++j) { - const Address& addr = *j; - s.protocol = addr.protocol; - s.host = addr.host; - s.port = addr.port; - attempt(c, s); - } - } - } -} - -void FailoverManager::attempt(Connection& c, ConnectionSettings s) -{ - try { - QPID_LOG(info, "Attempting to connect to " << s.host << " on " << s.port << "..."); - c.open(s); - failoverListener.reset(new FailoverListener(c)); - QPID_LOG(info, "Connected to " << s.host << " on " << s.port); - } catch (const Exception& e) { - QPID_LOG(info, "Could not connect to " << s.host << " on " << s.port << ": " << e.what()); - } -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Future.cpp b/cpp/src/qpid/client/Future.cpp deleted file mode 100644 index 740cd3df59..0000000000 --- a/cpp/src/qpid/client/Future.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Future.h" -#include "qpid/client/SessionImpl.h" - -namespace qpid { -namespace client { - -void Future::wait(SessionImpl& session) -{ - if (!complete) { - session.waitForCompletion(command); - } - complete = true; -} - -bool Future::isComplete(SessionImpl& session) -{ - return complete || session.isComplete(command); -} - -void Future::setFutureResult(boost::shared_ptr<FutureResult> r) -{ - result = r; -} - -}} diff --git a/cpp/src/qpid/client/FutureCompletion.cpp b/cpp/src/qpid/client/FutureCompletion.cpp deleted file mode 100644 index ccfb073855..0000000000 --- a/cpp/src/qpid/client/FutureCompletion.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/FutureCompletion.h" - -using namespace qpid::client; -using namespace qpid::sys; - -FutureCompletion::FutureCompletion() : complete(false) {} - -bool FutureCompletion::isComplete() const -{ - Monitor::ScopedLock l(lock); - return complete; -} - -void FutureCompletion::completed() -{ - Monitor::ScopedLock l(lock); - complete = true; - lock.notifyAll(); -} - -void FutureCompletion::waitForCompletion() const -{ - Monitor::ScopedLock l(lock); - while (!complete) { - lock.wait(); - } -} diff --git a/cpp/src/qpid/client/FutureResult.cpp b/cpp/src/qpid/client/FutureResult.cpp deleted file mode 100644 index 0237eb1464..0000000000 --- a/cpp/src/qpid/client/FutureResult.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/FutureResult.h" - -#include "qpid/client/SessionImpl.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -const std::string& FutureResult::getResult(SessionImpl& session) const -{ - waitForCompletion(); - session.assertOpen(); - return result; -} - -void FutureResult::received(const std::string& r) -{ - Monitor::ScopedLock l(lock); - result = r; - complete = true; - lock.notifyAll(); -} diff --git a/cpp/src/qpid/client/LoadPlugins.cpp b/cpp/src/qpid/client/LoadPlugins.cpp deleted file mode 100644 index 246eb60c67..0000000000 --- a/cpp/src/qpid/client/LoadPlugins.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "LoadPlugins.h" - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "qpid/Modules.h" -#include "qpid/sys/Shlib.h" -#include <string> -#include <vector> - -using std::vector; -using std::string; - -namespace qpid { -namespace client { - -namespace { - -struct LoadtimeInitialise { - LoadtimeInitialise() { - qpid::ModuleOptions moduleOptions(QPIDC_MODULE_DIR); - string defaultPath (moduleOptions.loadDir); - moduleOptions.parse (0, 0, QPIDC_CONF_FILE, true); - - for (vector<string>::iterator iter = moduleOptions.load.begin(); - iter != moduleOptions.load.end(); - iter++) - qpid::tryShlib (iter->data(), false); - - if (!moduleOptions.noLoad) { - bool isDefault = defaultPath == moduleOptions.loadDir; - qpid::loadModuleDir (moduleOptions.loadDir, isDefault); - } - } -}; - -} // namespace - -void theModuleLoader() { - static LoadtimeInitialise l; -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/LoadPlugins.h b/cpp/src/qpid/client/LoadPlugins.h deleted file mode 100644 index 0be4ae9f0c..0000000000 --- a/cpp/src/qpid/client/LoadPlugins.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _LoadPlugins_ -#define _LoadPlugins_ - -namespace qpid { -namespace client { - -void theModuleLoader(); - -}} - - -#endif diff --git a/cpp/src/qpid/client/LocalQueue.cpp b/cpp/src/qpid/client/LocalQueue.cpp deleted file mode 100644 index 0019adabaf..0000000000 --- a/cpp/src/qpid/client/LocalQueue.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/LocalQueue.h" -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/Exception.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/client/SubscriptionImpl.h" - -namespace qpid { -namespace client { - -using namespace framing; - -typedef PrivateImplRef<LocalQueue> PI; - -LocalQueue::LocalQueue() { PI::ctor(*this, new LocalQueueImpl()); } -LocalQueue::LocalQueue(const LocalQueue& x) : Handle<LocalQueueImpl>() { PI::copy(*this, x); } -LocalQueue::~LocalQueue() { PI::dtor(*this); } -LocalQueue& LocalQueue::operator=(const LocalQueue& x) { return PI::assign(*this, x); } - -Message LocalQueue::pop(sys::Duration timeout) { return impl->pop(timeout); } - -Message LocalQueue::get(sys::Duration timeout) { return impl->get(timeout); } - -bool LocalQueue::get(Message& result, sys::Duration timeout) { return impl->get(result, timeout); } - -bool LocalQueue::empty() const { return impl->empty(); } -size_t LocalQueue::size() const { return impl->size(); } - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/LocalQueueImpl.cpp b/cpp/src/qpid/client/LocalQueueImpl.cpp deleted file mode 100644 index 8b191728f4..0000000000 --- a/cpp/src/qpid/client/LocalQueueImpl.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/Exception.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/CompletionImpl.h" - -namespace qpid { -namespace client { - -using namespace framing; - -Message LocalQueueImpl::pop(sys::Duration timeout) { return get(timeout); } - -Message LocalQueueImpl::get(sys::Duration timeout) { - Message result; - bool ok = get(result, timeout); - if (!ok) throw Exception("Timed out waiting for a message"); - return result; -} - -bool LocalQueueImpl::get(Message& result, sys::Duration timeout) { - if (!queue) - throw ClosedException(); - FrameSet::shared_ptr content; - bool ok = queue->pop(content, timeout); - if (!ok) return false; - if (content->isA<MessageTransferBody>()) { - - *MessageImpl::get(result) = MessageImpl(*content); - boost::intrusive_ptr<SubscriptionImpl> si = PrivateImplRef<Subscription>::get(subscription); - assert(si); - if (si) si->received(result); - return true; - } - else - throw CommandInvalidException( - QPID_MSG("Unexpected method: " << content->getMethod())); -} - -bool LocalQueueImpl::empty() const -{ - if (!queue) - throw ClosedException(); - return queue->empty(); -} - -size_t LocalQueueImpl::size() const -{ - if (!queue) - throw ClosedException(); - return queue->size(); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/LocalQueueImpl.h b/cpp/src/qpid/client/LocalQueueImpl.h deleted file mode 100644 index 75b62cf203..0000000000 --- a/cpp/src/qpid/client/LocalQueueImpl.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef QPID_CLIENT_LOCALQUEUEIMPL_H -#define QPID_CLIENT_LOCALQUEUEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ClientImportExport.h" -#include "qpid/client/Handle.h" -#include "qpid/client/Message.h" -#include "qpid/client/Subscription.h" -#include "qpid/client/Demux.h" -#include "qpid/sys/Time.h" -#include "qpid/RefCounted.h" - -namespace qpid { -namespace client { - -/** - * A local queue to collect messages retrieved from a remote broker - * queue. Create a queue and subscribe it using the SubscriptionManager. - * Messages from the remote queue on the broker will be stored in the - * local queue until you retrieve them. - * - * \ingroup clientapi - * - * \details Using a Local Queue - * - * <pre> - * LocalQueue local_queue; - * subscriptions.subscribe(local_queue, string("message_queue")); - * for (int i=0; i<10; i++) { - * Message message = local_queue.get(); - * std::cout << message.getData() << std::endl; - * } - * </pre> - * - * <h2>Getting Messages</h2> - * - * <ul><li> - * <p>get()</p> - * <pre>Message message = local_queue.get();</pre> - * <pre>// Specifying timeouts (TIME_SEC, TIME_MSEC, TIME_USEC, TIME_NSEC) - *#include <qpid/sys/Time.h> - *Message message; - *local_queue.get(message, 5*sys::TIME_SEC);</pre></li></ul> - * - * <h2>Checking size</h2> - * <ul><li> - * <p>empty()</p> - * <pre>if (local_queue.empty()) { ... }</pre></li> - * <li><p>size()</p> - * <pre>std::cout << local_queue.size();</pre></li> - * </ul> - */ - -class LocalQueueImpl : public RefCounted { - public: - /** Wait up to timeout for the next message from the local queue. - *@param result Set to the message from the queue. - *@param timeout wait up this timeout for a message to appear. - *@return true if result was set, false if queue was empty after timeout. - */ - bool get(Message& result, sys::Duration timeout=0); - - /** Get the next message off the local queue, or wait up to the timeout - * for message from the broker queue. - *@param timeout wait up this timeout for a message to appear. - *@return message from the queue. - *@throw ClosedException if subscription is closed or timeout exceeded. - */ - Message get(sys::Duration timeout=sys::TIME_INFINITE); - - /** Synonym for get() */ - Message pop(sys::Duration timeout=sys::TIME_INFINITE); - - /** Return true if local queue is empty. */ - bool empty() const; - - /** Number of messages on the local queue */ - size_t size() const; - - private: - Demux::QueuePtr queue; - Subscription subscription; - friend class SubscriptionManagerImpl; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_LOCALQUEUEIMPL_H*/ diff --git a/cpp/src/qpid/client/Message.cpp b/cpp/src/qpid/client/Message.cpp deleted file mode 100644 index 00f911c57e..0000000000 --- a/cpp/src/qpid/client/Message.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Message.h" -#include "qpid/client/MessageImpl.h" - -namespace qpid { -namespace client { - -Message::Message(MessageImpl* mi) : impl(mi) {} - -Message::Message(const std::string& data, const std::string& routingKey) - : impl(new MessageImpl(data, routingKey)) {} - -Message::Message(const Message& m) : impl(new MessageImpl(*m.impl)) {} - -Message::~Message() { delete impl; } - -Message& Message::operator=(const Message& m) { *impl = *m.impl; return *this; } - -void Message::swap(Message& m) { std::swap(impl, m.impl); } - -std::string Message::getDestination() const { return impl->getDestination(); } -bool Message::isRedelivered() const { return impl->isRedelivered(); } -void Message::setRedelivered(bool redelivered) { impl->setRedelivered(redelivered); } -framing::FieldTable& Message::getHeaders() { return impl->getHeaders(); } -const framing::FieldTable& Message::getHeaders() const { return impl->getHeaders(); } -const framing::SequenceNumber& Message::getId() const { return impl->getId(); } - -void Message::setData(const std::string& s) { impl->setData(s); } -const std::string& Message::getData() const { return impl->getData(); } -std::string& Message::getData() { return impl->getData(); } - -void Message::appendData(const std::string& s) { impl->appendData(s); } - -bool Message::hasMessageProperties() const { return impl->hasMessageProperties(); } -framing::MessageProperties& Message::getMessageProperties() { return impl->getMessageProperties(); } -const framing::MessageProperties& Message::getMessageProperties() const { return impl->getMessageProperties(); } - -bool Message::hasDeliveryProperties() const { return impl->hasDeliveryProperties(); } -framing::DeliveryProperties& Message::getDeliveryProperties() { return impl->getDeliveryProperties(); } -const framing::DeliveryProperties& Message::getDeliveryProperties() const { return impl->getDeliveryProperties(); } - -}} diff --git a/cpp/src/qpid/client/MessageImpl.cpp b/cpp/src/qpid/client/MessageImpl.cpp deleted file mode 100644 index 865c462b15..0000000000 --- a/cpp/src/qpid/client/MessageImpl.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/MessageImpl.h" - -namespace qpid { -namespace client { - -MessageImpl::MessageImpl(const std::string& data, const std::string& routingKey) : TransferContent(data, routingKey) {} - -std::string MessageImpl::getDestination() const -{ - return method.getDestination(); -} - -bool MessageImpl::isRedelivered() const -{ - return hasDeliveryProperties() && getDeliveryProperties().getRedelivered(); -} - -void MessageImpl::setRedelivered(bool redelivered) -{ - getDeliveryProperties().setRedelivered(redelivered); -} - -framing::FieldTable& MessageImpl::getHeaders() -{ - return getMessageProperties().getApplicationHeaders(); -} - -const framing::FieldTable& MessageImpl::getHeaders() const -{ - return getMessageProperties().getApplicationHeaders(); -} - -const framing::MessageTransferBody& MessageImpl::getMethod() const -{ - return method; -} - -const framing::SequenceNumber& MessageImpl::getId() const -{ - return id; -} - -/**@internal for incoming messages */ -MessageImpl::MessageImpl(const framing::FrameSet& frameset) : - method(*frameset.as<framing::MessageTransferBody>()), id(frameset.getId()) -{ - populate(frameset); -} - -}} diff --git a/cpp/src/qpid/client/MessageImpl.h b/cpp/src/qpid/client/MessageImpl.h deleted file mode 100644 index a64ddd20d8..0000000000 --- a/cpp/src/qpid/client/MessageImpl.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_CLIENT_MESSAGEIMPL_H -#define QPID_CLIENT_MESSAGEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/TransferContent.h" -#include <string> - -namespace qpid { -namespace client { - -class MessageImpl : public framing::TransferContent -{ -public: - /** Create a Message. - *@param data Data for the message body. - *@param routingKey Passed to the exchange that routes the message. - */ - MessageImpl(const std::string& data=std::string(), - const std::string& routingKey=std::string()); - - /** The destination of messages sent to the broker is the exchange - * name. The destination of messages received from the broker is - * the delivery tag identifyig the local subscription (often this - * is the name of the subscribed queue.) - */ - std::string getDestination() const; - - /** Check the redelivered flag. */ - bool isRedelivered() const; - /** Set the redelivered flag. */ - void setRedelivered(bool redelivered); - - /** Get a modifyable reference to the message headers. */ - framing::FieldTable& getHeaders(); - - /** Get a non-modifyable reference to the message headers. */ - const framing::FieldTable& getHeaders() const; - - ///@internal - const framing::MessageTransferBody& getMethod() const; - ///@internal - const framing::SequenceNumber& getId() const; - - /**@internal for incoming messages */ - MessageImpl(const framing::FrameSet& frameset); - - static MessageImpl* get(Message& m) { return m.impl; } - static const MessageImpl* get(const Message& m) { return m.impl; } - -private: - //method and id are only set for received messages: - framing::MessageTransferBody method; - framing::SequenceNumber id; -}; - -}} - -#endif /*!QPID_CLIENT_MESSAGEIMPL_H*/ diff --git a/cpp/src/qpid/client/MessageListener.cpp b/cpp/src/qpid/client/MessageListener.cpp deleted file mode 100644 index 0f2a71287c..0000000000 --- a/cpp/src/qpid/client/MessageListener.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/MessageListener.h" - -qpid::client::MessageListener::~MessageListener() {} diff --git a/cpp/src/qpid/client/MessageReplayTracker.cpp b/cpp/src/qpid/client/MessageReplayTracker.cpp deleted file mode 100644 index 3afaae74e8..0000000000 --- a/cpp/src/qpid/client/MessageReplayTracker.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/MessageReplayTracker.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace client { - -MessageReplayTracker::MessageReplayTracker(uint f) : flushInterval(f), count(0) {} - -void MessageReplayTracker::send(const Message& message, const std::string& destination) -{ - buffer.push_back(ReplayRecord(message, destination)); - buffer.back().send(*this); - if (flushInterval && (++count % flushInterval == 0)) { - checkCompletion(); - if (!buffer.empty()) session.flush(); - } -} -void MessageReplayTracker::init(AsyncSession s) -{ - session = s; -} - -void MessageReplayTracker::replay(AsyncSession s) -{ - session = s; - std::for_each(buffer.begin(), buffer.end(), boost::bind(&ReplayRecord::send, _1, boost::ref(*this))); - session.flush(); - count = 0; -} - -void MessageReplayTracker::setFlushInterval(uint f) -{ - flushInterval = f; -} - -uint MessageReplayTracker::getFlushInterval() -{ - return flushInterval; -} - -void MessageReplayTracker::checkCompletion() -{ - buffer.remove_if(boost::bind(&ReplayRecord::isComplete, _1)); -} - -MessageReplayTracker::ReplayRecord::ReplayRecord(const Message& m, const std::string& d) : message(m), destination(d) {} - -void MessageReplayTracker::ReplayRecord::send(MessageReplayTracker& tracker) -{ - status = tracker.session.messageTransfer(arg::destination=destination, arg::content=message); -} - -bool MessageReplayTracker::ReplayRecord::isComplete() -{ - return status.isComplete(); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/PrivateImplRef.h b/cpp/src/qpid/client/PrivateImplRef.h deleted file mode 100644 index 503a383c31..0000000000 --- a/cpp/src/qpid/client/PrivateImplRef.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QPID_CLIENT_PRIVATEIMPL_H -#define QPID_CLIENT_PRIVATEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ClientImportExport.h" -#include <boost/intrusive_ptr.hpp> -#include "qpid/RefCounted.h" - -namespace qpid { -namespace client { - -// FIXME aconway 2009-04-24: details! -/** @file - * - * Helper class to implement a class with a private, reference counted - * implementation and reference semantics. - * - * Such classes are used in the public API to hide implementation, they - * should. Example of use: - * - * === Foo.h - * - * template <class T> PrivateImplRef; - * class FooImpl; - * - * Foo : public Handle<FooImpl> { - * public: - * Foo(FooImpl* = 0); - * Foo(const Foo&); - * ~Foo(); - * Foo& operator=(const Foo&); - * - * int fooDo(); // and other Foo functions... - * - * private: - * typedef FooImpl Impl; - * Impl* impl; - * friend class PrivateImplRef<Foo>; - * - * === Foo.cpp - * - * typedef PrivateImplRef<Foo> PI; - * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } - * Foo::Foo(const Foo& c) : Handle<FooImpl>() { PI::copy(*this, c); } - * Foo::~Foo() { PI::dtor(*this); } - * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } - * - * int foo::fooDo() { return impl->fooDo(); } - * - */ -template <class T> class PrivateImplRef { - public: - typedef typename T::Impl Impl; - typedef boost::intrusive_ptr<Impl> intrusive_ptr; - - static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } - - static void set(T& t, const intrusive_ptr& p) { - if (t.impl == p) return; - if (t.impl) boost::intrusive_ptr_release(t.impl); - t.impl = p.get(); - if (t.impl) boost::intrusive_ptr_add_ref(t.impl); - } - - // Helper functions to implement the ctor, dtor, copy, assign - static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); } - static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); } - static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); } - static T& assign(T& t, const T& x) { set(t, get(x)); return t;} -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_PRIVATEIMPL_H*/ diff --git a/cpp/src/qpid/client/QueueOptions.cpp b/cpp/src/qpid/client/QueueOptions.cpp deleted file mode 100644 index f4c1483859..0000000000 --- a/cpp/src/qpid/client/QueueOptions.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/QueueOptions.h" - -namespace qpid { -namespace client { - -enum QueueEventGeneration {ENQUEUE_ONLY=1, ENQUEUE_AND_DEQUEUE=2}; - - -QueueOptions::QueueOptions() -{} - -const std::string QueueOptions::strMaxCountKey("qpid.max_count"); -const std::string QueueOptions::strMaxSizeKey("qpid.max_size"); -const std::string QueueOptions::strTypeKey("qpid.policy_type"); -const std::string QueueOptions::strREJECT("reject"); -const std::string QueueOptions::strFLOW_TO_DISK("flow_to_disk"); -const std::string QueueOptions::strRING("ring"); -const std::string QueueOptions::strRING_STRICT("ring_strict"); -const std::string QueueOptions::strLastValueQueue("qpid.last_value_queue"); -const std::string QueueOptions::strPersistLastNode("qpid.persist_last_node"); -const std::string QueueOptions::strLVQMatchProperty("qpid.LVQ_key"); -const std::string QueueOptions::strLastValueQueueNoBrowse("qpid.last_value_queue_no_browse"); -const std::string QueueOptions::strQueueEventMode("qpid.queue_event_generation"); - - -QueueOptions::~QueueOptions() -{} - -void QueueOptions::setSizePolicy(QueueSizePolicy sp, uint64_t maxSize, uint32_t maxCount) -{ - if (maxCount) setInt(strMaxCountKey, maxCount); - if (maxSize) setInt(strMaxSizeKey, maxSize); - if (maxSize || maxCount){ - switch (sp) - { - case REJECT: - setString(strTypeKey, strREJECT); - break; - case FLOW_TO_DISK: - setString(strTypeKey, strFLOW_TO_DISK); - break; - case RING: - setString(strTypeKey, strRING); - break; - case RING_STRICT: - setString(strTypeKey, strRING_STRICT); - break; - case NONE: - clearSizePolicy(); - break; - } - } -} - - -void QueueOptions::setPersistLastNode() -{ - setInt(strPersistLastNode, 1); -} - -void QueueOptions::setOrdering(QueueOrderingPolicy op) -{ - if (op == LVQ){ - setInt(strLastValueQueue, 1); - }else if (op == LVQ_NO_BROWSE){ - setInt(strLastValueQueueNoBrowse, 1); - }else { - clearOrdering(); - } -} - -void QueueOptions::getLVQKey(std::string& key) -{ - key.assign(strLVQMatchProperty); -} - -void QueueOptions::clearSizePolicy() -{ - erase(strMaxCountKey); - erase(strMaxSizeKey); - erase(strTypeKey); -} - -void QueueOptions::clearPersistLastNode() -{ - erase(strPersistLastNode); -} - -void QueueOptions::clearOrdering() -{ - erase(strLastValueQueue); -} - -void QueueOptions::enableQueueEvents(bool enqueueOnly) -{ - setInt(strQueueEventMode, enqueueOnly ? ENQUEUE_ONLY : ENQUEUE_AND_DEQUEUE); -} - -} -} - - diff --git a/cpp/src/qpid/client/RdmaConnector.cpp b/cpp/src/qpid/client/RdmaConnector.cpp deleted file mode 100644 index 6af607198c..0000000000 --- a/cpp/src/qpid/client/RdmaConnector.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Connector.h" - -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/Msg.h" - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> - -// This stuff needs to abstracted out of here to a platform specific file -#include <netdb.h> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; -using boost::format; -using boost::str; - -class RdmaConnector : public Connector, public sys::Codec -{ - typedef std::deque<framing::AMQFrame> Frames; - - const uint16_t maxFrameSize; - sys::Mutex lock; - Frames frames; - size_t lastEof; // Position after last EOF in frames - uint64_t currentSize; - Bounds* bounds; - - framing::ProtocolVersion version; - bool initiated; - - sys::Mutex dataConnectedLock; - bool dataConnected; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::OutputHandler* output; - - Rdma::AsynchIO* aio; - Rdma::Connector* acon; - sys::Poller::shared_ptr poller; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - - ~RdmaConnector(); - - // Callbacks - void connected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&); - void connectionError(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, Rdma::ErrorType); - void disconnected(); - void rejected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&); - - void readbuff(Rdma::AsynchIO&, Rdma::Buffer*); - void writebuff(Rdma::AsynchIO&); - void writeDataBlock(const framing::AMQDataBlock& data); - void dataError(Rdma::AsynchIO&); - void drained(); - void connectionStopped(Rdma::Connector* acon, Rdma::AsynchIO* aio); - void dataStopped(Rdma::AsynchIO* aio); - - std::string identifier; - - void connect(const std::string& host, int port); - void close(); - void send(framing::AMQFrame& frame); - void abort() {} // TODO: need to fix this for heartbeat timeouts to work - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - sys::ShutdownHandler* getShutdownHandler() const; - framing::OutputHandler* getOutputHandler(); - const std::string& getIdentifier() const; - void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); - const qpid::sys::SecuritySettings* getSecuritySettings() { return 0; } - - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - -public: - RdmaConnector(Poller::shared_ptr, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new RdmaConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - Connector::registerFactory("rdma", &create); - Connector::registerFactory("ib", &create); - }; - } init; -} - - -RdmaConnector::RdmaConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - lastEof(0), - currentSize(0), - bounds(cimpl), - version(ver), - initiated(false), - dataConnected(false), - shutdownHandler(0), - aio(0), - acon(0), - poller(p) -{ - QPID_LOG(debug, "RdmaConnector created for " << version); -} - -namespace { - void deleteAsynchIO(Rdma::AsynchIO& aio) { - delete &aio; - } - - void deleteConnector(Rdma::ConnectionManager& con) { - delete &con; - } -} - -RdmaConnector::~RdmaConnector() { - QPID_LOG(debug, "~RdmaConnector " << identifier); - if (aio) { - aio->stop(deleteAsynchIO); - } - if (acon) { - acon->stop(deleteConnector); - } -} - -void RdmaConnector::connect(const std::string& host, int port){ - Mutex::ScopedLock l(dataConnectedLock); - assert(!dataConnected); - - acon = new Rdma::Connector( - Rdma::ConnectionParams(maxFrameSize, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&RdmaConnector::connected, this, poller, _1, _2), - boost::bind(&RdmaConnector::connectionError, this, poller, _1, _2), - boost::bind(&RdmaConnector::disconnected, this), - boost::bind(&RdmaConnector::rejected, this, poller, _1, _2)); - - SocketAddress sa(host, boost::lexical_cast<std::string>(port)); - acon->start(poller, sa); -} - -// The following only gets run when connected -void RdmaConnector::connected(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr ci, const Rdma::ConnectionParams& cp) { - try { - Mutex::ScopedLock l(dataConnectedLock); - assert(!dataConnected); - Rdma::QueuePair::intrusive_ptr q = ci->getQueuePair(); - - aio = new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit , Rdma::DEFAULT_WR_ENTRIES, - boost::bind(&RdmaConnector::readbuff, this, _1, _2), - boost::bind(&RdmaConnector::writebuff, this, _1), - 0, // write buffers full - boost::bind(&RdmaConnector::dataError, this, _1)); - - identifier = str(format("[%1% %2%]") % ci->getLocalName() % ci->getPeerName()); - ProtocolInitiation init(version); - writeDataBlock(init); - - aio->start(poller); - - dataConnected = true; - - return; - } catch (const Rdma::Exception& e) { - QPID_LOG(error, "Rdma: Cannot create new connection (Rdma exception): " << e.what()); - } catch (const std::exception& e) { - QPID_LOG(error, "Rdma: Cannot create new connection (unknown exception): " << e.what()); - } - dataConnected = false; - connectionStopped(acon, aio); -} - -void RdmaConnector::connectionError(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, Rdma::ErrorType) { - QPID_LOG(debug, "Connection Error " << identifier); - connectionStopped(acon, aio); -} - -// Bizarrely we seem to get rejected events *after* we've already got a connected event for some peer disconnects -// so we need to check whether the data connection is started or not in here -void RdmaConnector::rejected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams& cp) { - QPID_LOG(debug, "Connection Rejected " << identifier << ": " << cp.maxRecvBufferSize); - if (dataConnected) { - disconnected(); - } else { - connectionStopped(acon, aio); - } -} - -void RdmaConnector::disconnected() { - QPID_LOG(debug, "Connection disconnected " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - // If we're closed already then we'll get to drained() anyway - if (!dataConnected) return; - dataConnected = false; - } - // Make sure that all the disconnected actions take place on the data "thread" - aio->requestCallback(boost::bind(&RdmaConnector::drained, this)); -} - -void RdmaConnector::dataError(Rdma::AsynchIO&) { - QPID_LOG(debug, "Data Error " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - // If we're closed already then we'll get to drained() anyway - if (!dataConnected) return; - dataConnected = false; - } - drained(); -} - -void RdmaConnector::close() { - QPID_LOG(debug, "RdmaConnector::close " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) return; - dataConnected = false; - } - aio->drainWriteQueue(boost::bind(&RdmaConnector::drained, this)); -} - -void RdmaConnector::drained() { - QPID_LOG(debug, "RdmaConnector::drained " << identifier); - assert(!dataConnected); - assert(aio); - Rdma::AsynchIO* a = aio; - aio = 0; - a->stop(boost::bind(&RdmaConnector::dataStopped, this, a)); -} - -void RdmaConnector::dataStopped(Rdma::AsynchIO* a) { - QPID_LOG(debug, "RdmaConnector::dataStopped " << identifier); - assert(!dataConnected); - assert(acon); - Rdma::Connector* c = acon; - acon = 0; - c->stop(boost::bind(&RdmaConnector::connectionStopped, this, c, a)); -} - -void RdmaConnector::connectionStopped(Rdma::Connector* c, Rdma::AsynchIO* a) { - QPID_LOG(debug, "RdmaConnector::connectionStopped " << identifier); - assert(!dataConnected); - aio = 0; - acon = 0; - delete a; - delete c; - if (shutdownHandler) { - ShutdownHandler* s = shutdownHandler; - shutdownHandler = 0; - s->shutdown(); - } -} - -void RdmaConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void RdmaConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* RdmaConnector::getOutputHandler(){ - return this; -} - -sys::ShutdownHandler* RdmaConnector::getShutdownHandler() const { - return shutdownHandler; -} - -const std::string& RdmaConnector::getIdentifier() const { - return identifier; -} - -void RdmaConnector::send(AMQFrame& frame) { - // It is possible that we are called to write after we are already shutting down - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) return; - - bool notifyWrite = false; - { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - //only ask to write if this is the end of a frameset or if we - //already have a buffers worth of data - currentSize += frame.encodedSize(); - if (frame.getEof()) { - lastEof = frames.size(); - notifyWrite = true; - } else { - notifyWrite = (currentSize >= maxFrameSize); - } - } - if (notifyWrite) aio->notifyPendingWrite(); -} - -// Called in IO thread. (write idle routine) -// This is NOT only called in response to previously calling notifyPendingWrite -void RdmaConnector::writebuff(Rdma::AsynchIO&) { - // It's possible to be disconnected and be writable - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) { - return; - } - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - if (!codec->canEncode()) { - return; - } - Rdma::Buffer* buffer = aio->getSendBuffer(); - if (buffer) { - size_t encoded = codec->encode(buffer->bytes(), buffer->byteCount()); - buffer->dataCount(encoded); - aio->queueWrite(buffer); - } -} - -bool RdmaConnector::canEncode() -{ - Mutex::ScopedLock l(lock); - //have at least one full frameset or a whole buffers worth of data - return aio->writable() && (lastEof || currentSize >= maxFrameSize); -} - -size_t RdmaConnector::encode(const char* buffer, size_t size) -{ - framing::Buffer out(const_cast<char*>(buffer), size); - size_t bytesWritten(0); - { - Mutex::ScopedLock l(lock); - while (!frames.empty() && out.available() >= frames.front().encodedSize() ) { - frames.front().encode(out); - QPID_LOG(trace, "SENT " << identifier << ": " << frames.front()); - frames.pop_front(); - if (lastEof) --lastEof; - } - bytesWritten = size - out.available(); - currentSize -= bytesWritten; - } - if (bounds) bounds->reduce(bytesWritten); - return bytesWritten; -} - -void RdmaConnector::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) { - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - codec->decode(buff->bytes(), buff->dataCount()); -} - -size_t RdmaConnector::decode(const char* buffer, size_t size) -{ - framing::Buffer in(const_cast<char*>(buffer), size); - if (!initiated) { - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - //TODO: check the version is correct - QPID_LOG(debug, "RECV " << identifier << " INIT(" << protocolInit << ")"); - } - initiated = true; - } - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV " << identifier << ": " << frame); - input->received(frame); - } - return size - in.available(); -} - -void RdmaConnector::writeDataBlock(const AMQDataBlock& data) { - Rdma::Buffer* buff = aio->getSendBuffer(); - framing::Buffer out(buff->bytes(), buff->byteCount()); - data.encode(out); - buff->dataCount(data.encodedSize()); - aio->queueWrite(buff); -} - -void RdmaConnector::activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer> sl) -{ - securityLayer = sl; - securityLayer->init(this); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Results.cpp b/cpp/src/qpid/client/Results.cpp deleted file mode 100644 index 0de3e8bd04..0000000000 --- a/cpp/src/qpid/client/Results.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Results.h" -#include "qpid/client/FutureResult.h" -#include "qpid/framing/SequenceSet.h" - -using namespace qpid::framing; - -namespace qpid { -namespace client { - -Results::Results() {} - -Results::~Results() { - try { close(); } catch (const std::exception& /*e*/) { assert(0); } -} - -void Results::close() -{ - for (Listeners::iterator i = listeners.begin(); i != listeners.end(); i++) { - i->second->completed(); - } - listeners.clear(); -} - -void Results::completed(const SequenceSet& set) -{ - //call complete on those listeners whose ids fall within the set - Listeners::iterator i = listeners.begin(); - while (i != listeners.end()) { - if (set.contains(i->first)) { - i->second->completed(); - listeners.erase(i++); - } else { - i++; - } - } -} - -void Results::received(const SequenceNumber& id, const std::string& result) -{ - Listeners::iterator i = listeners.find(id); - if (i != listeners.end()) { - i->second->received(result); - listeners.erase(i); - } -} - -Results::FutureResultPtr Results::listenForResult(const SequenceNumber& id) -{ - FutureResultPtr l(new FutureResult()); - listeners[id] = l; - return l; -} - -}} diff --git a/cpp/src/qpid/client/Results.h b/cpp/src/qpid/client/Results.h deleted file mode 100644 index 4c49f6b05b..0000000000 --- a/cpp/src/qpid/client/Results.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SequenceNumber.h" -#include <map> -#include <boost/shared_ptr.hpp> - -#ifndef _Results_ -#define _Results_ - -namespace qpid { -namespace client { - -class FutureResult; - -///@internal -class Results -{ -public: - typedef boost::shared_ptr<FutureResult> FutureResultPtr; - - Results(); - ~Results(); - void completed(const framing::SequenceSet& set); - void received(const framing::SequenceNumber& id, const std::string& result); - FutureResultPtr listenForResult(const framing::SequenceNumber& point); - void close(); - -private: - typedef std::map<framing::SequenceNumber, FutureResultPtr> Listeners; - Listeners listeners; -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/client/SessionBase_0_10.cpp b/cpp/src/qpid/client/SessionBase_0_10.cpp deleted file mode 100644 index e114b7aacc..0000000000 --- a/cpp/src/qpid/client/SessionBase_0_10.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/SessionBase_0_10.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/Future.h" -#include "qpid/framing/all_method_bodies.h" - -namespace qpid { -namespace client { - -using namespace framing; - -SessionBase_0_10::SessionBase_0_10() {} -SessionBase_0_10::~SessionBase_0_10() {} - -void SessionBase_0_10::close() -{ - if (impl) impl->close(); -} - -void SessionBase_0_10::flush() -{ - impl->sendFlush(); -} - -void SessionBase_0_10::sync() -{ - ExecutionSyncBody b; - b.setSync(true); - impl->send(b).wait(*impl); -} - -void SessionBase_0_10::markCompleted(const framing::SequenceSet& ids, bool notifyPeer) -{ - impl->markCompleted(ids, notifyPeer); -} - -void SessionBase_0_10::markCompleted(const framing::SequenceNumber& id, bool cumulative, bool notifyPeer) -{ - impl->markCompleted(id, cumulative, notifyPeer); -} - -void SessionBase_0_10::sendCompletion() -{ - impl->sendCompletion(); -} - -uint16_t SessionBase_0_10::getChannel() const { return impl->getChannel(); } - -void SessionBase_0_10::suspend() { impl->suspend(); } -void SessionBase_0_10::resume(Connection c) { impl->resume(c.impl); } -uint32_t SessionBase_0_10::timeout(uint32_t seconds) { return impl->setTimeout(seconds); } - -SessionId SessionBase_0_10::getId() const { return impl->getId(); } - -bool SessionBase_0_10::isValid() const { return impl; } - -Connection SessionBase_0_10::getConnection() -{ - Connection c; - ConnectionAccess::setImpl(c, impl->getConnection()); - return c; -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/SessionBase_0_10Access.h b/cpp/src/qpid/client/SessionBase_0_10Access.h deleted file mode 100644 index 4d08a7ceaf..0000000000 --- a/cpp/src/qpid/client/SessionBase_0_10Access.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_SESSIONBASEACCESS_H -#define QPID_CLIENT_SESSIONBASEACCESS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SessionBase_0_10.h" - -/**@file @internal Internal use only */ - -namespace qpid { -namespace client { - -class SessionBase_0_10Access { - public: - SessionBase_0_10Access(SessionBase_0_10& sb_) : sb(sb_) {} - void set(const boost::shared_ptr<SessionImpl>& si) { sb.impl = si; } - boost::shared_ptr<SessionImpl> get() const { return sb.impl; } - private: - SessionBase_0_10& sb; -}; -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SESSIONBASEACCESS_H*/ diff --git a/cpp/src/qpid/client/SessionImpl.cpp b/cpp/src/qpid/client/SessionImpl.cpp deleted file mode 100644 index b507625b11..0000000000 --- a/cpp/src/qpid/client/SessionImpl.cpp +++ /dev/null @@ -1,824 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SessionImpl.h" - -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Future.h" - -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/ClientInvoker.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MethodContent.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/IntegerTypes.h" - -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> - -namespace { const std::string EMPTY; } - -namespace qpid { -namespace client { - -using namespace qpid::framing; -using namespace qpid::framing::session; //for detach codes - -typedef sys::Monitor::ScopedLock Lock; -typedef sys::Monitor::ScopedUnlock UnLock; -typedef sys::ScopedLock<sys::Semaphore> Acquire; - - -SessionImpl::SessionImpl(const std::string& name, boost::shared_ptr<ConnectionImpl> conn) - : state(INACTIVE), - detachedLifetime(0), - maxFrameSize(conn->getNegotiatedSettings().maxFrameSize), - id(conn->getNegotiatedSettings().username, name.empty() ? Uuid(true).str() : name), - connection(conn), - ioHandler(*this), - proxy(ioHandler), - nextIn(0), - nextOut(0), - sendMsgCredit(0), - doClearDeliveryPropertiesExchange(true), - autoDetach(true) -{ - channel.next = connection.get(); -} - -SessionImpl::~SessionImpl() { - { - Lock l(state); - if (state != DETACHED && state != DETACHING) { - if (autoDetach) { - QPID_LOG(warning, "Session was not closed cleanly: " << id); - // Inform broker but don't wait for detached as that deadlocks. - // The detached will be ignored as the channel will be invalid. - try { detach(); } catch (...) {} // ignore errors. - } - setState(DETACHED); - handleClosed(); - state.waitWaiters(); - } - delete sendMsgCredit; - } - connection->erase(channel); -} - - -FrameSet::shared_ptr SessionImpl::get() // user thread -{ - // No lock here: pop does a blocking wait. - return demux.getDefault()->pop(); -} - -const SessionId SessionImpl::getId() const //user thread -{ - return id; //id is immutable -} - -void SessionImpl::open(uint32_t timeout) // user thread -{ - Lock l(state); - if (state == INACTIVE) { - setState(ATTACHING); - proxy.attach(id.getName(), false); - waitFor(ATTACHED); - //TODO: timeout will not be set locally until get response to - //confirm, should we wait for that? - setTimeout(timeout); - proxy.commandPoint(nextOut, 0); - } else { - throw Exception("Open already called for this session"); - } -} - -void SessionImpl::close() //user thread -{ - Lock l(state); - // close() must be idempotent and no-throw as it will often be called in destructors. - if (state != DETACHED && state != DETACHING) { - try { - if (detachedLifetime) setTimeout(0); - detach(); - waitFor(DETACHED); - } catch (...) {} - setState(DETACHED); - } -} - -void SessionImpl::resume(boost::shared_ptr<ConnectionImpl>) // user thread -{ - throw NotImplementedException("Resume not yet implemented by client!"); -} - -void SessionImpl::suspend() //user thread -{ - Lock l(state); - detach(); -} - -void SessionImpl::detach() //call with lock held -{ - if (state == ATTACHED) { - setState(DETACHING); - proxy.detach(id.getName()); - } -} - - -uint16_t SessionImpl::getChannel() const // user thread -{ - return channel; -} - -void SessionImpl::setChannel(uint16_t c) // user thread -{ - //channel will only ever be set when session is detached (and - //about to be resumed) - channel = c; -} - -Demux& SessionImpl::getDemux() -{ - return demux; -} - -void SessionImpl::waitForCompletion(const SequenceNumber& id) -{ - Lock l(state); - waitForCompletionImpl(id); -} - -void SessionImpl::waitForCompletionImpl(const SequenceNumber& id) //call with lock held -{ - while (incompleteOut.contains(id)) { - checkOpen(); - state.wait(); - } -} - -bool SessionImpl::isComplete(const SequenceNumber& id) -{ - Lock l(state); - return !incompleteOut.contains(id); -} - -struct IsCompleteUpTo -{ - const SequenceNumber& id; - bool result; - - IsCompleteUpTo(const SequenceNumber& _id) : id(_id), result(true) {} - void operator()(const SequenceNumber& start, const SequenceNumber&) - { - if (start <= id) result = false; - } - -}; - -bool SessionImpl::isCompleteUpTo(const SequenceNumber& id) -{ - Lock l(state); - //return false if incompleteOut contains anything less than id, - //true otherwise - IsCompleteUpTo f(id); - incompleteIn.for_each(f); - return f.result; -} - -framing::SequenceNumber SessionImpl::getCompleteUpTo() -{ - SequenceNumber firstIncomplete; - { - Lock l(state); - firstIncomplete = incompleteIn.front(); - } - return --firstIncomplete; -} - -struct MarkCompleted -{ - const SequenceNumber& id; - SequenceSet& completedIn; - - MarkCompleted(const SequenceNumber& _id, SequenceSet& set) : id(_id), completedIn(set) {} - - void operator()(const SequenceNumber& start, const SequenceNumber& end) - { - if (id >= end) { - completedIn.add(start, end); - } else if (id >= start) { - completedIn.add(start, id); - } - } - -}; - -void SessionImpl::markCompleted(const SequenceSet& ids, bool notifyPeer) -{ - Lock l(state); - incompleteIn.remove(ids); - completedIn.add(ids); - if (notifyPeer) { - sendCompletion(); - } -} - -void SessionImpl::markCompleted(const SequenceNumber& id, bool cumulative, bool notifyPeer) -{ - Lock l(state); - if (cumulative) { - //everything in incompleteIn less than or equal to id is now complete - MarkCompleted f(id, completedIn); - incompleteIn.for_each(f); - //make sure id itself is in - completedIn.add(id); - //then remove anything thats completed from the incomplete set - incompleteIn.remove(completedIn); - } else if (incompleteIn.contains(id)) { - incompleteIn.remove(id); - completedIn.add(id); - } - if (notifyPeer) { - sendCompletion(); - } -} - -void SessionImpl::setException(const sys::ExceptionHolder& ex) { - Lock l(state); - setExceptionLH(ex); -} - -void SessionImpl::setExceptionLH(const sys::ExceptionHolder& ex) { // Call with lock held. - exceptionHolder = ex; - setState(DETACHED); -} - -/** - * Called by ConnectionImpl to notify active sessions when connection - * is explictly closed - */ -void SessionImpl::connectionClosed(uint16_t code, const std::string& text) { - setException(createConnectionException(code, text)); - handleClosed(); -} - -/** - * Called by ConnectionImpl to notify active sessions when connection - * is disconnected - */ -void SessionImpl::connectionBroke(const std::string& _text) { - setException(sys::ExceptionHolder(new TransportFailure(_text))); - handleClosed(); -} - -Future SessionImpl::send(const AMQBody& command) -{ - return sendCommand(command); -} - -Future SessionImpl::send(const AMQBody& command, const MethodContent& content) -{ - return sendCommand(command, &content); -} - -namespace { -// Functor for FrameSet::map to send header + content frames but, not method frames. -struct SendContentFn { - FrameHandler& handler; - void operator()(const AMQFrame& f) { - if (!f.getMethod()) - handler(const_cast<AMQFrame&>(f)); - } - SendContentFn(FrameHandler& h) : handler(h) {} -}; - -// Adaptor to make FrameSet look like MethodContent; used in cluster update client -struct MethodContentAdaptor : MethodContent -{ - AMQHeaderBody header; - const std::string content; - - MethodContentAdaptor(const FrameSet& f) : header(*f.getHeaders()), content(f.getContent()) {} - - AMQHeaderBody getHeader() const - { - return header; - } - const std::string& getData() const - { - return content; - } -}; - -} - -Future SessionImpl::send(const AMQBody& command, const FrameSet& content, bool reframe) { - Acquire a(sendLock); - SequenceNumber id = nextOut++; - { - Lock l(state); - checkOpen(); - incompleteOut.add(id); - } - Future f(id); - if (command.getMethod()->resultExpected()) { - Lock l(state); - //result listener must be set before the command is sent - f.setFutureResult(results.listenForResult(id)); - } - AMQFrame frame(command); - frame.setEof(false); - handleOut(frame); - - if (reframe) { - MethodContentAdaptor c(content); - sendContent(c); - } else { - SendContentFn send(out); - content.map(send); - } - return f; -} - -void SessionImpl::sendRawFrame(AMQFrame& frame) { - Acquire a(sendLock); - handleOut(frame); -} - -Future SessionImpl::sendCommand(const AMQBody& command, const MethodContent* content) -{ - // Only message transfers have content - if (content && sendMsgCredit) { - sendMsgCredit->acquire(); - } - Acquire a(sendLock); - SequenceNumber id = nextOut++; - { - Lock l(state); - checkOpen(); - incompleteOut.add(id); - } - Future f(id); - if (command.getMethod()->resultExpected()) { - Lock l(state); - //result listener must be set before the command is sent - f.setFutureResult(results.listenForResult(id)); - } - AMQFrame frame(command); - if (content) { - frame.setEof(false); - } - handleOut(frame); - if (content) { - sendContent(*content); - } - return f; -} - -void SessionImpl::sendContent(const MethodContent& content) -{ - AMQFrame header(content.getHeader()); - - // doClearDeliveryPropertiesExchange is set by cluster update client so - // it can send messages with delivery-properties.exchange set. - // - if (doClearDeliveryPropertiesExchange) { - // Normal client is not allowed to set the delivery-properties.exchange - // so clear it here. - AMQHeaderBody* headerp = static_cast<AMQHeaderBody*>(header.getBody()); - if (headerp && headerp->get<DeliveryProperties>()) - headerp->get<DeliveryProperties>(true)->clearExchangeFlag(); - } - header.setFirstSegment(false); - uint64_t data_length = content.getData().length(); - if(data_length > 0){ - header.setLastSegment(false); - handleOut(header); - /*Note: end of frame marker included in overhead but not in size*/ - const uint32_t frag_size = maxFrameSize - AMQFrame::frameOverhead(); - - if(data_length < frag_size){ - AMQFrame frame((AMQContentBody(content.getData()))); - frame.setFirstSegment(false); - handleOut(frame); - }else{ - uint32_t offset = 0; - uint32_t remaining = data_length - offset; - while (remaining > 0) { - uint32_t length = remaining > frag_size ? frag_size : remaining; - string frag(content.getData().substr(offset, length)); - AMQFrame frame((AMQContentBody(frag))); - frame.setFirstSegment(false); - frame.setLastSegment(true); - if (offset > 0) { - frame.setFirstFrame(false); - } - offset += length; - remaining = data_length - offset; - if (remaining) { - frame.setLastFrame(false); - } - handleOut(frame); - } - } - } else { - handleOut(header); - } -} - - -bool isMessageMethod(AMQMethodBody* method) -{ - return method->isA<MessageTransferBody>(); -} - -bool isMessageMethod(AMQBody* body) -{ - AMQMethodBody* method=body->getMethod(); - return method && isMessageMethod(method); -} - -bool isContentFrame(AMQFrame& frame) -{ - AMQBody* body = frame.getBody(); - uint8_t type = body->type(); - return type == HEADER_BODY || type == CONTENT_BODY || isMessageMethod(body); -} - -void SessionImpl::handleIn(AMQFrame& frame) // network thread -{ - try { - if (invoke(static_cast<SessionHandler&>(*this), *frame.getBody())) { - ; - } else if (invoke(static_cast<ExecutionHandler&>(*this), *frame.getBody())) { - //make sure the command id sequence and completion - //tracking takes account of execution commands - Lock l(state); - completedIn.add(nextIn++); - } else if (invoke(static_cast<MessageHandler&>(*this), *frame.getBody())) { - ; - } else { - //if not handled by this class, its for the application: - deliver(frame); - } - } - catch (const SessionException& e) { - setException(createSessionException(e.code, e.getMessage())); - } - catch (const ChannelException& e) { - setException(createChannelException(e.code, e.getMessage())); - } -} - -void SessionImpl::handleOut(AMQFrame& frame) // user thread -{ - sendFrame(frame, true); -} - -void SessionImpl::proxyOut(AMQFrame& frame) // network thread -{ - //Note: this case is treated slightly differently that command - //frames sent by application; session controls should not be - //blocked by bounds checking on the outgoing frame queue. - sendFrame(frame, false); -} - -void SessionImpl::sendFrame(AMQFrame& frame, bool canBlock) -{ - connection->expand(frame.encodedSize(), canBlock); - channel.handle(frame); -} - -void SessionImpl::deliver(AMQFrame& frame) // network thread -{ - if (!arriving) { - arriving = FrameSet::shared_ptr(new FrameSet(nextIn++)); - } - arriving->append(frame); - if (arriving->isComplete()) { - //message.transfers will be marked completed only when 'acked' - //as completion affects flow control; other commands will be - //considered completed as soon as processed here - if (arriving->isA<MessageTransferBody>()) { - Lock l(state); - incompleteIn.add(arriving->getId()); - } else { - Lock l(state); - completedIn.add(arriving->getId()); - } - demux.handle(arriving); - arriving.reset(); - } -} - -//control handler methods (called by network thread when controls are -//received from peer): - -void SessionImpl::attach(const std::string& /*name*/, bool /*force*/) -{ - throw NotImplementedException("Client does not support attach"); -} - -void SessionImpl::attached(const std::string& _name) -{ - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(ATTACHED); -} - -void SessionImpl::detach(const std::string& _name) -{ - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(DETACHED); - QPID_LOG(info, "Session detached by peer: " << id); - proxy.detached(_name, DETACH_CODE_NORMAL); - handleClosed(); -} - -void SessionImpl::detached(const std::string& _name, uint8_t _code) { - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(DETACHED); - if (_code) { - //TODO: make sure this works with execution.exception - don't - //want to overwrite the code from that - setExceptionLH(createChannelException(_code, "Session detached by peer")); - QPID_LOG(error, exceptionHolder.what()); - } - if (detachedLifetime == 0) { - handleClosed(); -} -} - -void SessionImpl::requestTimeout(uint32_t t) -{ - Lock l(state); - detachedLifetime = t; - proxy.timeout(t); -} - -void SessionImpl::timeout(uint32_t t) -{ - Lock l(state); - detachedLifetime = t; -} - -void SessionImpl::commandPoint(const framing::SequenceNumber& id, uint64_t offset) -{ - if (offset) throw NotImplementedException("Non-zero byte offset not yet supported for command-point"); - - Lock l(state); - nextIn = id; -} - -void SessionImpl::expected(const framing::SequenceSet& commands, const framing::Array& fragments) -{ - if (!commands.empty() || fragments.encodedSize()) { - throw NotImplementedException("Session resumption not yet supported"); - } -} - -void SessionImpl::confirmed(const framing::SequenceSet& /*commands*/, const framing::Array& /*fragments*/) -{ - //don't really care too much about this yet -} - -void SessionImpl::completed(const framing::SequenceSet& commands, bool timelyReply) -{ - Lock l(state); - incompleteOut.remove(commands); - state.notifyAll();//notify any waiters of completion - completedOut.add(commands); - //notify any waiting results of completion - results.completed(commands); - - if (timelyReply) { - proxy.knownCompleted(completedOut); - completedOut.clear(); - } -} - -void SessionImpl::knownCompleted(const framing::SequenceSet& commands) -{ - Lock l(state); - completedIn.remove(commands); -} - -void SessionImpl::flush(bool expected, bool confirmed, bool completed) -{ - Lock l(state); - if (expected) { - proxy.expected(SequenceSet(nextIn), Array()); - } - if (confirmed) { - proxy.confirmed(completedIn, Array()); - } - if (completed) { - proxy.completed(completedIn, true); - } -} - -void SessionImpl::sendCompletion() -{ - Lock l(state); - sendCompletionImpl(); -} - -void SessionImpl::sendFlush() -{ - Lock l(state); - proxy.flush(false, false, true); -} - -void SessionImpl::sendCompletionImpl() -{ - proxy.completed(completedIn, completedIn.span() > 1000); -} - -void SessionImpl::gap(const framing::SequenceSet& /*commands*/) -{ - throw NotImplementedException("gap not yet supported"); -} - -void SessionImpl::sync() {} - -void SessionImpl::result(const framing::SequenceNumber& commandId, const std::string& value) -{ - Lock l(state); - results.received(commandId, value); -} - -void SessionImpl::exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t /*fieldIndex*/, - const std::string& description, - const framing::FieldTable& /*errorInfo*/) -{ - Lock l(state); - setExceptionLH(createSessionException(errorCode, description)); - QPID_LOG(warning, "Exception received from broker: " << exceptionHolder.what() - << " [caused by " << commandId << " " << classCode << ":" << commandCode << "]"); - - if (detachedLifetime) - setTimeout(0); -} - -// Message methods: -void SessionImpl::accept(const qpid::framing::SequenceSet&) -{ -} - -void SessionImpl::reject(const qpid::framing::SequenceSet&, uint16_t, const std::string&) -{ -} - -void SessionImpl::release(const qpid::framing::SequenceSet&, bool) -{ -} - -MessageResumeResult SessionImpl::resume(const std::string&, const std::string&) -{ - throw NotImplementedException("resuming transfers not yet supported"); -} - -namespace { - const std::string QPID_SESSION_DEST = ""; - const uint8_t FLOW_MODE_CREDIT = 0; - const uint8_t CREDIT_MODE_MSG = 0; -} - -void SessionImpl::setFlowMode(const std::string& dest, uint8_t flowMode) -{ - if ( dest != QPID_SESSION_DEST ) { - QPID_LOG(warning, "Ignoring flow control for unknown destination: " << dest); - return; - } - - if ( flowMode != FLOW_MODE_CREDIT ) { - throw NotImplementedException("window flow control mode not supported by producer"); - } - Lock l(state); - sendMsgCredit = new sys::Semaphore(0); -} - -void SessionImpl::flow(const std::string& dest, uint8_t mode, uint32_t credit) -{ - if ( dest != QPID_SESSION_DEST ) { - QPID_LOG(warning, "Ignoring flow control for unknown destination: " << dest); - return; - } - - if ( mode != CREDIT_MODE_MSG ) { - return; - } - if (sendMsgCredit) { - sendMsgCredit->release(credit); - } -} - -void SessionImpl::stop(const std::string& dest) -{ - if ( dest != QPID_SESSION_DEST ) { - QPID_LOG(warning, "Ignoring flow control for unknown destination: " << dest); - return; - } - if (sendMsgCredit) { - sendMsgCredit->forceLock(); - } -} - -//private utility methods: - -inline void SessionImpl::setState(State s) //call with lock held -{ - state = s; -} - -inline void SessionImpl::waitFor(State s) //call with lock held -{ - // We can be DETACHED at any time - if (s == DETACHED) state.waitFor(DETACHED); - else state.waitFor(States(s, DETACHED)); - check(); -} - -void SessionImpl::check() const //call with lock held. -{ - exceptionHolder.raise(); -} - -void SessionImpl::checkOpen() const //call with lock held. -{ - check(); - if (state != ATTACHED) { - throw NotAttachedException(QPID_MSG("Session " << getId() << " isn't attached")); - } -} - -void SessionImpl::assertOpen() const -{ - Lock l(state); - checkOpen(); -} - -bool SessionImpl::hasError() const -{ - Lock l(state); - return !exceptionHolder.empty(); -} - -void SessionImpl::handleClosed() -{ - demux.close(exceptionHolder.empty() ? - sys::ExceptionHolder(new ClosedException()) : exceptionHolder); - results.close(); -} - -uint32_t SessionImpl::setTimeout(uint32_t seconds) { - proxy.requestTimeout(seconds); - // FIXME aconway 2008-10-07: wait for timeout response from broker - // and use value retured by broker. - detachedLifetime = seconds; - return detachedLifetime; -} - -uint32_t SessionImpl::getTimeout() const { - return detachedLifetime; -} - -boost::shared_ptr<ConnectionImpl> SessionImpl::getConnection() -{ - return connection; -} - -void SessionImpl::disableAutoDetach() { autoDetach = false; } - -}} diff --git a/cpp/src/qpid/client/SessionImpl.h b/cpp/src/qpid/client/SessionImpl.h deleted file mode 100644 index cd7b2c123d..0000000000 --- a/cpp/src/qpid/client/SessionImpl.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _SessionImpl_ -#define _SessionImpl_ - -#include "qpid/client/Demux.h" -#include "qpid/client/Execution.h" -#include "qpid/client/Results.h" -#include "qpid/client/ClientImportExport.h" - -#include "qpid/SessionId.h" -#include "qpid/SessionState.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ChannelHandler.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/AMQP_ClientOperations.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/sys/Semaphore.h" -#include "qpid/sys/StateMonitor.h" -#include "qpid/sys/ExceptionHolder.h" - -#include <boost/weak_ptr.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/optional.hpp> - -namespace qpid { - -namespace framing { - -class FrameSet; -class MethodContent; -class SequenceSet; - -} - -namespace client { - -class Future; -class ConnectionImpl; -class SessionHandler; - -///@internal -class SessionImpl : public framing::FrameHandler::InOutHandler, - public Execution, - private framing::AMQP_ClientOperations::SessionHandler, - private framing::AMQP_ClientOperations::ExecutionHandler, - private framing::AMQP_ClientOperations::MessageHandler -{ -public: - SessionImpl(const std::string& name, boost::shared_ptr<ConnectionImpl>); - ~SessionImpl(); - - - //NOTE: Public functions called in user thread. - framing::FrameSet::shared_ptr get(); - - const SessionId getId() const; - - uint16_t getChannel() const; - void setChannel(uint16_t channel); - - void open(uint32_t detachedLifetime); - void close(); - void resume(boost::shared_ptr<ConnectionImpl>); - void suspend(); - - QPID_CLIENT_EXTERN void assertOpen() const; - QPID_CLIENT_EXTERN bool hasError() const; - - Future send(const framing::AMQBody& command); - Future send(const framing::AMQBody& command, const framing::MethodContent& content); - /** - * This method takes the content as a FrameSet; if reframe=false, - * the caller is resposnible for ensuring that the header and - * content frames in that set are correct for this connection - * (right flags, right fragmentation etc). If reframe=true, then - * the header and content from the frameset will be copied and - * reframed correctly for the connection. - */ - QPID_CLIENT_EXTERN Future send(const framing::AMQBody& command, const framing::FrameSet& content, bool reframe=false); - void sendRawFrame(framing::AMQFrame& frame); - - Demux& getDemux(); - void markCompleted(const framing::SequenceNumber& id, bool cumulative, bool notifyPeer); - void markCompleted(const framing::SequenceSet& ids, bool notifyPeer); - bool isComplete(const framing::SequenceNumber& id); - bool isCompleteUpTo(const framing::SequenceNumber& id); - framing::SequenceNumber getCompleteUpTo(); - void waitForCompletion(const framing::SequenceNumber& id); - void sendCompletion(); - void sendFlush(); - - void setException(const sys::ExceptionHolder&); - - //NOTE: these are called by the network thread when the connection is closed or dies - void connectionClosed(uint16_t code, const std::string& text); - void connectionBroke(const std::string& text); - - /** Set timeout in seconds, returns actual timeout allowed by broker */ - uint32_t setTimeout(uint32_t requestedSeconds); - - /** Get timeout in seconds. */ - uint32_t getTimeout() const; - - /** - * get the Connection associated with this connection - */ - boost::shared_ptr<ConnectionImpl> getConnection(); - - void setDoClearDeliveryPropertiesExchange(bool b=true) { doClearDeliveryPropertiesExchange = b; } - - /** Suppress sending detach in destructor. Used by cluster to build session state */ - void disableAutoDetach(); - -private: - enum State { - INACTIVE, - ATTACHING, - ATTACHED, - DETACHING, - DETACHED - }; - typedef framing::AMQP_ClientOperations::SessionHandler SessionHandler; - typedef framing::AMQP_ClientOperations::ExecutionHandler ExecutionHandler; - typedef framing::AMQP_ClientOperations::MessageHandler MessageHandler; - typedef sys::StateMonitor<State, DETACHED> StateMonitor; - typedef StateMonitor::Set States; - - inline void setState(State s); - inline void waitFor(State); - - void setExceptionLH(const sys::ExceptionHolder&); // LH = lock held when called. - void detach(); - - void check() const; - void checkOpen() const; - void handleClosed(); - - void handleIn(framing::AMQFrame& frame); - void handleOut(framing::AMQFrame& frame); - /** - * Sends session controls. This case is treated slightly - * differently than command frames sent by the application via - * handleOut(); session controlsare not subject to bounds checking - * on the outgoing frame queue. - */ - void proxyOut(framing::AMQFrame& frame); - void sendFrame(framing::AMQFrame& frame, bool canBlock); - void deliver(framing::AMQFrame& frame); - - Future sendCommand(const framing::AMQBody&, const framing::MethodContent* = 0); - void sendContent(const framing::MethodContent&); - void waitForCompletionImpl(const framing::SequenceNumber& id); - - void sendCompletionImpl(); - - // Note: Following methods are called by network thread in - // response to session controls from the broker - void attach(const std::string& name, bool force); - void attached(const std::string& name); - void detach(const std::string& name); - void detached(const std::string& name, uint8_t detachCode); - void requestTimeout(uint32_t timeout); - void timeout(uint32_t timeout); - void commandPoint(const framing::SequenceNumber& commandId, uint64_t commandOffset); - void expected(const framing::SequenceSet& commands, const framing::Array& fragments); - void confirmed(const framing::SequenceSet& commands, const framing::Array& fragments); - void completed(const framing::SequenceSet& commands, bool timelyReply); - void knownCompleted(const framing::SequenceSet& commands); - void flush(bool expected, bool confirmed, bool completed); - void gap(const framing::SequenceSet& commands); - - // Note: Following methods are called by network thread in - // response to execution commands from the broker - void sync(); - void result(const framing::SequenceNumber& commandId, const std::string& value); - void exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t fieldIndex, - const std::string& description, - const framing::FieldTable& errorInfo); - - // Note: Following methods are called by network thread in - // response to message commands from the broker - // EXCEPT Message.Transfer - void accept(const qpid::framing::SequenceSet&); - void reject(const qpid::framing::SequenceSet&, uint16_t, const std::string&); - void release(const qpid::framing::SequenceSet&, bool); - qpid::framing::MessageResumeResult resume(const std::string&, const std::string&); - void setFlowMode(const std::string&, uint8_t); - void flow(const std::string&, uint8_t, uint32_t); - void stop(const std::string&); - - - sys::ExceptionHolder exceptionHolder; - mutable StateMonitor state; - mutable sys::Semaphore sendLock; - uint32_t detachedLifetime; - const uint64_t maxFrameSize; - const SessionId id; - - boost::shared_ptr<ConnectionImpl> connection; - - framing::FrameHandler::MemFunRef<SessionImpl, &SessionImpl::proxyOut> ioHandler; - framing::ChannelHandler channel; - framing::AMQP_ServerProxy::Session proxy; - - Results results; - Demux demux; - framing::FrameSet::shared_ptr arriving; - - framing::SequenceSet incompleteIn;//incoming commands that are as yet incomplete - framing::SequenceSet completedIn;//incoming commands that are have completed - framing::SequenceSet incompleteOut;//outgoing commands not yet known to be complete - framing::SequenceSet completedOut;//outgoing commands that we know to be completed - framing::SequenceNumber nextIn; - framing::SequenceNumber nextOut; - - SessionState sessionState; - - // Only keep track of message credit - sys::Semaphore* sendMsgCredit; - - bool doClearDeliveryPropertiesExchange; - - bool autoDetach; - - friend class client::SessionHandler; -}; - -}} // namespace qpid::client - -#endif diff --git a/cpp/src/qpid/client/SslConnector.cpp b/cpp/src/qpid/client/SslConnector.cpp deleted file mode 100644 index 35c7e6bdf6..0000000000 --- a/cpp/src/qpid/client/SslConnector.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Connector.h" - -#include "config.h" -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/ssl/util.h" -#include "qpid/sys/ssl/SslIo.h" -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/Msg.h" - -#include <iostream> -#include <map> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::sys::ssl; -using namespace qpid::framing; -using boost::format; -using boost::str; - - -class SslConnector : public Connector -{ - struct Buff; - - /** Batch up frames for writing to aio. */ - class Writer : public framing::FrameHandler { - typedef sys::ssl::SslIOBufferBase BufferBase; - typedef std::vector<framing::AMQFrame> Frames; - - const uint16_t maxFrameSize; - sys::Mutex lock; - sys::ssl::SslIO* aio; - BufferBase* buffer; - Frames frames; - size_t lastEof; // Position after last EOF in frames - framing::Buffer encode; - size_t framesEncoded; - std::string identifier; - Bounds* bounds; - - void writeOne(); - void newBuffer(); - - public: - - Writer(uint16_t maxFrameSize, Bounds*); - ~Writer(); - void init(std::string id, sys::ssl::SslIO*); - void handle(framing::AMQFrame&); - void write(sys::ssl::SslIO&); - }; - - const uint16_t maxFrameSize; - framing::ProtocolVersion version; - bool initiated; - SecuritySettings securitySettings; - - sys::Mutex closedLock; - bool closed; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::OutputHandler* output; - - Writer writer; - - sys::ssl::SslSocket socket; - - sys::ssl::SslIO* aio; - Poller::shared_ptr poller; - - ~SslConnector(); - - void readbuff(qpid::sys::ssl::SslIO&, qpid::sys::ssl::SslIOBufferBase*); - void writebuff(qpid::sys::ssl::SslIO&); - void writeDataBlock(const framing::AMQDataBlock& data); - void eof(qpid::sys::ssl::SslIO&); - void disconnected(qpid::sys::ssl::SslIO&); - - std::string identifier; - - void connect(const std::string& host, int port); - void init(); - void close(); - void send(framing::AMQFrame& frame); - void abort() {} // TODO: Need to fix for heartbeat timeouts to work - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - sys::ShutdownHandler* getShutdownHandler() const; - framing::OutputHandler* getOutputHandler(); - const std::string& getIdentifier() const; - const SecuritySettings* getSecuritySettings(); - void socketClosed(qpid::sys::ssl::SslIO&, const qpid::sys::ssl::SslSocket&); - -public: - SslConnector(Poller::shared_ptr p, framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -struct SslConnector::Buff : public SslIO::BufferBase { - Buff(size_t size) : SslIO::BufferBase(new char[size], size) {} - ~Buff() { delete [] bytes;} -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new SslConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - try { - SslOptions options; - options.parse (0, 0, QPIDC_CONF_FILE, true); - if (options.certDbPath.empty()) { - QPID_LOG(info, "SSL connector not enabled, you must set QPID_SSL_CERT_DB to enable it."); - } else { - initNSS(options); - Connector::registerFactory("ssl", &create); - } - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL connector: " << e.what()); - } - }; - - ~StaticInit() { shutdownNSS(); } - } init; -} - -SslConnector::SslConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - version(ver), - initiated(false), - closed(true), - shutdownHandler(0), - writer(maxFrameSize, cimpl), - aio(0), - poller(p) -{ - QPID_LOG(debug, "SslConnector created for " << version.toString()); - - if (settings.sslCertName != "") { - QPID_LOG(debug, "ssl-cert-name = " << settings.sslCertName); - socket.setCertName(settings.sslCertName); - } -} - -SslConnector::~SslConnector() { - close(); -} - -void SslConnector::connect(const std::string& host, int port){ - Mutex::ScopedLock l(closedLock); - assert(closed); - try { - socket.connect(host, port); - } catch (const std::exception& e) { - socket.close(); - throw ConnectionException(framing::connection::CLOSE_CODE_FRAMING_ERROR, e.what()); - } - - identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress()); - closed = false; - aio = new SslIO(socket, - boost::bind(&SslConnector::readbuff, this, _1, _2), - boost::bind(&SslConnector::eof, this, _1), - boost::bind(&SslConnector::disconnected, this, _1), - boost::bind(&SslConnector::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&SslConnector::writebuff, this, _1)); - writer.init(identifier, aio); -} - -void SslConnector::init(){ - Mutex::ScopedLock l(closedLock); - ProtocolInitiation init(version); - writeDataBlock(init); - for (int i = 0; i < 32; i++) { - aio->queueReadBuffer(new Buff(maxFrameSize)); - } - aio->start(poller); -} - -void SslConnector::close() { - Mutex::ScopedLock l(closedLock); - if (!closed) { - closed = true; - if (aio) - aio->queueWriteClose(); - } -} - -void SslConnector::socketClosed(SslIO&, const SslSocket&) { - if (aio) - aio->queueForDeletion(); - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void SslConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void SslConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* SslConnector::getOutputHandler() { - return this; -} - -sys::ShutdownHandler* SslConnector::getShutdownHandler() const { - return shutdownHandler; -} - -const std::string& SslConnector::getIdentifier() const { - return identifier; -} - -void SslConnector::send(AMQFrame& frame) { - writer.handle(frame); -} - -SslConnector::Writer::Writer(uint16_t s, Bounds* b) : maxFrameSize(s), aio(0), buffer(0), lastEof(0), bounds(b) -{ -} - -SslConnector::Writer::~Writer() { delete buffer; } - -void SslConnector::Writer::init(std::string id, sys::ssl::SslIO* a) { - Mutex::ScopedLock l(lock); - identifier = id; - aio = a; - newBuffer(); -} -void SslConnector::Writer::handle(framing::AMQFrame& frame) { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - if (frame.getEof() || (bounds && bounds->getCurrentSize() >= maxFrameSize)) { - lastEof = frames.size(); - aio->notifyPendingWrite(); - } - QPID_LOG(trace, "SENT " << identifier << ": " << frame); -} - -void SslConnector::Writer::writeOne() { - assert(buffer); - framesEncoded = 0; - - buffer->dataStart = 0; - buffer->dataCount = encode.getPosition(); - aio->queueWrite(buffer); - newBuffer(); -} - -void SslConnector::Writer::newBuffer() { - buffer = aio->getQueuedBuffer(); - if (!buffer) buffer = new Buff(maxFrameSize); - encode = framing::Buffer(buffer->bytes, buffer->byteCount); - framesEncoded = 0; -} - -// Called in IO thread. -void SslConnector::Writer::write(sys::ssl::SslIO&) { - Mutex::ScopedLock l(lock); - assert(buffer); - size_t bytesWritten(0); - for (size_t i = 0; i < lastEof; ++i) { - AMQFrame& frame = frames[i]; - uint32_t size = frame.encodedSize(); - if (size > encode.available()) writeOne(); - assert(size <= encode.available()); - frame.encode(encode); - ++framesEncoded; - bytesWritten += size; - } - frames.erase(frames.begin(), frames.begin()+lastEof); - lastEof = 0; - if (bounds) bounds->reduce(bytesWritten); - if (encode.getPosition() > 0) writeOne(); -} - -void SslConnector::readbuff(SslIO& aio, SslIO::BufferBase* buff) { - framing::Buffer in(buff->bytes+buff->dataStart, buff->dataCount); - - if (!initiated) { - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - //TODO: check the version is correct - QPID_LOG(debug, "RECV " << identifier << " INIT(" << protocolInit << ")"); - } - initiated = true; - } - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV " << identifier << ": " << frame); - input->received(frame); - } - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (in.available() != 0) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += buff->dataCount-in.available(); - buff->dataCount = in.available(); - aio.unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio.queueReadBuffer(buff); - } -} - -void SslConnector::writebuff(SslIO& aio_) { - writer.write(aio_); -} - -void SslConnector::writeDataBlock(const AMQDataBlock& data) { - SslIO::BufferBase* buff = new Buff(maxFrameSize); - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void SslConnector::eof(SslIO&) { - close(); -} - -void SslConnector::disconnected(SslIO&) { - close(); - socketClosed(*aio, socket); -} - -const SecuritySettings* SslConnector::getSecuritySettings() -{ - securitySettings.ssf = socket.getKeyLen(); - securitySettings.authid = "dummy";//set to non-empty string to enable external authentication - return &securitySettings; -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/StateManager.cpp b/cpp/src/qpid/client/StateManager.cpp deleted file mode 100644 index 839d92abdc..0000000000 --- a/cpp/src/qpid/client/StateManager.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/StateManager.h" -#include "qpid/framing/amqp_framing.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -StateManager::StateManager(int s) : state(s) {} - -void StateManager::waitForStateChange(int current) -{ - Monitor::ScopedLock l(stateLock); - while (state == current) { - stateLock.wait(); - } -} - -void StateManager::waitFor(int desired) -{ - Monitor::ScopedLock l(stateLock); - while (state != desired) { - stateLock.wait(); - } -} - -void StateManager::waitFor(std::set<int> desired) -{ - Monitor::ScopedLock l(stateLock); - while (desired.find(state) == desired.end()) { - stateLock.wait(); - } -} - -bool StateManager::waitFor(int desired, qpid::sys::Duration timeout) -{ - AbsTime end(now(), timeout); - Monitor::ScopedLock l(stateLock); - while (state != desired && now() < end) { - stateLock.wait(end); - } - return state == desired; -} - -bool StateManager::waitFor(std::set<int> desired, qpid::sys::Duration timeout) -{ - AbsTime end(now(), timeout); - Monitor::ScopedLock l(stateLock); - while (desired.find(state) == desired.end() && now() < end) { - stateLock.wait(end); - } - return desired.find(state) != desired.end(); -} - - -void StateManager::setState(int s) -{ - Monitor::ScopedLock l(stateLock); - state = s; - stateLock.notifyAll(); -} - -bool StateManager::setState(int s, int expected) -{ - Monitor::ScopedLock l(stateLock); - if (state == expected) { - state = s; - stateLock.notifyAll(); - return true; - } else { - return false; - } -} - -int StateManager::getState() const -{ - Monitor::ScopedLock l(stateLock); - return state; -} - diff --git a/cpp/src/qpid/client/StateManager.h b/cpp/src/qpid/client/StateManager.h deleted file mode 100644 index f06dbc493c..0000000000 --- a/cpp/src/qpid/client/StateManager.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _StateManager_ -#define _StateManager_ - -#include <set> -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace client { - -///@internal -class StateManager -{ - int state; - mutable sys::Monitor stateLock; - -public: - StateManager(int initial); - void setState(int state); - bool setState(int state, int expected); - int getState() const ; - void waitForStateChange(int current); - void waitFor(std::set<int> states); - void waitFor(int state); - bool waitFor(std::set<int> states, qpid::sys::Duration); - bool waitFor(int state, qpid::sys::Duration); -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/Subscription.cpp b/cpp/src/qpid/client/Subscription.cpp deleted file mode 100644 index 988f372604..0000000000 --- a/cpp/src/qpid/client/Subscription.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Subscription.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/framing/enum.h" - -namespace qpid { -namespace client { - -typedef PrivateImplRef<Subscription> PI; -Subscription::Subscription(SubscriptionImpl* p) { PI::ctor(*this, p); } -Subscription::~Subscription() { PI::dtor(*this); } -Subscription::Subscription(const Subscription& c) : Handle<SubscriptionImpl>() { PI::copy(*this, c); } -Subscription& Subscription::operator=(const Subscription& c) { return PI::assign(*this, c); } - - -std::string Subscription::getName() const { return impl->getName(); } -std::string Subscription::getQueue() const { return impl->getQueue(); } -const SubscriptionSettings& Subscription::getSettings() const { return impl->getSettings(); } -void Subscription::setFlowControl(const FlowControl& f) { impl->setFlowControl(f); } -void Subscription::setAutoAck(unsigned int n) { impl->setAutoAck(n); } -SequenceSet Subscription::getUnacquired() const { return impl->getUnacquired(); } -SequenceSet Subscription::getUnaccepted() const { return impl->getUnaccepted(); } -void Subscription::acquire(const SequenceSet& messageIds) { impl->acquire(messageIds); } -void Subscription::accept(const SequenceSet& messageIds) { impl->accept(messageIds); } -void Subscription::release(const SequenceSet& messageIds) { impl->release(messageIds); } -Session Subscription::getSession() const { return impl->getSession(); } -SubscriptionManager Subscription::getSubscriptionManager() { return impl->getSubscriptionManager(); } -void Subscription::cancel() { impl->cancel(); } -void Subscription::grantMessageCredit(uint32_t value) { impl->grantCredit(framing::message::CREDIT_UNIT_MESSAGE, value); } -void Subscription::grantByteCredit(uint32_t value) { impl->grantCredit(framing::message::CREDIT_UNIT_BYTE, value); } -}} // namespace qpid::client - - diff --git a/cpp/src/qpid/client/SubscriptionImpl.cpp b/cpp/src/qpid/client/SubscriptionImpl.cpp deleted file mode 100644 index a8a0b47d94..0000000000 --- a/cpp/src/qpid/client/SubscriptionImpl.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionSettings.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/client/PrivateImplRef.h" - -namespace qpid { -namespace client { - -using sys::Mutex; -using framing::MessageAcquireResult; - -SubscriptionImpl::SubscriptionImpl(SubscriptionManager m, const std::string& q, const SubscriptionSettings& s, const std::string& n, MessageListener* l) - : manager(*PrivateImplRef<SubscriptionManager>::get(m)), name(n), queue(q), settings(s), listener(l) -{} - -void SubscriptionImpl::subscribe() -{ - async(manager.getSession()).messageSubscribe( - arg::queue=queue, - arg::destination=name, - arg::acceptMode=settings.acceptMode, - arg::acquireMode=settings.acquireMode, - arg::exclusive=settings.exclusive); - setFlowControl(settings.flowControl); -} - -std::string SubscriptionImpl::getName() const { return name; } - -std::string SubscriptionImpl::getQueue() const { return queue; } - -const SubscriptionSettings& SubscriptionImpl::getSettings() const { - Mutex::ScopedLock l(lock); - return settings; -} - -void SubscriptionImpl::setFlowControl(const FlowControl& f) { - Mutex::ScopedLock l(lock); - AsyncSession s=manager.getSession(); - if (&settings.flowControl != &f) settings.flowControl = f; - s.messageSetFlowMode(name, f.window); - s.messageFlow(name, CREDIT_UNIT_MESSAGE, f.messages); - s.messageFlow(name, CREDIT_UNIT_BYTE, f.bytes); - s.sync(); -} - -void SubscriptionImpl::grantCredit(framing::message::CreditUnit unit, uint32_t value) { - async(manager.getSession()).messageFlow(name, unit, value); -} - -void SubscriptionImpl::setAutoAck(size_t n) { - Mutex::ScopedLock l(lock); - settings.autoAck = n; -} - -SequenceSet SubscriptionImpl::getUnacquired() const { Mutex::ScopedLock l(lock); return unacquired; } -SequenceSet SubscriptionImpl::getUnaccepted() const { Mutex::ScopedLock l(lock); return unaccepted; } - -void SubscriptionImpl::acquire(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - MessageAcquireResult result = manager.getSession().messageAcquire(messageIds); - unacquired.remove(result.getTransfers()); - if (settings.acceptMode == ACCEPT_MODE_EXPLICIT) - unaccepted.add(result.getTransfers()); -} - -void SubscriptionImpl::accept(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - manager.getSession().messageAccept(messageIds); - unaccepted.remove(messageIds); - switch (settings.completionMode) { - case COMPLETE_ON_ACCEPT: - manager.getSession().markCompleted(messageIds, true); - break; - case COMPLETE_ON_DELIVERY: - manager.getSession().sendCompletion(); - break; - default://do nothing - break; - } -} - -void SubscriptionImpl::release(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - manager.getSession().messageRelease(messageIds); - if (settings.acceptMode == ACCEPT_MODE_EXPLICIT) - unaccepted.remove(messageIds); -} - -Session SubscriptionImpl::getSession() const { return manager.getSession(); } - -SubscriptionManager SubscriptionImpl::getSubscriptionManager() { return SubscriptionManager(&manager); } - -void SubscriptionImpl::cancel() { manager.cancel(name); } - -void SubscriptionImpl::received(Message& m) { - Mutex::ScopedLock l(lock); - MessageImpl& mi = *MessageImpl::get(m); - if (mi.getMethod().getAcquireMode() == ACQUIRE_MODE_NOT_ACQUIRED) - unacquired.add(m.getId()); - else if (mi.getMethod().getAcceptMode() == ACCEPT_MODE_EXPLICIT) - unaccepted.add(m.getId()); - - if (listener) { - Mutex::ScopedUnlock u(lock); - listener->received(m); - } - - if (settings.completionMode == COMPLETE_ON_DELIVERY) { - manager.getSession().markCompleted(m.getId(), false, false); - } - if (settings.autoAck) { - if (unaccepted.size() >= settings.autoAck) { - async(manager.getSession()).messageAccept(unaccepted); - switch (settings.completionMode) { - case COMPLETE_ON_ACCEPT: - manager.getSession().markCompleted(unaccepted, true); - break; - case COMPLETE_ON_DELIVERY: - manager.getSession().sendCompletion(); - break; - default://do nothing - break; - } - unaccepted.clear(); - } - } -} - -Demux::QueuePtr SubscriptionImpl::divert() -{ - Session session(manager.getSession()); - Demux& demux = SessionBase_0_10Access(session).get()->getDemux(); - demuxRule = std::auto_ptr<ScopedDivert>(new ScopedDivert(name, demux)); - return demuxRule->getQueue(); -} - -void SubscriptionImpl::cancelDiversion() { - demuxRule.reset(); -} - -}} // namespace qpid::client - diff --git a/cpp/src/qpid/client/SubscriptionImpl.h b/cpp/src/qpid/client/SubscriptionImpl.h deleted file mode 100644 index da77213423..0000000000 --- a/cpp/src/qpid/client/SubscriptionImpl.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef QPID_CLIENT_SUBSCRIPTIONIMPL_H -#define QPID_CLIENT_SUBSCRIPTIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SubscriptionSettings.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/Session.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/Demux.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/Mutex.h" -#include "qpid/RefCounted.h" -#include "qpid/client/ClientImportExport.h" -#include <memory> - -namespace qpid { -namespace client { - -class SubscriptionManager; -class SubscriptionManagerImpl; - -class SubscriptionImpl : public RefCounted, public MessageListener { - public: - QPID_CLIENT_EXTERN SubscriptionImpl(SubscriptionManager, const std::string& queue, - const SubscriptionSettings&, const std::string& name, MessageListener* =0); - - /** The name of the subsctription, used as the "destination" for messages from the broker. - * Usually the same as the queue name but can be set differently. - */ - QPID_CLIENT_EXTERN std::string getName() const; - - /** Name of the queue this subscription subscribes to */ - QPID_CLIENT_EXTERN std::string getQueue() const; - - /** Get the flow control and acknowledgement settings for this subscription */ - QPID_CLIENT_EXTERN const SubscriptionSettings& getSettings() const; - - /** Set the flow control parameters */ - QPID_CLIENT_EXTERN void setFlowControl(const FlowControl&); - - /** Automatically acknowledge (acquire and accept) batches of n messages. - * You can disable auto-acknowledgement by setting n=0, and use acquire() and accept() - * to manually acquire and accept messages. - */ - QPID_CLIENT_EXTERN void setAutoAck(size_t n); - - /** Get the set of ID's for messages received by this subscription but not yet acquired. - * This will always be empty if acquireMode=ACQUIRE_MODE_PRE_ACQUIRED - */ - QPID_CLIENT_EXTERN SequenceSet getUnacquired() const; - - /** Get the set of ID's for messages acquired by this subscription but not yet accepted. */ - QPID_CLIENT_EXTERN SequenceSet getUnaccepted() const; - - /** Acquire messageIds and remove them from the un-acquired set for the session. */ - QPID_CLIENT_EXTERN void acquire(const SequenceSet& messageIds); - - /** Accept messageIds and remove them from the un-accepted set for the session. */ - QPID_CLIENT_EXTERN void accept(const SequenceSet& messageIds); - - /** Release messageIds and remove them from the un-accepted set for the session. */ - QPID_CLIENT_EXTERN void release(const SequenceSet& messageIds); - - /** Get the session associated with this subscription */ - QPID_CLIENT_EXTERN Session getSession() const; - - /** Get the subscription manager associated with this subscription */ - QPID_CLIENT_EXTERN SubscriptionManager getSubscriptionManager(); - - /** Send subscription request and issue appropriate flow control commands. */ - QPID_CLIENT_EXTERN void subscribe(); - - /** Cancel the subscription. */ - QPID_CLIENT_EXTERN void cancel(); - - /** Grant specified credit for this subscription **/ - QPID_CLIENT_EXTERN void grantCredit(framing::message::CreditUnit unit, uint32_t value); - - QPID_CLIENT_EXTERN void received(Message&); - - /** - * Set up demux diversion for messages sent to this subscription - */ - Demux::QueuePtr divert(); - /** - * Cancel any demux diversion that may have been setup for this - * subscription - */ - QPID_CLIENT_EXTERN void cancelDiversion(); - - private: - - mutable sys::Mutex lock; - SubscriptionManagerImpl& manager; - std::string name, queue; - SubscriptionSettings settings; - framing::SequenceSet unacquired, unaccepted; - MessageListener* listener; - std::auto_ptr<ScopedDivert> demuxRule; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SUBSCRIPTIONIMPL_H*/ diff --git a/cpp/src/qpid/client/SubscriptionManager.cpp b/cpp/src/qpid/client/SubscriptionManager.cpp deleted file mode 100644 index 485361d577..0000000000 --- a/cpp/src/qpid/client/SubscriptionManager.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/PrivateImplRef.h" - - -namespace qpid { -namespace client { - -typedef PrivateImplRef<SubscriptionManager> PI; - -SubscriptionManager::SubscriptionManager(const Session& s) { PI::ctor(*this, new SubscriptionManagerImpl(s)); } -SubscriptionManager::SubscriptionManager(SubscriptionManagerImpl* i) { PI::ctor(*this, i); } -SubscriptionManager::SubscriptionManager(const SubscriptionManager& x) : Runnable(), Handle<SubscriptionManagerImpl>() { PI::copy(*this, x); } -SubscriptionManager::~SubscriptionManager() { PI::dtor(*this); } -SubscriptionManager& SubscriptionManager::operator=(const SubscriptionManager& x) { return PI::assign(*this, x); } - -Subscription SubscriptionManager::subscribe( - MessageListener& listener, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ return impl->subscribe(listener, q, ss, n); } - -Subscription SubscriptionManager::subscribe( - LocalQueue& lq, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ return impl->subscribe(lq, q, ss, n); } - - -Subscription SubscriptionManager::subscribe( - MessageListener& listener, const std::string& q, const std::string& n) -{ return impl->subscribe(listener, q, n); } - - -Subscription SubscriptionManager::subscribe( - LocalQueue& lq, const std::string& q, const std::string& n) -{ return impl->subscribe(lq, q, n); } - -void SubscriptionManager::cancel(const std::string& dest) { return impl->cancel(dest); } - -void SubscriptionManager::setAutoStop(bool set) { impl->setAutoStop(set); } - -void SubscriptionManager::run() { impl->run(); } - -void SubscriptionManager::start() { impl->start(); } - -void SubscriptionManager::wait() { impl->wait(); } - -void SubscriptionManager::stop() { impl->stop(); } - -bool SubscriptionManager::get(Message& result, const std::string& queue, sys::Duration timeout) { - return impl->get(result, queue, timeout); -} - -Message SubscriptionManager::get(const std::string& queue, sys::Duration timeout) { - return impl->get(queue, timeout); -} - -Session SubscriptionManager::getSession() const { return impl->getSession(); } - -Subscription SubscriptionManager::getSubscription(const std::string& name) const { - return impl->getSubscription(name); -} -void SubscriptionManager::registerFailoverHandler (boost::function<void ()> fh) { - impl->registerFailoverHandler(fh); -} - -void SubscriptionManager::setFlowControl(const std::string& name, const FlowControl& flow) { - impl->setFlowControl(name, flow); -} - -void SubscriptionManager::setDefaultSettings(const SubscriptionSettings& s){ - impl->setDefaultSettings(s); -} - -void SubscriptionManager::setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window) { - impl->setFlowControl(name, FlowControl(messages, bytes, window)); -} - -void SubscriptionManager::setFlowControl(uint32_t messages, uint32_t bytes, bool window) { - impl->setFlowControl(messages, bytes, window); -} - -void SubscriptionManager::setAcceptMode(AcceptMode mode) { impl->setAcceptMode(mode); } -void SubscriptionManager::setAcquireMode(AcquireMode mode) { impl->setAcquireMode(mode); } - -}} // namespace qpid::client - - diff --git a/cpp/src/qpid/client/SubscriptionManagerImpl.cpp b/cpp/src/qpid/client/SubscriptionManagerImpl.cpp deleted file mode 100644 index a558d90be8..0000000000 --- a/cpp/src/qpid/client/SubscriptionManagerImpl.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/PrivateImplRef.h" -#include <qpid/client/Dispatcher.h> -#include <qpid/client/Session.h> -#include <qpid/client/MessageListener.h> -#include <qpid/framing/Uuid.h> -#include <set> -#include <sstream> - - -namespace qpid { -namespace client { - -SubscriptionManagerImpl::SubscriptionManagerImpl(const Session& s) - : dispatcher(s), session(s), autoStop(true) -{} - -Subscription SubscriptionManagerImpl::subscribe( - MessageListener& listener, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ - sys::Mutex::ScopedLock l(lock); - std::string name=n.empty() ? q:n; - boost::intrusive_ptr<SubscriptionImpl> si = new SubscriptionImpl(SubscriptionManager(this), q, ss, name, &listener); - dispatcher.listen(si); - //issue subscription request after listener is registered with dispatcher - si->subscribe(); - return subscriptions[name] = Subscription(si.get()); -} - -Subscription SubscriptionManagerImpl::subscribe( - LocalQueue& lq, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ - sys::Mutex::ScopedLock l(lock); - std::string name=n.empty() ? q:n; - boost::intrusive_ptr<SubscriptionImpl> si = new SubscriptionImpl(SubscriptionManager(this), q, ss, name, 0); - boost::intrusive_ptr<LocalQueueImpl> lqi = PrivateImplRef<LocalQueue>::get(lq); - lqi->queue=si->divert(); - si->subscribe(); - lqi->subscription = Subscription(si.get()); - return subscriptions[name] = lqi->subscription; -} - -Subscription SubscriptionManagerImpl::subscribe( - MessageListener& listener, const std::string& q, const std::string& n) -{ - return subscribe(listener, q, defaultSettings, n); -} - -Subscription SubscriptionManagerImpl::subscribe( - LocalQueue& lq, const std::string& q, const std::string& n) -{ - return subscribe(lq, q, defaultSettings, n); -} - -void SubscriptionManagerImpl::cancel(const std::string& dest) -{ - sys::Mutex::ScopedLock l(lock); - std::map<std::string, Subscription>::iterator i = subscriptions.find(dest); - if (i != subscriptions.end()) { - sync(session).messageCancel(dest); - dispatcher.cancel(dest); - Subscription s = i->second; - if (s.isValid()) - PrivateImplRef<Subscription>::get(s)->cancelDiversion(); - subscriptions.erase(i); - } -} - -void SubscriptionManagerImpl::setAutoStop(bool set) { autoStop=set; } - -void SubscriptionManagerImpl::run() -{ - dispatcher.setAutoStop(autoStop); - dispatcher.run(); -} - -void SubscriptionManagerImpl::start() -{ - dispatcher.setAutoStop(autoStop); - dispatcher.start(); -} - -void SubscriptionManagerImpl::wait() -{ - dispatcher.wait(); -} - -void SubscriptionManagerImpl::stop() -{ - dispatcher.stop(); -} - -bool SubscriptionManagerImpl::get(Message& result, const std::string& queue, sys::Duration timeout) { - LocalQueue lq; - std::string unique = framing::Uuid(true).str(); - subscribe(lq, queue, SubscriptionSettings(FlowControl::messageCredit(1)), unique); - SubscriptionManager sm(this); - AutoCancel ac(sm, unique); - //first wait for message to be delivered if a timeout has been specified - if (timeout && lq.get(result, timeout)) - return true; - //make sure message is not on queue before final check - sync(session).messageFlush(unique); - return lq.get(result, 0); -} - -Message SubscriptionManagerImpl::get(const std::string& queue, sys::Duration timeout) { - Message result; - if (!get(result, queue, timeout)) - throw Exception("Timed out waiting for a message"); - return result; -} - -Session SubscriptionManagerImpl::getSession() const { return session; } - -Subscription SubscriptionManagerImpl::getSubscription(const std::string& name) const { - sys::Mutex::ScopedLock l(lock); - std::map<std::string, Subscription>::const_iterator i = subscriptions.find(name); - if (i == subscriptions.end()) - throw Exception(QPID_MSG("Subscription not found: " << name)); - return i->second; -} - -void SubscriptionManagerImpl::registerFailoverHandler (boost::function<void ()> fh) { - dispatcher.registerFailoverHandler(fh); -} - -void SubscriptionManagerImpl::setFlowControl(const std::string& name, const FlowControl& flow) { - getSubscription(name).setFlowControl(flow); -} - -void SubscriptionManagerImpl::setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window) { - setFlowControl(name, FlowControl(messages, bytes, window)); -} - -}} // namespace qpid::client - - diff --git a/cpp/src/qpid/client/SubscriptionManagerImpl.h b/cpp/src/qpid/client/SubscriptionManagerImpl.h deleted file mode 100644 index 6376a05c45..0000000000 --- a/cpp/src/qpid/client/SubscriptionManagerImpl.h +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H -#define QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Mutex.h" -#include <qpid/client/Dispatcher.h> -#include <qpid/client/Completion.h> -#include <qpid/client/Session.h> -#include <qpid/client/AsyncSession.h> -#include <qpid/client/MessageListener.h> -#include <qpid/client/LocalQueue.h> -#include <qpid/client/Subscription.h> -#include <qpid/sys/Runnable.h> -#include <qpid/RefCounted.h> -#include <set> -#include <sstream> - -namespace qpid { -namespace client { - -/** - * A class to help create and manage subscriptions. - * - * Set up your subscriptions, then call run() to have messages - * delivered. - * - * \ingroup clientapi - * - * \details - * - * <h2>Subscribing and canceling subscriptions</h2> - * - * <ul> - * <li> - * <p>subscribe()</p> - * <pre> SubscriptionManager subscriptions(session); - * Listener listener(subscriptions); - * subscriptions.subscribe(listener, myQueue);</pre> - * <pre> SubscriptionManager subscriptions(session); - * LocalQueue local_queue; - * subscriptions.subscribe(local_queue, string("message_queue"));</pre></li> - * <li> - * <p>cancel()</p> - * <pre>subscriptions.cancel();</pre></li> - * </ul> - * - * <h2>Waiting for messages (and returning)</h2> - * - * <ul> - * <li> - * <p>run()</p> - * <pre> // Give up control to receive messages - * subscriptions.run();</pre></li> - * <li> - * <p>stop()</p> - * <pre>.// Use this code in a listener to return from run() - * subscriptions.stop();</pre></li> - * <li> - * <p>setAutoStop()</p> - * <pre>.// Return from subscriptions.run() when last subscription is cancelled - *.subscriptions.setAutoStop(true); - *.subscriptons.run(); - * </pre></li> - * <li> - * <p>Ending a subscription in a listener</p> - * <pre> - * void Listener::received(Message& message) { - * - * if (message.getData() == "That's all, folks!") { - * subscriptions.cancel(message.getDestination()); - * } - * } - * </pre> - * </li> - * </ul> - * - */ -class SubscriptionManagerImpl : public sys::Runnable, public RefCounted -{ - public: - /** Create a new SubscriptionManagerImpl associated with a session */ - SubscriptionManagerImpl(const Session& session); - - /** - * Subscribe a MessagesListener to receive messages from queue. - * - * Provide your own subclass of MessagesListener to process - * incoming messages. It will be called for each message received. - * - *@param listener Listener object to receive messages. - *@param queue Name of the queue to subscribe to. - *@param settings settings for the subscription. - *@param name unique destination name for the subscription, defaults to queue name. - */ - Subscription subscribe(MessageListener& listener, - const std::string& queue, - const SubscriptionSettings& settings, - const std::string& name=std::string()); - - /** - * Subscribe a LocalQueue to receive messages from queue. - * - * Incoming messages are stored in the queue for you to retrieve. - * - *@param queue Name of the queue to subscribe to. - *@param flow initial FlowControl for the subscription. - *@param name unique destination name for the subscription, defaults to queue name. - * If not specified, the queue name is used. - */ - Subscription subscribe(LocalQueue& localQueue, - const std::string& queue, - const SubscriptionSettings& settings, - const std::string& name=std::string()); - - /** - * Subscribe a MessagesListener to receive messages from queue. - * - * Provide your own subclass of MessagesListener to process - * incoming messages. It will be called for each message received. - * - *@param listener Listener object to receive messages. - *@param queue Name of the queue to subscribe to. - *@param name unique destination name for the subscription, defaults to queue name. - * If not specified, the queue name is used. - */ - Subscription subscribe(MessageListener& listener, - const std::string& queue, - const std::string& name=std::string()); - - /** - * Subscribe a LocalQueue to receive messages from queue. - * - * Incoming messages are stored in the queue for you to retrieve. - * - *@param queue Name of the queue to subscribe to. - *@param name unique destination name for the subscription, defaults to queue name. - * If not specified, the queue name is used. - */ - Subscription subscribe(LocalQueue& localQueue, - const std::string& queue, - const std::string& name=std::string()); - - - /** Get a single message from a queue. - *@param result is set to the message from the queue. - *@param timeout wait up this timeout for a message to appear. - *@return true if result was set, false if no message available after timeout. - */ - bool get(Message& result, const std::string& queue, sys::Duration timeout=0); - - /** Get a single message from a queue. - *@param timeout wait up this timeout for a message to appear. - *@return message from the queue. - *@throw Exception if the timeout is exceeded. - */ - Message get(const std::string& queue, sys::Duration timeout=sys::TIME_INFINITE); - - /** Get a subscription by name. - *@throw Exception if not found. - */ - Subscription getSubscription(const std::string& name) const; - - /** Cancel a subscription. See also: Subscription.cancel() */ - void cancel(const std::string& name); - - /** Deliver messages in the current thread until stop() is called. - * Only one thread may be running in a SubscriptionManager at a time. - * @see run - */ - void run(); - - /** Start a new thread to deliver messages. - * Only one thread may be running in a SubscriptionManager at a time. - * @see start - */ - void start(); - - /** - * Wait for the thread started by a call to start() to complete. - */ - void wait(); - - /** If set true, run() will stop when all subscriptions - * are cancelled. If false, run will only stop when stop() - * is called. True by default. - */ - void setAutoStop(bool set=true); - - /** Stop delivery. Causes run() to return, or the thread started with start() to exit. */ - void stop(); - - static const uint32_t UNLIMITED=0xFFFFFFFF; - - /** Set the flow control for a subscription. */ - void setFlowControl(const std::string& name, const FlowControl& flow); - - /** Set the flow control for a subscription. - *@param name: name of the subscription. - *@param messages: message credit. - *@param bytes: byte credit. - *@param window: if true use window-based flow control. - */ - void setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window=true); - - /** Set the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - void setDefaultSettings(const SubscriptionSettings& s) { defaultSettings = s; } - - /** Get the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - const SubscriptionSettings& getDefaultSettings() const { return defaultSettings; } - - /** Get the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - SubscriptionSettings& getDefaultSettings() { return defaultSettings; } - - /** - * Set the default flow control settings for subscribe() calls - * that don't include a SubscriptionSettings parameter. - * - *@param messages: message credit. - *@param bytes: byte credit. - *@param window: if true use window-based flow control. - */ - void setFlowControl(uint32_t messages, uint32_t bytes, bool window=true) { - defaultSettings.flowControl = FlowControl(messages, bytes, window); - } - - /** - *Set the default accept-mode for subscribe() calls that don't - *include a SubscriptionSettings parameter. - */ - void setAcceptMode(AcceptMode mode) { defaultSettings.acceptMode = mode; } - - /** - * Set the default acquire-mode subscribe()s that don't specify SubscriptionSettings. - */ - void setAcquireMode(AcquireMode mode) { defaultSettings.acquireMode = mode; } - - void registerFailoverHandler ( boost::function<void ()> fh ); - - Session getSession() const; - - private: - mutable sys::Mutex lock; - qpid::client::Dispatcher dispatcher; - qpid::client::AsyncSession session; - bool autoStop; - SubscriptionSettings defaultSettings; - std::map<std::string, Subscription> subscriptions; -}; - - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H*/ diff --git a/cpp/src/qpid/client/TCPConnector.cpp b/cpp/src/qpid/client/TCPConnector.cpp deleted file mode 100644 index d90781b365..0000000000 --- a/cpp/src/qpid/client/TCPConnector.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/TCPConnector.h" - -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Codec.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/Msg.h" - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; -using boost::format; -using boost::str; - -struct TCPConnector::Buff : public AsynchIO::BufferBase { - Buff(size_t size) : AsynchIO::BufferBase(new char[size], size) {} - ~Buff() { delete [] bytes;} -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new TCPConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - Connector::registerFactory("tcp", &create); - }; - } init; -} - -TCPConnector::TCPConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - lastEof(0), - currentSize(0), - bounds(cimpl), - version(ver), - initiated(false), - closed(true), - shutdownHandler(0), - connector(0), - aio(0), - poller(p) -{ - QPID_LOG(debug, "TCPConnector created for " << version); - settings.configureSocket(socket); -} - -TCPConnector::~TCPConnector() { - close(); -} - -void TCPConnector::connect(const std::string& host, int port) { - Mutex::ScopedLock l(lock); - assert(closed); - connector = AsynchConnector::create( - socket, - host, port, - boost::bind(&TCPConnector::connected, this, _1), - boost::bind(&TCPConnector::connectFailed, this, _3)); - closed = false; - - connector->start(poller); -} - -void TCPConnector::connected(const Socket&) { - connector = 0; - aio = AsynchIO::create(socket, - boost::bind(&TCPConnector::readbuff, this, _1, _2), - boost::bind(&TCPConnector::eof, this, _1), - boost::bind(&TCPConnector::disconnected, this, _1), - boost::bind(&TCPConnector::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&TCPConnector::writebuff, this, _1)); - start(aio); - initAmqp(); - aio->start(poller); -} - -void TCPConnector::start(sys::AsynchIO* aio_) { - aio = aio_; - for (int i = 0; i < 4; i++) { - aio->queueReadBuffer(new Buff(maxFrameSize)); - } - - identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress()); -} - -void TCPConnector::initAmqp() { - ProtocolInitiation init(version); - writeDataBlock(init); -} - -void TCPConnector::connectFailed(const std::string& msg) { - connector = 0; - QPID_LOG(warning, "Connect failed: " << msg); - socket.close(); - if (!closed) - closed = true; - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void TCPConnector::close() { - Mutex::ScopedLock l(lock); - if (!closed) { - closed = true; - if (aio) - aio->queueWriteClose(); - } -} - -void TCPConnector::socketClosed(AsynchIO&, const Socket&) { - if (aio) - aio->queueForDeletion(); - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void TCPConnector::abort() { - // Can't abort a closed connection - if (!closed) { - if (aio) { - // Established connection - aio->requestCallback(boost::bind(&TCPConnector::eof, this, _1)); - } else if (connector) { - // We're still connecting - connector->stop(); - connectFailed("Connection timedout"); - } - } -} - -void TCPConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void TCPConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* TCPConnector::getOutputHandler() { - return this; -} - -sys::ShutdownHandler* TCPConnector::getShutdownHandler() const { - return shutdownHandler; -} - -const std::string& TCPConnector::getIdentifier() const { - return identifier; -} - -void TCPConnector::send(AMQFrame& frame) { - bool notifyWrite = false; - { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - //only ask to write if this is the end of a frameset or if we - //already have a buffers worth of data - currentSize += frame.encodedSize(); - if (frame.getEof()) { - lastEof = frames.size(); - notifyWrite = true; - } else { - notifyWrite = (currentSize >= maxFrameSize); - } - /* - NOTE: Moving the following line into this mutex block - is a workaround for BZ 570168, in which the test - testConcurrentSenders causes a hang about 1.5% - of the time. ( To see the hang much more frequently - leave this line out of the mutex block, and put a - small usleep just before it.) - - TODO mgoulish - fix the underlying cause and then - move this call back outside the mutex. - */ - if (notifyWrite && !closed) aio->notifyPendingWrite(); - } -} - -void TCPConnector::writebuff(AsynchIO& /*aio*/) -{ - // It's possible to be disconnected and be writable - if (closed) - return; - - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - if (codec->canEncode()) { - std::auto_ptr<AsynchIO::BufferBase> buffer = std::auto_ptr<AsynchIO::BufferBase>(aio->getQueuedBuffer()); - if (!buffer.get()) buffer = std::auto_ptr<AsynchIO::BufferBase>(new Buff(maxFrameSize)); - - size_t encoded = codec->encode(buffer->bytes, buffer->byteCount); - - buffer->dataStart = 0; - buffer->dataCount = encoded; - aio->queueWrite(buffer.release()); - } -} - -// Called in IO thread. -bool TCPConnector::canEncode() -{ - Mutex::ScopedLock l(lock); - //have at least one full frameset or a whole buffers worth of data - return lastEof || currentSize >= maxFrameSize; -} - -// Called in IO thread. -size_t TCPConnector::encode(const char* buffer, size_t size) -{ - framing::Buffer out(const_cast<char*>(buffer), size); - size_t bytesWritten(0); - { - Mutex::ScopedLock l(lock); - while (!frames.empty() && out.available() >= frames.front().encodedSize() ) { - frames.front().encode(out); - QPID_LOG(trace, "SENT " << identifier << ": " << frames.front()); - frames.pop_front(); - if (lastEof) --lastEof; - } - bytesWritten = size - out.available(); - currentSize -= bytesWritten; - } - if (bounds) bounds->reduce(bytesWritten); - return bytesWritten; -} - -bool TCPConnector::readbuff(AsynchIO& aio, AsynchIO::BufferBase* buff) -{ - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - int32_t decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount); - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (decoded < buff->dataCount) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += decoded; - buff->dataCount -= decoded; - aio.unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio.queueReadBuffer(buff); - } - return true; -} - -size_t TCPConnector::decode(const char* buffer, size_t size) -{ - framing::Buffer in(const_cast<char*>(buffer), size); - if (!initiated) { - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - QPID_LOG(debug, "RECV " << identifier << " INIT(" << protocolInit << ")"); - if(!(protocolInit==version)){ - throw Exception(QPID_MSG("Unsupported version: " << protocolInit - << " supported version " << version)); - } - } - initiated = true; - } - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV " << identifier << ": " << frame); - input->received(frame); - } - return size - in.available(); -} - -void TCPConnector::writeDataBlock(const AMQDataBlock& data) { - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void TCPConnector::eof(AsynchIO&) { - close(); -} - -void TCPConnector::disconnected(AsynchIO&) { - close(); - socketClosed(*aio, socket); -} - -void TCPConnector::activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer> sl) -{ - securityLayer = sl; - securityLayer->init(this); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/TCPConnector.h b/cpp/src/qpid/client/TCPConnector.h deleted file mode 100644 index c756469182..0000000000 --- a/cpp/src/qpid/client/TCPConnector.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _TCPConnector_ -#define _TCPConnector_ - -#include "Connector.h" -#include "qpid/client/Bounds.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Codec.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/Thread.h" - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include <deque> -#include <string> - -namespace qpid { - -namespace framing { - class InitiationHandler; -} - -namespace client { - -class TCPConnector : public Connector, public sys::Codec -{ - typedef std::deque<framing::AMQFrame> Frames; - struct Buff; - - const uint16_t maxFrameSize; - - sys::Mutex lock; - Frames frames; // Outgoing frame queue - size_t lastEof; // Position after last EOF in frames - uint64_t currentSize; - Bounds* bounds; - - framing::ProtocolVersion version; - bool initiated; - bool closed; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::OutputHandler* output; - - sys::Socket socket; - - sys::AsynchConnector* connector; - sys::AsynchIO* aio; - std::string identifier; - boost::shared_ptr<sys::Poller> poller; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - - virtual void connected(const sys::Socket&); - void writeDataBlock(const framing::AMQDataBlock& data); - - void close(); - void send(framing::AMQFrame& frame); - void abort(); - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - sys::ShutdownHandler* getShutdownHandler() const; - framing::OutputHandler* getOutputHandler(); - const std::string& getIdentifier() const; - void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); - const qpid::sys::SecuritySettings* getSecuritySettings() { return 0; } - - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - -protected: - virtual ~TCPConnector(); - void connect(const std::string& host, int port); - void start(sys::AsynchIO* aio_); - void initAmqp(); - virtual void connectFailed(const std::string& msg); - bool readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void writebuff(qpid::sys::AsynchIO&); - void eof(qpid::sys::AsynchIO&); - void disconnected(qpid::sys::AsynchIO&); - void socketClosed(qpid::sys::AsynchIO&, const qpid::sys::Socket&); - -public: - TCPConnector(boost::shared_ptr<sys::Poller>, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -}} // namespace qpid::client - -#endif /* _TCPConnector_ */ diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp b/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp deleted file mode 100644 index bfb20118b5..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "AcceptTracker.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -void AcceptTracker::State::accept() -{ - unconfirmed.add(unaccepted); - unaccepted.clear(); -} - -void AcceptTracker::State::accept(qpid::framing::SequenceNumber id) -{ - if (unaccepted.contains(id)) { - unaccepted.remove(id); - unconfirmed.add(id); - } -} - -void AcceptTracker::State::release() -{ - unaccepted.clear(); -} - -uint32_t AcceptTracker::State::acceptsPending() -{ - return unconfirmed.size(); -} - -void AcceptTracker::State::completed(qpid::framing::SequenceSet& set) -{ - unconfirmed.remove(set); -} - -void AcceptTracker::delivered(const std::string& destination, const qpid::framing::SequenceNumber& id) -{ - aggregateState.unaccepted.add(id); - destinationState[destination].unaccepted.add(id); -} - -void AcceptTracker::accept(qpid::client::AsyncSession& session) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.accept(); - } - Record record; - record.status = session.messageAccept(aggregateState.unaccepted); - record.accepted = aggregateState.unaccepted; - pending.push_back(record); - aggregateState.accept(); -} - -void AcceptTracker::accept(qpid::framing::SequenceNumber id, qpid::client::AsyncSession& session) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.accept(id); - } - Record record; - record.accepted.add(id); - record.status = session.messageAccept(record.accepted); - pending.push_back(record); - aggregateState.accept(id); -} - -void AcceptTracker::release(qpid::client::AsyncSession& session) -{ - session.messageRelease(aggregateState.unaccepted); - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.release(); - } - aggregateState.release(); -} - -uint32_t AcceptTracker::acceptsPending() -{ - checkPending(); - return aggregateState.acceptsPending(); -} - -uint32_t AcceptTracker::acceptsPending(const std::string& destination) -{ - checkPending(); - return destinationState[destination].acceptsPending(); -} - -void AcceptTracker::reset() -{ - destinationState.clear(); - aggregateState.unaccepted.clear(); - aggregateState.unconfirmed.clear(); - pending.clear(); -} - -void AcceptTracker::checkPending() -{ - while (!pending.empty() && pending.front().status.isComplete()) { - completed(pending.front().accepted); - pending.pop_front(); - } -} - -void AcceptTracker::completed(qpid::framing::SequenceSet& set) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.completed(set); - } - aggregateState.completed(set); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h b/cpp/src/qpid/client/amqp0_10/AcceptTracker.h deleted file mode 100644 index 87890e41cc..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H -#define QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/AsyncSession.h" -#include "qpid/client/Completion.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceSet.h" -#include <deque> -#include <map> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -/** - * Tracks the set of messages requiring acceptance, and those for - * which an accept has been issued but is yet to be confirmed - * complete. - */ -class AcceptTracker -{ - public: - void delivered(const std::string& destination, const qpid::framing::SequenceNumber& id); - void accept(qpid::client::AsyncSession&); - void accept(qpid::framing::SequenceNumber, qpid::client::AsyncSession&); - void release(qpid::client::AsyncSession&); - uint32_t acceptsPending(); - uint32_t acceptsPending(const std::string& destination); - void reset(); - private: - struct State - { - /** - * ids of messages that have been delivered but not yet - * accepted - */ - qpid::framing::SequenceSet unaccepted; - /** - * ids of messages for which an accept has been issued but not - * yet confirmed as completed - */ - qpid::framing::SequenceSet unconfirmed; - - void accept(); - void accept(qpid::framing::SequenceNumber); - void release(); - uint32_t acceptsPending(); - void completed(qpid::framing::SequenceSet&); - }; - typedef std::map<std::string, State> StateMap; - struct Record - { - qpid::client::Completion status; - qpid::framing::SequenceSet accepted; - }; - typedef std::deque<Record> Records; - - State aggregateState; - StateMap destinationState; - Records pending; - - void checkPending(); - void completed(qpid::framing::SequenceSet&); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp deleted file mode 100644 index f1295a3b66..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp +++ /dev/null @@ -1,966 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/client/amqp0_10/MessageSource.h" -#include "qpid/client/amqp0_10/MessageSink.h" -#include "qpid/client/amqp0_10/OutgoingMessage.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/types/Variant.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/ExchangeBoundResult.h" -#include "qpid/framing/ExchangeQueryResult.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/QueueQueryResult.h" -#include "qpid/framing/ReplyTo.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include <boost/assign.hpp> -#include <boost/format.hpp> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::Exception; -using qpid::messaging::Address; -using qpid::messaging::AddressError; -using qpid::messaging::MalformedAddress; -using qpid::messaging::ResolutionError; -using qpid::messaging::NotFound; -using qpid::messaging::AssertionFailed; -using qpid::framing::ExchangeBoundResult; -using qpid::framing::ExchangeQueryResult; -using qpid::framing::FieldTable; -using qpid::framing::QueueQueryResult; -using qpid::framing::ReplyTo; -using qpid::framing::Uuid; -using namespace qpid::types; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; -using namespace boost::assign; - -class Verifier -{ - public: - Verifier(); - void verify(const Address& address) const; - private: - Variant::Map defined; - void verify(const Variant::Map& allowed, const Variant::Map& actual) const; -}; - -namespace{ -const Variant EMPTY_VARIANT; -const FieldTable EMPTY_FIELD_TABLE; -const Variant::List EMPTY_LIST; -const std::string EMPTY_STRING; - -//policy types -const std::string CREATE("create"); -const std::string ASSERT("assert"); -const std::string DELETE("delete"); - -//option names -const std::string NODE("node"); -const std::string LINK("link"); -const std::string MODE("mode"); -const std::string RELIABILITY("reliability"); -const std::string NAME("name"); -const std::string DURABLE("durable"); -const std::string X_DECLARE("x-declare"); -const std::string X_SUBSCRIBE("x-subscribe"); -const std::string X_BINDINGS("x-bindings"); -const std::string EXCHANGE("exchange"); -const std::string QUEUE("queue"); -const std::string KEY("key"); -const std::string ARGUMENTS("arguments"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string TYPE("type"); -const std::string EXCLUSIVE("exclusive"); -const std::string AUTO_DELETE("auto-delete"); - -//policy values -const std::string ALWAYS("always"); -const std::string NEVER("never"); -const std::string RECEIVER("receiver"); -const std::string SENDER("sender"); - -//address types -const std::string QUEUE_ADDRESS("queue"); -const std::string TOPIC_ADDRESS("topic"); - -//reliability options: -const std::string UNRELIABLE("unreliable"); -const std::string AT_MOST_ONCE("at-most-once"); -const std::string AT_LEAST_ONCE("at-least-once"); -const std::string EXACTLY_ONCE("exactly-once"); - -//receiver modes: -const std::string BROWSE("browse"); -const std::string CONSUME("consume"); - -//0-10 exchange types: -const std::string TOPIC_EXCHANGE("topic"); -const std::string FANOUT_EXCHANGE("fanout"); -const std::string DIRECT_EXCHANGE("direct"); -const std::string HEADERS_EXCHANGE("headers"); -const std::string XML_EXCHANGE("xml"); -const std::string WILDCARD_ANY("#"); - -const Verifier verifier; -} - -struct Binding -{ - Binding(const Variant::Map&); - Binding(const std::string& exchange, const std::string& queue, const std::string& key); - - std::string exchange; - std::string queue; - std::string key; - FieldTable arguments; -}; - -struct Bindings : std::vector<Binding> -{ - void add(const Variant::List& bindings); - void setDefaultExchange(const std::string&); - void setDefaultQueue(const std::string&); - void bind(qpid::client::AsyncSession& session); - void unbind(qpid::client::AsyncSession& session); - void check(qpid::client::AsyncSession& session); -}; - -class Node -{ - protected: - enum CheckMode {FOR_RECEIVER, FOR_SENDER}; - - Node(const Address& address); - - const std::string name; - Variant createPolicy; - Variant assertPolicy; - Variant deletePolicy; - Bindings nodeBindings; - Bindings linkBindings; - - static bool enabled(const Variant& policy, CheckMode mode); - static bool createEnabled(const Address& address, CheckMode mode); - static void convert(const Variant& option, FieldTable& arguments); - static std::vector<std::string> RECEIVER_MODES; - static std::vector<std::string> SENDER_MODES; -}; - - -class Queue : protected Node -{ - public: - Queue(const Address& address); - protected: - void checkCreate(qpid::client::AsyncSession&, CheckMode); - void checkAssert(qpid::client::AsyncSession&, CheckMode); - void checkDelete(qpid::client::AsyncSession&, CheckMode); - private: - const bool durable; - const bool autoDelete; - const bool exclusive; - const std::string alternateExchange; - FieldTable arguments; -}; - -class Exchange : protected Node -{ - public: - Exchange(const Address& address); - protected: - void checkCreate(qpid::client::AsyncSession&, CheckMode); - void checkAssert(qpid::client::AsyncSession&, CheckMode); - void checkDelete(qpid::client::AsyncSession&, CheckMode); - - protected: - const std::string specifiedType; - private: - const bool durable; - const bool autoDelete; - const std::string alternateExchange; - FieldTable arguments; -}; - -class QueueSource : public Queue, public MessageSource -{ - public: - QueueSource(const Address& address); - void subscribe(qpid::client::AsyncSession& session, const std::string& destination); - void cancel(qpid::client::AsyncSession& session, const std::string& destination); - private: - const AcceptMode acceptMode; - const AcquireMode acquireMode; - bool exclusive; - FieldTable options; -}; - -class Subscription : public Exchange, public MessageSource -{ - public: - Subscription(const Address&, const std::string& actualType); - void subscribe(qpid::client::AsyncSession& session, const std::string& destination); - void cancel(qpid::client::AsyncSession& session, const std::string& destination); - private: - const std::string queue; - const bool reliable; - const bool durable; - const std::string actualType; - FieldTable queueOptions; - FieldTable subscriptionOptions; - Bindings bindings; - - void bindSubject(const std::string& subject); - void bindAll(); - void add(const std::string& exchange, const std::string& key); - static std::string getSubscriptionName(const std::string& base, const std::string& name); -}; - -class ExchangeSink : public Exchange, public MessageSink -{ - public: - ExchangeSink(const Address& name); - void declare(qpid::client::AsyncSession& session, const std::string& name); - void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message); - void cancel(qpid::client::AsyncSession& session, const std::string& name); - private: -}; - -class QueueSink : public Queue, public MessageSink -{ - public: - QueueSink(const Address& name); - void declare(qpid::client::AsyncSession& session, const std::string& name); - void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message); - void cancel(qpid::client::AsyncSession& session, const std::string& name); - private: -}; -bool isQueue(qpid::client::Session session, const qpid::messaging::Address& address); -bool isTopic(qpid::client::Session session, const qpid::messaging::Address& address); - -bool in(const Variant& value, const std::vector<std::string>& choices) -{ - if (!value.isVoid()) { - for (std::vector<std::string>::const_iterator i = choices.begin(); i != choices.end(); ++i) { - if (value.asString() == *i) return true; - } - } - return false; -} - -const Variant& getOption(const Variant::Map& options, const std::string& name) -{ - Variant::Map::const_iterator j = options.find(name); - if (j == options.end()) { - return EMPTY_VARIANT; - } else { - return j->second; - } -} - -const Variant& getOption(const Address& address, const std::string& name) -{ - return getOption(address.getOptions(), name); -} - -bool getReceiverPolicy(const Address& address, const std::string& key) -{ - return in(getOption(address, key), list_of<std::string>(ALWAYS)(RECEIVER)); -} - -bool getSenderPolicy(const Address& address, const std::string& key) -{ - return in(getOption(address, key), list_of<std::string>(ALWAYS)(SENDER)); -} - -struct Opt -{ - Opt(const Address& address); - Opt(const Variant::Map& base); - Opt& operator/(const std::string& name); - operator bool() const; - std::string str() const; - const Variant::List& asList() const; - void collect(qpid::framing::FieldTable& args) const; - - const Variant::Map* options; - const Variant* value; -}; - -Opt::Opt(const Address& address) : options(&(address.getOptions())), value(0) {} -Opt::Opt(const Variant::Map& base) : options(&base), value(0) {} -Opt& Opt::operator/(const std::string& name) -{ - if (options) { - Variant::Map::const_iterator j = options->find(name); - if (j == options->end()) { - value = 0; - options = 0; - } else { - value = &(j->second); - if (value->getType() == VAR_MAP) options = &(value->asMap()); - else options = 0; - } - } - return *this; -} - - -Opt::operator bool() const -{ - return value && !value->isVoid() && value->asBool(); -} - -std::string Opt::str() const -{ - if (value) return value->asString(); - else return EMPTY_STRING; -} - -const Variant::List& Opt::asList() const -{ - if (value) return value->asList(); - else return EMPTY_LIST; -} - -void Opt::collect(qpid::framing::FieldTable& args) const -{ - if (value) { - translate(value->asMap(), args); - } -} - -bool AddressResolution::is_unreliable(const Address& address) -{ - - return in((Opt(address)/LINK/RELIABILITY).str(), - list_of<std::string>(UNRELIABLE)(AT_MOST_ONCE)); -} - -bool AddressResolution::is_reliable(const Address& address) -{ - return in((Opt(address)/LINK/RELIABILITY).str(), - list_of<std::string>(AT_LEAST_ONCE)(EXACTLY_ONCE)); -} - -std::string checkAddressType(qpid::client::Session session, const Address& address) -{ - verifier.verify(address); - if (address.getName().empty()) { - throw MalformedAddress("Name cannot be null"); - } - std::string type = (Opt(address)/NODE/TYPE).str(); - if (type.empty()) { - ExchangeBoundResult result = session.exchangeBound(arg::exchange=address.getName(), arg::queue=address.getName()); - if (result.getQueueNotFound() && result.getExchangeNotFound()) { - //neither a queue nor an exchange exists with that name; treat it as a queue - type = QUEUE_ADDRESS; - } else if (result.getExchangeNotFound()) { - //name refers to a queue - type = QUEUE_ADDRESS; - } else if (result.getQueueNotFound()) { - //name refers to an exchange - type = TOPIC_ADDRESS; - } else { - //both a queue and exchange exist for that name - throw ResolutionError("Ambiguous address, please specify queue or topic as node type"); - } - } - return type; -} - -std::auto_ptr<MessageSource> AddressResolution::resolveSource(qpid::client::Session session, - const Address& address) -{ - std::string type = checkAddressType(session, address); - if (type == TOPIC_ADDRESS) { - std::string exchangeType = sync(session).exchangeQuery(address.getName()).getType(); - std::auto_ptr<MessageSource> source(new Subscription(address, exchangeType)); - QPID_LOG(debug, "treating source address as topic: " << address); - return source; - } else if (type == QUEUE_ADDRESS) { - std::auto_ptr<MessageSource> source(new QueueSource(address)); - QPID_LOG(debug, "treating source address as queue: " << address); - return source; - } else { - throw ResolutionError("Unrecognised type: " + type); - } -} - - -std::auto_ptr<MessageSink> AddressResolution::resolveSink(qpid::client::Session session, - const qpid::messaging::Address& address) -{ - std::string type = checkAddressType(session, address); - if (type == TOPIC_ADDRESS) { - std::auto_ptr<MessageSink> sink(new ExchangeSink(address)); - QPID_LOG(debug, "treating target address as topic: " << address); - return sink; - } else if (type == QUEUE_ADDRESS) { - std::auto_ptr<MessageSink> sink(new QueueSink(address)); - QPID_LOG(debug, "treating target address as queue: " << address); - return sink; - } else { - throw ResolutionError("Unrecognised type: " + type); - } -} - -bool isBrowse(const Address& address) -{ - const Variant& mode = getOption(address, MODE); - if (!mode.isVoid()) { - std::string value = mode.asString(); - if (value == BROWSE) return true; - else if (value != CONSUME) throw ResolutionError("Invalid mode"); - } - return false; -} - -QueueSource::QueueSource(const Address& address) : - Queue(address), - acceptMode(AddressResolution::is_unreliable(address) ? ACCEPT_MODE_NONE : ACCEPT_MODE_EXPLICIT), - acquireMode(isBrowse(address) ? ACQUIRE_MODE_NOT_ACQUIRED : ACQUIRE_MODE_PRE_ACQUIRED), - exclusive(false) -{ - //extract subscription arguments from address options (nb: setting - //of accept-mode/acquire-mode/destination controlled though other - //options) - exclusive = Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE; - (Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(options); -} - -void QueueSource::subscribe(qpid::client::AsyncSession& session, const std::string& destination) -{ - checkCreate(session, FOR_RECEIVER); - checkAssert(session, FOR_RECEIVER); - linkBindings.bind(session); - session.messageSubscribe(arg::queue=name, - arg::destination=destination, - arg::acceptMode=acceptMode, - arg::acquireMode=acquireMode, - arg::exclusive=exclusive, - arg::arguments=options); -} - -void QueueSource::cancel(qpid::client::AsyncSession& session, const std::string& destination) -{ - linkBindings.unbind(session); - session.messageCancel(destination); - checkDelete(session, FOR_RECEIVER); -} - -std::string Subscription::getSubscriptionName(const std::string& base, const std::string& name) -{ - if (name.empty()) { - return (boost::format("%1%_%2%") % base % Uuid(true).str()).str(); - } else { - return (boost::format("%1%_%2%") % base % name).str(); - } -} - -Subscription::Subscription(const Address& address, const std::string& type) - : Exchange(address), - queue(getSubscriptionName(name, (Opt(address)/LINK/NAME).str())), - reliable(AddressResolution::is_reliable(address)), - durable(Opt(address)/LINK/DURABLE), - actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type) -{ - (Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions); - (Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions); - - if (!address.getSubject().empty()) bindSubject(address.getSubject()); - else if (linkBindings.empty()) bindAll(); -} - -void Subscription::bindSubject(const std::string& subject) -{ - if (actualType == HEADERS_EXCHANGE) { - Binding b(name, queue, subject); - b.arguments.setString("qpid.subject", subject); - b.arguments.setString("x-match", "all"); - bindings.push_back(b); - } else if (actualType == XML_EXCHANGE) { - Binding b(name, queue, subject); - std::string query = (boost::format("declare variable $qpid.subject external; $qpid.subject = '%1%'") - % subject).str(); - b.arguments.setString("xquery", query); - bindings.push_back(b); - } else { - //Note: the fanout exchange doesn't support any filtering, so - //the subject is ignored in that case - add(name, subject); - } -} - -void Subscription::bindAll() -{ - if (actualType == TOPIC_EXCHANGE) { - add(name, WILDCARD_ANY); - } else if (actualType == FANOUT_EXCHANGE) { - add(name, queue); - } else if (actualType == HEADERS_EXCHANGE) { - Binding b(name, queue, "match-all"); - b.arguments.setString("x-match", "all"); - bindings.push_back(b); - } else if (actualType == XML_EXCHANGE) { - Binding b(name, queue, EMPTY_STRING); - b.arguments.setString("xquery", "true()"); - bindings.push_back(b); - } else { - add(name, EMPTY_STRING); - } -} - -void Subscription::add(const std::string& exchange, const std::string& key) -{ - bindings.push_back(Binding(exchange, queue, key)); -} - -void Subscription::subscribe(qpid::client::AsyncSession& session, const std::string& destination) -{ - //create exchange if required and specified by policy: - checkCreate(session, FOR_RECEIVER); - checkAssert(session, FOR_RECEIVER); - - //create subscription queue: - session.queueDeclare(arg::queue=queue, arg::exclusive=true, - arg::autoDelete=!reliable, arg::durable=durable, arg::arguments=queueOptions); - //'default' binding: - bindings.bind(session); - //any explicit bindings: - linkBindings.setDefaultQueue(queue); - linkBindings.bind(session); - //subscribe to subscription queue: - AcceptMode accept = reliable ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE; - session.messageSubscribe(arg::queue=queue, arg::destination=destination, - arg::exclusive=true, arg::acceptMode=accept, arg::arguments=subscriptionOptions); -} - -void Subscription::cancel(qpid::client::AsyncSession& session, const std::string& destination) -{ - linkBindings.unbind(session); - session.messageCancel(destination); - session.queueDelete(arg::queue=queue); - checkDelete(session, FOR_RECEIVER); -} - -ExchangeSink::ExchangeSink(const Address& address) : Exchange(address) {} - -void ExchangeSink::declare(qpid::client::AsyncSession& session, const std::string&) -{ - checkCreate(session, FOR_SENDER); - checkAssert(session, FOR_SENDER); - linkBindings.bind(session); -} - -void ExchangeSink::send(qpid::client::AsyncSession& session, const std::string&, OutgoingMessage& m) -{ - m.message.getDeliveryProperties().setRoutingKey(m.getSubject()); - m.status = session.messageTransfer(arg::destination=name, arg::content=m.message); -} - -void ExchangeSink::cancel(qpid::client::AsyncSession& session, const std::string&) -{ - linkBindings.unbind(session); - checkDelete(session, FOR_SENDER); -} - -QueueSink::QueueSink(const Address& address) : Queue(address) {} - -void QueueSink::declare(qpid::client::AsyncSession& session, const std::string&) -{ - checkCreate(session, FOR_SENDER); - checkAssert(session, FOR_SENDER); - linkBindings.bind(session); -} -void QueueSink::send(qpid::client::AsyncSession& session, const std::string&, OutgoingMessage& m) -{ - m.message.getDeliveryProperties().setRoutingKey(name); - m.status = session.messageTransfer(arg::content=m.message); -} - -void QueueSink::cancel(qpid::client::AsyncSession& session, const std::string&) -{ - linkBindings.unbind(session); - checkDelete(session, FOR_SENDER); -} - -Address AddressResolution::convert(const qpid::framing::ReplyTo& rt) -{ - Address address; - if (rt.getExchange().empty()) {//if default exchange, treat as queue - address.setName(rt.getRoutingKey()); - address.setType(QUEUE_ADDRESS); - } else { - address.setName(rt.getExchange()); - address.setSubject(rt.getRoutingKey()); - address.setType(TOPIC_ADDRESS); - } - return address; -} - -qpid::framing::ReplyTo AddressResolution::convert(const Address& address) -{ - if (address.getType() == QUEUE_ADDRESS || address.getType().empty()) { - return ReplyTo(EMPTY_STRING, address.getName()); - } else if (address.getType() == TOPIC_ADDRESS) { - return ReplyTo(address.getName(), address.getSubject()); - } else { - QPID_LOG(notice, "Unrecognised type for reply-to: " << address.getType()); - return ReplyTo(EMPTY_STRING, address.getName());//treat as queue - } -} - -bool isQueue(qpid::client::Session session, const qpid::messaging::Address& address) -{ - return address.getType() == QUEUE_ADDRESS || - (address.getType().empty() && session.queueQuery(address.getName()).getQueue() == address.getName()); -} - -bool isTopic(qpid::client::Session session, const qpid::messaging::Address& address) -{ - if (address.getType().empty()) { - return !session.exchangeQuery(address.getName()).getNotFound(); - } else if (address.getType() == TOPIC_ADDRESS) { - return true; - } else { - return false; - } -} - -Node::Node(const Address& address) : name(address.getName()), - createPolicy(getOption(address, CREATE)), - assertPolicy(getOption(address, ASSERT)), - deletePolicy(getOption(address, DELETE)) -{ - nodeBindings.add((Opt(address)/NODE/X_BINDINGS).asList()); - linkBindings.add((Opt(address)/LINK/X_BINDINGS).asList()); -} - -Queue::Queue(const Address& a) : Node(a), - durable(Opt(a)/NODE/DURABLE), - autoDelete(Opt(a)/NODE/X_DECLARE/AUTO_DELETE), - exclusive(Opt(a)/NODE/X_DECLARE/EXCLUSIVE), - alternateExchange((Opt(a)/NODE/X_DECLARE/ALTERNATE_EXCHANGE).str()) -{ - (Opt(a)/NODE/X_DECLARE/ARGUMENTS).collect(arguments); - nodeBindings.setDefaultQueue(name); - linkBindings.setDefaultQueue(name); -} - -void Queue::checkCreate(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(createPolicy, mode)) { - QPID_LOG(debug, "Auto-creating queue '" << name << "'"); - try { - session.queueDeclare(arg::queue=name, - arg::durable=durable, - arg::autoDelete=autoDelete, - arg::exclusive=exclusive, - arg::alternateExchange=alternateExchange, - arg::arguments=arguments); - nodeBindings.bind(session); - session.sync(); - } catch (const qpid::framing::ResourceLockedException& e) { - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotAllowedException& e) { - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotFoundException& e) {//may be thrown when creating bindings - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } - } else { - try { - sync(session).queueDeclare(arg::queue=name, arg::passive=true); - } catch (const qpid::framing::NotFoundException& /*e*/) { - throw NotFound((boost::format("Queue %1% does not exist") % name).str()); - } - } -} - -void Queue::checkDelete(qpid::client::AsyncSession& session, CheckMode mode) -{ - //Note: queue-delete will cause a session exception if the queue - //does not exist, the query here prevents obvious cases of this - //but there is a race whenever two deletions are made concurrently - //so careful use of the delete policy is recommended at present - if (enabled(deletePolicy, mode) && sync(session).queueQuery(name).getQueue() == name) { - QPID_LOG(debug, "Auto-deleting queue '" << name << "'"); - sync(session).queueDelete(arg::queue=name); - } -} - -void Queue::checkAssert(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(assertPolicy, mode)) { - QueueQueryResult result = sync(session).queueQuery(name); - if (result.getQueue() != name) { - throw NotFound((boost::format("Queue not found: %1%") % name).str()); - } else { - if (durable && !result.getDurable()) { - throw AssertionFailed((boost::format("Queue not durable: %1%") % name).str()); - } - if (autoDelete && !result.getAutoDelete()) { - throw AssertionFailed((boost::format("Queue not set to auto-delete: %1%") % name).str()); - } - if (exclusive && !result.getExclusive()) { - throw AssertionFailed((boost::format("Queue not exclusive: %1%") % name).str()); - } - if (!alternateExchange.empty() && result.getAlternateExchange() != alternateExchange) { - throw AssertionFailed((boost::format("Alternate exchange does not match for %1%, expected %2%, got %3%") - % name % alternateExchange % result.getAlternateExchange()).str()); - } - for (FieldTable::ValueMap::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - FieldTable::ValuePtr v = result.getArguments().get(i->first); - if (!v) { - throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str()); - } else if (*i->second != *v) { - throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%") - % i->first % name % *(i->second) % *v).str()); - } - } - nodeBindings.check(session); - } - } -} - -Exchange::Exchange(const Address& a) : Node(a), - specifiedType((Opt(a)/NODE/X_DECLARE/TYPE).str()), - durable(Opt(a)/NODE/DURABLE), - autoDelete(Opt(a)/NODE/X_DECLARE/AUTO_DELETE), - alternateExchange((Opt(a)/NODE/X_DECLARE/ALTERNATE_EXCHANGE).str()) -{ - (Opt(a)/NODE/X_DECLARE/ARGUMENTS).collect(arguments); - nodeBindings.setDefaultExchange(name); - linkBindings.setDefaultExchange(name); -} - -void Exchange::checkCreate(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(createPolicy, mode)) { - try { - std::string type = specifiedType; - if (type.empty()) type = TOPIC_EXCHANGE; - session.exchangeDeclare(arg::exchange=name, - arg::type=type, - arg::durable=durable, - arg::autoDelete=autoDelete, - arg::alternateExchange=alternateExchange, - arg::arguments=arguments); - nodeBindings.bind(session); - session.sync(); - } catch (const qpid::framing::NotAllowedException& e) { - throw ResolutionError((boost::format("Create failed for exchange %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotFoundException& e) {//can be caused when creating bindings - throw ResolutionError((boost::format("Create failed for exchange %1%; %2%") % name % e.what()).str()); - } - } else { - try { - sync(session).exchangeDeclare(arg::exchange=name, arg::passive=true); - } catch (const qpid::framing::NotFoundException& /*e*/) { - throw NotFound((boost::format("Exchange %1% does not exist") % name).str()); - } - } -} - -void Exchange::checkDelete(qpid::client::AsyncSession& session, CheckMode mode) -{ - //Note: exchange-delete will cause a session exception if the - //exchange does not exist, the query here prevents obvious cases - //of this but there is a race whenever two deletions are made - //concurrently so careful use of the delete policy is recommended - //at present - if (enabled(deletePolicy, mode) && !sync(session).exchangeQuery(name).getNotFound()) { - sync(session).exchangeDelete(arg::exchange=name); - } -} - -void Exchange::checkAssert(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(assertPolicy, mode)) { - ExchangeQueryResult result = sync(session).exchangeQuery(name); - if (result.getNotFound()) { - throw NotFound((boost::format("Exchange not found: %1%") % name).str()); - } else { - if (specifiedType.size() && result.getType() != specifiedType) { - throw AssertionFailed((boost::format("Exchange %1% is of incorrect type, expected %2% but got %3%") - % name % specifiedType % result.getType()).str()); - } - if (durable && !result.getDurable()) { - throw AssertionFailed((boost::format("Exchange not durable: %1%") % name).str()); - } - //Note: Can't check auto-delete or alternate-exchange via - //exchange-query-result as these are not returned - //TODO: could use a passive declare to check alternate-exchange - for (FieldTable::ValueMap::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - FieldTable::ValuePtr v = result.getArguments().get(i->first); - if (!v) { - throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str()); - } else if (i->second != v) { - throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%") - % i->first % name % *(i->second) % *v).str()); - } - } - nodeBindings.check(session); - } - } -} - -Binding::Binding(const Variant::Map& b) : - exchange((Opt(b)/EXCHANGE).str()), - queue((Opt(b)/QUEUE).str()), - key((Opt(b)/KEY).str()) -{ - (Opt(b)/ARGUMENTS).collect(arguments); -} - -Binding::Binding(const std::string& e, const std::string& q, const std::string& k) : exchange(e), queue(q), key(k) {} - - -void Bindings::add(const Variant::List& list) -{ - for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - push_back(Binding(i->asMap())); - } -} - -void Bindings::setDefaultExchange(const std::string& exchange) -{ - for (Bindings::iterator i = begin(); i != end(); ++i) { - if (i->exchange.empty()) i->exchange = exchange; - } -} - -void Bindings::setDefaultQueue(const std::string& queue) -{ - for (Bindings::iterator i = begin(); i != end(); ++i) { - if (i->queue.empty()) i->queue = queue; - } -} - -void Bindings::bind(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - session.exchangeBind(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key, - arg::arguments=i->arguments); - } -} - -void Bindings::unbind(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - session.exchangeUnbind(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key); - } -} - -void Bindings::check(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - ExchangeBoundResult result = sync(session).exchangeBound(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key); - if (result.getQueueNotMatched() || result.getKeyNotMatched()) { - throw AssertionFailed((boost::format("No such binding [exchange=%1%, queue=%2%, key=%3%]") - % i->exchange % i->queue % i->key).str()); - } - } -} - -bool Node::enabled(const Variant& policy, CheckMode mode) -{ - bool result = false; - switch (mode) { - case FOR_RECEIVER: - result = in(policy, RECEIVER_MODES); - break; - case FOR_SENDER: - result = in(policy, SENDER_MODES); - break; - } - return result; -} - -bool Node::createEnabled(const Address& address, CheckMode mode) -{ - const Variant& policy = getOption(address, CREATE); - return enabled(policy, mode); -} - -void Node::convert(const Variant& options, FieldTable& arguments) -{ - if (!options.isVoid()) { - translate(options.asMap(), arguments); - } -} -std::vector<std::string> Node::RECEIVER_MODES = list_of<std::string>(ALWAYS) (RECEIVER); -std::vector<std::string> Node::SENDER_MODES = list_of<std::string>(ALWAYS) (SENDER); - -Verifier::Verifier() -{ - defined[CREATE] = true; - defined[ASSERT] = true; - defined[DELETE] = true; - defined[MODE] = true; - Variant::Map node; - node[TYPE] = true; - node[DURABLE] = true; - node[X_DECLARE] = true; - node[X_BINDINGS] = true; - defined[NODE] = node; - Variant::Map link; - link[NAME] = true; - link[DURABLE] = true; - link[RELIABILITY] = true; - link[X_SUBSCRIBE] = true; - link[X_DECLARE] = true; - link[X_BINDINGS] = true; - defined[LINK] = link; -} -void Verifier::verify(const Address& address) const -{ - verify(defined, address.getOptions()); -} - -void Verifier::verify(const Variant::Map& allowed, const Variant::Map& actual) const -{ - for (Variant::Map::const_iterator i = actual.begin(); i != actual.end(); ++i) { - Variant::Map::const_iterator option = allowed.find(i->first); - if (option == allowed.end()) { - throw AddressError((boost::format("Unrecognised option: %1%") % i->first).str()); - } else if (option->second.getType() == qpid::types::VAR_MAP) { - verify(option->second.asMap(), i->second.asMap()); - } - } -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/AddressResolution.h b/cpp/src/qpid/client/amqp0_10/AddressResolution.h deleted file mode 100644 index fc8f1a1d18..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AddressResolution.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H -#define QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Session.h" - -namespace qpid { - -namespace framing{ -class ReplyTo; -} - -namespace messaging { -class Address; -} - -namespace client { -namespace amqp0_10 { - -class MessageSource; -class MessageSink; - -/** - * Maps from a generic Address and optional Filter to an AMQP 0-10 - * MessageSource which will then be used by a ReceiverImpl instance - * created for the address. - */ -class AddressResolution -{ - public: - std::auto_ptr<MessageSource> resolveSource(qpid::client::Session session, - const qpid::messaging::Address& address); - - std::auto_ptr<MessageSink> resolveSink(qpid::client::Session session, - const qpid::messaging::Address& address); - - static qpid::messaging::Address convert(const qpid::framing::ReplyTo&); - static qpid::framing::ReplyTo convert(const qpid::messaging::Address&); - static bool is_unreliable(const qpid::messaging::Address& address); - static bool is_reliable(const qpid::messaging::Address& address); - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp deleted file mode 100644 index a87a8dea67..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "ConnectionImpl.h" -#include "SessionImpl.h" -#include "SimpleUrlParser.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include "qpid/Url.h" -#include <boost/intrusive_ptr.hpp> -#include <vector> -#include <sstream> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::types::Variant; -using qpid::types::VAR_LIST; -using qpid::framing::Uuid; - -namespace { -void convert(const Variant::List& from, std::vector<std::string>& to) -{ - for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i) { - to.push_back(i->asString()); - } -} - -std::string asString(const std::vector<std::string>& v) { - std::stringstream os; - os << "["; - for(std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i ) { - if (i != v.begin()) os << ", "; - os << *i; - } - os << "]"; - return os.str(); -} -} - -ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) : - reconnect(false), timeout(-1), limit(-1), - minReconnectInterval(3), maxReconnectInterval(60), - retries(0), reconnectOnLimitExceeded(true) -{ - setOptions(options); - urls.insert(urls.begin(), url); - QPID_LOG(debug, "Created connection " << url << " with " << options); -} - -void ConnectionImpl::setOptions(const Variant::Map& options) -{ - for (Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) { - setOption(i->first, i->second); - } -} - -void ConnectionImpl::setOption(const std::string& name, const Variant& value) -{ - sys::Mutex::ScopedLock l(lock); - if (name == "reconnect") { - reconnect = value; - } else if (name == "reconnect-timeout" || name == "reconnect_timeout") { - timeout = value; - } else if (name == "reconnect-limit" || name == "reconnect_limit") { - limit = value; - } else if (name == "reconnect-interval" || name == "reconnect_interval") { - maxReconnectInterval = minReconnectInterval = value; - } else if (name == "reconnect-interval-min" || name == "reconnect_interval_min") { - minReconnectInterval = value; - } else if (name == "reconnect-interval-max" || name == "reconnect_interval_max") { - maxReconnectInterval = value; - } else if (name == "reconnect-urls" || name == "reconnect_urls") { - if (value.getType() == VAR_LIST) { - convert(value.asList(), urls); - } else { - urls.push_back(value.asString()); - } - } else if (name == "username") { - settings.username = value.asString(); - } else if (name == "password") { - settings.password = value.asString(); - } else if (name == "sasl-mechanism" || name == "sasl_mechanism" || - name == "sasl-mechanisms" || name == "sasl_mechanisms") { - settings.mechanism = value.asString(); - } else if (name == "sasl-service" || name == "sasl_service") { - settings.service = value.asString(); - } else if (name == "sasl-min-ssf" || name == "sasl_min_ssf") { - settings.minSsf = value; - } else if (name == "sasl-max-ssf" || name == "sasl_max_ssf") { - settings.maxSsf = value; - } else if (name == "heartbeat") { - settings.heartbeat = value; - } else if (name == "tcp-nodelay" || name == "tcp_nodelay") { - settings.tcpNoDelay = value; - } else if (name == "locale") { - settings.locale = value.asString(); - } else if (name == "max-channels" || name == "max_channels") { - settings.maxChannels = value; - } else if (name == "max-frame-size" || name == "max_frame_size") { - settings.maxFrameSize = value; - } else if (name == "bounds") { - settings.bounds = value; - } else if (name == "transport") { - settings.protocol = value.asString(); - } else if (name == "ssl-cert-name" || name == "ssl_cert_name") { - settings.sslCertName = value.asString(); - } else { - throw qpid::messaging::MessagingException(QPID_MSG("Invalid option: " << name << " not recognised")); - } -} - - -void ConnectionImpl::close() -{ - while(true) { - messaging::Session session; - { - qpid::sys::Mutex::ScopedLock l(lock); - if (sessions.empty()) break; - session = sessions.begin()->second; - } - session.close(); - } - detach(); -} - -void ConnectionImpl::detach() -{ - qpid::sys::Mutex::ScopedLock l(lock); - connection.close(); -} - -bool ConnectionImpl::isOpen() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return connection.isOpen(); -} - -boost::intrusive_ptr<SessionImpl> getImplPtr(qpid::messaging::Session& session) -{ - return boost::dynamic_pointer_cast<SessionImpl>( - qpid::messaging::PrivateImplRef<qpid::messaging::Session>::get(session) - ); -} - -void ConnectionImpl::closed(SessionImpl& s) -{ - qpid::sys::Mutex::ScopedLock l(lock); - for (Sessions::iterator i = sessions.begin(); i != sessions.end(); ++i) { - if (getImplPtr(i->second).get() == &s) { - sessions.erase(i); - break; - } - } -} - -qpid::messaging::Session ConnectionImpl::getSession(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Sessions::const_iterator i = sessions.find(name); - if (i == sessions.end()) { - throw qpid::messaging::KeyError("No such session: " + name); - } else { - return i->second; - } -} - -qpid::messaging::Session ConnectionImpl::newSession(bool transactional, const std::string& n) -{ - std::string name = n.empty() ? Uuid(true).str() : n; - qpid::messaging::Session impl(new SessionImpl(*this, transactional)); - while (true) { - try { - getImplPtr(impl)->setSession(connection.newSession(name)); - qpid::sys::Mutex::ScopedLock l(lock); - sessions[name] = impl; - break; - } catch (const qpid::TransportFailure&) { - open(); - } catch (const qpid::SessionException& e) { - throw qpid::messaging::SessionError(e.what()); - } catch (const std::exception& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } - return impl; -} - -void ConnectionImpl::open() -{ - qpid::sys::AbsTime start = qpid::sys::now(); - qpid::sys::ScopedLock<qpid::sys::Semaphore> l(semaphore); - try { - if (!connection.isOpen()) connect(start); - } - catch (const types::Exception&) { throw; } - catch (const qpid::Exception& e) { throw messaging::ConnectionError(e.what()); } -} - -bool expired(const qpid::sys::AbsTime& start, int64_t timeout) -{ - if (timeout == 0) return true; - if (timeout < 0) return false; - qpid::sys::Duration used(start, qpid::sys::now()); - qpid::sys::Duration allowed = timeout * qpid::sys::TIME_SEC; - return allowed < used; -} - -void ConnectionImpl::connect(const qpid::sys::AbsTime& started) -{ - for (int64_t i = minReconnectInterval; !tryConnect(); i = std::min(i * 2, maxReconnectInterval)) { - if (!reconnect) { - throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)"); - } - if (limit >= 0 && retries++ >= limit) { - throw qpid::messaging::TransportFailure("Failed to connect within reconnect limit"); - } - if (expired(started, timeout)) { - throw qpid::messaging::TransportFailure("Failed to connect within reconnect timeout"); - } - else qpid::sys::sleep(i); - } - retries = 0; -} - -void ConnectionImpl::mergeUrls(const std::vector<Url>& more, const sys::Mutex::ScopedLock&) { - if (more.size()) { - for (size_t i = 0; i < more.size(); ++i) { - if (std::find(urls.begin(), urls.end(), more[i].str()) == urls.end()) { - urls.push_back(more[i].str()); - } - } - QPID_LOG(debug, "Added known-hosts, reconnect-urls=" << asString(urls)); - } -} - -bool ConnectionImpl::tryConnect() -{ - sys::Mutex::ScopedLock l(lock); - for (std::vector<std::string>::const_iterator i = urls.begin(); i != urls.end(); ++i) { - try { - QPID_LOG(info, "Trying to connect to " << *i << "..."); - //TODO: when url support is more complete can avoid this test here - if (i->find("amqp:") == 0) { - Url url(*i); - connection.open(url, settings); - } else { - SimpleUrlParser::parse(*i, settings); - connection.open(settings); - } - QPID_LOG(info, "Connected to " << *i); - mergeUrls(connection.getInitialBrokers(), l); - return resetSessions(l); - } catch (const qpid::ConnectionException& e) { - //TODO: need to fix timeout on - //qpid::client::Connection::open() so that it throws - //TransportFailure rather than a ConnectionException - QPID_LOG(info, "Failed to connect to " << *i << ": " << e.what()); - } - } - return false; -} - -bool ConnectionImpl::resetSessions(const sys::Mutex::ScopedLock& ) -{ - try { - qpid::sys::Mutex::ScopedLock l(lock); - for (Sessions::iterator i = sessions.begin(); i != sessions.end(); ++i) { - getImplPtr(i->second)->setSession(connection.newSession(i->first)); - } - return true; - } catch (const qpid::TransportFailure&) { - QPID_LOG(debug, "Connection failed while re-initialising sessions"); - return false; - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (reconnectOnLimitExceeded) { - QPID_LOG(debug, "Detaching and reconnecting due to: " << e.what()); - detach(); - return false; - } else { - throw qpid::messaging::TargetCapacityExceeded(e.what()); - } - } -} - -bool ConnectionImpl::backoff() -{ - if (reconnectOnLimitExceeded) { - detach(); - open(); - return true; - } else { - return false; - } -} -std::string ConnectionImpl::getAuthenticatedUsername() -{ - return connection.getNegotiatedSettings().username; -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h deleted file mode 100644 index 09f2038312..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H -#define QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/ConnectionImpl.h" -#include "qpid/types/Variant.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Semaphore.h" -#include <map> -#include <vector> - -namespace qpid { -struct Url; - -namespace client { -namespace amqp0_10 { - -class SessionImpl; - -class ConnectionImpl : public qpid::messaging::ConnectionImpl -{ - public: - ConnectionImpl(const std::string& url, const qpid::types::Variant::Map& options); - void open(); - bool isOpen() const; - void close(); - qpid::messaging::Session newSession(bool transactional, const std::string& name); - qpid::messaging::Session getSession(const std::string& name) const; - void closed(SessionImpl&); - void detach(); - void setOption(const std::string& name, const qpid::types::Variant& value); - bool backoff(); - std::string getAuthenticatedUsername(); - private: - typedef std::map<std::string, qpid::messaging::Session> Sessions; - - mutable qpid::sys::Mutex lock;//used to protect data structures - qpid::sys::Semaphore semaphore;//used to coordinate reconnection - Sessions sessions; - qpid::client::Connection connection; - std::vector<std::string> urls; - qpid::client::ConnectionSettings settings; - bool reconnect; - int64_t timeout; - int32_t limit; - int64_t minReconnectInterval; - int64_t maxReconnectInterval; - int32_t retries; - bool reconnectOnLimitExceeded; - - void setOptions(const qpid::types::Variant::Map& options); - void connect(const qpid::sys::AbsTime& started); - bool tryConnect(); - bool resetSessions(const sys::Mutex::ScopedLock&); // dummy parameter indicates call with lock held. - void mergeUrls(const std::vector<Url>& more, const sys::Mutex::ScopedLock&); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp b/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp deleted file mode 100644 index 71e89bdba1..0000000000 --- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/IncomingMessages.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/types/Variant.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/enum.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using namespace qpid::framing; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::messaging::MessageImplAccess; -using qpid::types::Variant; - -namespace { -const std::string EMPTY_STRING; - - -struct GetNone : IncomingMessages::Handler -{ - bool accept(IncomingMessages::MessageTransfer&) { return false; } -}; - -struct GetAny : IncomingMessages::Handler -{ - bool accept(IncomingMessages::MessageTransfer& transfer) - { - transfer.retrieve(0); - return true; - } -}; - -struct MatchAndTrack -{ - const std::string destination; - SequenceSet ids; - - MatchAndTrack(const std::string& d) : destination(d) {} - - bool operator()(boost::shared_ptr<qpid::framing::FrameSet> command) - { - if (command->as<MessageTransferBody>()->getDestination() == destination) { - ids.add(command->getId()); - return true; - } else { - return false; - } - } -}; - -struct Match -{ - const std::string destination; - uint32_t matched; - - Match(const std::string& d) : destination(d), matched(0) {} - - bool operator()(boost::shared_ptr<qpid::framing::FrameSet> command) - { - if (command->as<MessageTransferBody>()->getDestination() == destination) { - ++matched; - return true; - } else { - return false; - } - } -}; -} - -void IncomingMessages::setSession(qpid::client::AsyncSession s) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - incoming = SessionBase_0_10Access(session).get()->getDemux().getDefault(); - acceptTracker.reset(); -} - -bool IncomingMessages::get(Handler& handler, Duration timeout) -{ - { - sys::Mutex::ScopedLock l(lock); - //search through received list for any transfer of interest: - for (FrameSetQueue::iterator i = received.begin(); i != received.end(); i++) - { - MessageTransfer transfer(*i, *this); - if (handler.accept(transfer)) { - received.erase(i); - return true; - } - } - } - //none found, check incoming: - return process(&handler, timeout); -} - -bool IncomingMessages::getNextDestination(std::string& destination, Duration timeout) -{ - sys::Mutex::ScopedLock l(lock); - //if there is not already a received message, we must wait for one - if (received.empty() && !wait(timeout)) return false; - //else we have a message in received; return the corresponding destination - destination = received.front()->as<MessageTransferBody>()->getDestination(); - return true; -} - -void IncomingMessages::accept() -{ - sys::Mutex::ScopedLock l(lock); - acceptTracker.accept(session); -} - -void IncomingMessages::accept(qpid::framing::SequenceNumber id) -{ - sys::Mutex::ScopedLock l(lock); - acceptTracker.accept(id, session); -} - - -void IncomingMessages::releaseAll() -{ - { - //first process any received messages... - sys::Mutex::ScopedLock l(lock); - while (!received.empty()) { - retrieve(received.front(), 0); - received.pop_front(); - } - } - //then pump out any available messages from incoming queue... - GetAny handler; - while (process(&handler, 0)) ; - //now release all messages - sys::Mutex::ScopedLock l(lock); - acceptTracker.release(session); -} - -void IncomingMessages::releasePending(const std::string& destination) -{ - //first pump all available messages from incoming to received... - while (process(0, 0)) ; - - //now remove all messages for this destination from received list, recording their ids... - sys::Mutex::ScopedLock l(lock); - MatchAndTrack match(destination); - for (FrameSetQueue::iterator i = received.begin(); i != received.end(); i = match(*i) ? received.erase(i) : ++i) ; - //now release those messages - session.messageRelease(match.ids); -} - -/** - * Get a frameset that is accepted by the specified handler from - * session queue, waiting for up to the specified duration and - * returning true if this could be achieved, false otherwise. Messages - * that are not accepted by the handler are pushed onto received queue - * for later retrieval. - */ -bool IncomingMessages::process(Handler* handler, qpid::sys::Duration duration) -{ - AbsTime deadline(AbsTime::now(), duration); - FrameSet::shared_ptr content; - try { - for (Duration timeout = duration; incoming->pop(content, timeout); timeout = Duration(AbsTime::now(), deadline)) { - if (content->isA<MessageTransferBody>()) { - MessageTransfer transfer(content, *this); - if (handler && handler->accept(transfer)) { - QPID_LOG(debug, "Delivered " << *content->getMethod()); - return true; - } else { - //received message for another destination, keep for later - QPID_LOG(debug, "Pushed " << *content->getMethod() << " to received queue"); - sys::Mutex::ScopedLock l(lock); - received.push_back(content); - } - } else { - //TODO: handle other types of commands (e.g. message-accept, message-flow etc) - } - } - } - catch (const qpid::ClosedException&) {} // Just return false if queue closed. - return false; -} - -bool IncomingMessages::wait(qpid::sys::Duration duration) -{ - AbsTime deadline(AbsTime::now(), duration); - FrameSet::shared_ptr content; - for (Duration timeout = duration; incoming->pop(content, timeout); timeout = Duration(AbsTime::now(), deadline)) { - if (content->isA<MessageTransferBody>()) { - QPID_LOG(debug, "Pushed " << *content->getMethod() << " to received queue"); - sys::Mutex::ScopedLock l(lock); - received.push_back(content); - return true; - } else { - //TODO: handle other types of commands (e.g. message-accept, message-flow etc) - } - } - return false; -} - -uint32_t IncomingMessages::pendingAccept() -{ - sys::Mutex::ScopedLock l(lock); - return acceptTracker.acceptsPending(); -} -uint32_t IncomingMessages::pendingAccept(const std::string& destination) -{ - sys::Mutex::ScopedLock l(lock); - return acceptTracker.acceptsPending(destination); -} - -uint32_t IncomingMessages::available() -{ - //first pump all available messages from incoming to received... - while (process(0, 0)) {} - //return the count of received messages - sys::Mutex::ScopedLock l(lock); - return received.size(); -} - -uint32_t IncomingMessages::available(const std::string& destination) -{ - //first pump all available messages from incoming to received... - while (process(0, 0)) {} - - //count all messages for this destination from received list - sys::Mutex::ScopedLock l(lock); - return std::for_each(received.begin(), received.end(), Match(destination)).matched; -} - -void populate(qpid::messaging::Message& message, FrameSet& command); - -/** - * Called when message is retrieved; records retrieval for subsequent - * acceptance, marks the command as completed and converts command to - * message if message is required - */ -void IncomingMessages::retrieve(FrameSetPtr command, qpid::messaging::Message* message) -{ - if (message) { - populate(*message, *command); - } - const MessageTransferBody* transfer = command->as<MessageTransferBody>(); - if (transfer->getAcquireMode() == ACQUIRE_MODE_PRE_ACQUIRED && transfer->getAcceptMode() == ACCEPT_MODE_EXPLICIT) { - acceptTracker.delivered(transfer->getDestination(), command->getId()); - } - session.markCompleted(command->getId(), false, false); -} - -IncomingMessages::MessageTransfer::MessageTransfer(FrameSetPtr c, IncomingMessages& p) : content(c), parent(p) {} - -const std::string& IncomingMessages::MessageTransfer::getDestination() -{ - return content->as<MessageTransferBody>()->getDestination(); -} -void IncomingMessages::MessageTransfer::retrieve(qpid::messaging::Message* message) -{ - parent.retrieve(content, message); -} - - -namespace { -//TODO: unify conversion to and from 0-10 message that is currently -//split between IncomingMessages and OutgoingMessage -const std::string SUBJECT("qpid.subject"); - -const std::string X_APP_ID("x-amqp-0-10.app-id"); -const std::string X_ROUTING_KEY("x-amqp-0-10.routing-key"); -const std::string X_CONTENT_ENCODING("x-amqp-0-10.content-encoding"); -} - -void populateHeaders(qpid::messaging::Message& message, - const DeliveryProperties* deliveryProperties, - const MessageProperties* messageProperties) -{ - if (deliveryProperties) { - message.setTtl(qpid::messaging::Duration(deliveryProperties->getTtl())); - message.setDurable(deliveryProperties->getDeliveryMode() == DELIVERY_MODE_PERSISTENT); - message.setPriority(deliveryProperties->getPriority()); - message.setRedelivered(deliveryProperties->getRedelivered()); - } - if (messageProperties) { - message.setContentType(messageProperties->getContentType()); - if (messageProperties->hasReplyTo()) { - message.setReplyTo(AddressResolution::convert(messageProperties->getReplyTo())); - } - message.setSubject(messageProperties->getApplicationHeaders().getAsString(SUBJECT)); - message.getProperties().clear(); - translate(messageProperties->getApplicationHeaders(), message.getProperties()); - message.setCorrelationId(messageProperties->getCorrelationId()); - message.setUserId(messageProperties->getUserId()); - if (messageProperties->hasMessageId()) { - message.setMessageId(messageProperties->getMessageId().str()); - } - //expose 0-10 specific items through special properties: - // app-id, content-encoding - if (messageProperties->hasAppId()) { - message.getProperties()[X_APP_ID] = messageProperties->getAppId(); - } - if (messageProperties->hasContentEncoding()) { - message.getProperties()[X_CONTENT_ENCODING] = messageProperties->getContentEncoding(); - } - // routing-key, others? - if (deliveryProperties && deliveryProperties->hasRoutingKey()) { - message.getProperties()[X_ROUTING_KEY] = deliveryProperties->getRoutingKey(); - } - } -} - -void populateHeaders(qpid::messaging::Message& message, const AMQHeaderBody* headers) -{ - populateHeaders(message, headers->get<DeliveryProperties>(), headers->get<MessageProperties>()); -} - -void populate(qpid::messaging::Message& message, FrameSet& command) -{ - //need to be able to link the message back to the transfer it was delivered by - //e.g. for rejecting. - MessageImplAccess::get(message).setInternalId(command.getId()); - - message.setContent(command.getContent()); - - populateHeaders(message, command.getHeaders()); -} - - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h b/cpp/src/qpid/client/amqp0_10/IncomingMessages.h deleted file mode 100644 index f6a291bc68..0000000000 --- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H -#define QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include <boost/shared_ptr.hpp> -#include "qpid/client/AsyncSession.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/sys/Time.h" -#include "qpid/client/amqp0_10/AcceptTracker.h" - -namespace qpid { - -namespace framing{ -class FrameSet; -} - -namespace messaging { -class Message; -} - -namespace client { -namespace amqp0_10 { - -/** - * Queue of incoming messages. - */ -class IncomingMessages -{ - public: - typedef boost::shared_ptr<qpid::framing::FrameSet> FrameSetPtr; - class MessageTransfer - { - public: - const std::string& getDestination(); - void retrieve(qpid::messaging::Message* message); - private: - FrameSetPtr content; - IncomingMessages& parent; - - MessageTransfer(FrameSetPtr, IncomingMessages&); - friend class IncomingMessages; - }; - - struct Handler - { - virtual ~Handler() {} - virtual bool accept(MessageTransfer& transfer) = 0; - }; - - void setSession(qpid::client::AsyncSession session); - bool get(Handler& handler, qpid::sys::Duration timeout); - bool getNextDestination(std::string& destination, qpid::sys::Duration timeout); - void accept(); - void accept(qpid::framing::SequenceNumber id); - void releaseAll(); - void releasePending(const std::string& destination); - - uint32_t pendingAccept(); - uint32_t pendingAccept(const std::string& destination); - - uint32_t available(); - uint32_t available(const std::string& destination); - private: - typedef std::deque<FrameSetPtr> FrameSetQueue; - - sys::Mutex lock; - qpid::client::AsyncSession session; - boost::shared_ptr< sys::BlockingQueue<FrameSetPtr> > incoming; - FrameSetQueue received; - AcceptTracker acceptTracker; - - bool process(Handler*, qpid::sys::Duration); - bool wait(qpid::sys::Duration); - void retrieve(FrameSetPtr, qpid::messaging::Message*); - -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/MessageSink.h b/cpp/src/qpid/client/amqp0_10/MessageSink.h deleted file mode 100644 index 8d87a3c7bb..0000000000 --- a/cpp/src/qpid/client/amqp0_10/MessageSink.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_MESSAGESINK_H -#define QPID_CLIENT_AMQP0_10_MESSAGESINK_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/client/AsyncSession.h" - -namespace qpid { - -namespace messaging { -class Message; -} - -namespace client { -namespace amqp0_10 { - -struct OutgoingMessage; - -/** - * - */ -class MessageSink -{ - public: - virtual ~MessageSink() {} - virtual void declare(qpid::client::AsyncSession& session, const std::string& name) = 0; - virtual void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message) = 0; - virtual void cancel(qpid::client::AsyncSession& session, const std::string& name) = 0; - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_MESSAGESINK_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/MessageSource.h b/cpp/src/qpid/client/amqp0_10/MessageSource.h deleted file mode 100644 index 74f2732f59..0000000000 --- a/cpp/src/qpid/client/amqp0_10/MessageSource.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H -#define QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/client/AsyncSession.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -/** - * Abstraction behind which the AMQP 0-10 commands required to - * establish (and tear down) an incoming stream of messages from a - * given address are hidden. - */ -class MessageSource -{ - public: - virtual ~MessageSource() {} - virtual void subscribe(qpid::client::AsyncSession& session, const std::string& destination) = 0; - virtual void cancel(qpid::client::AsyncSession& session, const std::string& destination) = 0; - - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp deleted file mode 100644 index d93416da75..0000000000 --- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/OutgoingMessage.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/types/Variant.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/framing/enum.h" -#include <sstream> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::messaging::Address; -using qpid::messaging::MessageImplAccess; -using qpid::types::Variant; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; - -namespace { -//TODO: unify conversion to and from 0-10 message that is currently -//split between IncomingMessages and OutgoingMessage -const std::string SUBJECT("qpid.subject"); -const std::string X_APP_ID("x-amqp-0-10.app-id"); -const std::string X_ROUTING_KEY("x-amqp-0-10.routing-key"); -const std::string X_CONTENT_ENCODING("x-amqp-0-10.content-encoding"); -} - -void OutgoingMessage::convert(const qpid::messaging::Message& from) -{ - //TODO: need to avoid copying as much as possible - message.setData(from.getContent()); - message.getMessageProperties().setContentType(from.getContentType()); - message.getMessageProperties().setCorrelationId(from.getCorrelationId()); - message.getMessageProperties().setUserId(from.getUserId()); - const Address& address = from.getReplyTo(); - if (address) { - message.getMessageProperties().setReplyTo(AddressResolution::convert(address)); - } - translate(from.getProperties(), message.getMessageProperties().getApplicationHeaders()); - if (from.getTtl().getMilliseconds()) { - message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds()); - } - if (from.getDurable()) { - message.getDeliveryProperties().setDeliveryMode(DELIVERY_MODE_PERSISTENT); - } - if (from.getRedelivered()) { - message.getDeliveryProperties().setRedelivered(true); - } - if (from.getPriority()) message.getDeliveryProperties().setPriority(from.getPriority()); - - //allow certain 0-10 specific items to be set through special properties: - // message-id, app-id, content-encoding - if (from.getMessageId().size()) { - qpid::framing::Uuid uuid; - std::istringstream data(from.getMessageId()); - data >> uuid; - message.getMessageProperties().setMessageId(uuid); - } - Variant::Map::const_iterator i; - i = from.getProperties().find(X_APP_ID); - if (i != from.getProperties().end()) { - message.getMessageProperties().setAppId(i->second.asString()); - } - i = from.getProperties().find(X_CONTENT_ENCODING); - if (i != from.getProperties().end()) { - message.getMessageProperties().setContentEncoding(i->second.asString()); - } -} - -void OutgoingMessage::setSubject(const std::string& subject) -{ - if (!subject.empty()) { - message.getMessageProperties().getApplicationHeaders().setString(SUBJECT, subject); - } -} - -std::string OutgoingMessage::getSubject() const -{ - return message.getMessageProperties().getApplicationHeaders().getAsString(SUBJECT); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h deleted file mode 100644 index 0cdd2a2336..0000000000 --- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H -#define QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Completion.h" -#include "qpid/client/Message.h" - -namespace qpid { -namespace messaging { -class Message; -} -namespace client { -namespace amqp0_10 { - -struct OutgoingMessage -{ - qpid::client::Message message; - qpid::client::Completion status; - - void convert(const qpid::messaging::Message&); - void setSubject(const std::string& subject); - std::string getSubject() const; -}; - - - -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp b/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp deleted file mode 100644 index 030b804143..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "ReceiverImpl.h" -#include "AddressResolution.h" -#include "MessageSource.h" -#include "SessionImpl.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::messaging::NoMessageAvailable; -using qpid::messaging::Receiver; -using qpid::messaging::Duration; - -void ReceiverImpl::received(qpid::messaging::Message&) -{ - //TODO: should this be configurable - sys::Mutex::ScopedLock l(lock); - if (capacity && --window <= capacity/2) { - session.sendCompletion(); - window = capacity; - } -} - -qpid::messaging::Message ReceiverImpl::get(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!get(result, timeout)) throw NoMessageAvailable(); - return result; -} - -qpid::messaging::Message ReceiverImpl::fetch(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!fetch(result, timeout)) throw NoMessageAvailable(); - return result; -} - -bool ReceiverImpl::get(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - Get f(*this, message, timeout); - while (!parent->execute(f)) {} - return f.result; -} - -bool ReceiverImpl::fetch(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - Fetch f(*this, message, timeout); - while (!parent->execute(f)) {} - return f.result; -} - -void ReceiverImpl::close() -{ - execute<Close>(); -} - -void ReceiverImpl::start() -{ - sys::Mutex::ScopedLock l(lock); - if (state == STOPPED) { - state = STARTED; - startFlow(l); - } -} - -void ReceiverImpl::stop() -{ - sys::Mutex::ScopedLock l(lock); - state = STOPPED; - session.messageStop(destination); -} - -void ReceiverImpl::setCapacity(uint32_t c) -{ - execute1<SetCapacity>(c); -} - -void ReceiverImpl::startFlow(const sys::Mutex::ScopedLock&) -{ - if (capacity > 0) { - session.messageSetFlowMode(destination, FLOW_MODE_WINDOW); - session.messageFlow(destination, CREDIT_UNIT_MESSAGE, capacity); - session.messageFlow(destination, CREDIT_UNIT_BYTE, byteCredit); - window = capacity; - } -} - -void ReceiverImpl::init(qpid::client::AsyncSession s, AddressResolution& resolver) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - if (state == CANCELLED) return; - if (state == UNRESOLVED) { - source = resolver.resolveSource(session, address); - assert(source.get()); - state = STARTED; - } - source->subscribe(session, destination); - startFlow(l); -} - -const std::string& ReceiverImpl::getName() const { - sys::Mutex::ScopedLock l(lock); - return destination; -} - -uint32_t ReceiverImpl::getCapacity() -{ - sys::Mutex::ScopedLock l(lock); - return capacity; -} - -uint32_t ReceiverImpl::getAvailable() -{ - return parent->getReceivable(destination); -} - -uint32_t ReceiverImpl::getUnsettled() -{ - return parent->getUnsettledAcks(destination); -} - -ReceiverImpl::ReceiverImpl(SessionImpl& p, const std::string& name, - const qpid::messaging::Address& a) : - - parent(&p), destination(name), address(a), byteCredit(0xFFFFFFFF), - state(UNRESOLVED), capacity(0), window(0) {} - -bool ReceiverImpl::getImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; - } - return parent->get(*this, message, timeout); -} - -bool ReceiverImpl::fetchImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; - - if (capacity == 0 || state != STARTED) { - session.messageSetFlowMode(destination, FLOW_MODE_CREDIT); - session.messageFlow(destination, CREDIT_UNIT_MESSAGE, 1); - session.messageFlow(destination, CREDIT_UNIT_BYTE, 0xFFFFFFFF); - } - } - if (getImpl(message, timeout)) { - return true; - } else { - qpid::client::Session s; - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; // Might have been closed during get. - s = sync(session); - } - s.messageFlush(destination); - { - sys::Mutex::ScopedLock l(lock); - startFlow(l); //reallocate credit - } - return getImpl(message, Duration::IMMEDIATE); - } -} - -void ReceiverImpl::closeImpl() -{ - sys::Mutex::ScopedLock l(lock); - if (state != CANCELLED) { - state = CANCELLED; - sync(session).messageStop(destination); - parent->releasePending(destination); - source->cancel(session, destination); - parent->receiverCancelled(destination); - } -} - -bool ReceiverImpl::isClosed() const { - sys::Mutex::ScopedLock l(lock); - return state == CANCELLED; -} - -void ReceiverImpl::setCapacityImpl(uint32_t c) -{ - sys::Mutex::ScopedLock l(lock); - if (c != capacity) { - capacity = c; - if (state == STARTED) { - session.messageStop(destination); - startFlow(l); - } - } -} - -qpid::messaging::Session ReceiverImpl::getSession() const -{ - return qpid::messaging::Session(parent.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h b/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h deleted file mode 100644 index 5693b7b71f..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H -#define QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/ReceiverImpl.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/amqp0_10/SessionImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/sys/Mutex.h" -#include <boost/intrusive_ptr.hpp> -#include <memory> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -class AddressResolution; -class MessageSource; - -/** - * A receiver implementation based on an AMQP 0-10 subscription. - */ -class ReceiverImpl : public qpid::messaging::ReceiverImpl -{ - public: - - enum State {UNRESOLVED, STOPPED, STARTED, CANCELLED}; - - ReceiverImpl(SessionImpl& parent, const std::string& name, - const qpid::messaging::Address& address); - - void init(qpid::client::AsyncSession session, AddressResolution& resolver); - bool get(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - qpid::messaging::Message get(qpid::messaging::Duration timeout); - bool fetch(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - qpid::messaging::Message fetch(qpid::messaging::Duration timeout); - void close(); - void start(); - void stop(); - const std::string& getName() const; - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getAvailable(); - uint32_t getUnsettled(); - void received(qpid::messaging::Message& message); - qpid::messaging::Session getSession() const; - bool isClosed() const; - - private: - mutable sys::Mutex lock; - boost::intrusive_ptr<SessionImpl> parent; - const std::string destination; - const qpid::messaging::Address address; - const uint32_t byteCredit; - State state; - - std::auto_ptr<MessageSource> source; - uint32_t capacity; - qpid::client::AsyncSession session; - qpid::messaging::MessageListener* listener; - uint32_t window; - - void startFlow(const sys::Mutex::ScopedLock&); // Dummy param, call with lock held - //implementation of public facing methods - bool fetchImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - bool getImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - void closeImpl(); - void setCapacityImpl(uint32_t); - - //functors for public facing methods. - struct Command - { - ReceiverImpl& impl; - - Command(ReceiverImpl& i) : impl(i) {} - }; - - struct Get : Command - { - qpid::messaging::Message& message; - qpid::messaging::Duration timeout; - bool result; - - Get(ReceiverImpl& i, qpid::messaging::Message& m, qpid::messaging::Duration t) : - Command(i), message(m), timeout(t), result(false) {} - void operator()() { result = impl.getImpl(message, timeout); } - }; - - struct Fetch : Command - { - qpid::messaging::Message& message; - qpid::messaging::Duration timeout; - bool result; - - Fetch(ReceiverImpl& i, qpid::messaging::Message& m, qpid::messaging::Duration t) : - Command(i), message(m), timeout(t), result(false) {} - void operator()() { result = impl.fetchImpl(message, timeout); } - }; - - struct Close : Command - { - Close(ReceiverImpl& i) : Command(i) {} - void operator()() { impl.closeImpl(); } - }; - - struct SetCapacity : Command - { - uint32_t capacity; - - SetCapacity(ReceiverImpl& i, uint32_t c) : Command(i), capacity(c) {} - void operator()() { impl.setCapacityImpl(capacity); } - }; - - //helper templates for some common patterns - template <class F> void execute() - { - F f(*this); - parent->execute(f); - } - - template <class F, class P> void execute1(P p) - { - F f(*this, p); - parent->execute(f); - } -}; - -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp deleted file mode 100644 index f2f0f1a9e5..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "SenderImpl.h" -#include "MessageSink.h" -#include "SessionImpl.h" -#include "AddressResolution.h" -#include "OutgoingMessage.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -SenderImpl::SenderImpl(SessionImpl& _parent, const std::string& _name, - const qpid::messaging::Address& _address) : - parent(&_parent), name(_name), address(_address), state(UNRESOLVED), - capacity(50), window(0), flushed(false), unreliable(AddressResolution::is_unreliable(address)) {} - -void SenderImpl::send(const qpid::messaging::Message& message, bool sync) -{ - if (unreliable) { // immutable, don't need lock - UnreliableSend f(*this, &message); - parent->execute(f); - } else { - Send f(*this, &message); - while (f.repeat) parent->execute(f); - } - if (sync) parent->sync(true); -} - -void SenderImpl::close() -{ - execute<Close>(); -} - -void SenderImpl::setCapacity(uint32_t c) -{ - bool flush; - { - sys::Mutex::ScopedLock l(lock); - flush = c < capacity; - capacity = c; - } - execute1<CheckPendingSends>(flush); -} - -uint32_t SenderImpl::getCapacity() { - sys::Mutex::ScopedLock l(lock); - return capacity; -} - -uint32_t SenderImpl::getUnsettled() -{ - CheckPendingSends f(*this, false); - parent->execute(f); - return f.pending; -} - -void SenderImpl::init(qpid::client::AsyncSession s, AddressResolution& resolver) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - if (state == UNRESOLVED) { - sink = resolver.resolveSink(session, address); - state = ACTIVE; - } - if (state == CANCELLED) { - sink->cancel(session, name); - sys::Mutex::ScopedUnlock u(lock); - parent->senderCancelled(name); - } else { - sink->declare(session, name); - replay(l); - } -} - -void SenderImpl::waitForCapacity() -{ - sys::Mutex::ScopedLock l(lock); - //TODO: add option to throw exception rather than blocking? - if (!unreliable && capacity <= - (flushed ? checkPendingSends(false, l) : outgoing.size())) - { - //Initial implementation is very basic. As outgoing is - //currently only reduced on receiving completions and we are - //blocking anyway we may as well sync(). If successful that - //should clear all outstanding sends. - session.sync(); - checkPendingSends(false, l); - } - //flush periodically and check for conmpleted sends - if (++window > (capacity / 4)) {//TODO: make this configurable? - checkPendingSends(true, l); - window = 0; - } -} - -void SenderImpl::sendImpl(const qpid::messaging::Message& m) -{ - sys::Mutex::ScopedLock l(lock); - std::auto_ptr<OutgoingMessage> msg(new OutgoingMessage()); - msg->convert(m); - msg->setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject()); - outgoing.push_back(msg.release()); - sink->send(session, name, outgoing.back()); -} - -void SenderImpl::sendUnreliable(const qpid::messaging::Message& m) -{ - sys::Mutex::ScopedLock l(lock); - OutgoingMessage msg; - msg.convert(m); - msg.setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject()); - sink->send(session, name, msg); -} - -void SenderImpl::replay(const sys::Mutex::ScopedLock&) -{ - for (OutgoingMessages::iterator i = outgoing.begin(); i != outgoing.end(); ++i) { - i->message.setRedelivered(true); - sink->send(session, name, *i); - } -} - -uint32_t SenderImpl::checkPendingSends(bool flush) { - sys::Mutex::ScopedLock l(lock); - return checkPendingSends(flush, l); -} - -uint32_t SenderImpl::checkPendingSends(bool flush, const sys::Mutex::ScopedLock&) -{ - if (flush) { - session.flush(); - flushed = true; - } else { - flushed = false; - } - while (!outgoing.empty() && outgoing.front().status.isComplete()) { - outgoing.pop_front(); - } - return outgoing.size(); -} - -void SenderImpl::closeImpl() -{ - sys::Mutex::ScopedLock l(lock); - state = CANCELLED; - sink->cancel(session, name); - parent->senderCancelled(name); -} - -const std::string& SenderImpl::getName() const -{ - sys::Mutex::ScopedLock l(lock); - return name; -} - -qpid::messaging::Session SenderImpl::getSession() const -{ - sys::Mutex::ScopedLock l(lock); - return qpid::messaging::Session(parent.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.h b/cpp/src/qpid/client/amqp0_10/SenderImpl.h deleted file mode 100644 index c10c77ae18..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SenderImpl.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SENDERIMPL_H -#define QPID_CLIENT_AMQP0_10_SENDERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/SenderImpl.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/amqp0_10/SessionImpl.h" -#include <memory> -#include <boost/intrusive_ptr.hpp> -#include <boost/ptr_container/ptr_deque.hpp> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -class AddressResolution; -class MessageSink; -struct OutgoingMessage; - -/** - * - */ -class SenderImpl : public qpid::messaging::SenderImpl -{ - public: - enum State {UNRESOLVED, ACTIVE, CANCELLED}; - - SenderImpl(SessionImpl& parent, const std::string& name, - const qpid::messaging::Address& address); - void send(const qpid::messaging::Message&, bool sync); - void close(); - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getUnsettled(); - void init(qpid::client::AsyncSession, AddressResolution&); - const std::string& getName() const; - qpid::messaging::Session getSession() const; - - private: - mutable sys::Mutex lock; - boost::intrusive_ptr<SessionImpl> parent; - const std::string name; - const qpid::messaging::Address address; - State state; - std::auto_ptr<MessageSink> sink; - - qpid::client::AsyncSession session; - std::string destination; - std::string routingKey; - - typedef boost::ptr_deque<OutgoingMessage> OutgoingMessages; - OutgoingMessages outgoing; - uint32_t capacity; - uint32_t window; - bool flushed; - const bool unreliable; - - uint32_t checkPendingSends(bool flush); - // Dummy ScopedLock parameter means call with lock held - uint32_t checkPendingSends(bool flush, const sys::Mutex::ScopedLock&); - void replay(const sys::Mutex::ScopedLock&); - void waitForCapacity(); - - //logic for application visible methods: - void sendImpl(const qpid::messaging::Message&); - void sendUnreliable(const qpid::messaging::Message&); - void closeImpl(); - - - //functors for application visible methods (allowing locking and - //retry to be centralised): - struct Command - { - SenderImpl& impl; - - Command(SenderImpl& i) : impl(i) {} - }; - - struct Send : Command - { - const qpid::messaging::Message* message; - bool repeat; - - Send(SenderImpl& i, const qpid::messaging::Message* m) : Command(i), message(m), repeat(true) {} - void operator()() - { - impl.waitForCapacity(); - //from this point message will be recorded if there is any - //failure (and replayed) so need not repeat the call - repeat = false; - impl.sendImpl(*message); - } - }; - - struct UnreliableSend : Command - { - const qpid::messaging::Message* message; - - UnreliableSend(SenderImpl& i, const qpid::messaging::Message* m) : Command(i), message(m) {} - void operator()() - { - //TODO: ideally want to put messages on the outbound - //queue and pull them off in io thread, but the old - //0-10 client doesn't support that option so for now - //we simply don't queue unreliable messages - impl.sendUnreliable(*message); - } - }; - - struct Close : Command - { - Close(SenderImpl& i) : Command(i) {} - void operator()() { impl.closeImpl(); } - }; - - struct CheckPendingSends : Command - { - bool flush; - uint32_t pending; - CheckPendingSends(SenderImpl& i, bool f) : Command(i), flush(f), pending(0) {} - void operator()() { pending = impl.checkPendingSends(flush); } - }; - - //helper templates for some common patterns - template <class F> void execute() - { - F f(*this); - parent->execute(f); - } - - template <class F, class P> bool execute1(P p) - { - F f(*this, p); - return parent->execute(f); - } -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SENDERIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp b/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp deleted file mode 100644 index 75a71997fd..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/SessionImpl.h" -#include "qpid/client/amqp0_10/ConnectionImpl.h" -#include "qpid/client/amqp0_10/ReceiverImpl.h" -#include "qpid/client/amqp0_10/SenderImpl.h" -#include "qpid/client/amqp0_10/MessageSource.h" -#include "qpid/client/amqp0_10/MessageSink.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Session.h" -#include <boost/format.hpp> -#include <boost/function.hpp> -#include <boost/intrusive_ptr.hpp> - -using qpid::messaging::KeyError; -using qpid::messaging::NoMessageAvailable; -using qpid::messaging::MessagingException; -using qpid::messaging::TransactionAborted; -using qpid::messaging::SessionError; -using qpid::messaging::MessageImplAccess; -using qpid::messaging::Sender; -using qpid::messaging::Receiver; - -namespace qpid { -namespace client { -namespace amqp0_10 { - -typedef qpid::sys::Mutex::ScopedLock ScopedLock; -typedef qpid::sys::Mutex::ScopedUnlock ScopedUnlock; - -SessionImpl::SessionImpl(ConnectionImpl& c, bool t) : connection(&c), transactional(t) {} - -void SessionImpl::checkError() -{ - qpid::client::SessionBase_0_10Access s(session); - s.get()->assertOpen(); -} - -bool SessionImpl::hasError() -{ - qpid::client::SessionBase_0_10Access s(session); - return s.get()->hasError(); -} - -void SessionImpl::sync(bool block) -{ - if (block) retry<Sync>(); - else execute<NonBlockingSync>(); -} - -void SessionImpl::commit() -{ - if (!execute<Commit>()) { - throw TransactionAborted("Transaction aborted due to transport failure"); - } -} - -void SessionImpl::rollback() -{ - //If the session fails during this operation, the transaction will - //be rolled back anyway. - execute<Rollback>(); -} - -void SessionImpl::acknowledge(bool sync_) -{ - //Should probably throw an exception on failure here, or indicate - //it through a return type at least. Failure means that the - //message may be redelivered; i.e. the application cannot delete - //any state necessary for preventing reprocessing of the message - execute<Acknowledge>(); - sync(sync_); -} - -void SessionImpl::reject(qpid::messaging::Message& m) -{ - //Possibly want to somehow indicate failure here as well. Less - //clear need as compared to acknowledge however. - execute1<Reject>(m); -} - -void SessionImpl::release(qpid::messaging::Message& m) -{ - execute1<Release>(m); -} - -void SessionImpl::acknowledge(qpid::messaging::Message& m) -{ - //Should probably throw an exception on failure here, or indicate - //it through a return type at least. Failure means that the - //message may be redelivered; i.e. the application cannot delete - //any state necessary for preventing reprocessing of the message - execute1<Acknowledge1>(m); -} - -void SessionImpl::close() -{ - if (hasError()) { - ScopedLock l(lock); - senders.clear(); - receivers.clear(); - } else { - while (true) { - Sender s; - { - ScopedLock l(lock); - if (senders.empty()) break; - s = senders.begin()->second; - } - s.close(); // outside the lock, will call senderCancelled - } - while (true) { - Receiver r; - { - ScopedLock l(lock); - if (receivers.empty()) break; - r = receivers.begin()->second; - } - r.close(); // outside the lock, will call receiverCancelled - } - } - connection->closed(*this); - if (!hasError()) session.close(); -} - -template <class T, class S> boost::intrusive_ptr<S> getImplPtr(T& t) -{ - return boost::dynamic_pointer_cast<S>(qpid::messaging::PrivateImplRef<T>::get(t)); -} - -template <class T> void getFreeKey(std::string& key, T& map) -{ - std::string name = key; - int count = 1; - for (typename T::const_iterator i = map.find(name); i != map.end(); i = map.find(name)) { - name = (boost::format("%1%_%2%") % key % ++count).str(); - } - key = name; -} - - -void SessionImpl::setSession(qpid::client::Session s) -{ - ScopedLock l(lock); - session = s; - incoming.setSession(session); - if (transactional) session.txSelect(); - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr<Receiver, ReceiverImpl>(i->second)->init(session, resolver); - } - for (Senders::iterator i = senders.begin(); i != senders.end(); ++i) { - getImplPtr<Sender, SenderImpl>(i->second)->init(session, resolver); - } - session.sync(); -} - -struct SessionImpl::CreateReceiver : Command -{ - qpid::messaging::Receiver result; - const qpid::messaging::Address& address; - - CreateReceiver(SessionImpl& i, const qpid::messaging::Address& a) : - Command(i), address(a) {} - void operator()() { result = impl.createReceiverImpl(address); } -}; - -Receiver SessionImpl::createReceiver(const qpid::messaging::Address& address) -{ - return get1<CreateReceiver, Receiver>(address); -} - -Receiver SessionImpl::createReceiverImpl(const qpid::messaging::Address& address) -{ - ScopedLock l(lock); - std::string name = address.getName(); - getFreeKey(name, receivers); - Receiver receiver(new ReceiverImpl(*this, name, address)); - getImplPtr<Receiver, ReceiverImpl>(receiver)->init(session, resolver); - receivers[name] = receiver; - return receiver; -} - -struct SessionImpl::CreateSender : Command -{ - qpid::messaging::Sender result; - const qpid::messaging::Address& address; - - CreateSender(SessionImpl& i, const qpid::messaging::Address& a) : - Command(i), address(a) {} - void operator()() { result = impl.createSenderImpl(address); } -}; - -Sender SessionImpl::createSender(const qpid::messaging::Address& address) -{ - return get1<CreateSender, Sender>(address); -} - -Sender SessionImpl::createSenderImpl(const qpid::messaging::Address& address) -{ - ScopedLock l(lock); - std::string name = address.getName(); - getFreeKey(name, senders); - Sender sender(new SenderImpl(*this, name, address)); - getImplPtr<Sender, SenderImpl>(sender)->init(session, resolver); - senders[name] = sender; - return sender; -} - -Sender SessionImpl::getSender(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Senders::const_iterator i = senders.find(name); - if (i == senders.end()) { - throw KeyError(name); - } else { - return i->second; - } -} - -Receiver SessionImpl::getReceiver(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(name); - if (i == receivers.end()) { - throw KeyError(name); - } else { - return i->second; - } -} - -SessionImpl& SessionImpl::convert(qpid::messaging::Session& s) -{ - boost::intrusive_ptr<SessionImpl> impl = getImplPtr<qpid::messaging::Session, SessionImpl>(s); - if (!impl) { - throw SessionError(QPID_MSG("Configuration error; require qpid::client::amqp0_10::SessionImpl")); - } - return *impl; -} - -namespace { - -struct IncomingMessageHandler : IncomingMessages::Handler -{ - typedef boost::function1<bool, IncomingMessages::MessageTransfer&> Callback; - Callback callback; - - IncomingMessageHandler(Callback c) : callback(c) {} - - bool accept(IncomingMessages::MessageTransfer& transfer) - { - return callback(transfer); - } -}; - -} - - -bool SessionImpl::getNextReceiver(Receiver* receiver, IncomingMessages::MessageTransfer& transfer) -{ - ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(transfer.getDestination()); - if (i == receivers.end()) { - QPID_LOG(error, "Received message for unknown destination " << transfer.getDestination()); - return false; - } else { - *receiver = i->second; - return true; - } -} - -bool SessionImpl::accept(ReceiverImpl* receiver, - qpid::messaging::Message* message, - IncomingMessages::MessageTransfer& transfer) -{ - if (receiver->getName() == transfer.getDestination()) { - transfer.retrieve(message); - receiver->received(*message); - return true; - } else { - return false; - } -} - -qpid::sys::Duration adjust(qpid::messaging::Duration timeout) -{ - uint64_t ms = timeout.getMilliseconds(); - if (ms < (uint64_t) (qpid::sys::TIME_INFINITE/qpid::sys::TIME_MSEC)) { - return ms * qpid::sys::TIME_MSEC; - } else { - return qpid::sys::TIME_INFINITE; - } -} - -bool SessionImpl::getIncoming(IncomingMessages::Handler& handler, qpid::messaging::Duration timeout) -{ - return incoming.get(handler, adjust(timeout)); -} - -bool SessionImpl::get(ReceiverImpl& receiver, qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - IncomingMessageHandler handler(boost::bind(&SessionImpl::accept, this, &receiver, &message, _1)); - return getIncoming(handler, timeout); -} - -bool SessionImpl::nextReceiver(qpid::messaging::Receiver& receiver, qpid::messaging::Duration timeout) -{ - while (true) { - try { - std::string destination; - if (incoming.getNextDestination(destination, adjust(timeout))) { - qpid::sys::Mutex::ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(destination); - if (i == receivers.end()) { - throw qpid::messaging::ReceiverError(QPID_MSG("Received message for unknown destination " << destination)); - } else { - receiver = i->second; - } - return true; - } else { - return false; - } - } catch (TransportFailure&) { - reconnect(); - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (backoff()) return false; - else throw qpid::messaging::TargetCapacityExceeded(e.what()); - } catch (const qpid::framing::UnauthorizedAccessException& e) { - throw qpid::messaging::UnauthorizedAccess(e.what()); - } catch (const qpid::SessionException& e) { - throw qpid::messaging::SessionError(e.what()); - } catch (const qpid::ConnectionException& e) { - throw qpid::messaging::ConnectionError(e.what()); - } catch (const qpid::ChannelException& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } -} - -qpid::messaging::Receiver SessionImpl::nextReceiver(qpid::messaging::Duration timeout) -{ - qpid::messaging::Receiver receiver; - if (!nextReceiver(receiver, timeout)) throw NoMessageAvailable(); - if (!receiver) throw SessionError("Bad receiver returned!"); - return receiver; -} - -uint32_t SessionImpl::getReceivable() -{ - return get1<Receivable, uint32_t>((const std::string*) 0); -} -uint32_t SessionImpl::getReceivable(const std::string& destination) -{ - return get1<Receivable, uint32_t>(&destination); -} - -struct SessionImpl::Receivable : Command -{ - const std::string* destination; - uint32_t result; - - Receivable(SessionImpl& i, const std::string* d) : Command(i), destination(d), result(0) {} - void operator()() { result = impl.getReceivableImpl(destination); } -}; - -uint32_t SessionImpl::getReceivableImpl(const std::string* destination) -{ - ScopedLock l(lock); - if (destination) { - return incoming.available(*destination); - } else { - return incoming.available(); - } -} - -uint32_t SessionImpl::getUnsettledAcks() -{ - return get1<UnsettledAcks, uint32_t>((const std::string*) 0); -} - -uint32_t SessionImpl::getUnsettledAcks(const std::string& destination) -{ - return get1<UnsettledAcks, uint32_t>(&destination); -} - -struct SessionImpl::UnsettledAcks : Command -{ - const std::string* destination; - uint32_t result; - - UnsettledAcks(SessionImpl& i, const std::string* d) : Command(i), destination(d), result(0) {} - void operator()() { result = impl.getUnsettledAcksImpl(destination); } -}; - -uint32_t SessionImpl::getUnsettledAcksImpl(const std::string* destination) -{ - ScopedLock l(lock); - if (destination) { - return incoming.pendingAccept(*destination); - } else { - return incoming.pendingAccept(); - } -} - -void SessionImpl::syncImpl(bool block) -{ - if (block) session.sync(); - else session.flush(); - //cleanup unconfirmed accept records: - incoming.pendingAccept(); -} - -void SessionImpl::commitImpl() -{ - ScopedLock l(lock); - incoming.accept(); - session.txCommit(); -} - -void SessionImpl::rollbackImpl() -{ - ScopedLock l(lock); - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr<Receiver, ReceiverImpl>(i->second)->stop(); - } - //ensure that stop has been processed and all previously sent - //messages are available for release: - session.sync(); - incoming.releaseAll(); - session.txRollback(); - - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr<Receiver, ReceiverImpl>(i->second)->start(); - } -} - -void SessionImpl::acknowledgeImpl() -{ - ScopedLock l(lock); - if (!transactional) incoming.accept(); -} - -void SessionImpl::acknowledgeImpl(qpid::messaging::Message& m) -{ - ScopedLock l(lock); - if (!transactional) incoming.accept(MessageImplAccess::get(m).getInternalId()); -} - -void SessionImpl::rejectImpl(qpid::messaging::Message& m) -{ - SequenceSet set; - set.add(MessageImplAccess::get(m).getInternalId()); - session.messageReject(set); -} - -void SessionImpl::releaseImpl(qpid::messaging::Message& m) -{ - SequenceSet set; - set.add(MessageImplAccess::get(m).getInternalId()); - session.messageRelease(set); -} - -void SessionImpl::receiverCancelled(const std::string& name) -{ - ScopedLock l(lock); - receivers.erase(name); - session.sync(); - incoming.releasePending(name); -} - -void SessionImpl::releasePending(const std::string& name) -{ - ScopedLock l(lock); - incoming.releasePending(name); -} - -void SessionImpl::senderCancelled(const std::string& name) -{ - ScopedLock l(lock); - senders.erase(name); -} - -void SessionImpl::reconnect() -{ - connection->open(); -} - -bool SessionImpl::backoff() -{ - return connection->backoff(); -} - -qpid::messaging::Connection SessionImpl::getConnection() const -{ - return qpid::messaging::Connection(connection.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.h b/cpp/src/qpid/client/amqp0_10/SessionImpl.h deleted file mode 100644 index 2a2aa47df6..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SessionImpl.h +++ /dev/null @@ -1,247 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SESSIONIMPL_H -#define QPID_CLIENT_AMQP0_10_SESSIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/SessionImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/client/amqp0_10/IncomingMessages.h" -#include "qpid/sys/Mutex.h" -#include "qpid/framing/reply_exceptions.h" -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - -namespace messaging { -class Address; -class Connection; -class Message; -class Receiver; -class Sender; -class Session; -} - -namespace client { -namespace amqp0_10 { - -class ConnectionImpl; -class ReceiverImpl; -class SenderImpl; - -/** - * Implementation of the protocol independent Session interface using - * AMQP 0-10. - */ -class SessionImpl : public qpid::messaging::SessionImpl -{ - public: - SessionImpl(ConnectionImpl&, bool transactional); - void commit(); - void rollback(); - void acknowledge(bool sync); - void reject(qpid::messaging::Message&); - void release(qpid::messaging::Message&); - void acknowledge(qpid::messaging::Message& msg); - void close(); - void sync(bool block); - qpid::messaging::Sender createSender(const qpid::messaging::Address& address); - qpid::messaging::Receiver createReceiver(const qpid::messaging::Address& address); - - qpid::messaging::Sender getSender(const std::string& name) const; - qpid::messaging::Receiver getReceiver(const std::string& name) const; - - bool nextReceiver(qpid::messaging::Receiver& receiver, qpid::messaging::Duration timeout); - qpid::messaging::Receiver nextReceiver(qpid::messaging::Duration timeout); - - qpid::messaging::Connection getConnection() const; - void checkError(); - bool hasError(); - - bool get(ReceiverImpl& receiver, qpid::messaging::Message& message, qpid::messaging::Duration timeout); - - void releasePending(const std::string& destination); - void receiverCancelled(const std::string& name); - void senderCancelled(const std::string& name); - - uint32_t getReceivable(); - uint32_t getReceivable(const std::string& destination); - - uint32_t getUnsettledAcks(); - uint32_t getUnsettledAcks(const std::string& destination); - - void setSession(qpid::client::Session); - - template <class T> bool execute(T& f) - { - try { - f(); - return true; - } catch (const qpid::TransportFailure&) { - reconnect(); - return false; - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (backoff()) return false; - else throw qpid::messaging::TargetCapacityExceeded(e.what()); - } catch (const qpid::framing::UnauthorizedAccessException& e) { - throw qpid::messaging::UnauthorizedAccess(e.what()); - } catch (const qpid::SessionException& e) { - throw qpid::messaging::SessionError(e.what()); - } catch (const qpid::ConnectionException& e) { - throw qpid::messaging::ConnectionError(e.what()); - } catch (const qpid::ChannelException& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } - - static SessionImpl& convert(qpid::messaging::Session&); - - private: - typedef std::map<std::string, qpid::messaging::Receiver> Receivers; - typedef std::map<std::string, qpid::messaging::Sender> Senders; - - mutable qpid::sys::Mutex lock; - boost::intrusive_ptr<ConnectionImpl> connection; - qpid::client::Session session; - AddressResolution resolver; - IncomingMessages incoming; - Receivers receivers; - Senders senders; - const bool transactional; - - bool accept(ReceiverImpl*, qpid::messaging::Message*, IncomingMessages::MessageTransfer&); - bool getIncoming(IncomingMessages::Handler& handler, qpid::messaging::Duration timeout); - bool getNextReceiver(qpid::messaging::Receiver* receiver, IncomingMessages::MessageTransfer& transfer); - void reconnect(); - bool backoff(); - - void commitImpl(); - void rollbackImpl(); - void acknowledgeImpl(); - void acknowledgeImpl(qpid::messaging::Message&); - void rejectImpl(qpid::messaging::Message&); - void releaseImpl(qpid::messaging::Message&); - void closeImpl(); - void syncImpl(bool block); - qpid::messaging::Sender createSenderImpl(const qpid::messaging::Address& address); - qpid::messaging::Receiver createReceiverImpl(const qpid::messaging::Address& address); - uint32_t getReceivableImpl(const std::string* destination); - uint32_t getUnsettledAcksImpl(const std::string* destination); - - //functors for public facing methods (allows locking and retry - //logic to be centralised) - struct Command - { - SessionImpl& impl; - - Command(SessionImpl& i) : impl(i) {} - }; - - struct Commit : Command - { - Commit(SessionImpl& i) : Command(i) {} - void operator()() { impl.commitImpl(); } - }; - - struct Rollback : Command - { - Rollback(SessionImpl& i) : Command(i) {} - void operator()() { impl.rollbackImpl(); } - }; - - struct Acknowledge : Command - { - Acknowledge(SessionImpl& i) : Command(i) {} - void operator()() { impl.acknowledgeImpl(); } - }; - - struct Sync : Command - { - Sync(SessionImpl& i) : Command(i) {} - void operator()() { impl.syncImpl(true); } - }; - - struct NonBlockingSync : Command - { - NonBlockingSync(SessionImpl& i) : Command(i) {} - void operator()() { impl.syncImpl(false); } - }; - - struct Reject : Command - { - qpid::messaging::Message& message; - - Reject(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.rejectImpl(message); } - }; - - struct Release : Command - { - qpid::messaging::Message& message; - - Release(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.releaseImpl(message); } - }; - - struct Acknowledge1 : Command - { - qpid::messaging::Message& message; - - Acknowledge1(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.acknowledgeImpl(message); } - }; - - struct CreateSender; - struct CreateReceiver; - struct UnsettledAcks; - struct Receivable; - - //helper templates for some common patterns - template <class F> bool execute() - { - F f(*this); - return execute(f); - } - - template <class F> void retry() - { - while (!execute<F>()) {} - } - - template <class F, class P> bool execute1(P p) - { - F f(*this, p); - return execute(f); - } - - template <class F, class R, class P> R get1(P p) - { - F f(*this, p); - while (!execute(f)) {} - return f.result; - } -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SESSIONIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp deleted file mode 100644 index 327c2274a6..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "SimpleUrlParser.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Exception.h" -#include <boost/lexical_cast.hpp> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -bool split(const std::string& in, char delim, std::pair<std::string, std::string>& result) -{ - std::string::size_type i = in.find(delim); - if (i != std::string::npos) { - result.first = in.substr(0, i); - if (i+1 < in.size()) { - result.second = in.substr(i+1); - } - return true; - } else { - return false; - } -} - -void parseUsernameAndPassword(const std::string& in, qpid::client::ConnectionSettings& result) -{ - std::pair<std::string, std::string> parts; - if (!split(in, '/', parts)) { - result.username = in; - } else { - result.username = parts.first; - result.password = parts.second; - } -} - -void parseHostAndPort(const std::string& in, qpid::client::ConnectionSettings& result) -{ - std::pair<std::string, std::string> parts; - if (!split(in, ':', parts)) { - result.host = in; - } else { - result.host = parts.first; - if (parts.second.size()) { - result.port = boost::lexical_cast<uint16_t>(parts.second); - } - } -} - -void SimpleUrlParser::parse(const std::string& url, qpid::client::ConnectionSettings& result) -{ - std::pair<std::string, std::string> parts; - if (!split(url, '@', parts)) { - parseHostAndPort(url, result); - } else { - parseUsernameAndPassword(parts.first, result); - parseHostAndPort(parts.second, result); - } -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h deleted file mode 100644 index 24f90ca9d6..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H -#define QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> - -namespace qpid { -namespace client { - -struct ConnectionSettings; - -namespace amqp0_10 { - -/** - * Parses a simple url of the form user/password@hostname:port - */ -struct SimpleUrlParser -{ - static void parse(const std::string& url, qpid::client::ConnectionSettings& result); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H*/ diff --git a/cpp/src/qpid/client/windows/SaslFactory.cpp b/cpp/src/qpid/client/windows/SaslFactory.cpp deleted file mode 100644 index d1ae762f1b..0000000000 --- a/cpp/src/qpid/client/windows/SaslFactory.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SaslFactory.h" - -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" - -#include "boost/tokenizer.hpp" - -namespace qpid { - -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using qpid::framing::InternalErrorException; - -struct WindowsSaslSettings -{ - WindowsSaslSettings ( ) : - username ( std::string(0) ), - password ( std::string(0) ), - service ( std::string(0) ), - host ( std::string(0) ), - minSsf ( 0 ), - maxSsf ( 0 ) - { - } - - WindowsSaslSettings ( const std::string & user, const std::string & password, const std::string & service, const std::string & host, int minSsf, int maxSsf ) : - username(user), - password(password), - service(service), - host(host), - minSsf(minSsf), - maxSsf(maxSsf) - { - } - - std::string username, - password, - service, - host; - - int minSsf, - maxSsf; -}; - -class WindowsSasl : public Sasl -{ - public: - WindowsSasl( const std::string &, const std::string &, const std::string &, const std::string &, int, int ); - ~WindowsSasl(); - std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings); - std::string step(const std::string& challenge); - std::string getMechanism(); - std::string getUserId(); - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); - private: - WindowsSaslSettings settings; - std::string mechanism; -}; - -qpid::sys::Mutex SaslFactory::lock; -std::auto_ptr<SaslFactory> SaslFactory::instance; - -SaslFactory::SaslFactory() -{ -} - -SaslFactory::~SaslFactory() -{ -} - -SaslFactory& SaslFactory::getInstance() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!instance.get()) { - instance = std::auto_ptr<SaslFactory>(new SaslFactory()); - } - return *instance; -} - -std::auto_ptr<Sasl> SaslFactory::create( const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool ) -{ - std::auto_ptr<Sasl> sasl(new WindowsSasl( username, password, serviceName, hostName, minSsf, maxSsf )); - return sasl; -} - -namespace { - const std::string ANONYMOUS = "ANONYMOUS"; - const std::string PLAIN = "PLAIN"; -} - -WindowsSasl::WindowsSasl( const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf ) - : settings(username, password, serviceName, hostName, minSsf, maxSsf) -{ -} - -WindowsSasl::~WindowsSasl() -{ -} - -std::string WindowsSasl::start(const std::string& mechanisms, - const SecuritySettings* /*externalSettings*/) -{ - QPID_LOG(debug, "WindowsSasl::start(" << mechanisms << ")"); - - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep(" "); - bool havePlain = false; - bool haveAnon = false; - tokenizer mechs(mechanisms, sep); - for (tokenizer::iterator mech = mechs.begin(); - mech != mechs.end(); - ++mech) { - if (*mech == ANONYMOUS) - haveAnon = true; - else if (*mech == PLAIN) - havePlain = true; - } - if (!haveAnon && !havePlain) - throw InternalErrorException(QPID_MSG("Sasl error: no common mechanism")); - - std::string resp = ""; - if (havePlain) { - mechanism = PLAIN; - resp = ((char)0) + settings.username + ((char)0) + settings.password; - } - else { - mechanism = ANONYMOUS; - } - return resp; -} - -std::string WindowsSasl::step(const std::string& /*challenge*/) -{ - // Shouldn't get this for PLAIN... - throw InternalErrorException(QPID_MSG("Sasl step error")); -} - -std::string WindowsSasl::getMechanism() -{ - return mechanism; -} - -std::string WindowsSasl::getUserId() -{ - return std::string(); // TODO - when GSSAPI is supported, return userId for connection. -} - -std::auto_ptr<SecurityLayer> WindowsSasl::getSecurityLayer(uint16_t /*maxFrameSize*/) -{ - return std::auto_ptr<SecurityLayer>(0); -} - -} // namespace qpid diff --git a/cpp/src/qpid/client/windows/SslConnector.cpp b/cpp/src/qpid/client/windows/SslConnector.cpp deleted file mode 100644 index a33713e1a8..0000000000 --- a/cpp/src/qpid/client/windows/SslConnector.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/TCPConnector.h" - -#include "config.h" -#include "qpid/Msg.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/SslAsynchIO.h" - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -#include <memory.h> -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include <security.h> -#include <Schnlsp.h> -#undef SECURITY_WIN32 -#include <winsock2.h> - -namespace qpid { -namespace client { -namespace windows { - -using namespace qpid::sys; -using boost::format; -using boost::str; - - -class SslConnector : public qpid::client::TCPConnector -{ - qpid::sys::windows::ClientSslAsynchIO *shim; - boost::shared_ptr<qpid::sys::Poller> poller; - std::string brokerHost; - SCHANNEL_CRED cred; - CredHandle credHandle; - TimeStamp credExpiry; - - virtual ~SslConnector(); - void negotiationDone(SECURITY_STATUS status); - - // A number of AsynchIO callbacks go right through to TCPConnector, but - // we can't boost::bind to a protected ancestor, so these methods redirect - // to those TCPConnector methods. - bool redirectReadbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void redirectWritebuff(qpid::sys::AsynchIO&); - void redirectEof(qpid::sys::AsynchIO&); - -public: - SslConnector(boost::shared_ptr<qpid::sys::Poller>, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); - virtual void connect(const std::string& host, int port); - virtual void connected(const Socket&); - unsigned int getSSF(); -}; - -// Static constructor which registers connector here -namespace { - Connector* create(boost::shared_ptr<qpid::sys::Poller> p, - framing::ProtocolVersion v, - const ConnectionSettings& s, - ConnectionImpl* c) { - return new SslConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - try { - Connector::registerFactory("ssl", &create); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL connector: " << e.what()); - } - }; - ~StaticInit() { } - } init; -} - -void SslConnector::negotiationDone(SECURITY_STATUS status) -{ - if (status == SEC_E_OK) - initAmqp(); - else - connectFailed(QPID_MSG(qpid::sys::strError(status))); -} - -bool SslConnector::redirectReadbuff(qpid::sys::AsynchIO& a, - qpid::sys::AsynchIOBufferBase* b) { - return readbuff(a, b); -} - -void SslConnector::redirectWritebuff(qpid::sys::AsynchIO& a) { - writebuff(a); -} - -void SslConnector::redirectEof(qpid::sys::AsynchIO& a) { - eof(a); -} - -SslConnector::SslConnector(boost::shared_ptr<qpid::sys::Poller> p, - framing::ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : TCPConnector(p, ver, settings, cimpl), shim(0), poller(p) -{ - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_OUTBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - &credExpiry); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - QPID_LOG(debug, "SslConnector created for " << ver.toString()); -} - -SslConnector::~SslConnector() -{ - ::FreeCredentialsHandle(&credHandle); -} - - // Will this get reach via virtual method via boost::bind???? - -void SslConnector::connect(const std::string& host, int port) { - brokerHost = host; - TCPConnector::connect(host, port); -} - -void SslConnector::connected(const Socket& s) { - shim = new qpid::sys::windows::ClientSslAsynchIO(brokerHost, - s, - credHandle, - boost::bind(&SslConnector::redirectReadbuff, this, _1, _2), - boost::bind(&SslConnector::redirectEof, this, _1), - boost::bind(&SslConnector::redirectEof, this, _1), - 0, // closed - 0, // nobuffs - boost::bind(&SslConnector::redirectWritebuff, this, _1), - boost::bind(&SslConnector::negotiationDone, this, _1)); - start(shim); - shim->start(poller); -} - -unsigned int SslConnector::getSSF() -{ - return shim->getSslKeySize(); -} - -}}} // namespace qpid::client::windows |