From 13801557b6664426cac26384441ab0b19ff9abb5 Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Wed, 9 Dec 2015 16:24:23 +0100
Subject: Listen to IPv6 any address instead of only IPv4

This should enable IPv4/IPv6 dual-stack support for Swift(-en)
Jingle file-transfer support.

Add Connection::getRemoteAddress() method.

Test-Information:

Tested IPv6 file-transfer and IPv4 file-transfer between two
Swift instances.
Added integration test verifying IPv4 only, IPv6 only and
IPv4/IPv6 dual-stack support on the running platform.
Additionally added test to verify remote addresses on dual-stack
server.

Change-Id: Ie384a71833eacca554f69e6f12a1c8330d0d747f

diff --git a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp
index 94da1b1..3968c2c 100644
--- a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp
+++ b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp
@@ -1,22 +1,22 @@
 /*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
 
+#include <boost/bind.hpp>
+#include <boost/optional.hpp>
+
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>
 
-#include <boost/optional.hpp>
-#include <boost/bind.hpp>
-
 #include <Swiften/Component/ComponentConnector.h>
+#include <Swiften/EventLoop/DummyEventLoop.h>
 #include <Swiften/Network/Connection.h>
 #include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/Network/HostAddressPort.h>
 #include <Swiften/Network/StaticDomainNameResolver.h>
-#include <Swiften/Network/DummyTimerFactory.h>
-#include <Swiften/EventLoop/DummyEventLoop.h>
 
 using namespace Swift;
 
@@ -176,6 +176,7 @@ class ComponentConnectorTest : public CppUnit::TestFixture {
 				void disconnect() { assert(false); }
 				void write(const SafeByteArray&) { assert(false); }
 				HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+				HostAddressPort getRemoteAddress() const { return HostAddressPort(); }				
 
 				EventLoop* eventLoop;
 				boost::optional<HostAddressPort> hostAddressPort;
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp
index f531856..7b97698 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp
+++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp
@@ -117,7 +117,7 @@ void SOCKS5BytestreamServerManager::initialize() {
 		int port;
 		for (port = LISTEN_PORTS_BEGIN; port < LISTEN_PORTS_END; ++port) {
 			SWIFT_LOG(debug) << "Trying to start server on port " << port << std::endl;
-			connectionServer = connectionServerFactory->createConnectionServer(HostAddress("0.0.0.0"), port);
+			connectionServer = connectionServerFactory->createConnectionServer(HostAddress("::"), port);
 			boost::optional<ConnectionServer::Error> error = connectionServer->tryStart();
 			if (!error) {
 				break;
diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
index 78ea8ed..a0f6033 100644
--- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
@@ -4,11 +4,11 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
-#include <Swiften/Base/ByteArray.h>
-#include <QA/Checker/IO.h>
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
 
 #include <boost/bind.hpp>
 #include <boost/random/mersenne_twister.hpp>
@@ -16,11 +16,18 @@
 #include <boost/random/variate_generator.hpp>
 #include <boost/smart_ptr/make_shared.hpp>
 
+#include <QA/Checker/IO.h>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
 #include <Swiften/Base/Algorithm.h>
 #include <Swiften/Base/ByteArray.h>
 #include <Swiften/Base/Concat.h>
 #include <Swiften/Base/Log.h>
 #include <Swiften/Base/StartStopper.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 #include <Swiften/EventLoop/DummyEventLoop.h>
 #include <Swiften/FileTransfer/ByteArrayReadBytestream.h>
 #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h>
@@ -30,8 +37,6 @@
 #include <Swiften/Network/DummyConnection.h>
 #include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/Crypto/CryptoProvider.h>
-#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -278,6 +283,9 @@ private:
 			}
 
 			HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+			
+			HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
+
 			void disconnect() {
 				disconnectCalled = true;
 			}
diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp
index 6e90815..f495795 100644
--- a/Swiften/Network/BoostConnection.cpp
+++ b/Swiften/Network/BoostConnection.cpp
@@ -1,28 +1,29 @@
 /*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
 
 #include <Swiften/Network/BoostConnection.h>
 
+#include <algorithm>
 #include <iostream>
 #include <string>
-#include <algorithm>
-#include <boost/bind.hpp>
-#include <boost/thread.hpp>
+
 #include <boost/asio/placeholders.hpp>
 #include <boost/asio/write.hpp>
-#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/bind.hpp>
 #include <boost/numeric/conversion/cast.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/thread.hpp>
 
-#include <Swiften/Base/Log.h>
 #include <Swiften/Base/Algorithm.h>
-#include <Swiften/EventLoop/EventLoop.h>
 #include <Swiften/Base/ByteArray.h>
-#include <Swiften/Network/HostAddressPort.h>
-#include <Swiften/Base/sleep.h>
+#include <Swiften/Base/Log.h>
 #include <Swiften/Base/SafeAllocator.h>
+#include <Swiften/Base/sleep.h>
+#include <Swiften/EventLoop/EventLoop.h>
+#include <Swiften/Network/HostAddressPort.h>
 
 namespace Swift {
 
@@ -169,5 +170,9 @@ HostAddressPort BoostConnection::getLocalAddress() const {
 	return HostAddressPort(socket_.local_endpoint());
 }
 
+HostAddressPort BoostConnection::getRemoteAddress() const {
+	return HostAddressPort(socket_.remote_endpoint());
+}
+
 
 }
diff --git a/Swiften/Network/BoostConnection.h b/Swiften/Network/BoostConnection.h
index 8e89263..f933cd8 100644
--- a/Swiften/Network/BoostConnection.h
+++ b/Swiften/Network/BoostConnection.h
@@ -48,7 +48,8 @@ namespace Swift {
 				return socket_;
 			}
 
-			HostAddressPort getLocalAddress() const;
+			virtual HostAddressPort getLocalAddress() const;
+			virtual HostAddressPort getRemoteAddress() const;
 
 			bool setClientCertificate(CertificateWithKey::ref cert);
 
diff --git a/Swiften/Network/BoostConnectionServer.cpp b/Swiften/Network/BoostConnectionServer.cpp
index 2a4a51b..48b323d 100644
--- a/Swiften/Network/BoostConnectionServer.cpp
+++ b/Swiften/Network/BoostConnectionServer.cpp
@@ -1,17 +1,20 @@
 /*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
 
 #include <Swiften/Network/BoostConnectionServer.h>
 
-#include <boost/bind.hpp>
-#include <boost/system/system_error.hpp>
+#include <boost/asio/ip/v6_only.hpp>
 #include <boost/asio/placeholders.hpp>
+#include <boost/bind.hpp>
 #include <boost/numeric/conversion/cast.hpp>
 #include <boost/optional.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
 
+#include <Swiften/Base/Log.h>
 #include <Swiften/EventLoop/EventLoop.h>
 
 namespace Swift {
@@ -32,15 +35,18 @@ void BoostConnectionServer::start() {
 boost::optional<BoostConnectionServer::Error> BoostConnectionServer::tryStart() {
 	try {
 		assert(!acceptor_);
+		boost::asio::ip::tcp::endpoint endpoint;
 		if (address_.isValid()) {
-			acceptor_ = new boost::asio::ip::tcp::acceptor(
-				*ioService_, 
-				boost::asio::ip::tcp::endpoint(address_.getRawAddress(), boost::numeric_cast<unsigned short>(port_)));
+			endpoint = boost::asio::ip::tcp::endpoint(address_.getRawAddress(), boost::numeric_cast<unsigned short>(port_));
 		}
 		else {
-			acceptor_ = new boost::asio::ip::tcp::acceptor(
-				*ioService_, 
-				boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), boost::numeric_cast<unsigned short>(port_)));
+			endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), boost::numeric_cast<unsigned short>(port_));
+		}
+		acceptor_ = new boost::asio::ip::tcp::acceptor(*ioService_, endpoint);
+		if (endpoint.protocol() ==  boost::asio::ip::tcp::v6()) {
+			boost::system::error_code ec;
+			acceptor_->set_option(boost::asio::ip::v6_only(false), ec);
+			SWIFT_LOG_ASSERT(ec, warning) << "IPv4/IPv6 dual-stack support is not supported on this platform." << std::endl;
 		}
 		acceptNextConnection();
 	}
diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h
index 91fc40d..39b63d4 100644
--- a/Swiften/Network/Connection.h
+++ b/Swiften/Network/Connection.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -7,10 +7,10 @@
 #pragma once
 
 #include <boost/shared_ptr.hpp>
-#include <Swiften/Base/boost_bsignals.h>
 
 #include <Swiften/Base/API.h>
 #include <Swiften/Base/SafeByteArray.h>
+#include <Swiften/Base/boost_bsignals.h>
 
 namespace Swift {
 	class HostAddressPort;
@@ -33,6 +33,7 @@ namespace Swift {
 			virtual void write(const SafeByteArray& data) = 0;
 
 			virtual HostAddressPort getLocalAddress() const = 0;
+			virtual HostAddressPort getRemoteAddress() const = 0; 
 
 		public:
 			boost::signal<void (bool /* error */)> onConnectFinished;
