From 83434963a7b10b759ffe3fdc1312efdef282a450 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Tue, 19 Jun 2018 14:57:06 +0100
Subject: Don't double-connect to IP literals

Before this change, an IP literal would be attempted directly, and if
that failed it would then 'resolve' the literal and try the result.

Test-Information:
Added a unit test verifying the bug before fixing it.

Change-Id: Ic887c74152f5a4b259392dad402952b3777268b1

diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp
index 5eddaba..ca924bb 100644
--- a/Swiften/Network/Connector.cpp
+++ b/Swiften/Network/Connector.cpp
@@ -29,13 +29,13 @@ void Connector::start() {
     assert(!currentConnection);
     assert(!serviceQuery);
     assert(!timer);
-    queriedAllServices = false;
     auto hostAddress = HostAddress::fromString(hostname);
     if (timeoutMilliseconds > 0) {
         timer = timerFactory->createTimer(timeoutMilliseconds);
         timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this()));
     }
     if (serviceLookupPrefix) {
+        queriedAllServices = false;
         serviceQuery = resolver->createServiceQuery(*serviceLookupPrefix, hostname);
         serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1));
         serviceQuery->run();
diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp
index 95b3dd9..b8f4c7a 100644
--- a/Swiften/Network/StaticDomainNameResolver.cpp
+++ b/Swiften/Network/StaticDomainNameResolver.cpp
@@ -50,6 +50,10 @@ namespace {
             if (!resolver->getIsResponsive()) {
                 return;
             }
+            if (auto address = HostAddress::fromString(host)) {
+                // IP Literals should resolve to themselves
+                resolver->addAddress(host, *address);
+            }
             StaticDomainNameResolver::AddressesMap::const_iterator i = resolver->getAddresses().find(host);
             if (i != resolver->getAddresses().end()) {
                 eventLoop->postEvent(
diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp
index 8524439..658aaf7 100644
--- a/Swiften/Network/UnitTest/ConnectorTest.cpp
+++ b/Swiften/Network/UnitTest/ConnectorTest.cpp
@@ -26,6 +26,7 @@ class ConnectorTest : public CppUnit::TestFixture {
         CPPUNIT_TEST(testConnect);
         CPPUNIT_TEST(testConnect_NoServiceLookups);
         CPPUNIT_TEST(testConnect_NoServiceLookups_DefaultPort);
+        CPPUNIT_TEST(testConnect_OnlyLiteral);
         CPPUNIT_TEST(testConnect_FirstAddressHostFails);
         CPPUNIT_TEST(testConnect_NoSRVHost);
         CPPUNIT_TEST(testConnect_NoHosts);
@@ -119,6 +120,21 @@ class ConnectorTest : public CppUnit::TestFixture {
             CPPUNIT_ASSERT(!std::dynamic_pointer_cast<DomainNameResolveError>(error));
         }
 
+        void testConnect_OnlyLiteral() {
+            auto testling = Connector::create("1.1.1.1", 1234, boost::none, resolver, connectionFactory, timerFactory);
+            testling->onConnectFinished.connect(boost::bind(&ConnectorTest::handleConnectorFinished, this, _1, _2));
+
+            auto address1 = HostAddress::fromString("1.1.1.1").get();
+            connectionFactory->failingPorts.push_back(HostAddressPort(address1, 1234));
+
+            testling->start();
+            eventLoop->processEvents();
+
+            CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size()));
+            CPPUNIT_ASSERT(!connections[0]);
+            CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connectionFactory->createdConnections.size()));
+        }
+
         void testConnect_FirstAddressHostFails() {
             Connector::ref testling(createConnector());
 
@@ -356,12 +372,15 @@ class ConnectorTest : public CppUnit::TestFixture {
             }
 
             std::shared_ptr<Connection> createConnection() {
-                return std::make_shared<MockConnection>(failingPorts, isResponsive, eventLoop);
+                auto connection = std::make_shared<MockConnection>(failingPorts, isResponsive, eventLoop);
+                createdConnections.push_back(connection);
+                return connection;
             }
 
             EventLoop* eventLoop;
             bool isResponsive;
             std::vector<HostAddressPort> failingPorts;
+            std::vector<std::shared_ptr<MockConnection>> createdConnections;
         };
 
     private:
-- 
cgit v0.10.2-6-g49f6