Source code: com/strangeberry/rendezvous/DNSRecord.java
1 // Copyright (C) 2002 Strangeberry Inc.
2 // @(#)DNSRecord.java, 1.24, 01/14/2003
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 //
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 package com.strangeberry.rendezvous;
19
20 import java.io.*;
21 import java.net.*;
22 import java.util.*;
23
24 /**
25 * DNS record
26 *
27 * @author Arthur van Hoff
28 * @version 1.24, 01/14/2003
29 */
30 abstract class DNSRecord extends DNSEntry
31 {
32 int ttl;
33 long created;
34
35 /**
36 * Create a DNSRecord with a name, type, clazz, and ttl.
37 */
38 DNSRecord(String name, int type, int clazz, int ttl)
39 {
40 super(name, type, clazz);
41 this.ttl = ttl;
42 this.created = System.currentTimeMillis();
43 }
44
45 /**
46 * True if this record is the same as some other record.
47 */
48 public boolean equals(Object other)
49 {
50 return (other instanceof DNSRecord) && sameAs((DNSRecord)other);
51 }
52
53 /**
54 * True if this record is the same as some other record.
55 */
56 boolean sameAs(DNSRecord other)
57 {
58 return super.equals(other) && sameValue((DNSRecord)other);
59 }
60
61 /**
62 * True if this record has the same value as some other record.
63 */
64 abstract boolean sameValue(DNSRecord other);
65
66 /**
67 * True if this record is suppressed by the answers in a message.
68 */
69 boolean suppressedBy(DNSIncoming msg)
70 {
71 for (int i = msg.numAnswers ; i-- > 0 ;) {
72 if (suppressedBy((DNSRecord)msg.answers.elementAt(i))) {
73 return true;
74 }
75 }
76 return false;
77 }
78
79 /**
80 * True if this record would be supressed by an answer.
81 * This is the case if this record would not have a
82 * significantly longer TTL.
83 */
84 boolean suppressedBy(DNSRecord other)
85 {
86 if (sameAs(other) && (other.ttl > ttl / 2)) {
87 return true;
88 }
89 return false;
90 }
91
92 /**
93 * Get the expiration time of this record.
94 */
95 long getExpirationTime(int percent)
96 {
97 return created + (percent * ttl * 10L);
98 }
99
100 /**
101 * Get the remaining TTL for this record.
102 */
103 int getRemainingTTL(long now)
104 {
105 return (int)Math.max(0, (getExpirationTime(100) - now) / 1000);
106 }
107
108 /**
109 * Check if the record is expired.
110 */
111 boolean isExpired(long now)
112 {
113 return getExpirationTime(100) <= now;
114 }
115
116 /**
117 * Check if the record is stale, ie it has outlived
118 * more than half of its TTL.
119 */
120 boolean isStale(long now)
121 {
122 return getExpirationTime(50) <= now;
123 }
124
125 /**
126 * Reset the TTL of a record. This avoids having to
127 * update the entire record in the cache.
128 */
129 void resetTTL(DNSRecord other)
130 {
131 created = other.created;
132 ttl = other.ttl;
133 }
134
135 /**
136 * Write this record into an outgoing message.
137 */
138 abstract void write(DNSOutgoing out) throws IOException;
139
140 /**
141 * Address record.
142 */
143 static class Address extends DNSRecord
144 {
145 int addr;
146
147 Address(String name, int type, int clazz, int ttl, int addr)
148 {
149 super(name, type, clazz, ttl);
150 this.addr = addr;
151 }
152 void write(DNSOutgoing out) throws IOException
153 {
154 out.writeInt(addr);
155 }
156 boolean sameValue(DNSRecord other)
157 {
158 return (addr == ((Address)other).addr);
159 }
160 InetAddress getAddress()
161 {
162 try {
163 return InetAddress.getByName(getHostAddress());
164 } catch (UnknownHostException e) {
165 // should not happen
166 e.printStackTrace();
167 return null;
168 }
169 }
170 public String getHostAddress()
171 {
172 return ((addr >> 24) & 0xFF) + "." + ((addr >> 16) & 0xFF) + "." + ((addr >> 8) & 0xFF) + "." + (addr & 0xFF);
173 }
174 public String toString()
175 {
176 return toString(getHostAddress());
177 }
178 }
179
180 /**
181 * Pointer record.
182 */
183 static class Pointer extends DNSRecord
184 {
185 String alias;
186
187 Pointer(String name, int type, int clazz, int ttl, String alias)
188 {
189 super(name, type, clazz, ttl);
190 this.alias = alias;
191 }
192 void write(DNSOutgoing out) throws IOException
193 {
194 out.writeName(alias);
195 }
196 boolean sameValue(DNSRecord other)
197 {
198 return alias.equals(((Pointer)other).alias);
199 }
200 public String toString()
201 {
202 return toString(alias);
203 }
204 }
205
206 static class Text extends DNSRecord
207 {
208 byte text[];
209
210 Text(String name, int type, int clazz, int ttl, byte text[])
211 {
212 super(name, type, clazz, ttl);
213 this.text = text;
214 }
215 void write(DNSOutgoing out) throws IOException
216 {
217 out.writeBytes(text, 0, text.length);
218 }
219 boolean sameValue(DNSRecord other)
220 {
221 Text txt = (Text)other;
222 if (txt.text.length != text.length) {
223 return false;
224 }
225 for (int i = text.length ; i-- > 0 ;) {
226 if (txt.text[i] != text[i]) {
227 return false;
228 }
229 }
230 return true;
231 }
232 public String toString()
233 {
234 return toString((text.length > 10) ? new String(text, 0, 7) + "..." : new String(text));
235 }
236 }
237
238 /**
239 * Service record.
240 */
241 static class Service extends DNSRecord
242 {
243 int priority;
244 int weight;
245 int port;
246 String server;
247
248 Service(String name, int type, int clazz, int ttl, int priority, int weight, int port, String server)
249 {
250 super(name, type, clazz, ttl);
251 this.priority = priority;
252 this.weight = weight;
253 this.port = port;
254 this.server = server;
255 }
256 void write(DNSOutgoing out) throws IOException
257 {
258 out.writeShort(priority);
259 out.writeShort(weight);
260 out.writeShort(port);
261 out.writeName(server);
262 }
263 boolean sameValue(DNSRecord other)
264 {
265 Service s = (Service)other;
266 return (priority == s.priority) && (weight == s.weight) && (port == s.port) && server.equals(s.server);
267 }
268 public String toString()
269 {
270 return toString(server + ":" + port);
271 }
272 }
273
274 public String toString(String other)
275 {
276 return toString("record", ttl + "/" + getRemainingTTL(System.currentTimeMillis()) + "," + other);
277 }
278 }
279