/* * Copyright (c) 2014-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include #include #include #include #include #include #include #include #include #include #include using namespace Swift; SluiftComponent::SluiftComponent( const JID& jid, const std::string& password, NetworkFactories* networkFactories, SimpleEventLoop* eventLoop): networkFactories(networkFactories), eventLoop(eventLoop), tracer(NULL) { component = new Component(jid, password, networkFactories); component->onError.connect(boost::bind(&SluiftComponent::handleError, this, _1)); component->onMessageReceived.connect(boost::bind(&SluiftComponent::handleIncomingMessage, this, _1)); component->onPresenceReceived.connect(boost::bind(&SluiftComponent::handleIncomingPresence, this, _1)); } SluiftComponent::~SluiftComponent() { delete tracer; delete component; } void SluiftComponent::connect(const std::string& host, int port) { disconnectedError = boost::optional(); component->connect(host, port); } void SluiftComponent::setTraceEnabled(bool b) { if (b && !tracer) { tracer = new ComponentXMLTracer(component); } else if (!b && tracer) { delete tracer; tracer = NULL; } } void SluiftComponent::waitConnected(int timeout) { Watchdog watchdog(timeout, networkFactories->getTimerFactory()); while (!watchdog.getTimedOut() && !disconnectedError && !component->isAvailable()) { eventLoop->runUntilEvents(); } if (watchdog.getTimedOut()) { component->disconnect(); throw Lua::Exception("Timeout while connecting"); } if (disconnectedError) { throw Lua::Exception(getErrorString(*disconnectedError)); } } bool SluiftComponent::isConnected() const { return component->isAvailable(); } void SluiftComponent::disconnect() { component->disconnect(); while (component->isAvailable()) { eventLoop->runUntilEvents(); } } void SluiftComponent::setSoftwareVersion(const std::string& name, const std::string& version, const std::string& /* os */) { component->setSoftwareVersion(name, version); } boost::optional SluiftComponent::getNextEvent( int timeout, boost::function condition) { Watchdog watchdog(timeout, networkFactories->getTimerFactory()); size_t currentIndex = 0; while (true) { // Look for pending events in the queue while (currentIndex < pendingEvents.size()) { Event event = pendingEvents[currentIndex]; if (!condition || condition(event)) { pendingEvents.erase( pendingEvents.begin() + boost::numeric_cast(currentIndex)); return event; } ++currentIndex; } // Wait for new events while (!watchdog.getTimedOut() && currentIndex >= pendingEvents.size() && component->isAvailable()) { eventLoop->runUntilEvents(); } // Finish if we're disconnected or timed out if (watchdog.getTimedOut() || !component->isAvailable()) { return boost::optional(); } } } void SluiftComponent::handleIncomingMessage(boost::shared_ptr stanza) { pendingEvents.push_back(Event(stanza)); } void SluiftComponent::handleIncomingPresence(boost::shared_ptr stanza) { pendingEvents.push_back(Event(stanza)); } void SluiftComponent::handleRequestResponse(boost::shared_ptr response, boost::shared_ptr error) { requestResponse = response; requestError = error; requestResponseReceived = true; } void SluiftComponent::handleError(const boost::optional& error) { disconnectedError = error; } Sluift::Response SluiftComponent::doSendRequest(boost::shared_ptr request, int timeout) { requestResponse.reset(); requestError.reset(); requestResponseReceived = false; request->send(); Watchdog watchdog(timeout, networkFactories->getTimerFactory()); while (!watchdog.getTimedOut() && !requestResponseReceived) { eventLoop->runUntilEvents(); } return Sluift::Response(requestResponse, watchdog.getTimedOut() ? boost::make_shared(ErrorPayload::RemoteServerTimeout) : requestError); }