diff --git a/Swiften/Network/DummyConnection.h b/Swiften/Network/DummyConnection.h
index ef99c32..edc2473 100644
--- a/Swiften/Network/DummyConnection.h
+++ b/Swiften/Network/DummyConnection.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
@@ -9,10 +9,10 @@
 #include <boost/enable_shared_from_this.hpp>
 
 #include <Swiften/Base/API.h>
-#include <Swiften/Network/Connection.h>
-#include <Swiften/Network/HostAddressPort.h>
 #include <Swiften/EventLoop/EventLoop.h>
 #include <Swiften/EventLoop/EventOwner.h>
+#include <Swiften/Network/Connection.h>
+#include <Swiften/Network/HostAddressPort.h>
 
 namespace Swift {
 	class SWIFTEN_API DummyConnection : public Connection, public EventOwner,	public boost::enable_shared_from_this<DummyConnection> {
@@ -37,9 +37,14 @@ namespace Swift {
 				return localAddress;
 			}
 
+			HostAddressPort getRemoteAddress() const {
+				return remoteAddress;
+			}
+
 			boost::signal<void (const SafeByteArray&)> onDataSent;
 
 			EventLoop* eventLoop;
 			HostAddressPort localAddress;
+			HostAddressPort remoteAddress;
 	};
 }
