From 725c4e1ad0710606421f9705d994688116a9fc1f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 5 Apr 2010 14:10:17 +0200
Subject: Refactored DomainNameAddressQuery.

Result can now consist of multiple addresses.

diff --git a/Swiften/Network/CAresDomainNameResolver.cpp b/Swiften/Network/CAresDomainNameResolver.cpp
index c0bf8a0..bf860f2 100644
--- a/Swiften/Network/CAresDomainNameResolver.cpp
+++ b/Swiften/Network/CAresDomainNameResolver.cpp
@@ -95,16 +95,19 @@ class CAresDomainNameAddressQuery : public DomainNameAddressQuery, public CAresQ
 					// Check whether the different fields are what we expect them to be
 					struct in_addr addr;
 					addr.s_addr = *(unsigned int*)hosts->h_addr_list[0];
-					HostAddress result(inet_ntoa(addr));
-					MainEventLoop::postEvent(boost::bind(boost::ref(onResult), result, boost::optional<DomainNameResolveError>()), boost::dynamic_pointer_cast<CAresDomainNameAddressQuery>(shared_from_this())); 
+
+					std::vector<HostAddress> results;
+					results.push_back(HostAddress(inet_ntoa(addr)));
+
+					MainEventLoop::postEvent(boost::bind(boost::ref(onResult), results, boost::optional<DomainNameResolveError>()), boost::dynamic_pointer_cast<CAresDomainNameAddressQuery>(shared_from_this())); 
 					ares_free_hostent(hosts);
 				}
 				else {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onResult), HostAddress(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this());
+					MainEventLoop::postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this());
 				}
 			}
 			else if (status != ARES_EDESTRUCTION) {
-				MainEventLoop::postEvent(boost::bind(boost::ref(onResult), HostAddress(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this());
+				MainEventLoop::postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this());
 			}
 		}
 };
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp
index d372bf2..ff45481 100644
--- a/Swiften/Network/Connector.cpp
+++ b/Swiften/Network/Connector.cpp
@@ -64,22 +64,22 @@ void Connector::tryNextHostname() {
 	}
 }
 
-void Connector::handleAddressQueryResult(const HostAddress& address, boost::optional<DomainNameResolveError> error) {
+void Connector::handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) {
 	//std::cout << "Connector::handleAddressQueryResult(): Start" << std::endl;
 	addressQuery.reset();
 	if (!serviceQueryResults.empty()) {
 		DomainNameServiceQuery::Result serviceQueryResult = serviceQueryResults.front();
 		serviceQueryResults.pop_front();
-		if (error) {
+		if (error || addresses.empty()) {
 			//std::cout << "Connector::handleAddressQueryResult(): A lookup for SRV host " << serviceQueryResult.hostname << " failed." << std::endl;
 			tryNextHostname();
 		}
 		else {
 			//std::cout << "Connector::handleAddressQueryResult(): A lookup for SRV host " << serviceQueryResult.hostname << " succeeded: " << address.toString() << std::endl;
-			tryConnect(HostAddressPort(address, serviceQueryResult.port));
+			tryConnect(HostAddressPort(addresses[0], serviceQueryResult.port));
 		}
 	}
-	else if (error) {
+	else if (error || addresses.empty()) {
 		//std::cout << "Connector::handleAddressQueryResult(): Fallback address query failed. Giving up" << std::endl;
 		// The fallback address query failed
 		assert(queriedAllHosts);
@@ -88,7 +88,7 @@ void Connector::handleAddressQueryResult(const HostAddress& address, boost::opti
 	else {
 		//std::cout << "Connector::handleAddressQueryResult(): Fallback address query succeeded: " << address.toString() << std::endl;
 		// The fallback query succeeded
-		tryConnect(HostAddressPort(address, 5222));
+		tryConnect(HostAddressPort(addresses[0], 5222));
 	}
 }
 
diff --git a/Swiften/Network/Connector.h b/Swiften/Network/Connector.h
index 507f085..32dd9ab 100644
--- a/Swiften/Network/Connector.h
+++ b/Swiften/Network/Connector.h
@@ -28,7 +28,7 @@ namespace Swift {
 
 		private:
 			void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result);
-			void handleAddressQueryResult(const HostAddress& address, boost::optional<DomainNameResolveError> error);
+			void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error);
 			void queryAddress(const String& hostname);
 
 			void tryNextHostname();
diff --git a/Swiften/Network/DomainNameAddressQuery.h b/Swiften/Network/DomainNameAddressQuery.h
index 66a79db..53d0abf 100644
--- a/Swiften/Network/DomainNameAddressQuery.h
+++ b/Swiften/Network/DomainNameAddressQuery.h
@@ -14,6 +14,6 @@ namespace Swift {
 
 			virtual void run() = 0;
 
-			boost::signal<void (const HostAddress&, boost::optional<DomainNameResolveError>)> onResult;
+			boost::signal<void (const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>)> onResult;
 	};
 }
diff --git a/Swiften/Network/PlatformDomainNameResolver.cpp b/Swiften/Network/PlatformDomainNameResolver.cpp
index 7b8a6d5..636eac9 100644
--- a/Swiften/Network/PlatformDomainNameResolver.cpp
+++ b/Swiften/Network/PlatformDomainNameResolver.cpp
@@ -51,11 +51,15 @@ namespace {
 					emitError();
 				}
 				else {
-					boost::asio::ip::address address = (*endpointIterator).endpoint().address();
-					HostAddress result = (address.is_v4() ? HostAddress(&address.to_v4().to_bytes()[0], 4) : HostAddress(&address.to_v6().to_bytes()[0], 16));
+					std::vector<HostAddress> results;
+					for ( ; endpointIterator != boost::asio::ip::tcp::resolver::iterator(); ++endpointIterator) {
+						boost::asio::ip::address address = (*endpointIterator).endpoint().address();
+						results.push_back(address.is_v4() ? HostAddress(&address.to_v4().to_bytes()[0], 4) : HostAddress(&address.to_v6().to_bytes()[0], 16));
+					}
+
 					//std::cout << "PlatformDomainNameResolver::doRun(): Success" << std::endl;
 					MainEventLoop::postEvent(
-							boost::bind(boost::ref(onResult), result, boost::optional<DomainNameResolveError>()), 
+							boost::bind(boost::ref(onResult), results, boost::optional<DomainNameResolveError>()), 
 							shared_from_this());
 				}
 			}
@@ -67,7 +71,7 @@ namespace {
 		}
 
 		void emitError() {
-			MainEventLoop::postEvent(boost::bind(boost::ref(onResult), HostAddress(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this());
+			MainEventLoop::postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this());
 		}
 
 		boost::asio::io_service ioService;
diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp
index a7275d2..a751fdd 100644
--- a/Swiften/Network/StaticDomainNameResolver.cpp
+++ b/Swiften/Network/StaticDomainNameResolver.cpp
@@ -38,11 +38,13 @@ namespace {
 			}
 			StaticDomainNameResolver::AddressesMap::const_iterator i = resolver->getAddresses().find(host);
 			if (i != resolver->getAddresses().end()) {
+				std::vector<HostAddress> result;
+				result.push_back(i->second);
 				MainEventLoop::postEvent(
-						boost::bind(boost::ref(onResult), i->second, boost::optional<DomainNameResolveError>()));
+						boost::bind(boost::ref(onResult), result, boost::optional<DomainNameResolveError>()));
 			}
 			else {
-				MainEventLoop::postEvent(boost::bind(boost::ref(onResult), HostAddress(), boost::optional<DomainNameResolveError>(DomainNameResolveError())));
+				MainEventLoop::postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())));
 			}
 
 		}
