Add Cache to minidns

This commit is contained in:
Florian Schmaus 2014-06-12 09:29:35 +02:00
parent f66c0db63f
commit 7dd8cfc6e6
4 changed files with 88 additions and 43 deletions

View file

@ -24,6 +24,18 @@ if (isSnapshot) {
version += '-SNAPSHOT'
}
repositories {
mavenLocal()
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
dependencies {
compile 'org.igniterealtime.jxmpp:jxmpp-util-cache:0.1.0-alpha1-SNAPSHOT'
}
jar {
manifest {
instruction 'Implementation-GitRevision:', project.ext.gitCommit

View file

@ -17,6 +17,8 @@ import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jxmpp.util.cache.ExpirationCache;
import de.measite.minidns.Record.CLASS;
import de.measite.minidns.Record.TYPE;
@ -28,6 +30,9 @@ public class Client {
private static final Logger LOGGER = Logger.getLogger(Client.class.getName());
protected static final ExpirationCache<Question, DNSMessage> cache = new ExpirationCache<Question, DNSMessage>(
10, 1000 * 60 * 60 * 24);
/**
* The internal random class for sequence generation.
*/
@ -67,10 +72,7 @@ public class Client {
public DNSMessage query(String name, TYPE type, CLASS clazz, String host, int port)
throws IOException
{
Question q = new Question();
q.setClazz(clazz);
q.setType(type);
q.setName(name);
Question q = new Question(name, type, clazz);
return query(q, host, port);
}
@ -86,10 +88,7 @@ public class Client {
public DNSMessage query(String name, TYPE type, CLASS clazz, String host)
throws IOException
{
Question q = new Question();
q.setClazz(clazz);
q.setType(type);
q.setName(name);
Question q = new Question(name, type, clazz);
return query(q, host);
}
@ -102,10 +101,7 @@ public class Client {
*/
public DNSMessage query(String name, TYPE type, CLASS clazz)
{
Question q = new Question();
q.setClazz(clazz);
q.setType(type);
q.setName(name);
Question q = new Question(name, type, clazz);
return query(q);
}
@ -127,6 +123,10 @@ public class Client {
* @throws IOException On IOErrors.
*/
public DNSMessage query(Question q, String host, int port) throws IOException {
DNSMessage dnsMessage = cache.get(q);
if (dnsMessage != null) {
return dnsMessage;
}
DNSMessage message = new DNSMessage();
message.setQuestions(new Question[]{q});
message.setRecursionDesired(true);
@ -139,10 +139,16 @@ public class Client {
socket.send(packet);
packet = new DatagramPacket(new byte[bufferSize], bufferSize);
socket.receive(packet);
DNSMessage dnsMessage = DNSMessage.parse(packet.getData());
dnsMessage = DNSMessage.parse(packet.getData());
if (dnsMessage.getId() != message.getId()) {
return null;
}
for (Record record : dnsMessage.getAnswers()) {
if (record.isAnswer(q)) {
cache.put(q, dnsMessage, record.ttl);
break;
}
}
return dnsMessage;
}
}
@ -152,10 +158,19 @@ public class Client {
* @param q The question section of the DNS query.
*/
public DNSMessage query(Question q) {
// While this query method does in fact re-use query(Question, String)
// we still do a cache lookup here in order to avoid unnecessary
// findDNS()calls, which are expensive on Android. Note that we do not
// put the results back into the Cache, as this is already done by
// query(Question, String).
DNSMessage message = cache.get(q);
if (message != null) {
return message;
}
String dnsServer[] = findDNS();
for (String dns : dnsServer) {
try {
DNSMessage message = query(q, dns);
message = query(q, dns);
if (message == null) {
continue;
}

View file

@ -416,8 +416,7 @@ public class DNSMessage {
int additionalResourceRecordCount = dis.readUnsignedShort();
message.questions = new Question[questionCount];
while (questionCount-- > 0) {
Question q = new Question();
q.parse(dis, data);
Question q = Question.parse(dis, data);
message.questions[questionCount] = q;
}
message.answers = new Record[answerCount];

View file

@ -11,52 +11,71 @@ import de.measite.minidns.util.NameUtil;
public class Question {
private String name;
private final String name;
private TYPE type;
private final TYPE type;
private CLASS clazz = CLASS.IN;
private final CLASS clazz;
private byte[] byteArray;
public Question(String name, TYPE type, CLASS clazz) {
this.name = name;
this.type = type;
this.clazz = clazz;
}
public TYPE getType() {
return type;
}
public void setType(TYPE type) {
this.type = type;
}
public CLASS getClazz() {
return clazz;
}
public void setClazz(CLASS clazz) {
this.clazz = clazz;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
public static Question parse(DataInputStream dis, byte[] data) throws IOException {
String name = NameUtil.parse(dis, data);
TYPE type = TYPE.getType(dis.readUnsignedShort());
CLASS clazz = CLASS.getClass(dis.readUnsignedShort());
return new Question (name, type, clazz);
}
public void parse(DataInputStream dis, byte[] data) throws IOException {
this.name = NameUtil.parse(dis, data);
this.type = TYPE.getType(dis.readUnsignedShort());
this.clazz = CLASS.getClass(dis.readUnsignedShort());
public byte[] toByteArray() {
if (byteArray == null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.write(NameUtil.toByteArray(this.name));
dos.writeShort(type.getValue());
dos.writeShort(clazz.getValue());
dos.flush();
} catch (IOException e) {
// Should never happen
throw new IllegalStateException(e);
}
byteArray = baos.toByteArray();
}
return byteArray;
}
public byte[] toByteArray() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
DataOutputStream dos = new DataOutputStream(baos);
dos.write(NameUtil.toByteArray(this.name));
dos.writeShort(type.getValue());
dos.writeShort(clazz.getValue());
dos.flush();
return baos.toByteArray();
@Override
public int hashCode() {
return toByteArray().hashCode();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Question)) {
return false;
}
return this.hashCode() == other.hashCode();
}
}