diff --git a/Swiften/Network/FakeConnection.h b/Swiften/Network/FakeConnection.h
index 33a7fd9..ec62ad7 100644
--- a/Swiften/Network/FakeConnection.h
+++ b/Swiften/Network/FakeConnection.h
@@ -1,20 +1,21 @@
 /*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
 
 #pragma once
 
-#include <boost/optional.hpp>
-#include <boost/enable_shared_from_this.hpp>
 #include <vector>
 
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/optional.hpp>
+
 #include <Swiften/Base/API.h>
+#include <Swiften/EventLoop/EventLoop.h>
+#include <Swiften/EventLoop/EventOwner.h>
 #include <Swiften/Network/Connection.h>
 #include <Swiften/Network/HostAddressPort.h>
-#include <Swiften/EventLoop/EventOwner.h>
-#include <Swiften/EventLoop/EventLoop.h>
 
 namespace Swift {
 	class SWIFTEN_API FakeConnection : 
@@ -31,12 +32,15 @@ namespace Swift {
 			};
 
 			FakeConnection(EventLoop* eventLoop);
-			~FakeConnection();
+			virtual ~FakeConnection();
 
 			virtual void listen();
 			virtual HostAddressPort getLocalAddress() const {
 				return HostAddressPort();
 			}
+			virtual HostAddressPort getRemoteAddress() const {
+				return HostAddressPort();
+			}
 
 			void setError(const Error& e);
 			virtual void connect(const HostAddressPort& address);
diff --git a/Swiften/Network/ProxiedConnection.cpp b/Swiften/Network/ProxiedConnection.cpp
index 17f7e09..c44c1f5 100644
--- a/Swiften/Network/ProxiedConnection.cpp
+++ b/Swiften/Network/ProxiedConnection.cpp
@@ -104,6 +104,10 @@ HostAddressPort ProxiedConnection::getLocalAddress() const {
 	return connection_->getLocalAddress();
 }
 
+HostAddressPort ProxiedConnection::getRemoteAddress() const {
+	return connection_->getRemoteAddress();
+}
+
 void ProxiedConnection::setProxyInitializeFinished(bool success) {
 	connected_ = success;
 	if (!success) {
diff --git a/Swiften/Network/ProxiedConnection.h b/Swiften/Network/ProxiedConnection.h
index f301e84..f03c7ae 100644
--- a/Swiften/Network/ProxiedConnection.h
+++ b/Swiften/Network/ProxiedConnection.h
@@ -36,6 +36,7 @@ namespace Swift {
 			virtual void write(const SafeByteArray& data);
 
 			virtual HostAddressPort getLocalAddress() const;
+			virtual HostAddressPort getRemoteAddress() const;
 
 		private:
 			void handleConnectFinished(Connection::ref connection);
diff --git a/Swiften/Network/TLSConnection.cpp b/Swiften/Network/TLSConnection.cpp
index c69547d..c7087ae 100644
--- a/Swiften/Network/TLSConnection.cpp
+++ b/Swiften/Network/TLSConnection.cpp
@@ -66,6 +66,10 @@ HostAddressPort TLSConnection::getLocalAddress() const {
 	return connection->getLocalAddress();
 }
 
+HostAddressPort TLSConnection::getRemoteAddress() const {
+	return connection->getRemoteAddress();
+}
+
 TLSContext* TLSConnection::getTLSContext() const {
 	return context;
 }
diff --git a/Swiften/Network/TLSConnection.h b/Swiften/Network/TLSConnection.h
index a037eb1..b3acffc 100644
--- a/Swiften/Network/TLSConnection.h
+++ b/Swiften/Network/TLSConnection.h
@@ -32,6 +32,7 @@ namespace Swift {
 			virtual void write(const SafeByteArray& data);
 
 			virtual HostAddressPort getLocalAddress() const;
+			virtual HostAddressPort getRemoteAddress() const;
 
 			TLSContext* getTLSContext() const;
 
diff --git a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
index 83ad548..e8d8c4a 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionPoolTest.cpp
@@ -381,6 +381,7 @@ class BOSHConnectionPoolTest : public CppUnit::TestFixture {
 				}
 
 				HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+				HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
 
 				void disconnect() {
 					disconnected = true;
diff --git a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
index 349c282..8d26a09 100644
--- a/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/BOSHConnectionTest.cpp
@@ -236,6 +236,7 @@ class BOSHConnectionTest : public CppUnit::TestFixture {
 				}
 
 				HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+				HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
 
 				void disconnect() { 
 					disconnected = true;
diff --git a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
index 1fc19ba..3bafbf1 100644
--- a/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
+++ b/Swiften/Network/UnitTest/ChainedConnectorTest.cpp
@@ -1,23 +1,23 @@
 /*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
 
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-
 #include <boost/bind.hpp>
 #include <boost/smart_ptr/make_shared.hpp>
 
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <Swiften/EventLoop/DummyEventLoop.h>
 #include <Swiften/Network/ChainedConnector.h>
 #include <Swiften/Network/Connection.h>
 #include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/DomainNameResolveError.h>
+#include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/Network/HostAddressPort.h>
 #include <Swiften/Network/StaticDomainNameResolver.h>
-#include <Swiften/Network/DummyTimerFactory.h>
-#include <Swiften/EventLoop/DummyEventLoop.h>
-#include <Swiften/Network/DomainNameResolveError.h>
 
 using namespace Swift;
 
@@ -151,6 +151,7 @@ class ChainedConnectorTest : public CppUnit::TestFixture {
 				}
 
 				HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+				HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
 				void disconnect() { assert(false); }
 				void write(const SafeByteArray&) { assert(false); }
 
diff --git a/Swiften/Network/UnitTest/ConnectorTest.cpp b/Swiften/Network/UnitTest/ConnectorTest.cpp
index 161b114..a091074 100644
--- a/Swiften/Network/UnitTest/ConnectorTest.cpp
+++ b/Swiften/Network/UnitTest/ConnectorTest.cpp
@@ -1,23 +1,23 @@
 /*
- * Copyright (c) 2010-2014 Isode Limited.
+ * Copyright (c) 2010-2015 Isode Limited.
  * All rights reserved.
  * See the COPYING file for more information.
  */
 
