diff options
-rw-r--r-- | Swiften/Network/BoostNetworkFactories.cpp | 2 | ||||
-rwxr-xr-x | Swiften/Network/UnboundDomainNameResolver.cpp | 18 | ||||
-rwxr-xr-x | Swiften/Network/UnboundDomainNameResolver.h | 6 | ||||
-rw-r--r-- | Swiften/QA/NetworkTest/DomainNameResolverTest.cpp | 4 |
4 files changed, 19 insertions, 11 deletions
diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp index 72e826a..870ae97 100644 --- a/Swiften/Network/BoostNetworkFactories.cpp +++ b/Swiften/Network/BoostNetworkFactories.cpp @@ -12,61 +12,61 @@ #include <Swiften/Network/PlatformNATTraversalWorker.h> #include <Swiften/Parser/PlatformXMLParserFactory.h> #include <Swiften/Network/NullNATTraverser.h> #include <Swiften/Network/PlatformNetworkEnvironment.h> #include <Swiften/TLS/PlatformTLSFactories.h> #include <Swiften/Network/PlatformProxyProvider.h> #include <Swiften/IDN/PlatformIDNConverter.h> #include <Swiften/IDN/IDNConverter.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/Crypto/CryptoProvider.h> #ifdef USE_UNBOUND #include <Swiften/Network/UnboundDomainNameResolver.h> #else #include <Swiften/Network/PlatformDomainNameResolver.h> #endif namespace Swift { BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(eventLoop){ timerFactory = new BoostTimerFactory(ioServiceThread.getIOService(), eventLoop); connectionFactory = new BoostConnectionFactory(ioServiceThread.getIOService(), eventLoop); connectionServerFactory = new BoostConnectionServerFactory(ioServiceThread.getIOService(), eventLoop); #ifdef SWIFT_EXPERIMENTAL_FT natTraverser = new PlatformNATTraversalWorker(eventLoop); #else natTraverser = new NullNATTraverser(eventLoop); #endif networkEnvironment = new PlatformNetworkEnvironment(); xmlParserFactory = new PlatformXMLParserFactory(); tlsFactories = new PlatformTLSFactories(); proxyProvider = new PlatformProxyProvider(); idnConverter = PlatformIDNConverter::create(); #ifdef USE_UNBOUND // TODO: What to do about idnConverter. - domainNameResolver = new UnboundDomainNameResolver(ioServiceThread.getIOService(), eventLoop); + domainNameResolver = new UnboundDomainNameResolver(idnConverter, ioServiceThread.getIOService(), eventLoop); #else domainNameResolver = new PlatformDomainNameResolver(idnConverter, eventLoop); #endif cryptoProvider = PlatformCryptoProvider::create(); } BoostNetworkFactories::~BoostNetworkFactories() { delete cryptoProvider; delete domainNameResolver; delete idnConverter; delete proxyProvider; delete tlsFactories; delete xmlParserFactory; delete networkEnvironment; delete natTraverser; delete connectionServerFactory; delete connectionFactory; delete timerFactory; } TLSContextFactory* BoostNetworkFactories::getTLSContextFactory() const { return tlsFactories->getTLSContextFactory(); } } diff --git a/Swiften/Network/UnboundDomainNameResolver.cpp b/Swiften/Network/UnboundDomainNameResolver.cpp index d986385..bc280eb 100755 --- a/Swiften/Network/UnboundDomainNameResolver.cpp +++ b/Swiften/Network/UnboundDomainNameResolver.cpp @@ -1,51 +1,52 @@ /* * Copyright (c) 2013 Tobias Markmann * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #include "UnboundDomainNameResolver.h" #include <vector> #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <boost/enable_shared_from_this.hpp> #include <Swiften/Base/Log.h> #include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/IDN/IDNConverter.h> #include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/DomainNameResolveError.h> #include <Swiften/Network/DomainNameServiceQuery.h> #include <Swiften/Network/HostAddress.h> #include <Swiften/Network/TimerFactory.h> #include <arpa/inet.h> #include <unbound.h> #include <ldns/ldns.h> #include <unistd.h> namespace Swift { class UnboundQuery { public: UnboundQuery(UnboundDomainNameResolver* resolver, ub_ctx* context) : resolver(resolver), ubContext(context) {} virtual ~UnboundQuery() {} virtual void handleResult(int err, ub_result* result) = 0; protected: UnboundDomainNameResolver* resolver; ub_ctx* ubContext; }; struct UnboundWrapperHelper { UnboundWrapperHelper(UnboundDomainNameResolver* resolver, boost::shared_ptr<UnboundQuery> query) : resolver(resolver), query(query) {} UnboundDomainNameResolver* resolver; boost::shared_ptr<UnboundQuery> query; }; class UnboundDomainNameServiceQuery : public DomainNameServiceQuery, public UnboundQuery, public boost::enable_shared_from_this<UnboundDomainNameServiceQuery> { public: UnboundDomainNameServiceQuery(UnboundDomainNameResolver* resolver, ub_ctx* context, std::string name) : UnboundQuery(resolver, context), name(name) { } virtual ~UnboundDomainNameServiceQuery() { } @@ -141,101 +142,106 @@ class UnboundDomainNameAddressQuery : public DomainNameAddressQuery, public Unbo boost::optional<DomainNameResolveError> error; SWIFT_LOG(debug) << "Result for: " << name << std::endl; if(err != 0) { SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err) << std::endl; error = DomainNameResolveError(); } else { if(result->havedata) { for(int i=0; result->data[i]; i++) { char address[100]; const char* addressStr = 0; if ((addressStr = inet_ntop(AF_INET, result->data[i], address, 100))) { SWIFT_LOG(debug) << "IPv4 address: " << addressStr << std::endl; addresses.push_back(HostAddress(std::string(addressStr))); } else if ((addressStr = inet_ntop(AF_INET6, result->data[i], address, 100))) { SWIFT_LOG(debug) << "IPv6 address: " << addressStr << std::endl; addresses.push_back(HostAddress(std::string(addressStr))); } else { SWIFT_LOG(debug) << "inet_ntop() failed" << std::endl; error = DomainNameResolveError(); } } } else { error = DomainNameResolveError(); } } ub_resolve_free(result); onResult(addresses, error); } private: std::string name; }; -UnboundDomainNameResolver::UnboundDomainNameResolver(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), ubDescriptior(*ioService), eventLoop(eventLoop) { +UnboundDomainNameResolver::UnboundDomainNameResolver(IDNConverter* idnConverter, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : idnConverter(idnConverter), ioService(ioService), ubDescriptior(*ioService), eventLoop(eventLoop) { ubContext = ub_ctx_create(); if(!ubContext) { SWIFT_LOG(debug) << "could not create unbound context" << std::endl; } eventOwner = boost::make_shared<EventOwner>(); ub_ctx_async(ubContext, true); int ret; /* read /etc/resolv.conf for DNS proxy settings (from DHCP) */ if( (ret=ub_ctx_resolvconf(ubContext, const_cast<char*>("/etc/resolv.conf"))) != 0) { - SWIFT_LOG(debug) << "error reading resolv.conf: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; + SWIFT_LOG(error) << "error reading resolv.conf: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; } /* read /etc/hosts for locally supplied host addresses */ if( (ret=ub_ctx_hosts(ubContext, const_cast<char*>("/etc/hosts"))) != 0) { - SWIFT_LOG(debug) << "error reading hosts: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; + SWIFT_LOG(error) << "error reading hosts: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; } ubDescriptior.assign(ub_fd(ubContext)); ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); } UnboundDomainNameResolver::~UnboundDomainNameResolver() { eventLoop->removeEventsFromOwner(eventOwner); if (ubContext) { ub_ctx_delete(ubContext); } } void UnboundDomainNameResolver::unbound_callback(boost::shared_ptr<UnboundQuery> query, int err, ub_result* result) { query->handleResult(err, result); } void UnboundDomainNameResolver::unbound_callback_wrapper(void* data, int err, ub_result* result) { UnboundWrapperHelper* helper = static_cast<UnboundWrapperHelper*>(data); UnboundDomainNameResolver* resolver = helper->resolver; resolver->unbound_callback(helper->query, err, result); delete helper; } void UnboundDomainNameResolver::handleUBSocketReadable(boost::system::error_code) { eventLoop->postEvent(boost::bind(&UnboundDomainNameResolver::processData, this), eventOwner); ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); } void UnboundDomainNameResolver::processData() { if (ub_poll(ubContext)) { int ret = ub_process(ubContext); if(ret != 0) { SWIFT_LOG(debug) << "resolve error: " << ub_strerror(ret) << std::endl; } } } -boost::shared_ptr<DomainNameServiceQuery> UnboundDomainNameResolver::createServiceQuery(const std::string& name) { - return boost::make_shared<UnboundDomainNameServiceQuery>(this, ubContext, name); +boost::shared_ptr<DomainNameServiceQuery> UnboundDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) { + boost::optional<std::string> encodedDomain = idnConverter->getIDNAEncoded(domain); + std::string result; + if (encodedDomain) { + result = serviceLookupPrefix + *encodedDomain; + } + return boost::make_shared<UnboundDomainNameServiceQuery>(this, ubContext, result); } boost::shared_ptr<DomainNameAddressQuery> UnboundDomainNameResolver::createAddressQuery(const std::string& name) { - return boost::make_shared<UnboundDomainNameAddressQuery>(this, ubContext, name); + return boost::make_shared<UnboundDomainNameAddressQuery>(this, ubContext, idnConverter->getIDNAEncoded(name).get_value_or("")); } } diff --git a/Swiften/Network/UnboundDomainNameResolver.h b/Swiften/Network/UnboundDomainNameResolver.h index 0db8a66..6b78cf3 100755 --- a/Swiften/Network/UnboundDomainNameResolver.h +++ b/Swiften/Network/UnboundDomainNameResolver.h @@ -1,51 +1,53 @@ /* * Copyright (c) 2013 Tobias Markmann * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #pragma once #include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/Timer.h> #include <Swiften/EventLoop/EventOwner.h> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/asio.hpp> struct ub_ctx; struct ub_result; namespace Swift { class EventLoop; + class IDNConverter; class TimerFactory; class UnboundDomainNameResolver; class UnboundQuery; class UnboundDomainNameResolver : public DomainNameResolver, public EventOwner, public boost::enable_shared_from_this<UnboundDomainNameResolver> { public: - UnboundDomainNameResolver(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); + UnboundDomainNameResolver(IDNConverter* idnConverter, boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); virtual ~UnboundDomainNameResolver(); - virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name); + virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain); virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name); static void unbound_callback_wrapper(void* data, int err, ub_result* result); private: void unbound_callback(boost::shared_ptr<UnboundQuery> query, int err, ub_result* result); void handleUBSocketReadable(boost::system::error_code); void processData(); private: + IDNConverter* idnConverter; boost::shared_ptr<EventOwner> eventOwner; boost::shared_ptr<boost::asio::io_service> ioService; boost::asio::posix::stream_descriptor ubDescriptior; EventLoop* eventLoop; ub_ctx* ubContext; }; } diff --git a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp index 6d25f49..dcd2be8 100644 --- a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp +++ b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp @@ -23,74 +23,74 @@ #include <Swiften/Network/DomainNameAddressQuery.h> #include <Swiften/Network/DomainNameServiceQuery.h> #include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/IDN/IDNConverter.h> #include <Swiften/IDN/PlatformIDNConverter.h> using namespace Swift; struct CompareHostAddresses { bool operator()(const HostAddress& h1, const HostAddress& h2) { return h1.toString() < h2.toString(); } }; class DomainNameResolverTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DomainNameResolverTest); CPPUNIT_TEST(testResolveAddress); CPPUNIT_TEST(testResolveAddress_Error); #ifndef USE_UNBOUND CPPUNIT_TEST(testResolveAddress_IPv6); CPPUNIT_TEST(testResolveAddress_IPv4and6); CPPUNIT_TEST(testResolveAddress_International); #endif CPPUNIT_TEST(testResolveAddress_Localhost); CPPUNIT_TEST(testResolveAddress_Parallel); #ifndef USE_UNBOUND CPPUNIT_TEST(testResolveService); #endif CPPUNIT_TEST(testResolveService_Error); CPPUNIT_TEST_SUITE_END(); public: void setUp() { ioServiceThread = new BoostIOServiceThread(); eventLoop = new DummyEventLoop(); + idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); #ifdef USE_UNBOUND - resolver = new UnboundDomainNameResolver(ioServiceThread->getIOService(), eventLoop); + resolver = new UnboundDomainNameResolver(idnConverter.get(), ioServiceThread->getIOService(), eventLoop); #else - idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); resolver = new PlatformDomainNameResolver(idnConverter.get(), eventLoop); #endif resultsAvailable = false; } void tearDown() { delete ioServiceThread; delete resolver; delete eventLoop; } void testResolveAddress() { boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp.test.swift.im")); query->run(); waitForResults(); CPPUNIT_ASSERT(!addressQueryError); CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addressQueryResult.size())); CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), addressQueryResult[0].toString()); } void testResolveAddress_Error() { boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("invalid.test.swift.im")); query->run(); waitForResults(); CPPUNIT_ASSERT(addressQueryError); } void testResolveAddress_IPv6() { boost::shared_ptr<DomainNameAddressQuery> query(createAddressQuery("xmpp-ipv6.test.swift.im")); query->run(); |