summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2012-07-17 06:58:38 (GMT)
committerKevin Smith <git@kismith.co.uk>2012-07-17 11:01:15 (GMT)
commit8568b7b74fe962bf6d3252e9967aa3123968615c (patch)
tree2dd65509241cd52cb87df764c2255cec599fce12 /src
parentdbb5beeeb522bd937f235c619321594a25247749 (diff)
downloadstroke-8568b7b74fe962bf6d3252e9967aa3123968615c.zip
stroke-8568b7b74fe962bf6d3252e9967aa3123968615c.tar.bz2
Move DNS resolution into a thread to make the API asyncronous.
Diffstat (limited to 'src')
-rw-r--r--src/com/isode/stroke/network/PlatformDomainNameResolver.java94
-rw-r--r--src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java200
2 files changed, 75 insertions, 219 deletions
diff --git a/src/com/isode/stroke/network/PlatformDomainNameResolver.java b/src/com/isode/stroke/network/PlatformDomainNameResolver.java
index 45c8dce..ccdee6d 100644
--- a/src/com/isode/stroke/network/PlatformDomainNameResolver.java
+++ b/src/com/isode/stroke/network/PlatformDomainNameResolver.java
@@ -1,14 +1,14 @@
/*
- * Copyright (c) 2010, Isode Limited, London, England.
+ * Copyright (c) 2010-2012, Isode Limited, London, England.
* All rights reserved.
*/
/*
* Copyright (c) 2010, Remko Tronçon.
* All rights reserved.
*/
-
package com.isode.stroke.network;
+import com.isode.stroke.eventloop.Event.Callback;
import com.isode.stroke.eventloop.EventLoop;
import com.isode.stroke.eventloop.EventOwner;
import java.net.InetAddress;
@@ -16,79 +16,44 @@ import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
-
public class PlatformDomainNameResolver extends DomainNameResolver {
private class AddressQuery extends DomainNameAddressQuery implements EventOwner {
- AddressQuery(String host, EventLoop eventLoop) {
+
+ private class AddressQueryThread extends Thread {
+ @Override
+ public void run() {
+ final Collection<HostAddress> results = new ArrayList<HostAddress>();
+ try {
+ results.add(new HostAddress(InetAddress.getByName(hostname)));
+ } catch (UnknownHostException ex) {
+ }
+ eventLoop.postEvent(new Callback() {
+ public void run() {
+ onResult.emit(results, results.isEmpty() ? new DomainNameResolveError() : null);
+ }
+ });
+ }
+ }
+
+ AddressQuery(String host, EventLoop eventLoop) {
hostname = host;
this.eventLoop = eventLoop;
- //FIXME: port asyncDNS
-// thread = null;
-// safeToJoin = false;
}
- public void run() {
- //FIXME: port asyncDNS
- Collection<HostAddress> results = new ArrayList<HostAddress>();
- try {
- results.add(new HostAddress(InetAddress.getByName(hostname)));
- } catch (UnknownHostException ex) {
-
- }
- onResult.emit(results, results.isEmpty() ? new DomainNameResolveError() : null);
-
-// safeToJoin = false;
-// thread = new boost::thread(boost::bind(&AddressQuery::doRun, shared_from_this()));
- }
-// FIXME: Port async DNS.
-// 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;
- }
+ public void run() {
+ AddressQueryThread thread = new AddressQueryThread();
+ thread.setDaemon(true);
+ thread.start();
+ }
+ final String hostname;
+ final EventLoop eventLoop;
+ }
public PlatformDomainNameResolver(EventLoop eventLoop) {
this.eventLoop = eventLoop;
}
-
+
@Override
public DomainNameServiceQuery createServiceQuery(String name) {
return new PlatformDomainNameServiceQuery(getNormalized(name), eventLoop);
@@ -98,6 +63,5 @@ public class PlatformDomainNameResolver extends DomainNameResolver {
public DomainNameAddressQuery createAddressQuery(String name) {
return new AddressQuery(getNormalized(name), eventLoop);
}
-
private final EventLoop eventLoop;
}
diff --git a/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java b/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java
index 17b5478..66a38cc 100644
--- a/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java
+++ b/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java
@@ -1,15 +1,16 @@
/*
+ * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * All rights reserved.
+ */
+/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-/*
- * Copyright (c) 2010, Isode Limited, London, England.
- * All rights reserved.
- */
package com.isode.stroke.network;
+import com.isode.stroke.eventloop.Event.Callback;
import com.isode.stroke.eventloop.EventLoop;
import com.isode.stroke.eventloop.EventOwner;
import java.util.ArrayList;
@@ -21,9 +22,46 @@ import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
-
public class PlatformDomainNameServiceQuery extends DomainNameServiceQuery implements EventOwner {
+ private class QueryThread extends Thread {
+
+ @Override
+ public void run() {
+ final Collection<Result> results = new ArrayList<Result>();
+ Hashtable env = new Hashtable();
+ env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
+ env.put("java.naming.provider.url", "dns:");
+ try {
+ DirContext ctx = new InitialDirContext(env);
+ Attributes attrs = ctx.getAttributes(service, new String[]{"SRV"});
+ Attribute attribute = attrs.get("SRV");
+ for (int i = 0; attribute != null && i < attribute.size(); i++) {
+ /* SRV results are going to be returned in the space-separated format
+ * Priority Weight Port Target
+ * (See RFC2782)
+ */
+ String[] srvParts = ((String) attribute.get(i)).split(" ");
+ String host = srvParts[3];
+ if (host.endsWith(".")) {
+ host = host.substring(0, host.length() - 1);
+ }
+ Result result = new Result(host, Integer.parseInt(srvParts[2]), Integer.parseInt(srvParts[0]), Integer.parseInt(srvParts[1]));
+ results.add(result);
+ }
+ } catch (NamingException ex) {
+ /* Turns out that you get the exception just for not finding a result, so we want to fall through to A lookups and ignore.*/
+ }
+
+ eventLoop.postEvent(new Callback() {
+ public void run() {
+ onResult.emit(results);
+ }
+ });
+
+ }
+ }
+
public PlatformDomainNameServiceQuery(String service, EventLoop eventLoop) {
this.service = service;
this.eventLoop = eventLoop;
@@ -31,156 +69,10 @@ public class PlatformDomainNameServiceQuery extends DomainNameServiceQuery imple
@Override
public void run() {
- //TODO: Make async
- Collection<Result> results = new ArrayList<Result>();
- Hashtable env = new Hashtable();
- env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
- env.put("java.naming.provider.url", "dns:");
- try {
- DirContext ctx = new InitialDirContext(env);
- Attributes attrs = ctx.getAttributes(this.service, new String[]{"SRV"});
- Attribute attribute = attrs.get("SRV");
- for (int i = 0; attribute != null && i < attribute.size(); i++) {
- /* SRV results are going to be returned in the space-separated format
- * Priority Weight Port Target
- * (See RFC2782)
- */
- String[] srvParts = ((String) attribute.get(i)).split(" ");
- String host = srvParts[3];
- if (host.endsWith(".")) {
- host = host.substring(0, host.length() - 1);
- }
- Result result = new Result(host, Integer.parseInt(srvParts[2]), Integer.parseInt(srvParts[0]), Integer.parseInt(srvParts[1]));
- results.add(result);
- }
- } catch (NamingException ex) {
- /* Turns out that you get the exception just for not finding a result, so we want to fall through to A lookups and ignore.*/
- }
-
- onResult.emit(results);
+ QueryThread thread = new QueryThread();
+ thread.setDaemon(true);
+ thread.start();
}
-
-
-// void PlatformDomainNameServiceQuery::doRun() {
-// std::vector<DomainNameServiceQuery::Result> records;
-//
-//#if defined(SWIFTEN_PLATFORM_WINDOWS)
-// DNS_RECORD* responses;
-// // FIXME: This conversion doesn't work if unicode is deffed above
-// if (DnsQuery(service.getUTF8Data(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &responses, NULL) != ERROR_SUCCESS) {
-// emitError();
-// return;
-// }
-//
-// DNS_RECORD* currentEntry = responses;
-// while (currentEntry) {
-// if (currentEntry->wType == DNS_TYPE_SRV) {
-// DomainNameServiceQuery::Result record;
-// record.priority = currentEntry->Data.SRV.wPriority;
-// record.weight = currentEntry->Data.SRV.wWeight;
-// record.port = currentEntry->Data.SRV.wPort;
-//
-// // The pNameTarget is actually a PCWSTR, so I would have expected this
-// // conversion to not work at all, but it does.
-// // Actually, it doesn't. Fix this and remove explicit cast
-// // Remove unicode undef above as well
-// record.hostname = String((const char*) currentEntry->Data.SRV.pNameTarget);
-// records.push_back(record);
-// }
-// currentEntry = currentEntry->pNext;
-// }
-// DnsRecordListFree(responses, DnsFreeRecordList);
-//
-//#else
-// // Make sure we reinitialize the domain list every time
-// res_init();
-//
-// //std::cout << "SRV: Querying " << service << std::endl;
-// ByteArray response;
-// response.resize(NS_PACKETSZ);
-// int responseLength = res_query(const_cast<char*>(service.getUTF8Data()), ns_c_in, ns_t_srv, reinterpret_cast<u_char*>(response.getData()), response.getSize());
-// if (responseLength == -1) {
-// emitError();
-// return;
-// }
-//
-// // Parse header
-// HEADER* header = reinterpret_cast<HEADER*>(response.getData());
-// unsigned char* messageStart = reinterpret_cast<unsigned char*>(response.getData());
-// unsigned char* messageEnd = messageStart + responseLength;
-// unsigned char* currentEntry = messageStart + NS_HFIXEDSZ;
-//
-// // Skip over the queries
-// int queriesCount = ntohs(header->qdcount);
-// while (queriesCount > 0) {
-// int entryLength = dn_skipname(currentEntry, messageEnd);
-// if (entryLength < 0) {
-// emitError();
-// return;
-// }
-// currentEntry += entryLength + NS_QFIXEDSZ;
-// queriesCount--;
-// }
-//
-// // Process the SRV answers
-// int answersCount = ntohs(header->ancount);
-// while (answersCount > 0) {
-// DomainNameServiceQuery::Result record;
-//
-// int entryLength = dn_skipname(currentEntry, messageEnd);
-// currentEntry += entryLength;
-// currentEntry += NS_RRFIXEDSZ;
-//
-// // Priority
-// if (currentEntry + 2 >= messageEnd) {
-// emitError();
-// return;
-// }
-// record.priority = ns_get16(currentEntry);
-// currentEntry += 2;
-//
-// // Weight
-// if (currentEntry + 2 >= messageEnd) {
-// emitError();
-// return;
-// }
-// record.weight = ns_get16(currentEntry);
-// currentEntry += 2;
-//
-// // Port
-// if (currentEntry + 2 >= messageEnd) {
-// emitError();
-// return;
-// }
-// record.port = ns_get16(currentEntry);
-// currentEntry += 2;
-//
-// // Hostname
-// if (currentEntry >= messageEnd) {
-// emitError();
-// return;
-// }
-// ByteArray entry;
-// entry.resize(NS_MAXDNAME);
-// entryLength = dn_expand(messageStart, messageEnd, currentEntry, entry.getData(), entry.getSize());
-// if (entryLength < 0) {
-// emitError();
-// return;
-// }
-// record.hostname = String(entry.getData());
-// records.push_back(record);
-// currentEntry += entryLength;
-// answersCount--;
-// }
-//#endif
-//
-// safeToJoin = true;
-// std::sort(records.begin(), records.end(), ResultPriorityComparator());
-// //std::cout << "Sending out " << records.size() << " SRV results " << std::endl;
-// eventLoop->postEvent(boost::bind(boost::ref(onResult), records));
-//}
-
-
private final String service;
private final EventLoop eventLoop;
}