+#include <boost/bind.hpp>
+#include <boost/optional.hpp>
+
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>
 
-#include <boost/optional.hpp>
-#include <boost/bind.hpp>
-
-#include <Swiften/Network/Connector.h>
+#include <Swiften/EventLoop/DummyEventLoop.h>
 #include <Swiften/Network/Connection.h>
 #include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/Connector.h>
+#include <Swiften/Network/DomainNameAddressQuery.h>
+#include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/Network/HostAddressPort.h>
 #include <Swiften/Network/StaticDomainNameResolver.h>
-#include <Swiften/Network/DummyTimerFactory.h>
-#include <Swiften/EventLoop/DummyEventLoop.h>
-#include <Swiften/Network/DomainNameAddressQuery.h>
 
 using namespace Swift;
 
@@ -341,6 +341,7 @@ class ConnectorTest : public CppUnit::TestFixture {
 				}
 
 				HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+				HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
 				void disconnect() { assert(false); }
 				void write(const SafeByteArray&) { assert(false); }
 
diff --git a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
index 56ace5c..1d01214 100644
--- a/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
+++ b/Swiften/Network/UnitTest/HTTPConnectProxiedConnectionTest.cpp
@@ -386,6 +386,7 @@ class HTTPConnectProxiedConnectionTest : public CppUnit::TestFixture {
 				}
 
 				HostAddressPort getLocalAddress() const { return HostAddressPort(); }
