1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.dns;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.handler.codec.CorruptedFrameException;
20
21 import java.net.SocketAddress;
22
23 import static io.netty.util.internal.ObjectUtil.checkNotNull;
24
25 abstract class DnsResponseDecoder<A extends SocketAddress> {
26
27 private final DnsRecordDecoder recordDecoder;
28
29
30
31
32 DnsResponseDecoder(DnsRecordDecoder recordDecoder) {
33 this.recordDecoder = checkNotNull(recordDecoder, "recordDecoder");
34 }
35
36 final DnsResponse decode(A sender, A recipient, ByteBuf buffer) throws Exception {
37 final int id = buffer.readUnsignedShort();
38
39 final int flags = buffer.readUnsignedShort();
40 if (flags >> 15 == 0) {
41 throw new CorruptedFrameException("not a response");
42 }
43
44 final DnsResponse response = newResponse(
45 sender,
46 recipient,
47 id,
48 DnsOpCode.valueOf((byte) (flags >> 11 & 0xf)), DnsResponseCode.valueOf((byte) (flags & 0xf)));
49
50 response.setRecursionDesired((flags >> 8 & 1) == 1);
51 response.setAuthoritativeAnswer((flags >> 10 & 1) == 1);
52 response.setTruncated((flags >> 9 & 1) == 1);
53 response.setRecursionAvailable((flags >> 7 & 1) == 1);
54 response.setZ(flags >> 4 & 0x7);
55
56 boolean success = false;
57 try {
58 final int questionCount = DnsCodecUtil.checkRecordCount(DnsSection.QUESTION, buffer.readUnsignedShort());
59 final int answerCount = DnsCodecUtil.checkRecordCount(DnsSection.ANSWER, buffer.readUnsignedShort());
60 final int authorityRecordCount =
61 DnsCodecUtil.checkRecordCount(DnsSection.AUTHORITY, buffer.readUnsignedShort());
62 final int additionalRecordCount =
63 DnsCodecUtil.checkRecordCount(DnsSection.ADDITIONAL, buffer.readUnsignedShort());
64
65 decodeQuestions(response, buffer, questionCount);
66 if (!decodeRecords(response, DnsSection.ANSWER, buffer, answerCount)) {
67 success = true;
68 return response;
69 }
70 if (!decodeRecords(response, DnsSection.AUTHORITY, buffer, authorityRecordCount)) {
71 success = true;
72 return response;
73 }
74
75 decodeRecords(response, DnsSection.ADDITIONAL, buffer, additionalRecordCount);
76 success = true;
77 return response;
78 } finally {
79 if (!success) {
80 response.release();
81 }
82 }
83 }
84
85 protected abstract DnsResponse newResponse(A sender, A recipient, int id,
86 DnsOpCode opCode, DnsResponseCode responseCode) throws Exception;
87
88 private void decodeQuestions(DnsResponse response, ByteBuf buf, int questionCount) throws Exception {
89 for (int i = questionCount; i > 0; i --) {
90 response.addRecord(DnsSection.QUESTION, recordDecoder.decodeQuestion(buf));
91 }
92 }
93
94 private boolean decodeRecords(
95 DnsResponse response, DnsSection section, ByteBuf buf, int count) throws Exception {
96 for (int i = count; i > 0; i --) {
97 final DnsRecord r = recordDecoder.decodeRecord(buf);
98 if (r == null) {
99
100 return false;
101 }
102
103 response.addRecord(section, r);
104 }
105 return true;
106 }
107 }