1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.handler.codec.dns;
18
19 import io.netty.buffer.ByteBuf;
20 import io.netty.buffer.ByteBufUtil;
21 import io.netty.handler.codec.CorruptedFrameException;
22 import io.netty.util.CharsetUtil;
23
24 import static io.netty.handler.codec.dns.DefaultDnsRecordDecoder.*;
25
26 final class DnsCodecUtil {
27 private DnsCodecUtil() {
28
29 }
30
31 static void encodeDomainName(String name, ByteBuf buf) {
32 if (ROOT.equals(name)) {
33
34 buf.writeByte(0);
35 return;
36 }
37
38 final String[] labels = name.split("\\.");
39 for (String label : labels) {
40 final int labelLen = label.length();
41 if (labelLen == 0) {
42
43 break;
44 }
45
46 buf.writeByte(labelLen);
47 ByteBufUtil.writeAscii(buf, label);
48 }
49
50 buf.writeByte(0);
51 }
52
53 static String decodeDomainName(ByteBuf in) {
54 int position = -1;
55 int checked = 0;
56 final int end = in.writerIndex();
57 final int readable = in.readableBytes();
58
59
60
61
62
63
64
65
66 if (readable == 0) {
67 return ROOT;
68 }
69
70 final StringBuilder name = new StringBuilder(readable << 1);
71 while (in.isReadable()) {
72 final int len = in.readUnsignedByte();
73 final boolean pointer = (len & 0xc0) == 0xc0;
74 if (pointer) {
75 if (position == -1) {
76 position = in.readerIndex() + 1;
77 }
78
79 if (!in.isReadable()) {
80 throw new CorruptedFrameException("truncated pointer in a name");
81 }
82
83 final int next = (len & 0x3f) << 8 | in.readUnsignedByte();
84 if (next >= end) {
85 throw new CorruptedFrameException("name has an out-of-range pointer");
86 }
87 in.readerIndex(next);
88
89
90 checked += 2;
91 if (checked >= end) {
92 throw new CorruptedFrameException("name contains a loop.");
93 }
94 } else if (len != 0) {
95 if (!in.isReadable(len)) {
96 throw new CorruptedFrameException("truncated label in a name");
97 }
98 name.append(in.toString(in.readerIndex(), len, CharsetUtil.UTF_8)).append('.');
99 in.skipBytes(len);
100 } else {
101 break;
102 }
103 }
104
105 if (position != -1) {
106 in.readerIndex(position);
107 }
108
109 if (name.length() == 0) {
110 return ROOT;
111 }
112
113 if (name.charAt(name.length() - 1) != '.') {
114 name.append('.');
115 }
116
117 return name.toString();
118 }
119
120
121
122
123
124
125 static ByteBuf decompressDomainName(ByteBuf compression) {
126 String domainName = decodeDomainName(compression);
127 ByteBuf result = compression.alloc().buffer(domainName.length() << 1);
128 encodeDomainName(domainName, result);
129 return result;
130 }
131 }