summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/Network/BoostNetworkFactories.cpp2
-rwxr-xr-xSwiften/Network/UnboundDomainNameResolver.cpp18
-rwxr-xr-xSwiften/Network/UnboundDomainNameResolver.h6
-rw-r--r--Swiften/QA/NetworkTest/DomainNameResolverTest.cpp4
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();