diff --git a/src/dorkbox/network/dns/server/CNAMEResponse.java b/src/dorkbox/network/dns/server/CNAMEResponse.java new file mode 100644 index 00000000..0dd044c6 --- /dev/null +++ b/src/dorkbox/network/dns/server/CNAMEResponse.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.server; + + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.constants.DnsResponseCode; +import dorkbox.network.dns.records.DnsMessage; +import dorkbox.network.dns.records.DnsRecord; + +public class CNAMEResponse extends DefaultResponse { + final Name cname; + final int qtype; + + public CNAMEResponse(DnsRecord cname, int queryType) { + super(DnsResponseCode.NOERROR); + this.cname = cname.getName(); + this.qtype = queryType; + } + + @Override + public void postProcess(DnsMessage message) { + System.err.println("WHAT?"); + + // context.response().answer().add(this.cname); + // Response r = context.resolve(this.cname.oneName(), this.qtype); + // r.postProcess(context); + } +} diff --git a/src/dorkbox/network/dns/server/DNAMEResponse.java b/src/dorkbox/network/dns/server/DNAMEResponse.java new file mode 100644 index 00000000..a9c59ad1 --- /dev/null +++ b/src/dorkbox/network/dns/server/DNAMEResponse.java @@ -0,0 +1,54 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.server; + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.constants.DnsResponseCode; +import dorkbox.network.dns.records.DnsMessage; +import dorkbox.network.dns.records.DnsRecord; + +public class DNAMEResponse extends DefaultResponse { + + final Name dname; + final Name qname; + final int qtype; + + public DNAMEResponse(DnsRecord dname, Name qname, int qtype) { + super(DnsResponseCode.NOERROR); + + this.dname = dname.getName(); + this.qname = qname; + this.qtype = qtype; + } + + @Override + public void postProcess(DnsMessage context) { + System.err.println("WWHAT?"); + // DNSMessage res = context.response(); + // res.answer().add(this.dname); + // Name name = this.qname.replace(this.dname.name(), this.dname.oneName()); + // if (name == null) { + // context.response().header().rcode(RCode.YXDomain); + // } else { + // SingleNameRecord cname = new SingleNameRecord(RRType.CNAME, name); + // cname.name(this.qname); + // res.answer().add(cname); + // res.header().aa(true); + // Response r = context.resolve(name, this.qtype); + // r.postProcess(context); + // } + } +} diff --git a/src/dorkbox/network/dns/server/DefaultResponse.java b/src/dorkbox/network/dns/server/DefaultResponse.java new file mode 100644 index 00000000..d2baa942 --- /dev/null +++ b/src/dorkbox/network/dns/server/DefaultResponse.java @@ -0,0 +1,35 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.server; + +/** + * + */ +public abstract +class DefaultResponse implements Response { + private final int responseCode; + + public + DefaultResponse(int responseCode) { + this.responseCode = responseCode; + } + + @Override + public + int responseCode() { + return responseCode; + } +} diff --git a/src/dorkbox/network/dns/server/NoErrorResponse.java b/src/dorkbox/network/dns/server/NoErrorResponse.java new file mode 100644 index 00000000..9360f02d --- /dev/null +++ b/src/dorkbox/network/dns/server/NoErrorResponse.java @@ -0,0 +1,67 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.server; + +import java.util.Set; + +import dorkbox.network.dns.constants.DnsResponseCode; +import dorkbox.network.dns.constants.DnsSection; +import dorkbox.network.dns.constants.Flags; +import dorkbox.network.dns.records.DnsMessage; +import dorkbox.network.dns.records.DnsRecord; + +public +class NoErrorResponse extends DefaultResponse { + final Set records; + final boolean authoritativeAnswer; + + public + NoErrorResponse(Set records) { + this(records, true); + } + + public + NoErrorResponse(Set records, boolean authoritativeAnswer) { + super(DnsResponseCode.NOERROR); + this.records = records; + this.authoritativeAnswer = authoritativeAnswer; + } + + @Override + public + void postProcess(DnsMessage message) { + message.getHeader() + .setRcode(this.responseCode()); + + message.getHeader() + .setFlag(Flags.QR); + + if (this.authoritativeAnswer) { + message.getHeader() + .setFlag(Flags.AA); + } + else { + message.getHeader() + .unsetFlag(Flags.AA); + } + + for (DnsRecord record : records) { + message.addRecord(record, DnsSection.ANSWER); + } + + // TODO additional section ? + } +} diff --git a/src/dorkbox/network/dns/server/NotFoundResponse.java b/src/dorkbox/network/dns/server/NotFoundResponse.java new file mode 100644 index 00000000..a625e265 --- /dev/null +++ b/src/dorkbox/network/dns/server/NotFoundResponse.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.server; + +import dorkbox.network.dns.constants.DnsSection; +import dorkbox.network.dns.records.DnsMessage; +import dorkbox.network.dns.records.SOARecord; + +/** + * + */ +public +class NotFoundResponse extends DefaultResponse { + + final SOARecord soaRecord; + + public + NotFoundResponse(int rcode, SOARecord soaRecord) { + super(rcode); + this.soaRecord = soaRecord; + } + + @Override + public + void postProcess(DnsMessage message) { + message.getHeader().setRcode(this.responseCode()); + message.addRecord(this.soaRecord, DnsSection.AUTHORITY); + } +} diff --git a/src/dorkbox/network/dns/server/ReferralResponse.java b/src/dorkbox/network/dns/server/ReferralResponse.java new file mode 100644 index 00000000..0447df78 --- /dev/null +++ b/src/dorkbox/network/dns/server/ReferralResponse.java @@ -0,0 +1,41 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.server; + +import java.util.Set; + +import dorkbox.network.dns.constants.DnsResponseCode; +import dorkbox.network.dns.constants.DnsSection; +import dorkbox.network.dns.records.DnsMessage; +import dorkbox.network.dns.records.DnsRecord; + +public class ReferralResponse extends DefaultResponse { + final Set nsRecords; + + public ReferralResponse(Set records) { + super(DnsResponseCode.NOERROR); + this.nsRecords = records; + } + + @Override + public void postProcess(DnsMessage message) { + message.getHeader().setRcode(this.responseCode()); + + for (DnsRecord nsRecord : nsRecords) { + message.addRecord(nsRecord, DnsSection.AUTHORITY); + } + } +} diff --git a/src/dorkbox/network/dns/server/Response.java b/src/dorkbox/network/dns/server/Response.java new file mode 100644 index 00000000..5607711b --- /dev/null +++ b/src/dorkbox/network/dns/server/Response.java @@ -0,0 +1,28 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.server; + +import dorkbox.network.dns.records.DnsMessage; + +/** + * + */ +public +interface Response { + int responseCode(); + + void postProcess(DnsMessage message); +} diff --git a/src/dorkbox/network/dns/zone/AbstractZone.java b/src/dorkbox/network/dns/zone/AbstractZone.java new file mode 100644 index 00000000..44799ce5 --- /dev/null +++ b/src/dorkbox/network/dns/zone/AbstractZone.java @@ -0,0 +1,54 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.constants.DnsClass; + +public abstract class AbstractZone implements Zone { + + protected ZoneType type; + + protected int dnsClass; + + protected Name name; + + public AbstractZone(ZoneType type, Name name) { + this(type, DnsClass.IN, name); + } + + public AbstractZone(ZoneType type, int dnsClass, Name name) { + this.type = type; + this.dnsClass = dnsClass; + this.name = name; + } + + @Override + public ZoneType type() { + return this.type; + } + + @Override + public int dnsClass() { + return this.dnsClass; + } + + @Override + public Name name() { + return this.name; + } + +} diff --git a/src/dorkbox/network/dns/zone/ForwardZone.java b/src/dorkbox/network/dns/zone/ForwardZone.java new file mode 100644 index 00000000..895e7d4b --- /dev/null +++ b/src/dorkbox/network/dns/zone/ForwardZone.java @@ -0,0 +1,47 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.server.Response; + +public class ForwardZone extends AbstractZone { + + protected List forwarders = new ArrayList(); + + public ForwardZone(Name name) { + super(ZoneType.forward, name); + } + + public ForwardZone(int dnsclass, Name name) { + super(ZoneType.forward, dnsclass, name); + } + + public void addForwardHost(InetAddress host) { + this.forwarders.add(host); + } + + @Override + public + Response find(Name qname, int recordType) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/dorkbox/network/dns/zone/MasterZone.java b/src/dorkbox/network/dns/zone/MasterZone.java new file mode 100644 index 00000000..2309aacd --- /dev/null +++ b/src/dorkbox/network/dns/zone/MasterZone.java @@ -0,0 +1,211 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +import java.util.HashSet; +import java.util.NavigableSet; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.ConcurrentSkipListSet; + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.constants.DnsRecordType; +import dorkbox.network.dns.constants.DnsResponseCode; +import dorkbox.network.dns.records.DnsRecord; +import dorkbox.network.dns.records.SOARecord; +import dorkbox.network.dns.server.CNAMEResponse; +import dorkbox.network.dns.server.DNAMEResponse; +import dorkbox.network.dns.server.NoErrorResponse; +import dorkbox.network.dns.server.NotFoundResponse; +import dorkbox.network.dns.server.ReferralResponse; +import dorkbox.network.dns.server.Response; + +public +class MasterZone extends AbstractZone { + + final ConcurrentMap>> records = new ConcurrentSkipListMap>>(); + + final Response nxDomain; + final Response nxRRSet; + + public + MasterZone(Name name, SOARecord soaRecord) { + super(ZoneType.master, name); + + this.nxDomain = new NotFoundResponse(DnsResponseCode.NXDOMAIN, soaRecord); + this.nxRRSet = new NotFoundResponse(DnsResponseCode.NXRRSET, soaRecord); + } + + // add and remove needs queuing? + // if modify operations works on single thread, not conflict. + public synchronized + void add(DnsRecord rr) { + + for (; ; ) { + ConcurrentMap> current = this.records.get(rr.getName()); + if (current == null) { + ConcurrentMap> newone = new ConcurrentSkipListMap>(); + NavigableSet newset = new ConcurrentSkipListSet(); + newset.add(rr); + newone.put(rr.getType(), newset); + + ConcurrentMap> prevTypes = this.records.putIfAbsent(rr.getName(), newone); + if (prevTypes == null) { + break; + } + synchronized (prevTypes) { + Set prevRecs = prevTypes.putIfAbsent(rr.getType(), newset); + if (prevRecs == null) { + break; + } + prevRecs.add(rr); + break; + } + } + else { + synchronized (current) { + Set rrs = current.get(rr.getType()); + if (rrs == null) { + NavigableSet newset = new ConcurrentSkipListSet(); + newset.add(rr); + current.put(rr.getType(), newset); + break; + } + if (!rrs.isEmpty()) { + rrs.add(rr); + break; + } + } + } + } + } + + @Override + public + Response find(Name queryName, int recordType) { + if (!queryName.equals(this.name)) { + return this.nxDomain; + } + + ConcurrentMap> exactMatch = this.records.get(queryName); + + if (exactMatch != null) { + NavigableSet rrs = exactMatch.get(recordType); + + if (rrs != null) { + synchronized (rrs) { + if (rrs.isEmpty()) { + return new NoErrorResponse(rrs); + } + } + } + + if (DnsRecordType.ANY == recordType) { + Set newset = new HashSet(); + for (Integer type : exactMatch.keySet()) { + Set s = exactMatch.get(type); + if (s != null) { + synchronized (s) { + newset.addAll(s); + } + } + } + + if (newset.isEmpty()) { + return null; + } + } + + if (DnsRecordType.CNAME == recordType) { + rrs = exactMatch.get(DnsRecordType.CNAME); + + if (rrs != null) { + synchronized (rrs) { + if (!rrs.isEmpty()) { + return new CNAMEResponse(rrs.first(), recordType); + } + } + } + } + + return this.nxRRSet; + } + + for (Name qn = queryName.parent(1); !this.name() + .equals(qn); qn = qn.parent(1)) { + ConcurrentMap> match = this.records.get(qn); + + if (match != null) { + synchronized (match) { + if (!match.isEmpty()) { + NavigableSet set = match.get(DnsRecordType.NS); + if ((set != null) && (!set.isEmpty())) { + return new ReferralResponse(set); + } + + set = match.get(DnsRecordType.DNAME); + if ((set != null) && (!set.isEmpty())) { + return new DNAMEResponse(set.first(), queryName, recordType); + } + } + } + } + } + + for (Name qn = queryName; !this.name() + .equals(qn); qn = qn.parent(1)) { + Name wild = qn.wild(1); + + ConcurrentMap> match = this.records.get(wild); + if (match != null) { + synchronized (match) { + if (!match.isEmpty()) { + Set matchSet = match.get(recordType); + + if (!matchSet.isEmpty()) { + Set set = new HashSet(matchSet.size()); + for (DnsRecord rr : matchSet) { + set.add(DnsRecord.newRecord(queryName, rr.getType(), rr.getDClass(), rr.getTTL())); + } + + return new NoErrorResponse(set); + } + } + } + } + } + + return this.nxDomain; + } + + public synchronized + void remove(DnsRecord rr, boolean checkSets, boolean checkMap) { + ConcurrentMap> current = this.records.get(rr.getName()); + if (current != null) { + synchronized (current) { + NavigableSet sets = current.get(rr.getType()); + sets.remove(rr); + if (checkSets && sets.isEmpty()) { + current.remove(rr.getType()); + if (checkMap && current.isEmpty()) { + this.records.remove(rr.getName()); + } + } + } + } + } +} diff --git a/src/dorkbox/network/dns/zone/Query.java b/src/dorkbox/network/dns/zone/Query.java new file mode 100644 index 00000000..45cee24a --- /dev/null +++ b/src/dorkbox/network/dns/zone/Query.java @@ -0,0 +1,59 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + + +import java.util.List; + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.records.DnsRecord; + +/** + * @author taichi + */ +public +class Query { + + protected Name origin; + protected Name current; + + protected int dnsClass; + + protected Zone target; + + protected ZoneDatabase database; + + public + Query(Name origin, Name current, int dnsClass, Zone target, ZoneDatabase database) { + super(); + + this.origin = origin; + this.current = current; + this.dnsClass = dnsClass; + this.target = target; + this.database = database; + } + + protected + boolean contains(List rrs) { + for (DnsRecord rr : rrs) { + if (this.origin.equals(rr.getName())) { + return true; + } + } + return false; + } +} diff --git a/src/dorkbox/network/dns/zone/SearchResult.java b/src/dorkbox/network/dns/zone/SearchResult.java new file mode 100644 index 00000000..e72e12d0 --- /dev/null +++ b/src/dorkbox/network/dns/zone/SearchResult.java @@ -0,0 +1,36 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +import java.util.List; + +import dorkbox.network.dns.records.DnsRecord; + +public class SearchResult { + + public enum Status { + NXDOMAIN, SUCCESS + } + + List rrs; + + Status status = Status.NXDOMAIN; + + public SearchResult(List rrs) { + super(); + this.rrs = rrs; + } +} diff --git a/src/dorkbox/network/dns/zone/Zone.java b/src/dorkbox/network/dns/zone/Zone.java new file mode 100644 index 00000000..c9750ac4 --- /dev/null +++ b/src/dorkbox/network/dns/zone/Zone.java @@ -0,0 +1,30 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.server.Response; + +public +interface Zone { + int dnsClass(); + + Response find(Name qname, int recordType); + + Name name(); + + ZoneType type(); +} diff --git a/src/dorkbox/network/dns/zone/ZoneDatabase.java b/src/dorkbox/network/dns/zone/ZoneDatabase.java new file mode 100644 index 00000000..dc1bfbc6 --- /dev/null +++ b/src/dorkbox/network/dns/zone/ZoneDatabase.java @@ -0,0 +1,63 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +import java.util.Map; +import java.util.concurrent.ConcurrentSkipListMap; + +import dorkbox.network.dns.Name; + +public +class ZoneDatabase { + + protected Map zones = new ConcurrentSkipListMap(); + + public + void add(Zone zone/* TODO ZoneConfig? */) { + this.zones.put(new ZoneDatabaseKey(zone), zone); + } + + public + Query prepare(Name name, int dnsClass) { + ZoneDatabaseKey zk = new ZoneDatabaseKey(name, dnsClass); + Zone found = this.zones.get(zk); + if (found != null) { + // exact match + return new Query(name, name, dnsClass, found, this); + } + + Name child = name; + // partial match + for (int i = 0, size = this.zones.size(); i < size; i++) { + Name p = child.parent(1); + zk.name(p); + found = this.zones.get(zk); + if (found == null) { + if (p.labels() <= 1) { + break; + } + + child = p; + } + else { + return new Query(name, p, dnsClass, found, this); + } + } + + // not found. + return null; + } +} diff --git a/src/dorkbox/network/dns/zone/ZoneDatabaseKey.java b/src/dorkbox/network/dns/zone/ZoneDatabaseKey.java new file mode 100644 index 00000000..0622b57a --- /dev/null +++ b/src/dorkbox/network/dns/zone/ZoneDatabaseKey.java @@ -0,0 +1,95 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +import dorkbox.network.dns.Name; +import dorkbox.network.dns.records.DnsRecord; + +/** + * + */ +class ZoneDatabaseKey implements Comparable { + Name name; + int dnsclass; + + public + ZoneDatabaseKey(Zone z) { + this(z.name(), z.dnsClass()); + } + + public + ZoneDatabaseKey(DnsRecord rr) { + this(rr.getName(), rr.getDClass()); + } + + public + ZoneDatabaseKey(Name name, int dnsclass) { + this.name = name; + this.dnsclass = dnsclass; + } + + @Override + public + int compareTo(ZoneDatabaseKey o) { + if (o == null) { + return 1; + } + if (equals(o)) { + return 0; + } + return this.hashCode() - o.hashCode(); + } + + public + boolean equals(ZoneDatabaseKey other) { + return (this.dnsclass == other.dnsclass) && this.name.equals(other.name); + } + + @Override + public + boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null) { + return false; + } + if (getClass() != other.getClass()) { + return false; + } + return equals((ZoneDatabaseKey) other); + } + + @Override + public + int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + this.dnsclass; + result = prime * result + this.name.hashCode(); + return result; + } + + public + Name name() { + return this.name; + } + + public + void name(Name name) { + this.name = name; + } +} diff --git a/src/dorkbox/network/dns/zone/ZoneType.java b/src/dorkbox/network/dns/zone/ZoneType.java new file mode 100644 index 00000000..3bc7f60f --- /dev/null +++ b/src/dorkbox/network/dns/zone/ZoneType.java @@ -0,0 +1,21 @@ +/* + * Copyright 2018 dorkbox, llc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.network.dns.zone; + +public +enum ZoneType { + master, slave, stub, forward, rootHint +}