diff options
Diffstat (limited to 'Swiften/Network')
-rw-r--r-- | Swiften/Network/Connector.cpp | 4 | ||||
-rw-r--r-- | Swiften/Network/Connector.h | 3 | ||||
-rw-r--r-- | Swiften/Network/DummyTimerFactory.cpp | 57 | ||||
-rw-r--r-- | Swiften/Network/DummyTimerFactory.h | 22 | ||||
-rw-r--r-- | Swiften/Network/SConscript | 1 | ||||
-rw-r--r-- | Swiften/Network/StaticDomainNameResolver.cpp | 9 | ||||
-rw-r--r-- | Swiften/Network/StaticDomainNameResolver.h | 11 | ||||
-rw-r--r-- | Swiften/Network/UnitTest/ConnectorTest.cpp | 64 |
8 files changed, 167 insertions, 4 deletions
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp index e424f64..9ea5a7f 100644 --- a/Swiften/Network/Connector.cpp +++ b/Swiften/Network/Connector.cpp @@ -12,6 +12,10 @@ namespace Swift { Connector::Connector(const String& hostname, DomainNameResolver* resolver, ConnectionFactory* connectionFactory) : hostname(hostname), resolver(resolver), connectionFactory(connectionFactory), queriedAllHosts(true) { } +void Connector::setTimeoutMilliseconds(int milliseconds) { + timeoutMilliseconds = milliseconds; +} + void Connector::start() { //std::cout << "Connector::start()" << std::endl; assert(!currentConnection); diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h index cb885ab..6df3970 100644 --- a/Swiften/Network/Connector.h +++ b/Swiften/Network/Connector.h @@ -19,6 +19,7 @@ namespace Swift { public: Connector(const String& hostname, DomainNameResolver*, ConnectionFactory*); + void setTimeoutMilliseconds(int milliseconds); void start(); boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished; @@ -37,11 +38,11 @@ namespace Swift { String hostname; DomainNameResolver* resolver; ConnectionFactory* connectionFactory; + int timeoutMilliseconds; boost::shared_ptr<DomainNameServiceQuery> serviceQuery; std::deque<DomainNameServiceQuery::Result> serviceQueryResults; boost::shared_ptr<DomainNameAddressQuery> addressQuery; bool queriedAllHosts; boost::shared_ptr<Connection> currentConnection; }; - }; diff --git a/Swiften/Network/DummyTimerFactory.cpp b/Swiften/Network/DummyTimerFactory.cpp new file mode 100644 index 0000000..72523bb --- /dev/null +++ b/Swiften/Network/DummyTimerFactory.cpp @@ -0,0 +1,57 @@ +#include "Swiften/Network/DummyTimerFactory.h" + +#include <algorithm> + +#include "Swiften/Network/Timer.h" +#include "Swiften/Base/foreach.h" + +namespace Swift { + +class DummyTimerFactory::DummyTimer : public Timer { + public: + DummyTimer(int timeout) : timeout(timeout), isRunning(false) { + } + + virtual void start() { + isRunning = true; + } + + virtual void stop() { + isRunning = false; + } + + int timeout; + bool isRunning; +}; + + +DummyTimerFactory::DummyTimerFactory() : currentTime(0) { +} + +boost::shared_ptr<Timer> DummyTimerFactory::createTimer(int milliseconds) { + boost::shared_ptr<DummyTimer> timer(new DummyTimer(milliseconds)); + timers.push_back(timer); + return timer; +} + +static bool hasZeroTimeout(boost::shared_ptr<DummyTimerFactory::DummyTimer> timer) { + return timer->timeout == 0; +} + +void DummyTimerFactory::setTime(int time) { + assert(time > currentTime); + int increment = currentTime - time; + std::vector< boost::shared_ptr<DummyTimer> > notifyTimers(timers.begin(), timers.end()); + foreach(boost::shared_ptr<DummyTimer> timer, notifyTimers) { + if (increment >= timer->timeout) { + if (timer->isRunning) { + timer->onTick(); + } + timer->timeout = 0; + } + } + timers.erase(std::remove_if(timers.begin(), timers.end(), hasZeroTimeout), timers.end()); + currentTime = time; +} + +} diff --git a/Swiften/Network/DummyTimerFactory.h b/Swiften/Network/DummyTimerFactory.h new file mode 100644 index 0000000..feac029 --- /dev/null +++ b/Swiften/Network/DummyTimerFactory.h @@ -0,0 +1,22 @@ +#pragma once + +#include <list> + +#include "Swiften/Network/TimerFactory.h" + +namespace Swift { + class DummyTimerFactory : public TimerFactory { + public: + class DummyTimer; + + DummyTimerFactory(); + + virtual boost::shared_ptr<Timer> createTimer(int milliseconds); + void setTime(int time); + + private: + friend class DummyTimer; + int currentTime; + std::list<boost::shared_ptr<DummyTimer> > timers; + }; +} diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript index d63b673..767eee2 100644 --- a/Swiften/Network/SConscript +++ b/Swiften/Network/SConscript @@ -14,6 +14,7 @@ objects = myenv.StaticObject([ "ConnectionServer.cpp", "Connector.cpp", "TimerFactory.cpp", + "DummyTimerFactory.cpp", "BoostTimerFactory.cpp", "DomainNameResolver.cpp", "DomainNameAddressQuery.cpp", diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp index 609bbdd..a7275d2 100644 --- a/Swiften/Network/StaticDomainNameResolver.cpp +++ b/Swiften/Network/StaticDomainNameResolver.cpp @@ -13,6 +13,9 @@ namespace { ServiceQuery(const String& service, Swift::StaticDomainNameResolver* resolver) : service(service), resolver(resolver) {} virtual void run() { + if (!resolver->getIsResponsive()) { + return; + } std::vector<DomainNameServiceQuery::Result> results; for(StaticDomainNameResolver::ServicesCollection::const_iterator i = resolver->getServices().begin(); i != resolver->getServices().end(); ++i) { if (i->first == service) { @@ -30,6 +33,9 @@ namespace { AddressQuery(const String& host, StaticDomainNameResolver* resolver) : host(host), resolver(resolver) {} virtual void run() { + if (!resolver->getIsResponsive()) { + return; + } StaticDomainNameResolver::AddressesMap::const_iterator i = resolver->getAddresses().find(host); if (i != resolver->getAddresses().end()) { MainEventLoop::postEvent( @@ -48,6 +54,9 @@ namespace { namespace Swift { +StaticDomainNameResolver::StaticDomainNameResolver() : isResponsive(true) { +} + void StaticDomainNameResolver::addAddress(const String& domain, const HostAddress& address) { addresses[domain] = address; } diff --git a/Swiften/Network/StaticDomainNameResolver.h b/Swiften/Network/StaticDomainNameResolver.h index 0e877d3..d7e7ba4 100644 --- a/Swiften/Network/StaticDomainNameResolver.h +++ b/Swiften/Network/StaticDomainNameResolver.h @@ -19,6 +19,8 @@ namespace Swift { typedef std::vector< std::pair<String, DomainNameServiceQuery::Result> > ServicesCollection; public: + StaticDomainNameResolver(); + void addAddress(const String& domain, const HostAddress& address); void addService(const String& service, const DomainNameServiceQuery::Result& result); void addXMPPClientService(const String& domain, const HostAddressPort&); @@ -31,10 +33,19 @@ namespace Swift { return services; } + bool getIsResponsive() const { + return isResponsive; + } + + void setIsResponsive(bool b) { + isResponsive = b; + } + virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const String& name); virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const String& name); private: + bool isResponsive; AddressesMap addresses; ServicesCollection services; }; diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp index af1ad4e..08b9bc1 100644 --- a/Swiften/Network/UnitTest/ConnectorTest.cpp +++ b/Swiften/Network/UnitTest/ConnectorTest.cpp @@ -9,6 +9,7 @@ #include "Swiften/Network/ConnectionFactory.h" #include "Swiften/Network/HostAddressPort.h" #include "Swiften/Network/StaticDomainNameResolver.h" +#include "Swiften/Network/DummyTimerFactory.h" #include "Swiften/EventLoop/MainEventLoop.h" #include "Swiften/EventLoop/DummyEventLoop.h" @@ -23,6 +24,9 @@ class ConnectorTest : public CppUnit::TestFixture { CPPUNIT_TEST(testConnect_AllSRVHostsFailWithoutFallbackHost); CPPUNIT_TEST(testConnect_AllSRVHostsFailWithFallbackHost); CPPUNIT_TEST(testConnect_SRVAndFallbackHostsFail); + //CPPUNIT_TEST(testConnect_TimeoutDuringResolve); + //CPPUNIT_TEST(testConnect_TimeoutDuringConnect); + //CPPUNIT_TEST(testConnect_NoTimeout); CPPUNIT_TEST_SUITE_END(); public: @@ -33,9 +37,11 @@ class ConnectorTest : public CppUnit::TestFixture { eventLoop = new DummyEventLoop(); resolver = new StaticDomainNameResolver(); connectionFactory = new MockConnectionFactory(); + timerFactory = new DummyTimerFactory(); } void tearDown() { + delete timerFactory; delete connectionFactory; delete resolver; delete eventLoop; @@ -134,6 +140,50 @@ class ConnectorTest : public CppUnit::TestFixture { CPPUNIT_ASSERT(!connections[0]); } + void testConnect_TimeoutDuringResolve() { + std::auto_ptr<Connector> testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->setIsResponsive(false); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + void testConnect_TimeoutDuringConnect() { + std::auto_ptr<Connector> testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->addXMPPClientService("foo.com", host1); + connectionFactory->isResponsive = false; + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + void testConnect_NoTimeout() { + std::auto_ptr<Connector> testling(createConnector()); + testling->setTimeoutMilliseconds(10); + resolver->addXMPPClientService("foo.com", host1); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + } + + private: Connector* createConnector() { Connector* connector = new Connector("foo.com", resolver, connectionFactory); @@ -151,12 +201,14 @@ class ConnectorTest : public CppUnit::TestFixture { struct MockConnection : public Connection { public: - MockConnection(const std::vector<HostAddressPort>& failingPorts) : failingPorts(failingPorts) {} + MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive) : failingPorts(failingPorts), isResponsive(isResponsive) {} void listen() { assert(false); } void connect(const HostAddressPort& address) { hostAddressPort = address; - MainEventLoop::postEvent(boost::bind(boost::ref(onConnectFinished), std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end())); + if (isResponsive) { + MainEventLoop::postEvent(boost::bind(boost::ref(onConnectFinished), std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end())); + } } void disconnect() { assert(false); } @@ -164,13 +216,18 @@ class ConnectorTest : public CppUnit::TestFixture { boost::optional<HostAddressPort> hostAddressPort; std::vector<HostAddressPort> failingPorts; + bool isResponsive; }; struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory() : isResponsive(true) { + } + boost::shared_ptr<Connection> createConnection() { - return boost::shared_ptr<Connection>(new MockConnection(failingPorts)); + return boost::shared_ptr<Connection>(new MockConnection(failingPorts, isResponsive)); } + bool isResponsive; std::vector<HostAddressPort> failingPorts; }; @@ -181,6 +238,7 @@ class ConnectorTest : public CppUnit::TestFixture { DummyEventLoop* eventLoop; StaticDomainNameResolver* resolver; MockConnectionFactory* connectionFactory; + DummyTimerFactory* timerFactory; std::vector< boost::shared_ptr<MockConnection> > connections; }; |