|
ActiveMQ example source code file (DNSIncoming.java)
The ActiveMQ DNSIncoming.java source code/** * Copyright 2003-2005 Arthur van Hoff, Rick Blair * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.activemq.jmdns; import java.io.IOException; import java.net.DatagramPacket; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * Parse an incoming DNS message into its components. * * @version %I%, %G% * @author Arthur van Hoff, Werner Randelshofer, Pierre Frisch */ final class DNSIncoming { private static Logger logger = Logger.getLogger(DNSIncoming.class.toString()); // Implementation note: This vector should be immutable. // If a client of DNSIncoming changes the contents of this vector, // we get undesired results. To fix this, we have to migrate to // the Collections API of Java 1.2. i.e we replace Vector by List. // final static Vector EMPTY = new Vector(); private DatagramPacket packet; private int off; private int len; private byte data[]; int id; private int flags; private int numQuestions; int numAnswers; private int numAuthorities; private int numAdditionals; private long receivedTime; List questions; List answers; /** * Parse a message from a datagram packet. */ DNSIncoming(DatagramPacket packet) throws IOException { this.packet = packet; this.data = packet.getData(); this.len = packet.getLength(); this.off = packet.getOffset(); this.questions = Collections.EMPTY_LIST; this.answers = Collections.EMPTY_LIST; this.receivedTime = System.currentTimeMillis(); try { id = readUnsignedShort(); flags = readUnsignedShort(); numQuestions = readUnsignedShort(); numAnswers = readUnsignedShort(); numAuthorities = readUnsignedShort(); numAdditionals = readUnsignedShort(); // parse questions if (numQuestions > 0) { questions = Collections.synchronizedList(new ArrayList(numQuestions)); for (int i = 0; i < numQuestions; i++) { DNSQuestion question = new DNSQuestion(readName(), readUnsignedShort(), readUnsignedShort()); questions.add(question); } } // parse answers int n = numAnswers + numAuthorities + numAdditionals; if (n > 0) { answers = Collections.synchronizedList(new ArrayList(n)); for (int i = 0; i < n; i++) { String domain = readName(); int type = readUnsignedShort(); int clazz = readUnsignedShort(); int ttl = readInt(); int len = readUnsignedShort(); int end = off + len; DNSRecord rec = null; switch (type) { case DNSConstants.TYPE_A: // IPv4 case DNSConstants.TYPE_AAAA: // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested rec = new DNSRecord.Address(domain, type, clazz, ttl, readBytes(off, len)); break; case DNSConstants.TYPE_CNAME: case DNSConstants.TYPE_PTR: rec = new DNSRecord.Pointer(domain, type, clazz, ttl, readName()); break; case DNSConstants.TYPE_TXT: rec = new DNSRecord.Text(domain, type, clazz, ttl, readBytes(off, len)); break; case DNSConstants.TYPE_SRV: rec = new DNSRecord.Service(domain, type, clazz, ttl, readUnsignedShort(), readUnsignedShort(), readUnsignedShort(), readName()); break; case DNSConstants.TYPE_HINFO: // Maybe we should do something with those break; default : logger.finer("DNSIncoming() unknown type:" + type); break; } if (rec != null) { // Add a record, if we were able to create one. answers.add(rec); } else { // Addjust the numbers for the skipped record if (answers.size() < numAnswers) { numAnswers--; } else { if (answers.size() < numAnswers + numAuthorities) { numAuthorities--; } else { if (answers.size() < numAnswers + numAuthorities + numAdditionals) { numAdditionals--; } } } } off = end; } } } catch (IOException e) { logger.log(Level.WARNING, "DNSIncoming() dump " + print(true) + "\n exception ", e); throw e; } } /** * Check if the message is a query. */ boolean isQuery() { return (flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_QUERY; } /** * Check if the message is truncated. */ boolean isTruncated() { return (flags & DNSConstants.FLAGS_TC) != 0; } /** * Check if the message is a response. */ boolean isResponse() { return (flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_RESPONSE; } private int get(int off) throws IOException { if ((off < 0) || (off >= len)) { throw new IOException("parser error: offset=" + off); } return data[off] & 0xFF; } private int readUnsignedShort() throws IOException { return (get(off++) << 8) + get(off++); } private int readInt() throws IOException { return (readUnsignedShort() << 16) + readUnsignedShort(); } private byte[] readBytes(int off, int len) throws IOException { byte bytes[] = new byte[len]; System.arraycopy(data, off, bytes, 0, len); return bytes; } private void readUTF(StringBuffer buf, int off, int len) throws IOException { for (int end = off + len; off < end;) { int ch = get(off++); switch (ch >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx break; case 12: case 13: // 110x xxxx 10xx xxxx ch = ((ch & 0x1F) << 6) | (get(off++) & 0x3F); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx ch = ((ch & 0x0f) << 12) | ((get(off++) & 0x3F) << 6) | (get(off++) & 0x3F); break; default: // 10xx xxxx, 1111 xxxx ch = ((ch & 0x3F) << 4) | (get(off++) & 0x0f); break; } buf.append((char) ch); } } private String readName() throws IOException { StringBuffer buf = new StringBuffer(); int off = this.off; int next = -1; int first = off; while (true) { int len = get(off++); if (len == 0) { break; } switch (len & 0xC0) { case 0x00: //buf.append("[" + off + "]"); readUTF(buf, off, len); off += len; buf.append('.'); break; case 0xC0: //buf.append("<" + (off - 1) + ">"); if (next < 0) { next = off + 1; } off = ((len & 0x3F) << 8) | get(off++); if (off >= first) { throw new IOException("bad domain name: possible circular name detected"); } first = off; break; default: throw new IOException("bad domain name: '" + buf + "' at " + off); } } this.off = (next >= 0) ? next : off; return buf.toString(); } /** * Debugging. */ String print(boolean dump) { StringBuffer buf = new StringBuffer(); buf.append(toString() + "\n"); for (Iterator iterator = questions.iterator(); iterator.hasNext();) { buf.append(" ques:" + iterator.next() + "\n"); } int count = 0; for (Iterator iterator = answers.iterator(); iterator.hasNext(); count++) { if (count < numAnswers) { buf.append(" answ:"); } else { if (count < numAnswers + numAuthorities) { buf.append(" auth:"); } else { buf.append(" addi:"); } } buf.append(iterator.next() + "\n"); } if (dump) { for (int off = 0, len = packet.getLength(); off < len; off += 32) { int n = Math.min(32, len - off); if (off < 10) { buf.append(' '); } if (off < 100) { buf.append(' '); } buf.append(off); buf.append(':'); for (int i = 0; i < n; i++) { if ((i % 8) == 0) { buf.append(' '); } buf.append(Integer.toHexString((data[off + i] & 0xF0) >> 4)); buf.append(Integer.toHexString((data[off + i] & 0x0F) >> 0)); } buf.append("\n"); buf.append(" "); for (int i = 0; i < n; i++) { if ((i % 8) == 0) { buf.append(' '); } buf.append(' '); int ch = data[off + i] & 0xFF; buf.append(((ch > ' ') && (ch < 127)) ? (char) ch : '.'); } buf.append("\n"); // limit message size if (off + 32 >= 256) { buf.append("....\n"); break; } } } return buf.toString(); } public String toString() { StringBuffer buf = new StringBuffer(); buf.append(isQuery() ? "dns[query," : "dns[response,"); if (packet.getAddress() != null) { buf.append(packet.getAddress().getHostAddress()); } buf.append(':'); buf.append(packet.getPort()); buf.append(",len="); buf.append(packet.getLength()); buf.append(",id=0x"); buf.append(Integer.toHexString(id)); if (flags != 0) { buf.append(",flags=0x"); buf.append(Integer.toHexString(flags)); if ((flags & DNSConstants.FLAGS_QR_RESPONSE) != 0) { buf.append(":r"); } if ((flags & DNSConstants.FLAGS_AA) != 0) { buf.append(":aa"); } if ((flags & DNSConstants.FLAGS_TC) != 0) { buf.append(":tc"); } } if (numQuestions > 0) { buf.append(",questions="); buf.append(numQuestions); } if (numAnswers > 0) { buf.append(",answers="); buf.append(numAnswers); } if (numAuthorities > 0) { buf.append(",authorities="); buf.append(numAuthorities); } if (numAdditionals > 0) { buf.append(",additionals="); buf.append(numAdditionals); } buf.append("]"); return buf.toString(); } /** * Appends answers to this Incoming. * * @throws IllegalArgumentException If not a query or if Truncated. */ void append(DNSIncoming that) { if (this.isQuery() && this.isTruncated() && that.isQuery()) { this.questions.addAll(that.questions); this.numQuestions += that.numQuestions; if (Collections.EMPTY_LIST.equals(answers)) { answers = Collections.synchronizedList(new ArrayList()); } if (that.numAnswers > 0) { this.answers.addAll(this.numAnswers, that.answers.subList(0, that.numAnswers)); this.numAnswers += that.numAnswers; } if (that.numAuthorities > 0) { this.answers.addAll(this.numAnswers + this.numAuthorities, that.answers.subList(that.numAnswers, that.numAnswers + that.numAuthorities)); this.numAuthorities += that.numAuthorities; } if (that.numAdditionals > 0) { this.answers.addAll(that.answers.subList(that.numAnswers + that.numAuthorities, that.numAnswers + that.numAuthorities + that.numAdditionals)); this.numAdditionals += that.numAdditionals; } } else { throw new IllegalArgumentException(); } } int elapseSinceArrival() { return (int) (System.currentTimeMillis() - receivedTime); } } Other ActiveMQ examples (source code examples)Here is a short list of links related to this ActiveMQ DNSIncoming.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.