1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.dns;
17
18 import io.netty5.buffer.api.Buffer;
19 import io.netty5.buffer.api.BufferAllocator;
20 import io.netty5.handler.codec.CorruptedFrameException;
21
22 import java.net.SocketAddress;
23 import java.util.Objects;
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 = Objects.requireNonNull(recordDecoder, "recordDecoder");
34 }
35
36 final DnsResponse decode(A sender, A recipient, BufferAllocator allocator, Buffer 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 = buffer.readUnsignedShort();
59 final int answerCount = buffer.readUnsignedShort();
60 final int authorityRecordCount = buffer.readUnsignedShort();
61 final int additionalRecordCount = buffer.readUnsignedShort();
62
63 decodeQuestions(response, buffer, questionCount);
64 if (!decodeRecords(response, DnsSection.ANSWER, allocator, buffer, answerCount)) {
65 success = true;
66 return response;
67 }
68 if (!decodeRecords(response, DnsSection.AUTHORITY, allocator, buffer, authorityRecordCount)) {
69 success = true;
70 return response;
71 }
72
73 decodeRecords(response, DnsSection.ADDITIONAL, allocator, buffer, additionalRecordCount);
74 success = true;
75 return response;
76 } finally {
77 if (!success) {
78 response.release();
79 }
80 }
81 }
82
83 protected abstract DnsResponse newResponse(A sender, A recipient, int id,
84 DnsOpCode opCode, DnsResponseCode responseCode) throws Exception;
85
86 private void decodeQuestions(DnsResponse response, Buffer buf, int questionCount) throws Exception {
87 for (int i = questionCount; i > 0; i --) {
88 response.addRecord(DnsSection.QUESTION, recordDecoder.decodeQuestion(buf));
89 }
90 }
91
92 private boolean decodeRecords(DnsResponse response, DnsSection section,
93 BufferAllocator allocator, Buffer buf, int count) throws Exception {
94 for (int i = count; i > 0; i --) {
95 final DnsRecord r = recordDecoder.decodeRecord(allocator, buf);
96 if (r == null) {
97
98 return false;
99 }
100
101 response.addRecord(section, r);
102 }
103 return true;
104 }
105 }