summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2010-12-18 18:50:50 (GMT)
committerRemko Tronçon <git@el-tramo.be>2010-12-18 18:50:50 (GMT)
commit312a114c7e204cfe4cfe961509ab9b24ccde7860 (patch)
tree7649aba8b50de49f5259709ee3d34b035d83b33b /Swiften/Network/PlatformDomainNameResolver.cpp
parent790dd3e97c6634f6a256f2e072507b9d5f29348b (diff)
downloadswift-312a114c7e204cfe4cfe961509ab9b24ccde7860.zip
swift-312a114c7e204cfe4cfe961509ab9b24ccde7860.tar.bz2
Move all domain name resolve queries into one thread.
This avoids reentrancy problems on some platform DNS calls. Resolves: #443
Diffstat (limited to 'Swiften/Network/PlatformDomainNameResolver.cpp')
-rw-r--r--Swiften/Network/PlatformDomainNameResolver.cpp105
1 files changed, 37 insertions, 68 deletions
diff --git a/Swiften/Network/PlatformDomainNameResolver.cpp b/Swiften/Network/PlatformDomainNameResolver.cpp
index 3f72466..6a61337 100644
--- a/Swiften/Network/PlatformDomainNameResolver.cpp
+++ b/Swiften/Network/PlatformDomainNameResolver.cpp
@@ -11,10 +11,8 @@
#include <string>
#include <vector>
-#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
-#include <boost/enable_shared_from_this.hpp>
#include <algorithm>
#include "Swiften/Base/String.h"
@@ -23,84 +21,55 @@
#include "Swiften/EventLoop/EventLoop.h"
#include "Swiften/Network/HostAddressPort.h"
#include "Swiften/Network/DomainNameAddressQuery.h"
+#include <Swiften/Network/PlatformDomainNameAddressQuery.h>
using namespace Swift;
-namespace {
- struct AddressQuery : public DomainNameAddressQuery, public boost::enable_shared_from_this<AddressQuery>, public EventOwner {
- AddressQuery(const String& host, EventLoop* eventLoop) : hostname(host), eventLoop(eventLoop), thread(NULL), safeToJoin(false) {}
-
- ~AddressQuery() {
- if (safeToJoin) {
- thread->join();
- }
- else {
- // FIXME: UGLYYYYY
- }
- delete thread;
- }
-
- void run() {
- safeToJoin = false;
- thread = new boost::thread(boost::bind(&AddressQuery::doRun, shared_from_this()));
- }
-
- void doRun() {
- //std::cout << "PlatformDomainNameResolver::doRun()" << std::endl;
- boost::asio::ip::tcp::resolver resolver(ioService);
- boost::asio::ip::tcp::resolver::query query(hostname.getUTF8String(), "5222");
- try {
- //std::cout << "PlatformDomainNameResolver::doRun(): Resolving" << std::endl;
- boost::asio::ip::tcp::resolver::iterator endpointIterator = resolver.resolve(query);
- //std::cout << "PlatformDomainNameResolver::doRun(): Resolved" << std::endl;
- if (endpointIterator == boost::asio::ip::tcp::resolver::iterator()) {
- //std::cout << "PlatformDomainNameResolver::doRun(): Error 1" << std::endl;
- emitError();
- }
- else {
- 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;
- eventLoop->postEvent(
- boost::bind(boost::ref(onResult), results, boost::optional<DomainNameResolveError>()),
- shared_from_this());
- }
- }
- catch (...) {
- //std::cout << "PlatformDomainNameResolver::doRun(): Error 2" << std::endl;
- emitError();
- }
- safeToJoin = true;
- }
-
- void emitError() {
- eventLoop->postEvent(boost::bind(boost::ref(onResult), std::vector<HostAddress>(), boost::optional<DomainNameResolveError>(DomainNameResolveError())), shared_from_this());
- }
-
- boost::asio::io_service ioService;
- String hostname;
- EventLoop* eventLoop;
- boost::thread* thread;
- bool safeToJoin;
- };
+namespace Swift {
+PlatformDomainNameResolver::PlatformDomainNameResolver(EventLoop* eventLoop) : eventLoop(eventLoop), stopRequested(false) {
+ thread = new boost::thread(boost::bind(&PlatformDomainNameResolver::run, this));
}
-namespace Swift {
-
-PlatformDomainNameResolver::PlatformDomainNameResolver(EventLoop* eventLoop) : eventLoop(eventLoop) {
+PlatformDomainNameResolver::~PlatformDomainNameResolver() {
+ stopRequested = true;
+ addQueryToQueue(boost::shared_ptr<PlatformDomainNameQuery>());
+ thread->join();
}
boost::shared_ptr<DomainNameServiceQuery> PlatformDomainNameResolver::createServiceQuery(const String& name) {
- return boost::shared_ptr<DomainNameServiceQuery>(new PlatformDomainNameServiceQuery(IDNA::getEncoded(name), eventLoop));
+ return boost::shared_ptr<DomainNameServiceQuery>(new PlatformDomainNameServiceQuery(IDNA::getEncoded(name), eventLoop, this));
}
boost::shared_ptr<DomainNameAddressQuery> PlatformDomainNameResolver::createAddressQuery(const String& name) {
- return boost::shared_ptr<DomainNameAddressQuery>(new AddressQuery(IDNA::getEncoded(name), eventLoop));
+ return boost::shared_ptr<DomainNameAddressQuery>(new PlatformDomainNameAddressQuery(IDNA::getEncoded(name), eventLoop, this));
+}
+
+void PlatformDomainNameResolver::run() {
+ while (!stopRequested) {
+ PlatformDomainNameQuery::ref query;
+ {
+ boost::unique_lock<boost::mutex> lock(queueMutex);
+ while (queue.empty()) {
+ queueNonEmpty.wait(lock);
+ }
+ query = queue.front();
+ queue.pop_front();
+ }
+ // Check whether we don't have a non-null query (used to stop the
+ // resolver)
+ if (query) {
+ query->runBlocking();
+ }
+ }
+}
+
+void PlatformDomainNameResolver::addQueryToQueue(PlatformDomainNameQuery::ref query) {
+ {
+ boost::lock_guard<boost::mutex> lock(queueMutex);
+ queue.push_back(query);
+ }
+ queueNonEmpty.notify_one();
}
}