add dns resolver code
This commit is contained in:
parent
ada04aef58
commit
fc565512cc
131 changed files with 21681 additions and 0 deletions
3
netty-handler-codec-dns/build.gradle
Normal file
3
netty-handler-codec-dns/build.gradle
Normal file
|
@ -0,0 +1,3 @@
|
|||
dependencies {
|
||||
api project(':netty-handler')
|
||||
}
|
|
@ -0,0 +1,478 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.util.AbstractReferenceCounted;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import io.netty.util.ReferenceCounted;
|
||||
import io.netty.util.ResourceLeakDetector;
|
||||
import io.netty.util.ResourceLeakDetectorFactory;
|
||||
import io.netty.util.ResourceLeakTracker;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
/**
|
||||
* A skeletal implementation of {@link DnsMessage}.
|
||||
*/
|
||||
@UnstableApi
|
||||
public abstract class AbstractDnsMessage extends AbstractReferenceCounted implements DnsMessage {
|
||||
|
||||
private static final ResourceLeakDetector<DnsMessage> leakDetector =
|
||||
ResourceLeakDetectorFactory.instance().newResourceLeakDetector(DnsMessage.class);
|
||||
|
||||
private static final int SECTION_QUESTION = DnsSection.QUESTION.ordinal();
|
||||
private static final int SECTION_COUNT = 4;
|
||||
|
||||
private final ResourceLeakTracker<DnsMessage> leak = leakDetector.track(this);
|
||||
private short id;
|
||||
private DnsOpCode opCode;
|
||||
private boolean recursionDesired;
|
||||
private byte z;
|
||||
|
||||
// To reduce the memory footprint of a message,
|
||||
// each of the following fields is a single record or a list of records.
|
||||
private Object questions;
|
||||
private Object answers;
|
||||
private Object authorities;
|
||||
private Object additionals;
|
||||
|
||||
/**
|
||||
* Creates a new instance with the specified {@code id} and {@link DnsOpCode#QUERY} opCode.
|
||||
*/
|
||||
protected AbstractDnsMessage(int id) {
|
||||
this(id, DnsOpCode.QUERY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with the specified {@code id} and {@code opCode}.
|
||||
*/
|
||||
protected AbstractDnsMessage(int id, DnsOpCode opCode) {
|
||||
setId(id);
|
||||
setOpCode(opCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return id & 0xFFFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage setId(int id) {
|
||||
this.id = (short) id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsOpCode opCode() {
|
||||
return opCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage setOpCode(DnsOpCode opCode) {
|
||||
this.opCode = checkNotNull(opCode, "opCode");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecursionDesired() {
|
||||
return recursionDesired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage setRecursionDesired(boolean recursionDesired) {
|
||||
this.recursionDesired = recursionDesired;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int z() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage setZ(int z) {
|
||||
this.z = (byte) (z & 7);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int count(DnsSection section) {
|
||||
return count(sectionOrdinal(section));
|
||||
}
|
||||
|
||||
private int count(int section) {
|
||||
final Object records = sectionAt(section);
|
||||
if (records == null) {
|
||||
return 0;
|
||||
}
|
||||
if (records instanceof DnsRecord) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<DnsRecord> recordList = (List<DnsRecord>) records;
|
||||
return recordList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int count() {
|
||||
int count = 0;
|
||||
for (int i = 0; i < SECTION_COUNT; i ++) {
|
||||
count += count(i);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends DnsRecord> T recordAt(DnsSection section) {
|
||||
return recordAt(sectionOrdinal(section));
|
||||
}
|
||||
|
||||
private <T extends DnsRecord> T recordAt(int section) {
|
||||
final Object records = sectionAt(section);
|
||||
if (records == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (records instanceof DnsRecord) {
|
||||
return castRecord(records);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<DnsRecord> recordList = (List<DnsRecord>) records;
|
||||
if (recordList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return castRecord(recordList.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends DnsRecord> T recordAt(DnsSection section, int index) {
|
||||
return recordAt(sectionOrdinal(section), index);
|
||||
}
|
||||
|
||||
private <T extends DnsRecord> T recordAt(int section, int index) {
|
||||
final Object records = sectionAt(section);
|
||||
if (records == null) {
|
||||
throw new IndexOutOfBoundsException("index: " + index + " (expected: none)");
|
||||
}
|
||||
|
||||
if (records instanceof DnsRecord) {
|
||||
if (index == 0) {
|
||||
return castRecord(records);
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException("index: " + index + "' (expected: 0)");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<DnsRecord> recordList = (List<DnsRecord>) records;
|
||||
return castRecord(recordList.get(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage setRecord(DnsSection section, DnsRecord record) {
|
||||
setRecord(sectionOrdinal(section), record);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void setRecord(int section, DnsRecord record) {
|
||||
clear(section);
|
||||
setSection(section, checkQuestion(section, record));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends DnsRecord> T setRecord(DnsSection section, int index, DnsRecord record) {
|
||||
return setRecord(sectionOrdinal(section), index, record);
|
||||
}
|
||||
|
||||
private <T extends DnsRecord> T setRecord(int section, int index, DnsRecord record) {
|
||||
checkQuestion(section, record);
|
||||
|
||||
final Object records = sectionAt(section);
|
||||
if (records == null) {
|
||||
throw new IndexOutOfBoundsException("index: " + index + " (expected: none)");
|
||||
}
|
||||
|
||||
if (records instanceof DnsRecord) {
|
||||
if (index == 0) {
|
||||
setSection(section, record);
|
||||
return castRecord(records);
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException("index: " + index + " (expected: 0)");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<DnsRecord> recordList = (List<DnsRecord>) records;
|
||||
return castRecord(recordList.set(index, record));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage addRecord(DnsSection section, DnsRecord record) {
|
||||
addRecord(sectionOrdinal(section), record);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addRecord(int section, DnsRecord record) {
|
||||
checkQuestion(section, record);
|
||||
|
||||
final Object records = sectionAt(section);
|
||||
if (records == null) {
|
||||
setSection(section, record);
|
||||
return;
|
||||
}
|
||||
|
||||
if (records instanceof DnsRecord) {
|
||||
final List<DnsRecord> recordList = newRecordList();
|
||||
recordList.add(castRecord(records));
|
||||
recordList.add(record);
|
||||
setSection(section, recordList);
|
||||
return;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<DnsRecord> recordList = (List<DnsRecord>) records;
|
||||
recordList.add(record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage addRecord(DnsSection section, int index, DnsRecord record) {
|
||||
addRecord(sectionOrdinal(section), index, record);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addRecord(int section, int index, DnsRecord record) {
|
||||
checkQuestion(section, record);
|
||||
|
||||
final Object records = sectionAt(section);
|
||||
if (records == null) {
|
||||
if (index != 0) {
|
||||
throw new IndexOutOfBoundsException("index: " + index + " (expected: 0)");
|
||||
}
|
||||
|
||||
setSection(section, record);
|
||||
return;
|
||||
}
|
||||
|
||||
if (records instanceof DnsRecord) {
|
||||
final List<DnsRecord> recordList;
|
||||
if (index == 0) {
|
||||
recordList = newRecordList();
|
||||
recordList.add(record);
|
||||
recordList.add(castRecord(records));
|
||||
} else if (index == 1) {
|
||||
recordList = newRecordList();
|
||||
recordList.add(castRecord(records));
|
||||
recordList.add(record);
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException("index: " + index + " (expected: 0 or 1)");
|
||||
}
|
||||
setSection(section, recordList);
|
||||
return;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<DnsRecord> recordList = (List<DnsRecord>) records;
|
||||
recordList.add(index, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends DnsRecord> T removeRecord(DnsSection section, int index) {
|
||||
return removeRecord(sectionOrdinal(section), index);
|
||||
}
|
||||
|
||||
private <T extends DnsRecord> T removeRecord(int section, int index) {
|
||||
final Object records = sectionAt(section);
|
||||
if (records == null) {
|
||||
throw new IndexOutOfBoundsException("index: " + index + " (expected: none)");
|
||||
}
|
||||
|
||||
if (records instanceof DnsRecord) {
|
||||
if (index != 0) {
|
||||
throw new IndexOutOfBoundsException("index: " + index + " (expected: 0)");
|
||||
}
|
||||
|
||||
T record = castRecord(records);
|
||||
setSection(section, null);
|
||||
return record;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<DnsRecord> recordList = (List<DnsRecord>) records;
|
||||
return castRecord(recordList.remove(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage clear(DnsSection section) {
|
||||
clear(sectionOrdinal(section));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage clear() {
|
||||
for (int i = 0; i < SECTION_COUNT; i ++) {
|
||||
clear(i);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void clear(int section) {
|
||||
final Object recordOrList = sectionAt(section);
|
||||
setSection(section, null);
|
||||
if (recordOrList instanceof ReferenceCounted) {
|
||||
((ReferenceCounted) recordOrList).release();
|
||||
} else if (recordOrList instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<DnsRecord> list = (List<DnsRecord>) recordOrList;
|
||||
if (!list.isEmpty()) {
|
||||
for (Object r : list) {
|
||||
ReferenceCountUtil.release(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage touch() {
|
||||
return (DnsMessage) super.touch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage touch(Object hint) {
|
||||
if (leak != null) {
|
||||
leak.record(hint);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage retain() {
|
||||
return (DnsMessage) super.retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsMessage retain(int increment) {
|
||||
return (DnsMessage) super.retain(increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deallocate() {
|
||||
clear();
|
||||
|
||||
final ResourceLeakTracker<DnsMessage> leak = this.leak;
|
||||
if (leak != null) {
|
||||
boolean closed = leak.close(this);
|
||||
assert closed;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof DnsMessage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DnsMessage that = (DnsMessage) obj;
|
||||
if (id() != that.id()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this instanceof DnsQuery) {
|
||||
if (!(that instanceof DnsQuery)) {
|
||||
return false;
|
||||
}
|
||||
} else if (that instanceof DnsQuery) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id() * 31 + (this instanceof DnsQuery? 0 : 1);
|
||||
}
|
||||
|
||||
private Object sectionAt(int section) {
|
||||
switch (section) {
|
||||
case 0:
|
||||
return questions;
|
||||
case 1:
|
||||
return answers;
|
||||
case 2:
|
||||
return authorities;
|
||||
case 3:
|
||||
return additionals;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new Error(); // Should never reach here.
|
||||
}
|
||||
|
||||
private void setSection(int section, Object value) {
|
||||
switch (section) {
|
||||
case 0:
|
||||
questions = value;
|
||||
return;
|
||||
case 1:
|
||||
answers = value;
|
||||
return;
|
||||
case 2:
|
||||
authorities = value;
|
||||
return;
|
||||
case 3:
|
||||
additionals = value;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new Error(); // Should never reach here.
|
||||
}
|
||||
|
||||
private static int sectionOrdinal(DnsSection section) {
|
||||
return checkNotNull(section, "section").ordinal();
|
||||
}
|
||||
|
||||
private static DnsRecord checkQuestion(int section, DnsRecord record) {
|
||||
if (section == SECTION_QUESTION && !(checkNotNull(record, "record") instanceof DnsQuestion)) {
|
||||
throw new IllegalArgumentException(
|
||||
"record: " + record + " (expected: " + StringUtil.simpleClassName(DnsQuestion.class) + ')');
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends DnsRecord> T castRecord(Object record) {
|
||||
return (T) record;
|
||||
}
|
||||
|
||||
private static ArrayList<DnsRecord> newRecordList() {
|
||||
return new ArrayList<DnsRecord>(2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 2016 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
/**
|
||||
* An <a href="https://tools.ietf.org/html/rfc6891#section-6.1">OPT RR</a> record.
|
||||
*
|
||||
* This is used for <a href="https://tools.ietf.org/html/rfc6891#section-6.1.3">
|
||||
* Extension Mechanisms for DNS (EDNS(0))</a>.
|
||||
*/
|
||||
@UnstableApi
|
||||
public abstract class AbstractDnsOptPseudoRrRecord extends AbstractDnsRecord implements DnsOptPseudoRecord {
|
||||
|
||||
protected AbstractDnsOptPseudoRrRecord(int maxPayloadSize, int extendedRcode, int version) {
|
||||
super(StringUtil.EMPTY_STRING, DnsRecordType.OPT, maxPayloadSize, packIntoLong(extendedRcode, version));
|
||||
}
|
||||
|
||||
protected AbstractDnsOptPseudoRrRecord(int maxPayloadSize) {
|
||||
super(StringUtil.EMPTY_STRING, DnsRecordType.OPT, maxPayloadSize, 0);
|
||||
}
|
||||
|
||||
// See https://tools.ietf.org/html/rfc6891#section-6.1.3
|
||||
private static long packIntoLong(int val, int val2) {
|
||||
// We are currently not support DO and Z fields, just use 0.
|
||||
return ((val & 0xffL) << 24 | (val2 & 0xff) << 16) & 0xFFFFFFFFL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extendedRcode() {
|
||||
return (short) (((int) timeToLive() >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int version() {
|
||||
return (short) (((int) timeToLive() >> 16) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int flags() {
|
||||
return (short) ((short) timeToLive() & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringBuilder().toString();
|
||||
}
|
||||
|
||||
final StringBuilder toStringBuilder() {
|
||||
return new StringBuilder(64)
|
||||
.append(StringUtil.simpleClassName(this))
|
||||
.append('(')
|
||||
.append("OPT flags:")
|
||||
.append(flags())
|
||||
.append(" version:")
|
||||
.append(version())
|
||||
.append(" extendedRecode:")
|
||||
.append(extendedRcode())
|
||||
.append(" udp:")
|
||||
.append(dnsClass())
|
||||
.append(')');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import java.net.IDN;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
|
||||
|
||||
/**
|
||||
* A skeletal implementation of {@link DnsRecord}.
|
||||
*/
|
||||
@UnstableApi
|
||||
public abstract class AbstractDnsRecord implements DnsRecord {
|
||||
|
||||
private final String name;
|
||||
private final DnsRecordType type;
|
||||
private final short dnsClass;
|
||||
private final long timeToLive;
|
||||
private int hashCode;
|
||||
|
||||
/**
|
||||
* Creates a new {@link #CLASS_IN IN-class} record.
|
||||
*
|
||||
* @param name the domain name
|
||||
* @param type the type of the record
|
||||
* @param timeToLive the TTL value of the record
|
||||
*/
|
||||
protected AbstractDnsRecord(String name, DnsRecordType type, long timeToLive) {
|
||||
this(name, type, CLASS_IN, timeToLive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new record.
|
||||
*
|
||||
* @param name the domain name
|
||||
* @param type the type of the record
|
||||
* @param dnsClass the class of the record, usually one of the following:
|
||||
* <ul>
|
||||
* <li>{@link #CLASS_IN}</li>
|
||||
* <li>{@link #CLASS_CSNET}</li>
|
||||
* <li>{@link #CLASS_CHAOS}</li>
|
||||
* <li>{@link #CLASS_HESIOD}</li>
|
||||
* <li>{@link #CLASS_NONE}</li>
|
||||
* <li>{@link #CLASS_ANY}</li>
|
||||
* </ul>
|
||||
* @param timeToLive the TTL value of the record
|
||||
*/
|
||||
protected AbstractDnsRecord(String name, DnsRecordType type, int dnsClass, long timeToLive) {
|
||||
checkPositiveOrZero(timeToLive, "timeToLive");
|
||||
// Convert to ASCII which will also check that the length is not too big.
|
||||
// See:
|
||||
// - https://github.com/netty/netty/issues/4937
|
||||
// - https://github.com/netty/netty/issues/4935
|
||||
this.name = appendTrailingDot(IDNtoASCII(name));
|
||||
this.type = checkNotNull(type, "type");
|
||||
this.dnsClass = (short) dnsClass;
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
|
||||
private static String IDNtoASCII(String name) {
|
||||
checkNotNull(name, "name");
|
||||
if (PlatformDependent.isAndroid() && DefaultDnsRecordDecoder.ROOT.equals(name)) {
|
||||
// Prior Android 10 there was a bug that did not correctly parse ".".
|
||||
//
|
||||
// See https://github.com/netty/netty/issues/10034
|
||||
return name;
|
||||
}
|
||||
return IDN.toASCII(name);
|
||||
}
|
||||
|
||||
private static String appendTrailingDot(String name) {
|
||||
if (name.length() > 0 && name.charAt(name.length() - 1) != '.') {
|
||||
return name + '.';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DnsRecordType type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int dnsClass() {
|
||||
return dnsClass & 0xFFFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long timeToLive() {
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof DnsRecord)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DnsRecord that = (DnsRecord) obj;
|
||||
final int hashCode = this.hashCode;
|
||||
if (hashCode != 0 && hashCode != that.hashCode()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return type().intValue() == that.type().intValue() &&
|
||||
dnsClass() == that.dnsClass() &&
|
||||
name().equals(that.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int hashCode = this.hashCode;
|
||||
if (hashCode != 0) {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
return this.hashCode = name.hashCode() * 31 + type().intValue() * 31 + dnsClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(64);
|
||||
|
||||
buf.append(StringUtil.simpleClassName(this))
|
||||
.append('(')
|
||||
.append(name())
|
||||
.append(' ')
|
||||
.append(timeToLive())
|
||||
.append(' ');
|
||||
|
||||
DnsMessageUtil.appendRecordClass(buf, dnsClass())
|
||||
.append(' ')
|
||||
.append(type().name())
|
||||
.append(')');
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* A {@link DnsQuery} implementation for UDP/IP.
|
||||
*/
|
||||
@UnstableApi
|
||||
public class DatagramDnsQuery extends DefaultDnsQuery
|
||||
implements AddressedEnvelope<DatagramDnsQuery, InetSocketAddress> {
|
||||
|
||||
private final InetSocketAddress sender;
|
||||
private final InetSocketAddress recipient;
|
||||
|
||||
/**
|
||||
* Creates a new instance with the {@link DnsOpCode#QUERY} {@code opCode}.
|
||||
*
|
||||
* @param sender the address of the sender
|
||||
* @param recipient the address of the recipient
|
||||
* @param id the {@code ID} of the DNS query
|
||||
*/
|
||||
public DatagramDnsQuery(
|
||||
InetSocketAddress sender, InetSocketAddress recipient, int id) {
|
||||
this(sender, recipient, id, DnsOpCode.QUERY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param sender the address of the sender
|
||||
* @param recipient the address of the recipient
|
||||
* @param id the {@code ID} of the DNS query
|
||||
* @param opCode the {@code opCode} of the DNS query
|
||||
*/
|
||||
public DatagramDnsQuery(
|
||||
InetSocketAddress sender, InetSocketAddress recipient, int id, DnsOpCode opCode) {
|
||||
super(id, opCode);
|
||||
|
||||
if (recipient == null && sender == null) {
|
||||
throw new NullPointerException("recipient and sender");
|
||||
}
|
||||
|
||||
this.sender = sender;
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery content() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress sender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress recipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery setId(int id) {
|
||||
return (DatagramDnsQuery) super.setId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery setOpCode(DnsOpCode opCode) {
|
||||
return (DatagramDnsQuery) super.setOpCode(opCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery setRecursionDesired(boolean recursionDesired) {
|
||||
return (DatagramDnsQuery) super.setRecursionDesired(recursionDesired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery setZ(int z) {
|
||||
return (DatagramDnsQuery) super.setZ(z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery setRecord(DnsSection section, DnsRecord record) {
|
||||
return (DatagramDnsQuery) super.setRecord(section, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery addRecord(DnsSection section, DnsRecord record) {
|
||||
return (DatagramDnsQuery) super.addRecord(section, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery addRecord(DnsSection section, int index, DnsRecord record) {
|
||||
return (DatagramDnsQuery) super.addRecord(section, index, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery clear(DnsSection section) {
|
||||
return (DatagramDnsQuery) super.clear(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery clear() {
|
||||
return (DatagramDnsQuery) super.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery touch() {
|
||||
return (DatagramDnsQuery) super.touch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery touch(Object hint) {
|
||||
return (DatagramDnsQuery) super.touch(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery retain() {
|
||||
return (DatagramDnsQuery) super.retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsQuery retain(int increment) {
|
||||
return (DatagramDnsQuery) super.retain(increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(obj instanceof AddressedEnvelope)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final AddressedEnvelope<?, SocketAddress> that = (AddressedEnvelope<?, SocketAddress>) obj;
|
||||
if (sender() == null) {
|
||||
if (that.sender() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!sender().equals(that.sender())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recipient() == null) {
|
||||
if (that.recipient() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!recipient().equals(that.recipient())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = super.hashCode();
|
||||
if (sender() != null) {
|
||||
hashCode = hashCode * 31 + sender().hashCode();
|
||||
}
|
||||
if (recipient() != null) {
|
||||
hashCode = hashCode * 31 + recipient().hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
/**
|
||||
* Decodes a {@link DatagramPacket} into a {@link DatagramDnsQuery}.
|
||||
*/
|
||||
@UnstableApi
|
||||
@ChannelHandler.Sharable
|
||||
public class DatagramDnsQueryDecoder extends MessageToMessageDecoder<DatagramPacket> {
|
||||
|
||||
private final DnsRecordDecoder recordDecoder;
|
||||
|
||||
/**
|
||||
* Creates a new decoder with {@linkplain DnsRecordDecoder#DEFAULT the default record decoder}.
|
||||
*/
|
||||
public DatagramDnsQueryDecoder() {
|
||||
this(DnsRecordDecoder.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new decoder with the specified {@code recordDecoder}.
|
||||
*/
|
||||
public DatagramDnsQueryDecoder(DnsRecordDecoder recordDecoder) {
|
||||
this.recordDecoder = checkNotNull(recordDecoder, "recordDecoder");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, final DatagramPacket packet, List<Object> out) throws Exception {
|
||||
DnsQuery query = DnsMessageUtil.decodeDnsQuery(recordDecoder, packet.content(),
|
||||
new DnsMessageUtil.DnsQueryFactory() {
|
||||
@Override
|
||||
public DnsQuery newQuery(int id, DnsOpCode dnsOpCode) {
|
||||
return new DatagramDnsQuery(packet.sender(), packet.recipient(), id, dnsOpCode);
|
||||
}
|
||||
});
|
||||
out.add(query);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Encodes a {@link DatagramDnsQuery} (or an {@link AddressedEnvelope} of {@link DnsQuery}} into a
|
||||
* {@link DatagramPacket}.
|
||||
*/
|
||||
@UnstableApi
|
||||
@ChannelHandler.Sharable
|
||||
public class DatagramDnsQueryEncoder extends MessageToMessageEncoder<AddressedEnvelope<DnsQuery, InetSocketAddress>> {
|
||||
|
||||
private final DnsQueryEncoder encoder;
|
||||
|
||||
/**
|
||||
* Creates a new encoder with {@linkplain DnsRecordEncoder#DEFAULT the default record encoder}.
|
||||
*/
|
||||
public DatagramDnsQueryEncoder() {
|
||||
this(DnsRecordEncoder.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new encoder with the specified {@code recordEncoder}.
|
||||
*/
|
||||
public DatagramDnsQueryEncoder(DnsRecordEncoder recordEncoder) {
|
||||
this.encoder = new DnsQueryEncoder(recordEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(
|
||||
ChannelHandlerContext ctx,
|
||||
AddressedEnvelope<DnsQuery, InetSocketAddress> in, List<Object> out) throws Exception {
|
||||
|
||||
final InetSocketAddress recipient = in.recipient();
|
||||
final DnsQuery query = in.content();
|
||||
final ByteBuf buf = allocateBuffer(ctx, in);
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
encoder.encode(query, buf);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
buf.release();
|
||||
}
|
||||
}
|
||||
|
||||
out.add(new DatagramPacket(buf, recipient, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a {@link ByteBuf} which will be used for constructing a datagram packet.
|
||||
* Sub-classes may override this method to return a {@link ByteBuf} with a perfect matching initial capacity.
|
||||
*/
|
||||
protected ByteBuf allocateBuffer(
|
||||
ChannelHandlerContext ctx,
|
||||
@SuppressWarnings("unused") AddressedEnvelope<DnsQuery, InetSocketAddress> msg) throws Exception {
|
||||
return ctx.alloc().ioBuffer(1024);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* A {@link DnsResponse} implementation for UDP/IP.
|
||||
*/
|
||||
@UnstableApi
|
||||
public class DatagramDnsResponse extends DefaultDnsResponse
|
||||
implements AddressedEnvelope<DatagramDnsResponse, InetSocketAddress> {
|
||||
|
||||
private final InetSocketAddress sender;
|
||||
private final InetSocketAddress recipient;
|
||||
|
||||
/**
|
||||
* Creates a new instance with the {@link DnsOpCode#QUERY} {@code opCode} and
|
||||
* the {@link DnsResponseCode#NOERROR} {@code RCODE}.
|
||||
*
|
||||
* @param sender the address of the sender
|
||||
* @param recipient the address of the recipient
|
||||
* @param id the {@code ID} of the DNS response
|
||||
*/
|
||||
public DatagramDnsResponse(InetSocketAddress sender, InetSocketAddress recipient, int id) {
|
||||
this(sender, recipient, id, DnsOpCode.QUERY, DnsResponseCode.NOERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with the {@link DnsResponseCode#NOERROR} responseCode.
|
||||
*
|
||||
* @param sender the address of the sender
|
||||
* @param recipient the address of the recipient
|
||||
* @param id the {@code ID} of the DNS response
|
||||
* @param opCode the {@code opCode} of the DNS response
|
||||
*/
|
||||
public DatagramDnsResponse(InetSocketAddress sender, InetSocketAddress recipient, int id, DnsOpCode opCode) {
|
||||
this(sender, recipient, id, opCode, DnsResponseCode.NOERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param sender the address of the sender
|
||||
* @param recipient the address of the recipient
|
||||
* @param id the {@code ID} of the DNS response
|
||||
* @param opCode the {@code opCode} of the DNS response
|
||||
* @param responseCode the {@code RCODE} of the DNS response
|
||||
*/
|
||||
public DatagramDnsResponse(
|
||||
InetSocketAddress sender, InetSocketAddress recipient,
|
||||
int id, DnsOpCode opCode, DnsResponseCode responseCode) {
|
||||
super(id, opCode, responseCode);
|
||||
|
||||
if (recipient == null && sender == null) {
|
||||
throw new NullPointerException("recipient and sender");
|
||||
}
|
||||
|
||||
this.sender = sender;
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse content() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress sender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress recipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setAuthoritativeAnswer(boolean authoritativeAnswer) {
|
||||
return (DatagramDnsResponse) super.setAuthoritativeAnswer(authoritativeAnswer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setTruncated(boolean truncated) {
|
||||
return (DatagramDnsResponse) super.setTruncated(truncated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setRecursionAvailable(boolean recursionAvailable) {
|
||||
return (DatagramDnsResponse) super.setRecursionAvailable(recursionAvailable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setCode(DnsResponseCode code) {
|
||||
return (DatagramDnsResponse) super.setCode(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setId(int id) {
|
||||
return (DatagramDnsResponse) super.setId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setOpCode(DnsOpCode opCode) {
|
||||
return (DatagramDnsResponse) super.setOpCode(opCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setRecursionDesired(boolean recursionDesired) {
|
||||
return (DatagramDnsResponse) super.setRecursionDesired(recursionDesired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setZ(int z) {
|
||||
return (DatagramDnsResponse) super.setZ(z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse setRecord(DnsSection section, DnsRecord record) {
|
||||
return (DatagramDnsResponse) super.setRecord(section, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse addRecord(DnsSection section, DnsRecord record) {
|
||||
return (DatagramDnsResponse) super.addRecord(section, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse addRecord(DnsSection section, int index, DnsRecord record) {
|
||||
return (DatagramDnsResponse) super.addRecord(section, index, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse clear(DnsSection section) {
|
||||
return (DatagramDnsResponse) super.clear(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse clear() {
|
||||
return (DatagramDnsResponse) super.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse touch() {
|
||||
return (DatagramDnsResponse) super.touch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse touch(Object hint) {
|
||||
return (DatagramDnsResponse) super.touch(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse retain() {
|
||||
return (DatagramDnsResponse) super.retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramDnsResponse retain(int increment) {
|
||||
return (DatagramDnsResponse) super.retain(increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(obj instanceof AddressedEnvelope)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final AddressedEnvelope<?, SocketAddress> that = (AddressedEnvelope<?, SocketAddress>) obj;
|
||||
if (sender() == null) {
|
||||
if (that.sender() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!sender().equals(that.sender())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recipient() == null) {
|
||||
return that.recipient() == null;
|
||||
} else {
|
||||
return recipient().equals(that.recipient());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = super.hashCode();
|
||||
if (sender() != null) {
|
||||
hashCode = hashCode * 31 + sender().hashCode();
|
||||
}
|
||||
if (recipient() != null) {
|
||||
hashCode = hashCode * 31 + recipient().hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.dns;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.CorruptedFrameException;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Decodes a {@link DatagramPacket} |