1 /** 2 * 3 */ 4 package javax.jmdns.impl; 5 6 import java.util.ArrayList; 7 import java.util.Collection; 8 import java.util.Collections; 9 import java.util.LinkedList; 10 import java.util.List; 11 12 import javax.jmdns.impl.constants.DNSConstants; 13 14 /** 15 * DNSMessage define a DNS message either incoming or outgoing. 16 * 17 * @author Werner Randelshofer, Rick Blair, Pierre Frisch 18 */ 19 public abstract class DNSMessage { 20 21 /** 22 * 23 */ 24 public static final boolean MULTICAST = true; 25 26 /** 27 * 28 */ 29 public static final boolean UNICAST = false; 30 31 // protected DatagramPacket _packet; 32 // protected int _off; 33 // protected int _len; 34 // protected byte[] _data; 35 36 private int _id; 37 38 boolean _multicast; 39 40 private int _flags; 41 42 protected final List<DNSQuestion> _questions; 43 44 protected final List<DNSRecord> _answers; 45 46 protected final List<DNSRecord> _authoritativeAnswers; 47 48 protected final List<DNSRecord> _additionals; 49 50 /** 51 * @param flags 52 * @param id 53 * @param multicast 54 */ 55 protected DNSMessage(int flags, int id, boolean multicast) { 56 super(); 57 _flags = flags; 58 _id = id; 59 _multicast = multicast; 60 _questions = Collections.synchronizedList(new LinkedList<DNSQuestion>()); 61 _answers = Collections.synchronizedList(new LinkedList<DNSRecord>()); 62 _authoritativeAnswers = Collections.synchronizedList(new LinkedList<DNSRecord>()); 63 _additionals = Collections.synchronizedList(new LinkedList<DNSRecord>()); 64 } 65 66 // public DatagramPacket getPacket() { 67 // return _packet; 68 // } 69 // 70 // public int getOffset() { 71 // return _off; 72 // } 73 // 74 // public int getLength() { 75 // return _len; 76 // } 77 // 78 // public byte[] getData() { 79 // if ( _data == null ) _data = new byte[DNSConstants.MAX_MSG_TYPICAL]; 80 // return _data; 81 // } 82 83 /** 84 * @return message id 85 */ 86 public int getId() { 87 return (_multicast ? 0 : _id); 88 } 89 90 /** 91 * @param id 92 * the id to set 93 */ 94 public void setId(int id) { 95 this._id = id; 96 } 97 98 /** 99 * @return message flags 100 */ 101 public int getFlags() { 102 return _flags; 103 } 104 105 /** 106 * @param flags 107 * the flags to set 108 */ 109 public void setFlags(int flags) { 110 this._flags = flags; 111 } 112 113 /** 114 * @return true if multicast 115 */ 116 public boolean isMulticast() { 117 return _multicast; 118 } 119 120 /** 121 * @return list of questions 122 */ 123 public Collection<? extends DNSQuestion> getQuestions() { 124 return _questions; 125 } 126 127 /** 128 * @return number of questions in the message 129 */ 130 public int getNumberOfQuestions() { 131 return this.getQuestions().size(); 132 } 133 134 public Collection<? extends DNSRecord> getAllAnswers() { 135 List<DNSRecord> aList = new ArrayList<DNSRecord>(_answers.size() + _authoritativeAnswers.size() + _additionals.size()); 136 aList.addAll(_answers); 137 aList.addAll(_authoritativeAnswers); 138 aList.addAll(_additionals); 139 return aList; 140 } 141 142 /** 143 * @return list of answers 144 */ 145 public Collection<? extends DNSRecord> getAnswers() { 146 return _answers; 147 } 148 149 /** 150 * @return number of answers in the message 151 */ 152 public int getNumberOfAnswers() { 153 return this.getAnswers().size(); 154 } 155 156 /** 157 * @return list of authorities 158 */ 159 public Collection<? extends DNSRecord> getAuthorities() { 160 return _authoritativeAnswers; 161 } 162 163 /** 164 * @return number of authorities in the message 165 */ 166 public int getNumberOfAuthorities() { 167 return this.getAuthorities().size(); 168 } 169 170 /** 171 * @return list of additional answers 172 */ 173 public Collection<? extends DNSRecord> getAdditionals() { 174 return _additionals; 175 } 176 177 /** 178 * @return number of additional in the message 179 */ 180 public int getNumberOfAdditionals() { 181 return this.getAdditionals().size(); 182 } 183 184 /** 185 * Check if the message is truncated. 186 * 187 * @return true if the message was truncated 188 */ 189 public boolean isTruncated() { 190 return (_flags & DNSConstants.FLAGS_TC) != 0; 191 } 192 193 /** 194 * Check if the message is a query. 195 * 196 * @return true is the message is a query 197 */ 198 public boolean isQuery() { 199 return (_flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_QUERY; 200 } 201 202 /** 203 * Check if the message is a response. 204 * 205 * @return true is the message is a response 206 */ 207 public boolean isResponse() { 208 return (_flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_RESPONSE; 209 } 210 211 /** 212 * Check if the message is empty 213 * 214 * @return true is the message is empty 215 */ 216 public boolean isEmpty() { 217 return (this.getNumberOfQuestions() + this.getNumberOfAnswers() + this.getNumberOfAuthorities() + this.getNumberOfAdditionals()) == 0; 218 } 219 220 /** 221 * Debugging. 222 */ 223 String print() { 224 StringBuffer buf = new StringBuffer(200); 225 buf.append(this.toString()); 226 buf.append("\n"); 227 for (DNSQuestion question : _questions) { 228 buf.append("\tquestion: "); 229 buf.append(question); 230 buf.append("\n"); 231 } 232 for (DNSRecord answer : _answers) { 233 buf.append("\tanswer: "); 234 buf.append(answer); 235 buf.append("\n"); 236 } 237 for (DNSRecord answer : _authoritativeAnswers) { 238 buf.append("\tauthoritative: "); 239 buf.append(answer); 240 buf.append("\n"); 241 } 242 for (DNSRecord answer : _additionals) { 243 buf.append("\tadditional: "); 244 buf.append(answer); 245 buf.append("\n"); 246 } 247 return buf.toString(); 248 } 249 250 /** 251 * Debugging. 252 * 253 * @param data 254 * @return data dump 255 */ 256 protected String print(byte[] data) { 257 StringBuilder buf = new StringBuilder(4000); 258 for (int off = 0, len = data.length; off < len; off += 32) { 259 int n = Math.min(32, len - off); 260 if (off < 0x10) { 261 buf.append(' '); 262 } 263 if (off < 0x100) { 264 buf.append(' '); 265 } 266 if (off < 0x1000) { 267 buf.append(' '); 268 } 269 buf.append(Integer.toHexString(off)); 270 buf.append(':'); 271 int index = 0; 272 for (index = 0; index < n; index++) { 273 if ((index % 8) == 0) { 274 buf.append(' '); 275 } 276 buf.append(Integer.toHexString((data[off + index] & 0xF0) >> 4)); 277 buf.append(Integer.toHexString((data[off + index] & 0x0F) >> 0)); 278 } 279 // for incomplete lines 280 if (index < 32) { 281 for (int i = index; i < 32; i++) { 282 if ((i % 8) == 0) { 283 buf.append(' '); 284 } 285 buf.append(" "); 286 } 287 } 288 buf.append(" "); 289 for (index = 0; index < n; index++) { 290 if ((index % 8) == 0) { 291 buf.append(' '); 292 } 293 int ch = data[off + index] & 0xFF; 294 buf.append(((ch > ' ') && (ch < 127)) ? (char) ch : '.'); 295 } 296 buf.append("\n"); 297 298 // limit message size 299 if (off + 32 >= 2048) { 300 buf.append("....\n"); 301 break; 302 } 303 } 304 return buf.toString(); 305 } 306 307 } 308