summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Network/BoostNetworkFactories.cpp5
-rw-r--r--Swiften/Network/SConscript9
-rw-r--r--Swiften/Network/UnboundDomainNameResolver.cpp221
-rw-r--r--Swiften/Network/UnboundDomainNameResolver.h22
-rw-r--r--Swiften/SConscript3
5 files changed, 258 insertions, 2 deletions
diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp
index 488e519..091a70a 100644
--- a/Swiften/Network/BoostNetworkFactories.cpp
+++ b/Swiften/Network/BoostNetworkFactories.cpp
@@ -15,12 +15,15 @@
#include <Swiften/TLS/PlatformTLSFactories.h>
#include <Swiften/Network/PlatformProxyProvider.h>
+#include <Swiften/Network/UnboundDomainNameResolver.h>
+
namespace Swift {
BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(eventLoop){
timerFactory = new BoostTimerFactory(ioServiceThread.getIOService(), eventLoop);
connectionFactory = new BoostConnectionFactory(ioServiceThread.getIOService(), eventLoop);
- domainNameResolver = new PlatformDomainNameResolver(eventLoop);
+ domainNameResolver = new UnboundDomainNameResolver(eventLoop, timerFactory);
+ //domainNameResolver = new PlatformDomainNameResolver(eventLoop);
connectionServerFactory = new BoostConnectionServerFactory(ioServiceThread.getIOService(), eventLoop);
#ifdef SWIFT_EXPERIMENTAL_FT
natTraverser = new PlatformNATTraversalWorker(eventLoop);
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index 0d0abbd..429ca51 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -5,6 +5,10 @@ myenv.MergeFlags(myenv["LIBIDN_FLAGS"])
if myenv.get("HAVE_CARES", False) :
myenv.MergeFlags(myenv.get("CARES_FLAGS", {}))
+if myenv.get("unbound", False) :
+ myenv.MergeFlags(myenv.get("UNBOUND_FLAGS", {}))
+ myenv.MergeFlags(myenv.get("LDNS_FLAGS", {}))
+
sourceList = [
"HTTPConnectProxiedConnection.cpp",
"HTTPConnectProxiedConnectionFactory.cpp",
@@ -17,7 +21,7 @@ sourceList = [
"BoostIOServiceThread.cpp",
"BOSHConnection.cpp",
"BOSHConnectionPool.cpp",
- "CachingNameOnlyDomainNameResolver.cpp",
+ "CachingNameOnlyDomainNameResolver.cpp",
"ConnectionFactory.cpp",
"ConnectionServer.cpp",
"ConnectionServerFactory.cpp",
@@ -57,6 +61,9 @@ sourceList = [
if myenv.get("HAVE_CARES", False) :
sourceList.append("CAresDomainNameResolver.cpp")
+
+if myenv.get("unbound", False) :
+ sourceList.append("UnboundDomainNameResolver.cpp")
if myenv["PLATFORM"] == "darwin" :
myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"])
diff --git a/Swiften/Network/UnboundDomainNameResolver.cpp b/Swiften/Network/UnboundDomainNameResolver.cpp
new file mode 100644
index 0000000..1b36012
--- /dev/null
+++ b/Swiften/Network/UnboundDomainNameResolver.cpp
@@ -0,0 +1,221 @@
+#include "UnboundDomainNameResolver.h"
+
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Base/Log.h>
+#include <Swiften/Network/DomainNameAddressQuery.h>
+#include <Swiften/Network/DomainNameResolveError.h>
+#include <Swiften/Network/DomainNameServiceQuery.h>
+#include <Swiften/Network/HostAddress.h>
+#include <Swiften/Network/Timer.h>
+#include <Swiften/Network/TimerFactory.h>
+
+
+#include <arpa/inet.h>
+#include <ldns/ldns.h>
+#include <unbound.h>
+#include <unistd.h>
+
+namespace Swift {
+
+class UnboundDomainNameServiceQuery : public DomainNameServiceQuery {
+ public:
+ UnboundDomainNameServiceQuery(TimerFactory* timerFactory, const std::string& name) : timerFactory(timerFactory), name(name), ubContext(0) {
+
+ }
+
+ virtual ~UnboundDomainNameServiceQuery() {
+ if (ubContext) {
+ ub_ctx_delete(ubContext);
+ }
+ }
+
+ static void unbound_service_callback(void* data, int err, struct ub_result* result) {
+ UnboundDomainNameServiceQuery* query = static_cast<UnboundDomainNameServiceQuery*>(data);
+ query->handleResult(err, result);
+ }
+
+ virtual void run() {
+ int retval;
+
+ /* create context */
+ ubContext = ub_ctx_create();
+ if(!ubContext) {
+ SWIFT_LOG(debug) << "could not create unbound context" << std::endl;
+ return;
+ }
+ ub_ctx_async(ubContext, true);
+ retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_SRV,
+ 1 /* CLASS IN (internet) */,
+ this, unbound_service_callback, NULL);
+ if(retval != 0) {
+ SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval) << std::endl;
+ }
+
+ timer = timerFactory->createTimer(500);
+ timer->onTick.connect(boost::bind(&UnboundDomainNameServiceQuery::processData, this));
+ timer->start();
+ }
+
+ void processData() {
+ if (ub_poll(ubContext)) {
+ int ret = ub_process(ubContext);
+ if(ret != 0) {
+ SWIFT_LOG(debug) << "resolve error: " << ub_strerror(ret) << std::endl;
+ }
+ } else {
+ timer->start();
+ }
+ }
+
+ void handleResult(int err, struct ub_result* result) {
+ std::vector<DomainNameServiceQuery::Result> serviceRecords;
+
+ if(err != 0) {
+ SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err) << std::endl;
+ } else {
+ if(result->havedata) {
+ ldns_pkt* replyPacket = 0;
+ ldns_buffer* buffer = ldns_buffer_new(1024);
+ if (buffer && ldns_wire2pkt(&replyPacket, static_cast<const uint8_t*>(result->answer_packet), result->answer_len) == LDNS_STATUS_OK) {
+ ldns_rr_list* rrList = ldns_pkt_answer(replyPacket);
+ for (size_t n = 0; n < ldns_rr_list_rr_count(rrList); n++) {
+ ldns_rr* rr = ldns_rr_list_rr(rrList, n);
+ if ((ldns_rr_get_type(rr) != LDNS_RR_TYPE_SRV) ||
+ (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) ||
+ (ldns_rr_rd_count(rr) != 4)) {
+ continue;
+ }
+
+ DomainNameServiceQuery::Result serviceRecord;
+ serviceRecord.priority = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
+ serviceRecord.weight = ldns_rdf2native_int16(ldns_rr_rdf(rr, 1));
+ serviceRecord.port = ldns_rdf2native_int16(ldns_rr_rdf(rr, 2));
+
+ ldns_buffer_rewind(buffer);
+ if ((ldns_rdf2buffer_str_dname(buffer, ldns_rr_rdf(rr, 3)) != LDNS_STATUS_OK) ||
+ (ldns_buffer_position(buffer) < 2) ||
+ !ldns_buffer_reserve(buffer, 1)) {
+ // either name invalid, empty or buffer to small
+ continue;
+ }
+ char terminator = 0;
+ ldns_buffer_write(buffer, &terminator, sizeof(terminator));
+
+ serviceRecord.hostname = std::string(reinterpret_cast<char*>(ldns_buffer_at(buffer, 0)));
+ serviceRecords.push_back(serviceRecord);
+ SWIFT_LOG(debug) << "hostname " << serviceRecord.hostname << " added" << std::endl;
+ }
+ }
+ if (replyPacket) ldns_pkt_free(replyPacket);
+ if (buffer) ldns_buffer_free(buffer);
+ }
+ }
+
+ ub_resolve_free(result);
+ onResult(serviceRecords);
+ }
+
+ private:
+ TimerFactory* timerFactory;
+ Timer::ref timer;
+ std::string name;
+ ub_ctx* ubContext;
+};
+
+class UnboundDomainNameAddressQuery : public DomainNameAddressQuery {
+ public:
+ UnboundDomainNameAddressQuery(TimerFactory* timerFactory, const std::string& name) : timerFactory(timerFactory), name(name), ubContext(0) {
+
+ }
+
+ virtual ~UnboundDomainNameAddressQuery() {
+ if (ubContext) {
+ ub_ctx_delete(ubContext);
+ }
+ }
+
+ static void unbound_address_callback(void* data, int err, struct ub_result* result) {
+ UnboundDomainNameAddressQuery* query = static_cast<UnboundDomainNameAddressQuery*>(data);
+ query->handleResult(err, result);
+ }
+
+ virtual void run() {
+ int retval;
+
+ /* create context */
+ ubContext = ub_ctx_create();
+ if(!ubContext) {
+ SWIFT_LOG(debug) << "could not create unbound context" << std::endl;
+ return;
+ }
+
+ ub_ctx_async(ubContext, true);
+ retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_A,
+ 1 /* CLASS IN (internet) */,
+ this, unbound_address_callback, NULL);
+ if(retval != 0) {
+ SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval) << std::endl;
+ }
+
+ timer = timerFactory->createTimer(500);
+ timer->onTick.connect(boost::bind(&UnboundDomainNameAddressQuery::processData, this));
+ timer->start();
+ }
+
+ void processData() {
+ if (ub_poll(ubContext)) {
+ int ret = ub_process(ubContext);
+ if(ret != 0) {
+ SWIFT_LOG(debug) << "resolve error: " << ub_strerror(ret) << std::endl;
+ }
+ } else {
+ timer->start();
+ }
+ }
+
+ void handleResult(int err, struct ub_result* result) {
+ std::vector<HostAddress> addresses;
+ boost::optional<DomainNameResolveError> error;
+
+ 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++) {
+ addresses.push_back(HostAddress(std::string(inet_ntoa(* (struct in_addr*)result->data[i]))));
+ }
+ }
+ }
+
+ ub_resolve_free(result);
+ onResult(addresses, error);
+ }
+
+ private:
+ TimerFactory* timerFactory;
+ Timer::ref timer;
+ std::string name;
+ ub_ctx* ubContext;
+
+};
+
+UnboundDomainNameResolver::UnboundDomainNameResolver(EventLoop* eventLoop, TimerFactory* timerFactory) : eventLoop(eventLoop), timerFactory(timerFactory) {
+}
+
+UnboundDomainNameResolver::~UnboundDomainNameResolver() {
+}
+
+boost::shared_ptr<DomainNameServiceQuery> UnboundDomainNameResolver::createServiceQuery(const std::string& name) {
+ return boost::make_shared<UnboundDomainNameServiceQuery>(timerFactory, name);
+}
+
+boost::shared_ptr<DomainNameAddressQuery> UnboundDomainNameResolver::createAddressQuery(const std::string& name) {
+ return boost::make_shared<UnboundDomainNameAddressQuery>(timerFactory, name);
+}
+
+}
diff --git a/Swiften/Network/UnboundDomainNameResolver.h b/Swiften/Network/UnboundDomainNameResolver.h
new file mode 100644
index 0000000..37cf2f6
--- /dev/null
+++ b/Swiften/Network/UnboundDomainNameResolver.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <Swiften/Network/DomainNameResolver.h>
+
+namespace Swift {
+ class EventLoop;
+ class TimerFactory;
+
+ class UnboundDomainNameResolver : public DomainNameResolver {
+ public:
+ UnboundDomainNameResolver(EventLoop* eventLoop, TimerFactory* timerFactory);
+ virtual ~UnboundDomainNameResolver();
+
+ virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name);
+ virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name);
+
+ private:
+ EventLoop* eventLoop;
+ TimerFactory* timerFactory;
+ };
+
+}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index c12d3b2..42c1588 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -8,6 +8,9 @@ Import("env")
swiften_dep_modules = ["BOOST", "GCONF", "LIBIDN", "ZLIB", "OPENSSL", "LIBXML", "EXPAT", "AVAHI", "LIBMINIUPNPC", "LIBNATPMP"]
+if env["unbound"] :
+ swiften_dep_modules.extend(["LDNS", "UNBOUND"])
+
if env["SCONS_STAGE"] == "flags" :
env["SWIFTEN_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift")
version_match = re.match("(\d+)\.(\d+).*", env["SWIFTEN_VERSION"])