diff --git a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp
index 09837d6..ec9d555 100644
--- a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp
+++ b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp
@@ -16,7 +16,8 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(DomainNameResolverTest);
 		CPPUNIT_TEST(testResolveAddress);
 		CPPUNIT_TEST(testResolveAddress_Error);
-		//CPPUNIT_TEST(testResolveAddress_IPv6);
+		CPPUNIT_TEST(testResolveAddress_IPv6);
+		CPPUNIT_TEST(testResolveAddress_IPv4and6);
 		CPPUNIT_TEST(testResolveAddress_International);
 		CPPUNIT_TEST(testResolveAddress_Localhost);
 		CPPUNIT_TEST(testResolveService);
@@ -44,7 +45,8 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 			waitForResults();
 
 			CPPUNIT_ASSERT(!addressQueryError);
-			CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), addressQueryResult.toString());
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size()));
+			CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), addressQueryResult[0].toString());
 		}
 
 		void testResolveAddress_Error() {
@@ -63,7 +65,19 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 			waitForResults();
 
 			CPPUNIT_ASSERT(!addressQueryError);
-			CPPUNIT_ASSERT_EQUAL(std::string("0000:0000:0000:0000:0000:ffff:0a00:0104"), addressQueryResult.toString());
+			CPPUNIT_ASSERT_EQUAL(std::string("0000:0000:0000:0000:0000:ffff:0a00:0104"), addressQueryResult[0].toString());
+		}
+
+		void testResolveAddress_IPv4and6() {
+			boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp-ipv46.test.swift.im"));
+
+			query->run();
+			waitForResults();
+
+			CPPUNIT_ASSERT(!addressQueryError);
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(addressQueryResult.size()));
+			CPPUNIT_ASSERT_EQUAL(std::string("1234:5678:9abc:def0:0fed:cba9:8765:4321"), addressQueryResult[0].toString());
+			CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.7"), addressQueryResult[1].toString());
 		}
 
 		void testResolveAddress_International() {
@@ -73,7 +87,8 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 			waitForResults();
 
 			CPPUNIT_ASSERT(!addressQueryError);
-			CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.3"), addressQueryResult.toString());
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size()));
+			CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.3"), addressQueryResult[0].toString());
 		}
 
 		void testResolveAddress_Localhost() {
@@ -83,7 +98,8 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 			waitForResults();
 
 			CPPUNIT_ASSERT(!addressQueryError);
-			CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), addressQueryResult.toString());
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size()));
+			CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), addressQueryResult[0].toString());
 		}
 
 
@@ -126,8 +142,8 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 				return result;
 			}
 
-			void handleAddressQueryResult(const HostAddress& address, boost::optional<DomainNameResolveError> error) {
-				addressQueryResult = address;
+			void handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) {
+				addressQueryResult = addresses;
 				addressQueryError = error;
 				resultsAvailable = true;
 			}
@@ -159,7 +175,7 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 	private:
 		DummyEventLoop* eventLoop;
 		bool resultsAvailable;
-		HostAddress addressQueryResult;
+		std::vector<HostAddress> addressQueryResult;
 		boost::optional<DomainNameResolveError> addressQueryError;
 		std::vector<DomainNameServiceQuery::Result> serviceQueryResult;
 		PlatformDomainNameResolver* resolver;
-- 
cgit v0.10.2-6-g49f6