+				HostAddressPort getRemoteAddress() const { return HostAddressPort(); }
 
 				void disconnect() { 
 					disconnected = true;
diff --git a/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp b/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp
index abe2f05..67b4bfa 100644
--- a/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp
+++ b/Swiften/QA/NetworkTest/BoostConnectionServerTest.cpp
@@ -26,6 +26,7 @@ class BoostConnectionServerTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testIPv4Server);
 		CPPUNIT_TEST(testIPv6Server);
 		CPPUNIT_TEST(testIPv4IPv6DualStackServer);
+		CPPUNIT_TEST(testIPv6DualStackServerPeerAddress);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -36,6 +37,7 @@ class BoostConnectionServerTest : public CppUnit::TestFixture {
 			stoppedError_.reset();
 			receivedNewConnection_ = false;
 			connectFinished_ = false;
+			remoteAddress_ = boost::optional<HostAddressPort>();
 		}
 
 		void tearDown() {
@@ -147,13 +149,54 @@ class BoostConnectionServerTest : public CppUnit::TestFixture {
 			testling->stop();
 		}
 
+		void testIPv6DualStackServerPeerAddress() {
+			BoostConnectionServer::ref testling = BoostConnectionServer::create(HostAddress("::"), 9999, boostIOServiceThread_->getIOService(), eventLoop_);
+			testling->onNewConnection.connect(boost::bind(&BoostConnectionServerTest::handleNewConnection, this, _1));
+			testling->start();
+
+			// Test IPv4.
+			BoostConnection::ref clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_);
+			clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1));
+			clientTestling->connect(HostAddressPort(HostAddress("127.0.0.1"), 9999));
+
+			while (!connectFinished_) {
+				Swift::sleep(10);
+				eventLoop_->processEvents();
+			}
+
+			CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_);
+			// The IPv4 localhost mapped to a IPv6 address is expected here.
+			CPPUNIT_ASSERT(HostAddress("::ffff:127.0.0.1") == remoteAddress_.get().getAddress());
+
+			receivedNewConnection_ = false;
+			connectFinished_ = false;
+			remoteAddress_ = boost::optional<HostAddressPort>();
+
+			// Test IPv6.
+			clientTestling = BoostConnection::create(boostIOServiceThread_->getIOService(), eventLoop_);
+			clientTestling->onConnectFinished.connect(boost::bind(&BoostConnectionServerTest::handleConnectFinished, this, _1));
+			clientTestling->connect(HostAddressPort(HostAddress("::1"), 9999));
+
+			while (!connectFinished_) {
+				Swift::sleep(10);
+				eventLoop_->processEvents();
+			}
+
+			CPPUNIT_ASSERT_EQUAL(true, receivedNewConnection_);
+			// The IPv6 local host is expected here.
+			CPPUNIT_ASSERT(HostAddress("::1") == remoteAddress_.get().getAddress());
+
+			testling->stop();
+		}
+
 		void handleStopped_(boost::optional<BoostConnectionServer::Error> e) {
 			stopped_ = true;
 			stoppedError_ = e;
 		}
 
-		void handleNewConnection(boost::shared_ptr<Connection> /*connection*/) {
+		void handleNewConnection(boost::shared_ptr<Connection> connection) {
 			receivedNewConnection_ = true;
+			remoteAddress_ = connection->getRemoteAddress();
 		}
 
 		void handleConnectFinished(bool /*error*/) {
@@ -167,6 +210,7 @@ class BoostConnectionServerTest : public CppUnit::TestFixture {
 		bool receivedNewConnection_;
 		bool connectFinished_;
 		boost::optional<BoostConnectionServer::Error> stoppedError_;
+		boost::optional<HostAddressPort> remoteAddress_;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(BoostConnectionServerTest);
-- 
cgit v0.10.2-6-g49f6