package org.zarroboogs.smartzpn.dns;
import java.nio.ByteBuffer;
public class DnsPacket {
public DnsHeader Header;
public Question[] Questions;
public Resource[] Resources;
public Resource[] AResources;
public Resource[] EResources;
public int Size;
public static DnsPacket FromBytes(ByteBuffer buffer) {
if (buffer.limit() < 12)
return null;
if (buffer.limit() > 512)
return null;
DnsPacket packet = new DnsPacket();
packet.Size = buffer.limit();
packet.Header = DnsHeader.FromBytes(buffer);
if (packet.Header.QuestionCount > 2 || packet.Header.ResourceCount > 50 || packet.Header.AResourceCount > 50 || packet.Header.EResourceCount > 50) {
return null;
}
packet.Questions = new Question[packet.Header.QuestionCount];
packet.Resources = new Resource[packet.Header.ResourceCount];
packet.AResources = new Resource[packet.Header.AResourceCount];
packet.EResources = new Resource[packet.Header.EResourceCount];
for (int i = 0; i < packet.Questions.length; i++) {
packet.Questions[i] = Question.FromBytes(buffer);
}
for (int i = 0; i < packet.Resources.length; i++) {
packet.Resources[i] = Resource.FromBytes(buffer);
}
for (int i = 0; i < packet.AResources.length; i++) {
packet.AResources[i] = Resource.FromBytes(buffer);
}
for (int i = 0; i < packet.EResources.length; i++) {
packet.EResources[i] = Resource.FromBytes(buffer);
}
return packet;
}
public void ToBytes(ByteBuffer buffer) {
Header.QuestionCount = 0;
Header.ResourceCount = 0;
Header.AResourceCount = 0;
Header.EResourceCount = 0;
if (Questions != null)
Header.QuestionCount = (short) Questions.length;
if (Resources != null)
Header.ResourceCount = (short) Resources.length;
if (AResources != null)
Header.AResourceCount = (short) AResources.length;
if (EResources != null)
Header.EResourceCount = (short) EResources.length;
this.Header.ToBytes(buffer);
for (int i = 0; i < Header.QuestionCount; i++) {
this.Questions[i].ToBytes(buffer);
}
for (int i = 0; i < Header.ResourceCount; i++) {
this.Resources[i].ToBytes(buffer);
}
for (int i = 0; i < Header.AResourceCount; i++) {
this.AResources[i].ToBytes(buffer);
}
for (int i = 0; i < Header.EResourceCount; i++) {
this.EResources[i].ToBytes(buffer);
}
}
public static String ReadDomain(ByteBuffer buffer, int dnsHeaderOffset) {
StringBuilder sb = new StringBuilder();
int len = 0;
while (buffer.hasRemaining() && (len = (buffer.get() & 0xFF)) > 0) {
if ((len & 0xc0) == 0xc0)// pointer 高2位为11表示是指针。如:1100 0000
{
// 指针的取值是前一字节的后6位加后一字节的8位共14位的值。
int pointer = buffer.get() & 0xFF;// 低8位
pointer |= (len & 0x3F) << 8;// 高6位
ByteBuffer newBuffer = ByteBuffer.wrap(buffer.array(), dnsHeaderOffset + pointer, dnsHeaderOffset + buffer.limit());
sb.append(ReadDomain(newBuffer, dnsHeaderOffset));
return sb.toString();
} else {
while (len > 0 && buffer.hasRemaining()) {
sb.append((char) (buffer.get() & 0xFF));
len--;
}
sb.append('.');
}
}
if (len == 0 && sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);//去掉末尾的点(.)
}
return sb.toString();
}
public static void WriteDomain(String domain, ByteBuffer buffer) {
if (domain == null || domain == "") {
buffer.put((byte) 0);
return;
}
String[] arr = domain.split("\\.");
for (String item : arr) {
if (arr.length > 1) {
buffer.put((byte) item.length());
}
for (int i = 0; i < item.length(); i++) {
buffer.put((byte) item.codePointAt(i));
}
}
}
}