package org.handwerkszeug.dns;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.handwerkszeug.dns.record.AbstractRecord;
import io.netty.buffer.ByteBuf;
/**
* RFC1035 4. MESSAGES
*
*
* +---------------------+
* | Header |
* +---------------------+
* | Question | the question for the name server
* +---------------------+
* | Answer | RRs answering the question
* +---------------------+
* | Authority | RRs pointing toward an authority
* +---------------------+
* | Additional | RRs holding additional information
* +---------------------+
*
*
* @author taichi
*/
public class DNSMessage {
protected Header header;
protected List question;
protected List answer;
protected List authority;
protected List additional;
protected int messageSize;
public DNSMessage(Header header) {
this.header(header);
this.question = new ArrayList();
this.answer = new ArrayList();
this.authority = new ArrayList();
this.additional = new ArrayList();
}
public DNSMessage() {
this(new Header());
}
public DNSMessage(DNSMessage from) {
this(new Header(from.header()));
this.question().addAll(from.question());
this.answer().addAll(from.answer());
this.authority().addAll(from.authority());
this.additional().addAll(from.additional());
this.messageSize(from.messageSize());
}
public DNSMessage(ByteBuf buffer) {
this.header = new Header(buffer);
if (this.header.rcode().equals(RCode.FormErr)) {
this.question = Collections.emptyList();
this.answer = Collections.emptyList();
this.authority = Collections.emptyList();
this.additional = Collections.emptyList();
} else {
this.parse(buffer);
}
}
protected void parse(ByteBuf buffer) {
Header header = this.header();
int q = header.qdcount();
if (q < 1) {
this.question = Collections.emptyList();
}
else {
this.question(new ArrayList(q));
for (int i = 0; i < q; i++) {
this.question()
.add(AbstractRecord.parseSection(buffer));
}
}
this.answer(parse(buffer, header.ancount()));
this.authority(parse(buffer, header.nscount()));
this.additional(parse(buffer, header.arcount()));
this.messageSize(buffer.readerIndex());
}
protected static
List parse(ByteBuf buffer, int size) {
if (size < 1) {
return Collections.emptyList();
}
List result = new ArrayList(size);
for (int i = 0; i < size; i++) {
ResourceRecord rr = AbstractRecord.parseSection(buffer);
rr.parse(buffer);
result.add(rr);
}
return result;
}
public void write(ByteBuf buffer) {
header().qdcount(this.question().size());
header().ancount(this.answer().size());
header().nscount(this.authority().size());
header().arcount(this.additional().size());
header().write(buffer);
NameCompressor nc = new SimpleNameCompressor();
for (ResourceRecord rr : this.question()) {
AbstractRecord.writeSection(buffer, nc, rr);
}
write(buffer, nc, answer());
write(buffer, nc, authority());
write(buffer, nc, additional());
}
protected void write(ByteBuf buffer, NameCompressor compressor,
List list) {
for (ResourceRecord rr : list) {
AbstractRecord.writeSection(buffer, compressor, rr);
rr.write(buffer, compressor);
}
}
public Header header() {
return this.header;
}
public void header(Header header) {
this.header = header;
}
/**
* 4.1.2. Question section format
*/
public List question() {
return this.question;
}
public void question(List list) {
this.question = list;
}
public List answer() {
return this.answer;
}
public void answer(List list) {
this.answer = list;
}
public List authority() {
return this.authority;
}
public void authority(List list) {
this.authority = list;
}
public List additional() {
return this.additional;
}
public void additional(List list) {
this.additional = list;
}
public int messageSize() {
return this.messageSize;
}
public void messageSize(int size) {
this.messageSize = size;
}
}