diff options
Diffstat (limited to 'Swiften/Component/ComponentSession.cpp')
-rw-r--r-- | Swiften/Component/ComponentSession.cpp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/Swiften/Component/ComponentSession.cpp b/Swiften/Component/ComponentSession.cpp new file mode 100644 index 0000000..75ee467 --- /dev/null +++ b/Swiften/Component/ComponentSession.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Component/ComponentSession.h" + +#include <boost/bind.hpp> + +#include "Swiften/Elements/ProtocolHeader.h" +#include "Swiften/Elements/ComponentHandshake.h" +#include "Swiften/Session/SessionStream.h" +#include "Swiften/Component/ComponentHandshakeGenerator.h" + +namespace Swift { + +ComponentSession::ComponentSession(const JID& jid, const String& secret, boost::shared_ptr<SessionStream> stream) : jid(jid), secret(secret), stream(stream), state(Initial) { +} + +ComponentSession::~ComponentSession() { +} + +void ComponentSession::start() { + stream->onStreamStartReceived.connect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.connect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); + stream->onError.connect(boost::bind(&ComponentSession::handleStreamError, shared_from_this(), _1)); + + assert(state == Initial); + state = WaitingForStreamStart; + sendStreamHeader(); +} + +void ComponentSession::sendStreamHeader() { + ProtocolHeader header; + header.setTo(jid); + stream->writeHeader(header); +} + +void ComponentSession::sendStanza(boost::shared_ptr<Stanza> stanza) { + stream->writeElement(stanza); +} + +void ComponentSession::handleStreamStart(const ProtocolHeader& header) { + checkState(WaitingForStreamStart); + state = Authenticating; + stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret)))); +} + +void ComponentSession::handleElement(boost::shared_ptr<Element> element) { + if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { + if (getState() == Initialized) { + onStanzaReceived(stanza); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else if (ComponentHandshake::cast(element)) { + if (!checkState(Authenticating)) { + return; + } + stream->setWhitespacePingEnabled(true); + state = Initialized; + onInitialized(); + } + else if (getState() == Authenticating) { + // FIXME: We should actually check the element received + finishSession(Error::AuthenticationFailedError); + } + else { + finishSession(Error::UnexpectedElementError); + } +} + +bool ComponentSession::checkState(State state) { + if (this->state != state) { + finishSession(Error::UnexpectedElementError); + return false; + } + return true; +} + +void ComponentSession::handleStreamError(boost::shared_ptr<Swift::Error> error) { + finishSession(error); +} + +void ComponentSession::finish() { + finishSession(boost::shared_ptr<Error>()); +} + +void ComponentSession::finishSession(Error::Type error) { + finishSession(boost::shared_ptr<Swift::ComponentSession::Error>(new Swift::ComponentSession::Error(error))); +} + +void ComponentSession::finishSession(boost::shared_ptr<Swift::Error> error) { + state = Finished; + stream->setWhitespacePingEnabled(false); + stream->onStreamStartReceived.disconnect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.disconnect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); + stream->onError.disconnect(boost::bind(&ComponentSession::handleStreamError, shared_from_this(), _1)); + if (stream->isAvailable()) { + stream->writeFooter(); + } + onFinished(error); +} + +} |