mirror of https://github.com/apache/activemq.git
AMQ-4056: Upgraded jmDNS to 3.4.1, and removed old obsolte activemq-jmdns module that is no longer needed.
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1387052 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1802116df8
commit
9a32e38627
|
@ -38,6 +38,7 @@
|
||||||
javax.annotation*;resolution:=optional,
|
javax.annotation*;resolution:=optional,
|
||||||
javax.transaction*;resolution:=optional,
|
javax.transaction*;resolution:=optional,
|
||||||
javax.security*;resolution:=optional,
|
javax.security*;resolution:=optional,
|
||||||
|
javax.jmdns*;resolution:=optional,
|
||||||
org.codehaus.jettison*;resolution:=optional,
|
org.codehaus.jettison*;resolution:=optional,
|
||||||
org.apache.activeio*;resolution:=optional,
|
org.apache.activeio*;resolution:=optional,
|
||||||
org.apache.camel*;resolution:=optional,
|
org.apache.camel*;resolution:=optional,
|
||||||
|
@ -219,8 +220,8 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>javax.jmdns</groupId>
|
||||||
<artifactId>activemq-jmdns_1.0</artifactId>
|
<artifactId>jmdns</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -21,7 +21,7 @@ import java.net.InetAddress;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.apache.activemq.jmdns.JmDNS;
|
import javax.jmdns.JmDNS;
|
||||||
|
|
||||||
public final class JmDNSFactory {
|
public final class JmDNSFactory {
|
||||||
|
|
||||||
|
@ -39,20 +39,14 @@ public final class JmDNSFactory {
|
||||||
UsageTracker tracker = registry.get(address);
|
UsageTracker tracker = registry.get(address);
|
||||||
if (tracker == null) {
|
if (tracker == null) {
|
||||||
tracker = new UsageTracker();
|
tracker = new UsageTracker();
|
||||||
tracker.jmDNS = new JmDNS(address) {
|
tracker.jmDNS = JmDNS.create(address);
|
||||||
public void close() {
|
|
||||||
if (onClose(address)) {
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
registry.put(address, tracker);
|
registry.put(address, tracker);
|
||||||
}
|
}
|
||||||
tracker.count.incrementAndGet();
|
tracker.count.incrementAndGet();
|
||||||
return tracker.jmDNS;
|
return tracker.jmDNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static synchronized boolean onClose(InetAddress address) {
|
static synchronized boolean onClose(InetAddress address, JmDNS dns) {
|
||||||
UsageTracker tracker = registry.get(address);
|
UsageTracker tracker = registry.get(address);
|
||||||
if (tracker != null) {
|
if (tracker != null) {
|
||||||
if (tracker.count.decrementAndGet() == 0) {
|
if (tracker.count.decrementAndGet() == 0) {
|
||||||
|
|
|
@ -23,11 +23,10 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import javax.jmdns.JmDNS;
|
||||||
import org.apache.activemq.jmdns.JmDNS;
|
import javax.jmdns.ServiceEvent;
|
||||||
import org.apache.activemq.jmdns.ServiceEvent;
|
import javax.jmdns.ServiceInfo;
|
||||||
import org.apache.activemq.jmdns.ServiceInfo;
|
import javax.jmdns.ServiceListener;
|
||||||
import org.apache.activemq.jmdns.ServiceListener;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.DiscoveryEvent;
|
import org.apache.activemq.command.DiscoveryEvent;
|
||||||
import org.apache.activemq.transport.discovery.DiscoveryAgent;
|
import org.apache.activemq.transport.discovery.DiscoveryAgent;
|
||||||
|
@ -46,7 +45,7 @@ import org.slf4j.LoggerFactory;
|
||||||
public class ZeroconfDiscoveryAgent implements DiscoveryAgent, ServiceListener {
|
public class ZeroconfDiscoveryAgent implements DiscoveryAgent, ServiceListener {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ZeroconfDiscoveryAgent.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ZeroconfDiscoveryAgent.class);
|
||||||
|
|
||||||
private static final String TYPE_SUFFIX = "ActiveMQ-4.";
|
private static final String TYPE_SUFFIX = "ActiveMQ-5.";
|
||||||
|
|
||||||
private JmDNS jmdns;
|
private JmDNS jmdns;
|
||||||
private InetAddress localAddress;
|
private InetAddress localAddress;
|
||||||
|
@ -92,7 +91,11 @@ public class ZeroconfDiscoveryAgent implements DiscoveryAgent, ServiceListener {
|
||||||
final JmDNS closeTarget = jmdns;
|
final JmDNS closeTarget = jmdns;
|
||||||
Thread thread = new Thread() {
|
Thread thread = new Thread() {
|
||||||
public void run() {
|
public void run() {
|
||||||
closeTarget.close();
|
try {
|
||||||
|
JmDNSFactory.onClose(getLocalAddress(), closeTarget);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.debug("Error closing JmDNS " + getLocalhost() + ". This exception will be ignored.", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,7 +203,7 @@ public class ZeroconfDiscoveryAgent implements DiscoveryAgent, ServiceListener {
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("Registering service type: " + type + " name: " + name + " details: " + map);
|
LOG.debug("Registering service type: " + type + " name: " + name + " details: " + map);
|
||||||
}
|
}
|
||||||
return new ServiceInfo(type, name + "." + type, port, weight, priority, "");
|
return ServiceInfo.create(type, name + "." + type, port, weight, priority, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JmDNS createJmDNS() throws IOException {
|
protected JmDNS createJmDNS() throws IOException {
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<artifactId>activemq-parent</artifactId>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<version>5.7-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>activemq-jmdns_1.0</artifactId>
|
|
||||||
<name>ActiveMQ :: jmdns 1.0</name>
|
|
||||||
|
|
||||||
<description>
|
|
||||||
The activemq-jmdns_1.0 source is derived from http://repo1.maven.org/maven2/jmdns/jmdns/1.0/jmdns-1.0-sources.jar
|
|
||||||
|
|
||||||
Changes to apache activemq version:
|
|
||||||
- renamed package javax.jmdns to org.apache.activemq.jmdns
|
|
||||||
- removed classes with lgpl source headers, leaving only the org.apache.activemq.jmdns package.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<skip>true</skip>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
|
@ -1,270 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A table of DNS entries. This is a hash table which
|
|
||||||
* can handle multiple entries with the same name.
|
|
||||||
* <p/>
|
|
||||||
* Storing multiple entries with the same name is implemented using a
|
|
||||||
* linked list of <code>CacheNode</code>'s.
|
|
||||||
* <p/>
|
|
||||||
* The current implementation of the API of DNSCache does expose the
|
|
||||||
* cache nodes to clients. Clients must explicitly deal with the nodes
|
|
||||||
* when iterating over entries in the cache. Here's how to iterate over
|
|
||||||
* all entries in the cache:
|
|
||||||
* <pre>
|
|
||||||
* for (Iterator i=dnscache.iterator(); i.hasNext(); ) {
|
|
||||||
* for (DNSCache.CacheNode n = (DNSCache.CacheNode) i.next(); n != null; n.next()) {
|
|
||||||
* DNSEntry entry = n.getValue();
|
|
||||||
* ...do something with entry...
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
* <p/>
|
|
||||||
* And here's how to iterate over all entries having a given name:
|
|
||||||
* <pre>
|
|
||||||
* for (DNSCache.CacheNode n = (DNSCache.CacheNode) dnscache.find(name); n != null; n.next()) {
|
|
||||||
* DNSEntry entry = n.getValue();
|
|
||||||
* ...do something with entry...
|
|
||||||
* }
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Werner Randelshofer, Rick Blair
|
|
||||||
*/
|
|
||||||
class DNSCache
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(DNSCache.class.toString());
|
|
||||||
// Implementation note:
|
|
||||||
// We might completely hide the existence of CacheNode's in a future version
|
|
||||||
// of DNSCache. But this will require to implement two (inner) classes for
|
|
||||||
// the iterators that will be returned by method <code>iterator()</code> and
|
|
||||||
// method <code>find(name)</code>.
|
|
||||||
// Since DNSCache is not a public class, it does not seem worth the effort
|
|
||||||
// to clean its API up that much.
|
|
||||||
|
|
||||||
// [PJYF Oct 15 2004] This should implements Collections that would be amuch cleaner implementation
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of DNSEntry's in the cache.
|
|
||||||
*/
|
|
||||||
private int size;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The hashtable used internally to store the entries of the cache.
|
|
||||||
* Keys are instances of String. The String contains an unqualified service
|
|
||||||
* name.
|
|
||||||
* Values are linked lists of CacheNode instances.
|
|
||||||
*/
|
|
||||||
private HashMap hashtable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache nodes are used to implement storage of multiple DNSEntry's of the
|
|
||||||
* same name in the cache.
|
|
||||||
*/
|
|
||||||
public static class CacheNode
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(CacheNode.class.toString());
|
|
||||||
private DNSEntry value;
|
|
||||||
private CacheNode next;
|
|
||||||
|
|
||||||
public CacheNode(DNSEntry value)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CacheNode next()
|
|
||||||
{
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DNSEntry getValue()
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a table with a given initial size.
|
|
||||||
*/
|
|
||||||
public DNSCache(final int size)
|
|
||||||
{
|
|
||||||
hashtable = new HashMap(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the cache.
|
|
||||||
*/
|
|
||||||
public synchronized void clear()
|
|
||||||
{
|
|
||||||
hashtable.clear();
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an entry to the table.
|
|
||||||
*/
|
|
||||||
public synchronized void add(final DNSEntry entry)
|
|
||||||
{
|
|
||||||
//logger.log("DNSCache.add("+entry.getName()+")");
|
|
||||||
CacheNode newValue = new CacheNode(entry);
|
|
||||||
CacheNode node = (CacheNode) hashtable.get(entry.getName());
|
|
||||||
if (node == null)
|
|
||||||
{
|
|
||||||
hashtable.put(entry.getName(), newValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newValue.next = node.next;
|
|
||||||
node.next = newValue;
|
|
||||||
}
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a specific entry from the table. Returns true if the
|
|
||||||
* entry was found.
|
|
||||||
*/
|
|
||||||
public synchronized boolean remove(DNSEntry entry)
|
|
||||||
{
|
|
||||||
CacheNode node = (CacheNode) hashtable.get(entry.getName());
|
|
||||||
if (node != null)
|
|
||||||
{
|
|
||||||
if (node.value == entry)
|
|
||||||
{
|
|
||||||
if (node.next == null)
|
|
||||||
{
|
|
||||||
hashtable.remove(entry.getName());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hashtable.put(entry.getName(), node.next);
|
|
||||||
}
|
|
||||||
size--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheNode previous = node;
|
|
||||||
node = node.next;
|
|
||||||
while (node != null)
|
|
||||||
{
|
|
||||||
if (node.value == entry)
|
|
||||||
{
|
|
||||||
previous.next = node.next;
|
|
||||||
size--;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
previous = node;
|
|
||||||
node = node.next;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a matching DNS entry from the table (using equals).
|
|
||||||
* Returns the entry that was found.
|
|
||||||
*/
|
|
||||||
public synchronized DNSEntry get(DNSEntry entry)
|
|
||||||
{
|
|
||||||
for (CacheNode node = find(entry.getName()); node != null; node = node.next)
|
|
||||||
{
|
|
||||||
if (node.value.equals(entry))
|
|
||||||
{
|
|
||||||
return node.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a matching DNS entry from the table.
|
|
||||||
*/
|
|
||||||
public synchronized DNSEntry get(String name, int type, int clazz)
|
|
||||||
{
|
|
||||||
for (CacheNode node = find(name); node != null; node = node.next)
|
|
||||||
{
|
|
||||||
if (node.value.type == type && node.value.clazz == clazz)
|
|
||||||
{
|
|
||||||
return node.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterates over all cache nodes.
|
|
||||||
* The iterator returns instances of DNSCache.CacheNode.
|
|
||||||
* Each instance returned is the first node of a linked list.
|
|
||||||
* To retrieve all entries, one must iterate over this linked list. See
|
|
||||||
* code snippets in the header of the class.
|
|
||||||
*/
|
|
||||||
public Iterator iterator()
|
|
||||||
{
|
|
||||||
return Collections.unmodifiableCollection(hashtable.values()).iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterate only over items with matching name.
|
|
||||||
* Returns an instance of DNSCache.CacheNode or null.
|
|
||||||
* If an instance is returned, it is the first node of a linked list.
|
|
||||||
* To retrieve all entries, one must iterate over this linked list.
|
|
||||||
*/
|
|
||||||
public synchronized CacheNode find(String name)
|
|
||||||
{
|
|
||||||
return (CacheNode) hashtable.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List all entries for debugging.
|
|
||||||
*/
|
|
||||||
public synchronized void print()
|
|
||||||
{
|
|
||||||
for (Iterator i = iterator(); i.hasNext();)
|
|
||||||
{
|
|
||||||
for (CacheNode n = (CacheNode) i.next(); n != null; n = n.next)
|
|
||||||
{
|
|
||||||
System.out.println(n.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized String toString()
|
|
||||||
{
|
|
||||||
StringBuffer aLog = new StringBuffer();
|
|
||||||
aLog.append("\t---- cache ----");
|
|
||||||
for (Iterator i = iterator(); i.hasNext();)
|
|
||||||
{
|
|
||||||
for (CacheNode n = (CacheNode) i.next(); n != null; n = n.next)
|
|
||||||
{
|
|
||||||
aLog.append("\n\t\t" + n.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return aLog.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,138 +0,0 @@
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DNS constants.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
|
|
||||||
*/
|
|
||||||
final class DNSConstants
|
|
||||||
{
|
|
||||||
|
|
||||||
// changed to final class - jeffs
|
|
||||||
final static String MDNS_GROUP = "224.0.0.251";
|
|
||||||
final static String MDNS_GROUP_IPV6 = "FF02::FB";
|
|
||||||
final static int MDNS_PORT = 5353;
|
|
||||||
final static int DNS_PORT = 53;
|
|
||||||
final static int DNS_TTL = 60 * 60; // default one hour TTL
|
|
||||||
// final static int DNS_TTL = 120 * 60; // two hour TTL (draft-cheshire-dnsext-multicastdns.txt ch 13)
|
|
||||||
|
|
||||||
final static int MAX_MSG_TYPICAL = 1460;
|
|
||||||
final static int MAX_MSG_ABSOLUTE = 8972;
|
|
||||||
|
|
||||||
final static int FLAGS_QR_MASK = 0x8000; // Query response mask
|
|
||||||
final static int FLAGS_QR_QUERY = 0x0000; // Query
|
|
||||||
final static int FLAGS_QR_RESPONSE = 0x8000; // Response
|
|
||||||
|
|
||||||
final static int FLAGS_AA = 0x0400; // Authorative answer
|
|
||||||
final static int FLAGS_TC = 0x0200; // Truncated
|
|
||||||
final static int FLAGS_RD = 0x0100; // Recursion desired
|
|
||||||
final static int FLAGS_RA = 0x8000; // Recursion available
|
|
||||||
|
|
||||||
final static int FLAGS_Z = 0x0040; // Zero
|
|
||||||
final static int FLAGS_AD = 0x0020; // Authentic data
|
|
||||||
final static int FLAGS_CD = 0x0010; // Checking disabled
|
|
||||||
|
|
||||||
final static int CLASS_IN = 1; // Final Static Internet
|
|
||||||
final static int CLASS_CS = 2; // CSNET
|
|
||||||
final static int CLASS_CH = 3; // CHAOS
|
|
||||||
final static int CLASS_HS = 4; // Hesiod
|
|
||||||
final static int CLASS_NONE = 254; // Used in DNS UPDATE [RFC 2136]
|
|
||||||
final static int CLASS_ANY = 255; // Not a DNS class, but a DNS query class, meaning "all classes"
|
|
||||||
final static int CLASS_MASK = 0x7FFF; // Multicast DNS uses the bottom 15 bits to identify the record class...
|
|
||||||
final static int CLASS_UNIQUE = 0x8000; // ... and the top bit indicates that all other cached records are now invalid
|
|
||||||
|
|
||||||
final static int TYPE_IGNORE = 0; // This is a hack to stop further processing
|
|
||||||
final static int TYPE_A = 1; // Address
|
|
||||||
final static int TYPE_NS = 2; // Name Server
|
|
||||||
final static int TYPE_MD = 3; // Mail Destination
|
|
||||||
final static int TYPE_MF = 4; // Mail Forwarder
|
|
||||||
final static int TYPE_CNAME = 5; // Canonical Name
|
|
||||||
final static int TYPE_SOA = 6; // Start of Authority
|
|
||||||
final static int TYPE_MB = 7; // Mailbox
|
|
||||||
final static int TYPE_MG = 8; // Mail Group
|
|
||||||
final static int TYPE_MR = 9; // Mail Rename
|
|
||||||
final static int TYPE_NULL = 10; // NULL RR
|
|
||||||
final static int TYPE_WKS = 11; // Well-known-service
|
|
||||||
final static int TYPE_PTR = 12; // Domain Name pofinal static inter
|
|
||||||
final static int TYPE_HINFO = 13; // Host information
|
|
||||||
final static int TYPE_MINFO = 14; // Mailbox information
|
|
||||||
final static int TYPE_MX = 15; // Mail exchanger
|
|
||||||
final static int TYPE_TXT = 16; // Arbitrary text string
|
|
||||||
final static int TYPE_RP = 17; // for Responsible Person [RFC1183]
|
|
||||||
final static int TYPE_AFSDB = 18; // for AFS Data Base location [RFC1183]
|
|
||||||
final static int TYPE_X25 = 19; // for X.25 PSDN address [RFC1183]
|
|
||||||
final static int TYPE_ISDN = 20; // for ISDN address [RFC1183]
|
|
||||||
final static int TYPE_RT = 21; // for Route Through [RFC1183]
|
|
||||||
final static int TYPE_NSAP = 22; // for NSAP address, NSAP style A record [RFC1706]
|
|
||||||
final static int TYPE_NSAP_PTR = 23; //
|
|
||||||
final static int TYPE_SIG = 24; // for security signature [RFC2931]
|
|
||||||
final static int TYPE_KEY = 25; // for security key [RFC2535]
|
|
||||||
final static int TYPE_PX = 26; // X.400 mail mapping information [RFC2163]
|
|
||||||
final static int TYPE_GPOS = 27; // Geographical Position [RFC1712]
|
|
||||||
final static int TYPE_AAAA = 28; // IP6 Address [Thomson]
|
|
||||||
final static int TYPE_LOC = 29; // Location Information [Vixie]
|
|
||||||
final static int TYPE_NXT = 30; // Next Domain - OBSOLETE [RFC2535, RFC3755]
|
|
||||||
final static int TYPE_EID = 31; // Endpoint Identifier [Patton]
|
|
||||||
final static int TYPE_NIMLOC = 32; // Nimrod Locator [Patton]
|
|
||||||
final static int TYPE_SRV = 33; // Server Selection [RFC2782]
|
|
||||||
final static int TYPE_ATMA = 34; // ATM Address [Dobrowski]
|
|
||||||
final static int TYPE_NAPTR = 35; // Naming Authority Pointer [RFC2168, RFC2915]
|
|
||||||
final static int TYPE_KX = 36; // Key Exchanger [RFC2230]
|
|
||||||
final static int TYPE_CERT = 37; // CERT [RFC2538]
|
|
||||||
final static int TYPE_A6 = 38; // A6 [RFC2874]
|
|
||||||
final static int TYPE_DNAME = 39; // DNAME [RFC2672]
|
|
||||||
final static int TYPE_SINK = 40; // SINK [Eastlake]
|
|
||||||
final static int TYPE_OPT = 41; // OPT [RFC2671]
|
|
||||||
final static int TYPE_APL = 42; // APL [RFC3123]
|
|
||||||
final static int TYPE_DS = 43; // Delegation Signer [RFC3658]
|
|
||||||
final static int TYPE_SSHFP = 44; // SSH Key Fingerprint [RFC-ietf-secsh-dns-05.txt]
|
|
||||||
final static int TYPE_RRSIG = 46; // RRSIG [RFC3755]
|
|
||||||
final static int TYPE_NSEC = 47; // NSEC [RFC3755]
|
|
||||||
final static int TYPE_DNSKEY = 48; // DNSKEY [RFC3755]
|
|
||||||
final static int TYPE_UINFO = 100; // [IANA-Reserved]
|
|
||||||
final static int TYPE_UID = 101; // [IANA-Reserved]
|
|
||||||
final static int TYPE_GID = 102; // [IANA-Reserved]
|
|
||||||
final static int TYPE_UNSPEC = 103; // [IANA-Reserved]
|
|
||||||
final static int TYPE_TKEY = 249; // Transaction Key [RFC2930]
|
|
||||||
final static int TYPE_TSIG = 250; // Transaction Signature [RFC2845]
|
|
||||||
final static int TYPE_IXFR = 251; // Incremental transfer [RFC1995]
|
|
||||||
final static int TYPE_AXFR = 252; // Transfer of an entire zone [RFC1035]
|
|
||||||
final static int TYPE_MAILA = 253; // Mailbox-related records (MB, MG or MR) [RFC1035]
|
|
||||||
final static int TYPE_MAILB = 254; // Mail agent RRs (Obsolete - see MX) [RFC1035]
|
|
||||||
final static int TYPE_ANY = 255; // Request for all records [RFC1035]
|
|
||||||
|
|
||||||
//Time Intervals for various functions
|
|
||||||
|
|
||||||
final static int SHARED_QUERY_TIME = 20; //milliseconds before send shared query
|
|
||||||
final static int QUERY_WAIT_INTERVAL = 225; //milliseconds between query loops.
|
|
||||||
final static int PROBE_WAIT_INTERVAL = 250; //milliseconds between probe loops.
|
|
||||||
final static int RESPONSE_MIN_WAIT_INTERVAL = 20; //minimal wait interval for response.
|
|
||||||
final static int RESPONSE_MAX_WAIT_INTERVAL = 115; //maximal wait interval for response
|
|
||||||
final static int PROBE_CONFLICT_INTERVAL = 1000; //milliseconds to wait after conflict.
|
|
||||||
final static int PROBE_THROTTLE_COUNT = 10; //After x tries go 1 time a sec. on probes.
|
|
||||||
final static int PROBE_THROTTLE_COUNT_INTERVAL = 5000; //We only increment the throttle count, if
|
|
||||||
// the previous increment is inside this interval.
|
|
||||||
final static int ANNOUNCE_WAIT_INTERVAL = 1000; //milliseconds between Announce loops.
|
|
||||||
final static int RECORD_REAPER_INTERVAL = 10000; //milliseconds between cache cleanups.
|
|
||||||
final static int KNOWN_ANSWER_TTL = 120;
|
|
||||||
final static int ANNOUNCED_RENEWAL_TTL_INTERVAL = DNS_TTL * 500; // 50% of the TTL in milliseconds
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DNS entry with a name, type, and class. This is the base
|
|
||||||
* class for questions and records.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Pierre Frisch, Rick Blair
|
|
||||||
*/
|
|
||||||
class DNSEntry
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(DNSEntry.class.toString());
|
|
||||||
String key;
|
|
||||||
String name;
|
|
||||||
int type;
|
|
||||||
int clazz;
|
|
||||||
boolean unique;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an entry.
|
|
||||||
*/
|
|
||||||
DNSEntry(String name, int type, int clazz)
|
|
||||||
{
|
|
||||||
this.key = name.toLowerCase();
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
this.clazz = clazz & DNSConstants.CLASS_MASK;
|
|
||||||
this.unique = (clazz & DNSConstants.CLASS_UNIQUE) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if two entries have exactly the same name, type, and class.
|
|
||||||
*/
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (obj instanceof DNSEntry)
|
|
||||||
{
|
|
||||||
DNSEntry other = (DNSEntry) obj;
|
|
||||||
return name.equals(other.name) && type == other.type && clazz == other.clazz;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overriden, to return a value which is consistent with the value returned
|
|
||||||
* by equals(Object).
|
|
||||||
*/
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
return name.hashCode() + type + clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a string given a clazz.
|
|
||||||
*/
|
|
||||||
static String getClazz(int clazz)
|
|
||||||
{
|
|
||||||
switch (clazz & DNSConstants.CLASS_MASK)
|
|
||||||
{
|
|
||||||
case DNSConstants.CLASS_IN:
|
|
||||||
return "in";
|
|
||||||
case DNSConstants.CLASS_CS:
|
|
||||||
return "cs";
|
|
||||||
case DNSConstants.CLASS_CH:
|
|
||||||
return "ch";
|
|
||||||
case DNSConstants.CLASS_HS:
|
|
||||||
return "hs";
|
|
||||||
case DNSConstants.CLASS_NONE:
|
|
||||||
return "none";
|
|
||||||
case DNSConstants.CLASS_ANY:
|
|
||||||
return "any";
|
|
||||||
default:
|
|
||||||
return "?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a string given a type.
|
|
||||||
*/
|
|
||||||
static String getType(int type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case DNSConstants.TYPE_A:
|
|
||||||
return "a";
|
|
||||||
case DNSConstants.TYPE_AAAA:
|
|
||||||
return "aaaa";
|
|
||||||
case DNSConstants.TYPE_NS:
|
|
||||||
return "ns";
|
|
||||||
case DNSConstants.TYPE_MD:
|
|
||||||
return "md";
|
|
||||||
case DNSConstants.TYPE_MF:
|
|
||||||
return "mf";
|
|
||||||
case DNSConstants.TYPE_CNAME:
|
|
||||||
return "cname";
|
|
||||||
case DNSConstants.TYPE_SOA:
|
|
||||||
return "soa";
|
|
||||||
case DNSConstants.TYPE_MB:
|
|
||||||
return "mb";
|
|
||||||
case DNSConstants.TYPE_MG:
|
|
||||||
return "mg";
|
|
||||||
case DNSConstants.TYPE_MR:
|
|
||||||
return "mr";
|
|
||||||
case DNSConstants.TYPE_NULL:
|
|
||||||
return "null";
|
|
||||||
case DNSConstants.TYPE_WKS:
|
|
||||||
return "wks";
|
|
||||||
case DNSConstants.TYPE_PTR:
|
|
||||||
return "ptr";
|
|
||||||
case DNSConstants.TYPE_HINFO:
|
|
||||||
return "hinfo";
|
|
||||||
case DNSConstants.TYPE_MINFO:
|
|
||||||
return "minfo";
|
|
||||||
case DNSConstants.TYPE_MX:
|
|
||||||
return "mx";
|
|
||||||
case DNSConstants.TYPE_TXT:
|
|
||||||
return "txt";
|
|
||||||
case DNSConstants.TYPE_SRV:
|
|
||||||
return "srv";
|
|
||||||
case DNSConstants.TYPE_ANY:
|
|
||||||
return "any";
|
|
||||||
default:
|
|
||||||
return "?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString(String hdr, String other)
|
|
||||||
{
|
|
||||||
return hdr + "[" + getType(type) + "," + getClazz(clazz) + (unique ? "-unique," : ",") + name + ((other != null) ? "," + other + "]" : "]");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,478 +0,0 @@
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
// REMIND: Listener should follow Java idiom for listener or have a different
|
|
||||||
// name.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DNSListener.
|
|
||||||
* Listener for record updates.
|
|
||||||
*
|
|
||||||
* @author Werner Randelshofer, Rick Blair
|
|
||||||
* @version 1.0 May 22, 2004 Created.
|
|
||||||
*/
|
|
||||||
public interface DNSListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Update a DNS record.
|
|
||||||
*/
|
|
||||||
void updateRecord(JmDNS jmdns, long now, DNSRecord record);
|
|
||||||
}
|
|
|
@ -1,394 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.Hashtable;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An outgoing DNS message.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Rick Blair, Werner Randelshofer
|
|
||||||
*/
|
|
||||||
final class DNSOutgoing
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(DNSOutgoing.class.toString());
|
|
||||||
int id;
|
|
||||||
int flags;
|
|
||||||
private boolean multicast;
|
|
||||||
private int numQuestions;
|
|
||||||
private int numAnswers;
|
|
||||||
private int numAuthorities;
|
|
||||||
private int numAdditionals;
|
|
||||||
private Hashtable names;
|
|
||||||
|
|
||||||
byte data[];
|
|
||||||
int off;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an outgoing multicast query or response.
|
|
||||||
*/
|
|
||||||
DNSOutgoing(int flags)
|
|
||||||
{
|
|
||||||
this(flags, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an outgoing query or response.
|
|
||||||
*/
|
|
||||||
DNSOutgoing(int flags, boolean multicast)
|
|
||||||
{
|
|
||||||
this.flags = flags;
|
|
||||||
this.multicast = multicast;
|
|
||||||
names = new Hashtable();
|
|
||||||
data = new byte[DNSConstants.MAX_MSG_TYPICAL];
|
|
||||||
off = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a question to the message.
|
|
||||||
*/
|
|
||||||
void addQuestion(DNSQuestion rec) throws IOException
|
|
||||||
{
|
|
||||||
if (numAnswers > 0 || numAuthorities > 0 || numAdditionals > 0)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Questions must be added before answers");
|
|
||||||
}
|
|
||||||
numQuestions++;
|
|
||||||
writeQuestion(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an answer if it is not suppressed.
|
|
||||||
*/
|
|
||||||
void addAnswer(DNSIncoming in, DNSRecord rec) throws IOException
|
|
||||||
{
|
|
||||||
if (numAuthorities > 0 || numAdditionals > 0)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Answers must be added before authorities and additionals");
|
|
||||||
}
|
|
||||||
if (!rec.suppressedBy(in))
|
|
||||||
{
|
|
||||||
addAnswer(rec, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an additional answer to the record. Omit if there is no room.
|
|
||||||
*/
|
|
||||||
void addAdditionalAnswer(DNSIncoming in, DNSRecord rec) throws IOException
|
|
||||||
{
|
|
||||||
if ((off < DNSConstants.MAX_MSG_TYPICAL - 200) && !rec.suppressedBy(in))
|
|
||||||
{
|
|
||||||
writeRecord(rec, 0);
|
|
||||||
numAdditionals++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an answer to the message.
|
|
||||||
*/
|
|
||||||
void addAnswer(DNSRecord rec, long now) throws IOException
|
|
||||||
{
|
|
||||||
if (numAuthorities > 0 || numAdditionals > 0)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Questions must be added before answers");
|
|
||||||
}
|
|
||||||
if (rec != null)
|
|
||||||
{
|
|
||||||
if ((now == 0) || !rec.isExpired(now))
|
|
||||||
{
|
|
||||||
writeRecord(rec, now);
|
|
||||||
numAnswers++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private LinkedList authorativeAnswers = new LinkedList();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an authorative answer to the message.
|
|
||||||
*/
|
|
||||||
void addAuthorativeAnswer(DNSRecord rec) throws IOException
|
|
||||||
{
|
|
||||||
if (numAdditionals > 0)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Authorative answers must be added before additional answers");
|
|
||||||
}
|
|
||||||
authorativeAnswers.add(rec);
|
|
||||||
writeRecord(rec, 0);
|
|
||||||
numAuthorities++;
|
|
||||||
|
|
||||||
// VERIFY:
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeByte(int value) throws IOException
|
|
||||||
{
|
|
||||||
if (off >= data.length)
|
|
||||||
{
|
|
||||||
throw new IOException("buffer full");
|
|
||||||
}
|
|
||||||
data[off++] = (byte) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeBytes(String str, int off, int len) throws IOException
|
|
||||||
{
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
writeByte(str.charAt(off + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeBytes(byte data[]) throws IOException
|
|
||||||
{
|
|
||||||
if (data != null)
|
|
||||||
{
|
|
||||||
writeBytes(data, 0, data.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeBytes(byte data[], int off, int len) throws IOException
|
|
||||||
{
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
writeByte(data[off + i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeShort(int value) throws IOException
|
|
||||||
{
|
|
||||||
writeByte(value >> 8);
|
|
||||||
writeByte(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeInt(int value) throws IOException
|
|
||||||
{
|
|
||||||
writeShort(value >> 16);
|
|
||||||
writeShort(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeUTF(String str, int off, int len) throws IOException
|
|
||||||
{
|
|
||||||
// compute utf length
|
|
||||||
int utflen = 0;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
int ch = str.charAt(off + i);
|
|
||||||
if ((ch >= 0x0001) && (ch <= 0x007F))
|
|
||||||
{
|
|
||||||
utflen += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ch > 0x07FF)
|
|
||||||
{
|
|
||||||
utflen += 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
utflen += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// write utf length
|
|
||||||
writeByte(utflen);
|
|
||||||
// write utf data
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
int ch = str.charAt(off + i);
|
|
||||||
if ((ch >= 0x0001) && (ch <= 0x007F))
|
|
||||||
{
|
|
||||||
writeByte(ch);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ch > 0x07FF)
|
|
||||||
{
|
|
||||||
writeByte(0xE0 | ((ch >> 12) & 0x0F));
|
|
||||||
writeByte(0x80 | ((ch >> 6) & 0x3F));
|
|
||||||
writeByte(0x80 | ((ch >> 0) & 0x3F));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
writeByte(0xC0 | ((ch >> 6) & 0x1F));
|
|
||||||
writeByte(0x80 | ((ch >> 0) & 0x3F));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeName(String name) throws IOException
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int n = name.indexOf('.');
|
|
||||||
if (n < 0)
|
|
||||||
{
|
|
||||||
n = name.length();
|
|
||||||
}
|
|
||||||
if (n <= 0)
|
|
||||||
{
|
|
||||||
writeByte(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Integer offset = (Integer) names.get(name);
|
|
||||||
if (offset != null)
|
|
||||||
{
|
|
||||||
int val = offset.intValue();
|
|
||||||
|
|
||||||
if (val > off)
|
|
||||||
{
|
|
||||||
logger.log(Level.WARNING, "DNSOutgoing writeName failed val=" + val + " name=" + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeByte((val >> 8) | 0xC0);
|
|
||||||
writeByte(val);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
names.put(name, new Integer(off));
|
|
||||||
writeUTF(name, 0, n);
|
|
||||||
name = name.substring(n);
|
|
||||||
if (name.startsWith("."))
|
|
||||||
{
|
|
||||||
name = name.substring(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeQuestion(DNSQuestion question) throws IOException
|
|
||||||
{
|
|
||||||
writeName(question.name);
|
|
||||||
writeShort(question.type);
|
|
||||||
writeShort(question.clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeRecord(DNSRecord rec, long now) throws IOException
|
|
||||||
{
|
|
||||||
int save = off;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
writeName(rec.name);
|
|
||||||
writeShort(rec.type);
|
|
||||||
writeShort(rec.clazz | ((rec.unique && multicast) ? DNSConstants.CLASS_UNIQUE : 0));
|
|
||||||
writeInt((now == 0) ? rec.ttl : rec.getRemainingTTL(now));
|
|
||||||
writeShort(0);
|
|
||||||
int start = off;
|
|
||||||
rec.write(this);
|
|
||||||
int len = off - start;
|
|
||||||
data[start - 2] = (byte) (len >> 8);
|
|
||||||
data[start - 1] = (byte) (len & 0xFF);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
off = save;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finish the message before sending it off.
|
|
||||||
*/
|
|
||||||
void finish() throws IOException
|
|
||||||
{
|
|
||||||
int save = off;
|
|
||||||
off = 0;
|
|
||||||
|
|
||||||
writeShort(multicast ? 0 : id);
|
|
||||||
writeShort(flags);
|
|
||||||
writeShort(numQuestions);
|
|
||||||
writeShort(numAnswers);
|
|
||||||
writeShort(numAuthorities);
|
|
||||||
writeShort(numAdditionals);
|
|
||||||
off = save;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isQuery()
|
|
||||||
{
|
|
||||||
return (flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_QUERY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty()
|
|
||||||
{
|
|
||||||
return numQuestions == 0 && numAuthorities == 0
|
|
||||||
&& numAdditionals == 0 && numAnswers == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
buf.append(isQuery() ? "dns[query," : "dns[response,");
|
|
||||||
//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(",\nnames=" + names);
|
|
||||||
buf.append(",\nauthorativeAnswers=" + authorativeAnswers);
|
|
||||||
|
|
||||||
buf.append("]");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A DNS question.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff
|
|
||||||
*/
|
|
||||||
final class DNSQuestion extends DNSEntry
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(DNSQuestion.class.toString());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a question.
|
|
||||||
*/
|
|
||||||
DNSQuestion(String name, int type, int clazz)
|
|
||||||
{
|
|
||||||
super(name, type, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this question is answered by a given DNS record.
|
|
||||||
*/
|
|
||||||
boolean answeredBy(DNSRecord rec)
|
|
||||||
{
|
|
||||||
return (clazz == rec.clazz) && ((type == rec.type) || (type == DNSConstants.TYPE_ANY)) &&
|
|
||||||
name.equals(rec.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For debugging only.
|
|
||||||
*/
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return toString("question", null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,686 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.ByteArrayOutputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.Inet4Address;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DNS record
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Rick Blair, Werner Randelshofer, Pierre Frisch
|
|
||||||
*/
|
|
||||||
public abstract class DNSRecord extends DNSEntry
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(DNSRecord.class.toString());
|
|
||||||
int ttl;
|
|
||||||
private long created;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a DNSRecord with a name, type, clazz, and ttl.
|
|
||||||
*/
|
|
||||||
DNSRecord(String name, int type, int clazz, int ttl)
|
|
||||||
{
|
|
||||||
super(name, type, clazz);
|
|
||||||
this.ttl = ttl;
|
|
||||||
this.created = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if this record is the same as some other record.
|
|
||||||
*/
|
|
||||||
public boolean equals(Object other)
|
|
||||||
{
|
|
||||||
return (other instanceof DNSRecord) && sameAs((DNSRecord) other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if this record is the same as some other record.
|
|
||||||
*/
|
|
||||||
boolean sameAs(DNSRecord other)
|
|
||||||
{
|
|
||||||
return super.equals(other) && sameValue((DNSRecord) other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if this record has the same value as some other record.
|
|
||||||
*/
|
|
||||||
abstract boolean sameValue(DNSRecord other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if this record has the same type as some other record.
|
|
||||||
*/
|
|
||||||
boolean sameType(DNSRecord other)
|
|
||||||
{
|
|
||||||
return type == other.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a query represented by this record.
|
|
||||||
*
|
|
||||||
* @return Returns true if a conflict with one of the services registered
|
|
||||||
* with JmDNS or with the hostname occured.
|
|
||||||
*/
|
|
||||||
abstract boolean handleQuery(JmDNS dns, long expirationTime);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a responserepresented by this record.
|
|
||||||
*
|
|
||||||
* @return Returns true if a conflict with one of the services registered
|
|
||||||
* with JmDNS or with the hostname occured.
|
|
||||||
*/
|
|
||||||
abstract boolean handleResponse(JmDNS dns);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds this as an answer to the provided outgoing datagram.
|
|
||||||
*/
|
|
||||||
abstract DNSOutgoing addAnswer(JmDNS dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if this record is suppressed by the answers in a message.
|
|
||||||
*/
|
|
||||||
boolean suppressedBy(DNSIncoming msg)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (int i = msg.numAnswers; i-- > 0;)
|
|
||||||
{
|
|
||||||
if (suppressedBy((DNSRecord) msg.answers.get(i)))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (ArrayIndexOutOfBoundsException e)
|
|
||||||
{
|
|
||||||
logger.log(Level.WARNING, "suppressedBy() message " + msg + " exception ", e);
|
|
||||||
// msg.print(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if this record would be supressed by an answer.
|
|
||||||
* This is the case if this record would not have a
|
|
||||||
* significantly longer TTL.
|
|
||||||
*/
|
|
||||||
boolean suppressedBy(DNSRecord other)
|
|
||||||
{
|
|
||||||
if (sameAs(other) && (other.ttl > ttl / 2))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the expiration time of this record.
|
|
||||||
*/
|
|
||||||
long getExpirationTime(int percent)
|
|
||||||
{
|
|
||||||
return created + (percent * ttl * 10L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the remaining TTL for this record.
|
|
||||||
*/
|
|
||||||
int getRemainingTTL(long now)
|
|
||||||
{
|
|
||||||
return (int) Math.max(0, (getExpirationTime(100) - now) / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the record is expired.
|
|
||||||
*/
|
|
||||||
public boolean isExpired(long now)
|
|
||||||
{
|
|
||||||
return getExpirationTime(100) <= now;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the record is stale, ie it has outlived
|
|
||||||
* more than half of its TTL.
|
|
||||||
*/
|
|
||||||
boolean isStale(long now)
|
|
||||||
{
|
|
||||||
return getExpirationTime(50) <= now;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the TTL of a record. This avoids having to
|
|
||||||
* update the entire record in the cache.
|
|
||||||
*/
|
|
||||||
void resetTTL(DNSRecord other)
|
|
||||||
{
|
|
||||||
created = other.created;
|
|
||||||
ttl = other.ttl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write this record into an outgoing message.
|
|
||||||
*/
|
|
||||||
abstract void write(DNSOutgoing out) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address record.
|
|
||||||
*/
|
|
||||||
public static class Address extends DNSRecord
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(Address.class.toString());
|
|
||||||
InetAddress addr;
|
|
||||||
|
|
||||||
Address(String name, int type, int clazz, int ttl, InetAddress addr)
|
|
||||||
{
|
|
||||||
super(name, type, clazz, ttl);
|
|
||||||
this.addr = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Address(String name, int type, int clazz, int ttl, byte[] rawAddress)
|
|
||||||
{
|
|
||||||
super(name, type, clazz, ttl);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.addr = InetAddress.getByAddress(rawAddress);
|
|
||||||
}
|
|
||||||
catch (UnknownHostException exception)
|
|
||||||
{
|
|
||||||
logger.log(Level.WARNING, "Address() exception ", exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
if (addr != null)
|
|
||||||
{
|
|
||||||
byte[] buffer = addr.getAddress();
|
|
||||||
if (DNSConstants.TYPE_A == type)
|
|
||||||
{
|
|
||||||
// If we have a type A records we should answer with a IPv4 address
|
|
||||||
if (addr instanceof Inet4Address)
|
|
||||||
{
|
|
||||||
// All is good
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get the last four bytes
|
|
||||||
byte[] tempbuffer = buffer;
|
|
||||||
buffer = new byte[4];
|
|
||||||
System.arraycopy(tempbuffer, 12, buffer, 0, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we have a type AAAA records we should answer with a IPv6 address
|
|
||||||
if (addr instanceof Inet4Address)
|
|
||||||
{
|
|
||||||
byte[] tempbuffer = buffer;
|
|
||||||
buffer = new byte[16];
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if (i < 11)
|
|
||||||
{
|
|
||||||
buffer[i] = tempbuffer[i - 12];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int length = buffer.length;
|
|
||||||
out.writeBytes(buffer, 0, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean same(DNSRecord other)
|
|
||||||
{
|
|
||||||
return ((sameName(other)) && ((sameValue(other))));
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean sameName(DNSRecord other)
|
|
||||||
{
|
|
||||||
return name.equalsIgnoreCase(((Address) other).name);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean sameValue(DNSRecord other)
|
|
||||||
{
|
|
||||||
return addr.equals(((Address) other).getAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
InetAddress getAddress()
|
|
||||||
{
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a byte array representation of this record.
|
|
||||||
* This is needed for tie-break tests according to
|
|
||||||
* draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
|
|
||||||
*/
|
|
||||||
private byte[] toByteArray()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
|
||||||
DataOutputStream dout = new DataOutputStream(bout);
|
|
||||||
dout.write(name.getBytes("UTF8"));
|
|
||||||
dout.writeShort(type);
|
|
||||||
dout.writeShort(clazz);
|
|
||||||
//dout.writeInt(len);
|
|
||||||
byte[] buffer = addr.getAddress();
|
|
||||||
for (int i = 0; i < buffer.length; i++)
|
|
||||||
{
|
|
||||||
dout.writeByte(buffer[i]);
|
|
||||||
}
|
|
||||||
dout.close();
|
|
||||||
return bout.toByteArray();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new InternalError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does a lexicographic comparison of the byte array representation
|
|
||||||
* of this record and that record.
|
|
||||||
* This is needed for tie-break tests according to
|
|
||||||
* draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
|
|
||||||
*/
|
|
||||||
private int lexCompare(DNSRecord.Address that)
|
|
||||||
{
|
|
||||||
byte[] thisBytes = this.toByteArray();
|
|
||||||
byte[] thatBytes = that.toByteArray();
|
|
||||||
for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); i < n; i++)
|
|
||||||
{
|
|
||||||
if (thisBytes[i] > thatBytes[i])
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (thisBytes[i] < thatBytes[i])
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return thisBytes.length - thatBytes.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the necessary actions, when this as a query.
|
|
||||||
*/
|
|
||||||
boolean handleQuery(JmDNS dns, long expirationTime)
|
|
||||||
{
|
|
||||||
DNSRecord.Address dnsAddress = dns.getLocalHost().getDNSAddressRecord(this);
|
|
||||||
if (dnsAddress != null)
|
|
||||||
{
|
|
||||||
if (dnsAddress.sameType(this) && dnsAddress.sameName(this) && (!dnsAddress.sameValue(this)))
|
|
||||||
{
|
|
||||||
logger.finer("handleQuery() Conflicting probe detected. dns state " + dns.getState() + " lex compare " + lexCompare(dnsAddress));
|
|
||||||
// Tie-breaker test
|
|
||||||
if (dns.getState().isProbing() && lexCompare(dnsAddress) >= 0)
|
|
||||||
{
|
|
||||||
// We lost the tie-break. We have to choose a different name.
|
|
||||||
dns.getLocalHost().incrementHostName();
|
|
||||||
dns.getCache().clear();
|
|
||||||
for (Iterator i = dns.services.values().iterator(); i.hasNext();)
|
|
||||||
{
|
|
||||||
ServiceInfo info = (ServiceInfo) i.next();
|
|
||||||
info.revertState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dns.revertState();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the necessary actions, when this as a response.
|
|
||||||
*/
|
|
||||||
boolean handleResponse(JmDNS dns)
|
|
||||||
{
|
|
||||||
DNSRecord.Address dnsAddress = dns.getLocalHost().getDNSAddressRecord(this);
|
|
||||||
if (dnsAddress != null)
|
|
||||||
{
|
|
||||||
if (dnsAddress.sameType(this) && dnsAddress.sameName(this) && (!dnsAddress.sameValue(this)))
|
|
||||||
{
|
|
||||||
logger.finer("handleResponse() Denial detected");
|
|
||||||
|
|
||||||
if (dns.getState().isProbing())
|
|
||||||
{
|
|
||||||
dns.getLocalHost().incrementHostName();
|
|
||||||
dns.getCache().clear();
|
|
||||||
for (Iterator i = dns.services.values().iterator(); i.hasNext();)
|
|
||||||
{
|
|
||||||
ServiceInfo info = (ServiceInfo) i.next();
|
|
||||||
info.revertState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dns.revertState();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DNSOutgoing addAnswer(JmDNS dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return toString(" address '" + (addr != null ? addr.getHostAddress() : "null") + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pointer record.
|
|
||||||
*/
|
|
||||||
public static class Pointer extends DNSRecord
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(Pointer.class.toString());
|
|
||||||
String alias;
|
|
||||||
|
|
||||||
Pointer(String name, int type, int clazz, int ttl, String alias)
|
|
||||||
{
|
|
||||||
super(name, type, clazz, ttl);
|
|
||||||
this.alias = alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
out.writeName(alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean sameValue(DNSRecord other)
|
|
||||||
{
|
|
||||||
return alias.equals(((Pointer) other).alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handleQuery(JmDNS dns, long expirationTime)
|
|
||||||
{
|
|
||||||
// Nothing to do (?)
|
|
||||||
// I think there is no possibility for conflicts for this record type?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handleResponse(JmDNS dns)
|
|
||||||
{
|
|
||||||
// Nothing to do (?)
|
|
||||||
// I think there is no possibility for conflicts for this record type?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getAlias()
|
|
||||||
{
|
|
||||||
return alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
DNSOutgoing addAnswer(JmDNS dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return toString(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Text extends DNSRecord
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(Text.class.toString());
|
|
||||||
final public byte text[];
|
|
||||||
|
|
||||||
Text(String name, int type, int clazz, int ttl, byte text[])
|
|
||||||
{
|
|
||||||
super(name, type, clazz, ttl);
|
|
||||||
this.text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
out.writeBytes(text, 0, text.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean sameValue(DNSRecord other)
|
|
||||||
{
|
|
||||||
Text txt = (Text) other;
|
|
||||||
if (txt.text.length != text.length)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = text.length; i-- > 0;)
|
|
||||||
{
|
|
||||||
if (txt.text[i] != text[i])
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handleQuery(JmDNS dns, long expirationTime)
|
|
||||||
{
|
|
||||||
// Nothing to do (?)
|
|
||||||
// I think there is no possibility for conflicts for this record type?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handleResponse(JmDNS dns)
|
|
||||||
{
|
|
||||||
// Nothing to do (?)
|
|
||||||
// Shouldn't we care if we get a conflict at this level?
|
|
||||||
/*
|
|
||||||
ServiceInfo info = (ServiceInfo) dns.services.get(name.toLowerCase());
|
|
||||||
if (info != null) {
|
|
||||||
if (! Arrays.equals(text,info.text)) {
|
|
||||||
info.revertState();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DNSOutgoing addAnswer(JmDNS dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return toString((text.length > 10) ? new String(text, 0, 7) + "..." : new String(text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service record.
|
|
||||||
*/
|
|
||||||
public static class Service extends DNSRecord
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(Service.class.toString());
|
|
||||||
int priority;
|
|
||||||
int weight;
|
|
||||||
int port;
|
|
||||||
String server;
|
|
||||||
|
|
||||||
Service(String name, int type, int clazz, int ttl, int priority, int weight, int port, String server)
|
|
||||||
{
|
|
||||||
super(name, type, clazz, ttl);
|
|
||||||
this.priority = priority;
|
|
||||||
this.weight = weight;
|
|
||||||
this.port = port;
|
|
||||||
this.server = server;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
out.writeShort(priority);
|
|
||||||
out.writeShort(weight);
|
|
||||||
out.writeShort(port);
|
|
||||||
out.writeName(server);
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] toByteArray()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
|
||||||
DataOutputStream dout = new DataOutputStream(bout);
|
|
||||||
dout.write(name.getBytes("UTF8"));
|
|
||||||
dout.writeShort(type);
|
|
||||||
dout.writeShort(clazz);
|
|
||||||
//dout.writeInt(len);
|
|
||||||
dout.writeShort(priority);
|
|
||||||
dout.writeShort(weight);
|
|
||||||
dout.writeShort(port);
|
|
||||||
dout.write(server.getBytes("UTF8"));
|
|
||||||
dout.close();
|
|
||||||
return bout.toByteArray();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new InternalError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int lexCompare(DNSRecord.Service that)
|
|
||||||
{
|
|
||||||
byte[] thisBytes = this.toByteArray();
|
|
||||||
byte[] thatBytes = that.toByteArray();
|
|
||||||
for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); i < n; i++)
|
|
||||||
{
|
|
||||||
if (thisBytes[i] > thatBytes[i])
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (thisBytes[i] < thatBytes[i])
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return thisBytes.length - thatBytes.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean sameValue(DNSRecord other)
|
|
||||||
{
|
|
||||||
Service s = (Service) other;
|
|
||||||
return (priority == s.priority) && (weight == s.weight) && (port == s.port) && server.equals(s.server);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handleQuery(JmDNS dns, long expirationTime)
|
|
||||||
{
|
|
||||||
ServiceInfo info = (ServiceInfo) dns.services.get(name.toLowerCase());
|
|
||||||
if (info != null
|
|
||||||
&& (port != info.port || !server.equalsIgnoreCase(dns.getLocalHost().getName())))
|
|
||||||
{
|
|
||||||
logger.finer("handleQuery() Conflicting probe detected");
|
|
||||||
|
|
||||||
// Tie breaker test
|
|
||||||
if (info.getState().isProbing() && lexCompare(new DNSRecord.Service(info.getQualifiedName(), DNSConstants.TYPE_SRV,
|
|
||||||
DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE,
|
|
||||||
DNSConstants.DNS_TTL, info.priority,
|
|
||||||
info.weight, info.port, dns.getLocalHost().getName())) >= 0)
|
|
||||||
{
|
|
||||||
// We lost the tie break
|
|
||||||
String oldName = info.getQualifiedName().toLowerCase();
|
|
||||||
info.setName(dns.incrementName(info.getName()));
|
|
||||||
dns.services.remove(oldName);
|
|
||||||
dns.services.put(info.getQualifiedName().toLowerCase(), info);
|
|
||||||
logger.finer("handleQuery() Lost tie break: new unique name chosen:" + info.getName());
|
|
||||||
|
|
||||||
}
|
|
||||||
info.revertState();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handleResponse(JmDNS dns)
|
|
||||||
{
|
|
||||||
ServiceInfo info = (ServiceInfo) dns.services.get(name.toLowerCase());
|
|
||||||
if (info != null
|
|
||||||
&& (port != info.port || !server.equalsIgnoreCase(dns.getLocalHost().getName())))
|
|
||||||
{
|
|
||||||
logger.finer("handleResponse() Denial detected");
|
|
||||||
|
|
||||||
if (info.getState().isProbing())
|
|
||||||
{
|
|
||||||
String oldName = info.getQualifiedName().toLowerCase();
|
|
||||||
info.setName(dns.incrementName(info.getName()));
|
|
||||||
dns.services.remove(oldName);
|
|
||||||
dns.services.put(info.getQualifiedName().toLowerCase(), info);
|
|
||||||
logger.finer("handleResponse() New unique name chose:" + info.getName());
|
|
||||||
|
|
||||||
}
|
|
||||||
info.revertState();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DNSOutgoing addAnswer(JmDNS dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException
|
|
||||||
{
|
|
||||||
ServiceInfo info = (ServiceInfo) dns.services.get(name.toLowerCase());
|
|
||||||
if (info != null)
|
|
||||||
{
|
|
||||||
if (this.port == info.port != server.equals(dns.getLocalHost().getName()))
|
|
||||||
{
|
|
||||||
return dns.addAnswer(in, addr, port, out,
|
|
||||||
new DNSRecord.Service(info.getQualifiedName(), DNSConstants.TYPE_SRV,
|
|
||||||
DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE,
|
|
||||||
DNSConstants.DNS_TTL, info.priority,
|
|
||||||
info.weight, info.port, dns.getLocalHost().getName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return toString(server + ":" + port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString(String other)
|
|
||||||
{
|
|
||||||
return toString("record", ttl + "/" + getRemainingTTL(System.currentTimeMillis()) + "," + other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.ArrayList;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DNSState defines the possible states for services registered with JmDNS.
|
|
||||||
*
|
|
||||||
* @author Werner Randelshofer, Rick Blair
|
|
||||||
* @version 1.0 May 23, 2004 Created.
|
|
||||||
*/
|
|
||||||
public class DNSState implements Comparable
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(DNSState.class.toString());
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ordinal of next state to be created.
|
|
||||||
*/
|
|
||||||
private static int nextOrdinal = 0;
|
|
||||||
/**
|
|
||||||
* Assign an ordinal to this state.
|
|
||||||
*/
|
|
||||||
private final int ordinal = nextOrdinal++;
|
|
||||||
/**
|
|
||||||
* Logical sequence of states.
|
|
||||||
* The sequence is consistent with the ordinal of a state.
|
|
||||||
* This is used for advancing through states.
|
|
||||||
*/
|
|
||||||
private final static ArrayList sequence = new ArrayList();
|
|
||||||
|
|
||||||
private DNSState(String name)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
sequence.add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String toString()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final DNSState PROBING_1 = new DNSState("probing 1");
|
|
||||||
public static final DNSState PROBING_2 = new DNSState("probing 2");
|
|
||||||
public static final DNSState PROBING_3 = new DNSState("probing 3");
|
|
||||||
public static final DNSState ANNOUNCING_1 = new DNSState("announcing 1");
|
|
||||||
public static final DNSState ANNOUNCING_2 = new DNSState("announcing 2");
|
|
||||||
public static final DNSState ANNOUNCED = new DNSState("announced");
|
|
||||||
public static final DNSState CANCELED = new DNSState("canceled");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next advanced state.
|
|
||||||
* In general, this advances one step in the following sequence: PROBING_1,
|
|
||||||
* PROBING_2, PROBING_3, ANNOUNCING_1, ANNOUNCING_2, ANNOUNCED.
|
|
||||||
* Does not advance for ANNOUNCED and CANCELED state.
|
|
||||||
*/
|
|
||||||
public final DNSState advance()
|
|
||||||
{
|
|
||||||
return (isProbing() || isAnnouncing()) ? (DNSState) sequence.get(ordinal + 1) : this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns to the next reverted state.
|
|
||||||
* All states except CANCELED revert to PROBING_1.
|
|
||||||
* Status CANCELED does not revert.
|
|
||||||
*/
|
|
||||||
public final DNSState revert()
|
|
||||||
{
|
|
||||||
return (this == CANCELED) ? this : PROBING_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if this is a probing state.
|
|
||||||
*/
|
|
||||||
public boolean isProbing()
|
|
||||||
{
|
|
||||||
return compareTo(PROBING_1) >= 0 && compareTo(PROBING_3) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if this is an announcing state.
|
|
||||||
*/
|
|
||||||
public boolean isAnnouncing()
|
|
||||||
{
|
|
||||||
return compareTo(ANNOUNCING_1) >= 0 && compareTo(ANNOUNCING_2) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if this is an announced state.
|
|
||||||
*/
|
|
||||||
public boolean isAnnounced()
|
|
||||||
{
|
|
||||||
return compareTo(ANNOUNCED) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares two states.
|
|
||||||
* The states compare as follows:
|
|
||||||
* PROBING_1 < PROBING_2 < PROBING_3 < ANNOUNCING_1 <
|
|
||||||
* ANNOUNCING_2 < RESPONDING < ANNOUNCED < CANCELED.
|
|
||||||
*/
|
|
||||||
public int compareTo(Object o)
|
|
||||||
{
|
|
||||||
return ordinal - ((DNSState) o).ordinal;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,150 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.net.*;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HostInfo information on the local host to be able to cope with change of addresses.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Pierre Frisch, Werner Randelshofer
|
|
||||||
*/
|
|
||||||
class HostInfo
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(HostInfo.class.toString());
|
|
||||||
protected String name;
|
|
||||||
protected InetAddress address;
|
|
||||||
protected NetworkInterface interfaze;
|
|
||||||
/**
|
|
||||||
* This is used to create a unique name for the host name.
|
|
||||||
*/
|
|
||||||
private int hostNameCount;
|
|
||||||
|
|
||||||
public HostInfo(InetAddress address, String name)
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
this.address = address;
|
|
||||||
this.name = name;
|
|
||||||
if (address != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
interfaze = NetworkInterface.getByInetAddress(address);
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
// FIXME Shouldn't we take an action here?
|
|
||||||
logger.log(Level.WARNING, "LocalHostInfo() exception ", exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InetAddress getAddress()
|
|
||||||
{
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NetworkInterface getInterface()
|
|
||||||
{
|
|
||||||
return interfaze;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized String incrementHostName()
|
|
||||||
{
|
|
||||||
hostNameCount++;
|
|
||||||
int plocal = name.indexOf(".local.");
|
|
||||||
int punder = name.lastIndexOf("-");
|
|
||||||
name = name.substring(0, (punder == -1 ? plocal : punder)) + "-" + hostNameCount + ".local.";
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean shouldIgnorePacket(DatagramPacket packet)
|
|
||||||
{
|
|
||||||
boolean result = false;
|
|
||||||
if (getAddress() != null)
|
|
||||||
{
|
|
||||||
InetAddress from = packet.getAddress();
|
|
||||||
if (from != null)
|
|
||||||
{
|
|
||||||
if (from.isLinkLocalAddress() && (!getAddress().isLinkLocalAddress()))
|
|
||||||
{
|
|
||||||
// Ignore linklocal packets on regular interfaces, unless this is
|
|
||||||
// also a linklocal interface. This is to avoid duplicates. This is
|
|
||||||
// a terrible hack caused by the lack of an API to get the address
|
|
||||||
// of the interface on which the packet was received.
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
if (from.isLoopbackAddress() && (!getAddress().isLoopbackAddress()))
|
|
||||||
{
|
|
||||||
// Ignore loopback packets on a regular interface unless this is
|
|
||||||
// also a loopback interface.
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DNSRecord.Address getDNSAddressRecord(DNSRecord.Address address)
|
|
||||||
{
|
|
||||||
return (DNSConstants.TYPE_AAAA == address.type ? getDNS6AddressRecord() : getDNS4AddressRecord());
|
|
||||||
}
|
|
||||||
|
|
||||||
DNSRecord.Address getDNS4AddressRecord()
|
|
||||||
{
|
|
||||||
if ((getAddress() != null) &&
|
|
||||||
((getAddress() instanceof Inet4Address) ||
|
|
||||||
((getAddress() instanceof Inet6Address) && (((Inet6Address) getAddress()).isIPv4CompatibleAddress()))))
|
|
||||||
{
|
|
||||||
return new DNSRecord.Address(getName(), DNSConstants.TYPE_A, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, getAddress());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DNSRecord.Address getDNS6AddressRecord()
|
|
||||||
{
|
|
||||||
if ((getAddress() != null) && (getAddress() instanceof Inet6Address))
|
|
||||||
{
|
|
||||||
return new DNSRecord.Address(getName(), DNSConstants.TYPE_AAAA, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, getAddress());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
buf.append("local host info[");
|
|
||||||
buf.append(getName() != null ? getName() : "no name");
|
|
||||||
buf.append(", ");
|
|
||||||
buf.append(getInterface() != null ? getInterface().getDisplayName() : "???");
|
|
||||||
buf.append(":");
|
|
||||||
buf.append(getAddress() != null ? getAddress().getHostAddress() : "no address");
|
|
||||||
buf.append("]");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,113 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.EventObject;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ServiceEvent.
|
|
||||||
*
|
|
||||||
* @author Werner Randelshofer, Rick Blair
|
|
||||||
* @version %I%, %G%
|
|
||||||
*/
|
|
||||||
public class ServiceEvent extends EventObject
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(ServiceEvent.class.toString());
|
|
||||||
/**
|
|
||||||
* The type name of the service.
|
|
||||||
*/
|
|
||||||
private String type;
|
|
||||||
/**
|
|
||||||
* The instance name of the service. Or null, if the event was
|
|
||||||
* fired to a service type listener.
|
|
||||||
*/
|
|
||||||
private String name;
|
|
||||||
/**
|
|
||||||
* The service info record, or null if the service could be be resolved.
|
|
||||||
* This is also null, if the event was fired to a service type listener.
|
|
||||||
*/
|
|
||||||
private ServiceInfo info;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance.
|
|
||||||
*
|
|
||||||
* @param source the JmDNS instance which originated the event.
|
|
||||||
* @param type the type name of the service.
|
|
||||||
* @param name the instance name of the service.
|
|
||||||
* @param info the service info record, or null if the service could be be resolved.
|
|
||||||
*/
|
|
||||||
public ServiceEvent(JmDNS source, String type, String name, ServiceInfo info)
|
|
||||||
{
|
|
||||||
super(source);
|
|
||||||
this.type = type;
|
|
||||||
this.name = name;
|
|
||||||
this.info = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the JmDNS instance which originated the event.
|
|
||||||
*/
|
|
||||||
public JmDNS getDNS()
|
|
||||||
{
|
|
||||||
return (JmDNS) getSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the fully qualified type of the service.
|
|
||||||
*/
|
|
||||||
public String getType()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the instance name of the service.
|
|
||||||
* Always returns null, if the event is sent to a service type listener.
|
|
||||||
*/
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the service info record, or null if the service could not be
|
|
||||||
* resolved.
|
|
||||||
* Always returns null, if the event is sent to a service type listener.
|
|
||||||
*/
|
|
||||||
public ServiceInfo getInfo()
|
|
||||||
{
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
buf.append("<" + getClass().getName() + "> ");
|
|
||||||
buf.append(super.toString());
|
|
||||||
buf.append(" name ");
|
|
||||||
buf.append(getName());
|
|
||||||
buf.append(" type ");
|
|
||||||
buf.append(getType());
|
|
||||||
buf.append(" info ");
|
|
||||||
buf.append(getInfo());
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,673 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JmDNS service information.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer
|
|
||||||
*/
|
|
||||||
public class ServiceInfo implements DNSListener
|
|
||||||
{
|
|
||||||
private static Logger logger = Logger.getLogger(ServiceInfo.class.toString());
|
|
||||||
public final static byte[] NO_VALUE = new byte[0];
|
|
||||||
JmDNS dns;
|
|
||||||
|
|
||||||
// State machine
|
|
||||||
/**
|
|
||||||
* The state of this service info.
|
|
||||||
* This is used only for services announced by JmDNS.
|
|
||||||
* <p/>
|
|
||||||
* For proper handling of concurrency, this variable must be
|
|
||||||
* changed only using methods advanceState(), revertState() and cancel().
|
|
||||||
*/
|
|
||||||
private DNSState state = DNSState.PROBING_1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Task associated to this service info.
|
|
||||||
* Possible tasks are JmDNS.Prober, JmDNS.Announcer, JmDNS.Responder,
|
|
||||||
* JmDNS.Canceler.
|
|
||||||
*/
|
|
||||||
TimerTask task;
|
|
||||||
|
|
||||||
String type;
|
|
||||||
private String name;
|
|
||||||
String server;
|
|
||||||
int port;
|
|
||||||
int weight;
|
|
||||||
int priority;
|
|
||||||
byte text[];
|
|
||||||
Hashtable props;
|
|
||||||
InetAddress addr;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a service description for registrating with JmDNS.
|
|
||||||
*
|
|
||||||
* @param type fully qualified service type name, such as <code>_http._tcp.local.</code>.
|
|
||||||
* @param name unqualified service instance name, such as <code>foobar</code>
|
|
||||||
* @param port the local port on which the service runs
|
|
||||||
* @param text string describing the service
|
|
||||||
*/
|
|
||||||
public ServiceInfo(String type, String name, int port, String text)
|
|
||||||
{
|
|
||||||
this(type, name, port, 0, 0, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a service description for registrating with JmDNS.
|
|
||||||
*
|
|
||||||
* @param type fully qualified service type name, such as <code>_http._tcp.local.</code>.
|
|
||||||
* @param name unqualified service instance name, such as <code>foobar</code>
|
|
||||||
* @param port the local port on which the service runs
|
|
||||||
* @param weight weight of the service
|
|
||||||
* @param priority priority of the service
|
|
||||||
* @param text string describing the service
|
|
||||||
*/
|
|
||||||
public ServiceInfo(String type, String name, int port, int weight, int priority, String text)
|
|
||||||
{
|
|
||||||
this(type, name, port, weight, priority, (byte[]) null);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(text.length());
|
|
||||||
writeUTF(out, text);
|
|
||||||
this.text = out.toByteArray();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("unexpected exception: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a service description for registrating with JmDNS. The properties hashtable must
|
|
||||||
* map property names to either Strings or byte arrays describing the property values.
|
|
||||||
*
|
|
||||||
* @param type fully qualified service type name, such as <code>_http._tcp.local.</code>.
|
|
||||||
* @param name unqualified service instance name, such as <code>foobar</code>
|
|
||||||
* @param port the local port on which the service runs
|
|
||||||
* @param weight weight of the service
|
|
||||||
* @param priority priority of the service
|
|
||||||
* @param props properties describing the service
|
|
||||||
*/
|
|
||||||
public ServiceInfo(String type, String name, int port, int weight, int priority, Hashtable props)
|
|
||||||
{
|
|
||||||
this(type, name, port, weight, priority, new byte[0]);
|
|
||||||
if (props != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(256);
|
|
||||||
for (Enumeration e = props.keys(); e.hasMoreElements();)
|
|
||||||
{
|
|
||||||
String key = (String) e.nextElement();
|
|
||||||
Object val = props.get(key);
|
|
||||||
ByteArrayOutputStream out2 = new ByteArrayOutputStream(100);
|
|
||||||
writeUTF(out2, key);
|
|
||||||
if (val instanceof String)
|
|
||||||
{
|
|
||||||
out2.write('=');
|
|
||||||
writeUTF(out2, (String) val);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (val instanceof byte[])
|
|
||||||
{
|
|
||||||
out2.write('=');
|
|
||||||
byte[] bval = (byte[]) val;
|
|
||||||
out2.write(bval, 0, bval.length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (val != NO_VALUE)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("invalid property value: " + val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
byte data[] = out2.toByteArray();
|
|
||||||
out.write(data.length);
|
|
||||||
out.write(data, 0, data.length);
|
|
||||||
}
|
|
||||||
this.text = out.toByteArray();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("unexpected exception: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a service description for registrating with JmDNS.
|
|
||||||
*
|
|
||||||
* @param type fully qualified service type name, such as <code>_http._tcp.local.</code>.
|
|
||||||
* @param name unqualified service instance name, such as <code>foobar</code>
|
|
||||||
* @param port the local port on which the service runs
|
|
||||||
* @param weight weight of the service
|
|
||||||
* @param priority priority of the service
|
|
||||||
* @param text bytes describing the service
|
|
||||||
*/
|
|
||||||
public ServiceInfo(String type, String name, int port, int weight, int priority, byte text[])
|
|
||||||
{
|
|
||||||
this.type = type;
|
|
||||||
this.name = name;
|
|
||||||
this.port = port;
|
|
||||||
this.weight = weight;
|
|
||||||
this.priority = priority;
|
|
||||||
this.text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a service record during service discovery.
|
|
||||||
*/
|
|
||||||
ServiceInfo(String type, String name)
|
|
||||||
{
|
|
||||||
if (!type.endsWith("."))
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("type must be fully qualified DNS name ending in '.': " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.type = type;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* During recovery we need to duplicate service info to reregister them
|
|
||||||
*/
|
|
||||||
ServiceInfo(ServiceInfo info)
|
|
||||||
{
|
|
||||||
if (info != null)
|
|
||||||
{
|
|
||||||
this.type = info.type;
|
|
||||||
this.name = info.name;
|
|
||||||
this.port = info.port;
|
|
||||||
this.weight = info.weight;
|
|
||||||
this.priority = info.priority;
|
|
||||||
this.text = info.text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fully qualified service type name, such as <code>_http._tcp.local.</code> .
|
|
||||||
*/
|
|
||||||
public String getType()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unqualified service instance name, such as <code>foobar</code> .
|
|
||||||
*/
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service instance name.
|
|
||||||
*
|
|
||||||
* @param name unqualified service instance name, such as <code>foobar</code>
|
|
||||||
*/
|
|
||||||
void setName(String name)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fully qualified service name, such as <code>foobar._http._tcp.local.</code> .
|
|
||||||
*/
|
|
||||||
public String getQualifiedName()
|
|
||||||
{
|
|
||||||
return name + "." + type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the server.
|
|
||||||
*/
|
|
||||||
public String getServer()
|
|
||||||
{
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the host address of the service (ie X.X.X.X).
|
|
||||||
*/
|
|
||||||
public String getHostAddress()
|
|
||||||
{
|
|
||||||
return (addr != null ? addr.getHostAddress() : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public InetAddress getAddress()
|
|
||||||
{
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the InetAddress of the service.
|
|
||||||
*/
|
|
||||||
public InetAddress getInetAddress()
|
|
||||||
{
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the port for the service.
|
|
||||||
*/
|
|
||||||
public int getPort()
|
|
||||||
{
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the priority of the service.
|
|
||||||
*/
|
|
||||||
public int getPriority()
|
|
||||||
{
|
|
||||||
return priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the weight of the service.
|
|
||||||
*/
|
|
||||||
public int getWeight()
|
|
||||||
{
|
|
||||||
return weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the text for the serivce as raw bytes.
|
|
||||||
*/
|
|
||||||
public byte[] getTextBytes()
|
|
||||||
{
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the text for the service. This will interpret the text bytes
|
|
||||||
* as a UTF8 encoded string. Will return null if the bytes are not
|
|
||||||
* a valid UTF8 encoded string.
|
|
||||||
*/
|
|
||||||
public String getTextString()
|
|
||||||
{
|
|
||||||
if ((text == null) || (text.length == 0) || ((text.length == 1) && (text[0] == 0)))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return readUTF(text, 0, text.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the URL for this service. An http URL is created by
|
|
||||||
* combining the address, port, and path properties.
|
|
||||||
*/
|
|
||||||
public String getURL()
|
|
||||||
{
|
|
||||||
return getURL("http");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the URL for this service. An URL is created by
|
|
||||||
* combining the protocol, address, port, and path properties.
|
|
||||||
*/
|
|
||||||
public String getURL(String protocol)
|
|
||||||
{
|
|
||||||
String url = protocol + "://" + getAddress() + ":" + getPort();
|
|
||||||
String path = getPropertyString("path");
|
|
||||||
if (path != null)
|
|
||||||
{
|
|
||||||
if (path.indexOf("://") >= 0)
|
|
||||||
{
|
|
||||||
url = path;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
url += path.startsWith("/") ? path : "/" + path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a property of the service. This involves decoding the
|
|
||||||
* text bytes into a property list. Returns null if the property
|
|
||||||
* is not found or the text data could not be decoded correctly.
|
|
||||||
*/
|
|
||||||
public synchronized byte[] getPropertyBytes(String name)
|
|
||||||
{
|
|
||||||
return (byte[]) getProperties().get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a property of the service. This involves decoding the
|
|
||||||
* text bytes into a property list. Returns null if the property
|
|
||||||
* is not found, the text data could not be decoded correctly, or
|
|
||||||
* the resulting bytes are not a valid UTF8 string.
|
|
||||||
*/
|
|
||||||
public synchronized String getPropertyString(String name)
|
|
||||||
{
|
|
||||||
byte data[] = (byte[]) getProperties().get(name);
|
|
||||||
if (data == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (data == NO_VALUE)
|
|
||||||
{
|
|
||||||
return "true";
|
|
||||||
}
|
|
||||||
return readUTF(data, 0, data.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumeration of the property names.
|
|
||||||
*/
|
|
||||||
public Enumeration getPropertyNames()
|
|
||||||
{
|
|
||||||
Hashtable props = getProperties();
|
|
||||||
return (props != null) ? props.keys() : new Vector().elements();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a UTF string with a length to a stream.
|
|
||||||
*/
|
|
||||||
void writeUTF(OutputStream out, String str) throws IOException
|
|
||||||
{
|
|
||||||
for (int i = 0, len = str.length(); i < len; i++)
|
|
||||||
{
|
|
||||||
int c = str.charAt(i);
|
|
||||||
if ((c >= 0x0001) && (c <= 0x007F))
|
|
||||||
{
|
|
||||||
out.write(c);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (c > 0x07FF)
|
|
||||||
{
|
|
||||||
out.write(0xE0 | ((c >> 12) & 0x0F));
|
|
||||||
out.write(0x80 | ((c >> 6) & 0x3F));
|
|
||||||
out.write(0x80 | ((c >> 0) & 0x3F));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out.write(0xC0 | ((c >> 6) & 0x1F));
|
|
||||||
out.write(0x80 | ((c >> 0) & 0x3F));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read data bytes as a UTF stream.
|
|
||||||
*/
|
|
||||||
String readUTF(byte data[], int off, int len)
|
|
||||||
{
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
for (int end = off + len; off < end;)
|
|
||||||
{
|
|
||||||
int ch = data[off++] & 0xFF;
|
|
||||||
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:
|
|
||||||
if (off >= len)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// 110x xxxx 10xx xxxx
|
|
||||||
ch = ((ch & 0x1F) << 6) | (data[off++] & 0x3F);
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
if (off + 2 >= len)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
|
||||||
ch = ((ch & 0x0f) << 12) | ((data[off++] & 0x3F) << 6) | (data[off++] & 0x3F);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (off + 1 >= len)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// 10xx xxxx, 1111 xxxx
|
|
||||||
ch = ((ch & 0x3F) << 4) | (data[off++] & 0x0f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf.append((char) ch);
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized Hashtable getProperties()
|
|
||||||
{
|
|
||||||
if ((props == null) && (text != null))
|
|
||||||
{
|
|
||||||
Hashtable props = new Hashtable();
|
|
||||||
int off = 0;
|
|
||||||
while (off < text.length)
|
|
||||||
{
|
|
||||||
// length of the next key value pair
|
|
||||||
int len = text[off++] & 0xFF;
|
|
||||||
if ((len == 0) || (off + len > text.length))
|
|
||||||
{
|
|
||||||
props.clear();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// look for the '='
|
|
||||||
int i = 0;
|
|
||||||
for (; (i < len) && (text[off + i] != '='); i++)
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the property name
|
|
||||||
String name = readUTF(text, off, i);
|
|
||||||
if (name == null)
|
|
||||||
{
|
|
||||||
props.clear();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == len)
|
|
||||||
{
|
|
||||||
props.put(name, NO_VALUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
byte value[] = new byte[len - ++i];
|
|
||||||
System.arraycopy(text, off + i, value, 0, len - i);
|
|
||||||
props.put(name, value);
|
|
||||||
off += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.props = props;
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
// REMIND: Oops, this shouldn't be public!
|
|
||||||
/**
|
|
||||||
* JmDNS callback to update a DNS record.
|
|
||||||
*/
|
|
||||||
public void updateRecord(JmDNS jmdns, long now, DNSRecord rec)
|
|
||||||
{
|
|
||||||
if ((rec != null) && !rec.isExpired(now))
|
|
||||||
{
|
|
||||||
switch (rec.type)
|
|
||||||
{
|
|
||||||
case DNSConstants.TYPE_A: // IPv4
|
|
||||||
case DNSConstants.TYPE_AAAA: // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested
|
|
||||||
if (rec.name.equals(server))
|
|
||||||
{
|
|
||||||
addr = ((DNSRecord.Address) rec).getAddress();
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DNSConstants.TYPE_SRV:
|
|
||||||
if (rec.name.equals(getQualifiedName()))
|
|
||||||
{
|
|
||||||
DNSRecord.Service srv = (DNSRecord.Service) rec;
|
|
||||||
server = srv.server;
|
|
||||||
port = srv.port;
|
|
||||||
weight = srv.weight;
|
|
||||||
priority = srv.priority;
|
|
||||||
addr = null;
|
|
||||||
// changed to use getCache() instead - jeffs
|
|
||||||
// updateRecord(jmdns, now, (DNSRecord)jmdns.cache.get(server, TYPE_A, CLASS_IN));
|
|
||||||
updateRecord(jmdns, now, (DNSRecord) jmdns.getCache().get(server, DNSConstants.TYPE_A, DNSConstants.CLASS_IN));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DNSConstants.TYPE_TXT:
|
|
||||||
if (rec.name.equals(getQualifiedName()))
|
|
||||||
{
|
|
||||||
DNSRecord.Text txt = (DNSRecord.Text) rec;
|
|
||||||
text = txt.text;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Future Design Pattern
|
|
||||||
// This is done, to notify the wait loop in method
|
|
||||||
// JmDNS.getServiceInfo(type, name, timeout);
|
|
||||||
if (hasData() && dns != null)
|
|
||||||
{
|
|
||||||
dns.handleServiceResolved(this);
|
|
||||||
dns = null;
|
|
||||||
}
|
|
||||||
synchronized (this)
|
|
||||||
{
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the service info is filled with data.
|
|
||||||
*/
|
|
||||||
boolean hasData()
|
|
||||||
{
|
|
||||||
return server != null && addr != null && text != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// State machine
|
|
||||||
/**
|
|
||||||
* Sets the state and notifies all objects that wait on the ServiceInfo.
|
|
||||||
*/
|
|
||||||
synchronized void advanceState()
|
|
||||||
{
|
|
||||||
state = state.advance();
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the state and notifies all objects that wait on the ServiceInfo.
|
|
||||||
*/
|
|
||||||
synchronized void revertState()
|
|
||||||
{
|
|
||||||
state = state.revert();
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the state and notifies all objects that wait on the ServiceInfo.
|
|
||||||
*/
|
|
||||||
synchronized void cancel()
|
|
||||||
{
|
|
||||||
state = DNSState.CANCELED;
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current state of this info.
|
|
||||||
*/
|
|
||||||
DNSState getState()
|
|
||||||
{
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
return getQualifiedName().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
return (obj instanceof ServiceInfo) && getQualifiedName().equals(((ServiceInfo) obj).getQualifiedName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNiceTextString()
|
|
||||||
{
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
for (int i = 0, len = text.length; i < len; i++)
|
|
||||||
{
|
|
||||||
if (i >= 20)
|
|
||||||
{
|
|
||||||
buf.append("...");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int ch = text[i] & 0xFF;
|
|
||||||
if ((ch < ' ') || (ch > 127))
|
|
||||||
{
|
|
||||||
buf.append("\\0");
|
|
||||||
buf.append(Integer.toString(ch, 8));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf.append((char) ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
buf.append("service[");
|
|
||||||
buf.append(getQualifiedName());
|
|
||||||
buf.append(',');
|
|
||||||
buf.append(getAddress());
|
|
||||||
buf.append(':');
|
|
||||||
buf.append(port);
|
|
||||||
buf.append(',');
|
|
||||||
buf.append(getNiceTextString());
|
|
||||||
buf.append(']');
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.EventListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener for service updates.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Werner Randelshofer
|
|
||||||
*/
|
|
||||||
public interface ServiceListener extends EventListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* A service has been added.
|
|
||||||
*
|
|
||||||
* @param event The ServiceEvent providing the name and fully qualified type
|
|
||||||
* of the service.
|
|
||||||
*/
|
|
||||||
void serviceAdded(ServiceEvent event);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service has been removed.
|
|
||||||
*
|
|
||||||
* @param event The ServiceEvent providing the name and fully qualified type
|
|
||||||
* of the service.
|
|
||||||
*/
|
|
||||||
void serviceRemoved(ServiceEvent event);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service has been resolved. Its details are now available in the
|
|
||||||
* ServiceInfo record.
|
|
||||||
*
|
|
||||||
* @param event The ServiceEvent providing the name, the fully qualified
|
|
||||||
* type of the service, and the service info record, or null if the service
|
|
||||||
* could not be resolved.
|
|
||||||
*/
|
|
||||||
void serviceResolved(ServiceEvent event);
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.util.EventListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener for service types.
|
|
||||||
*
|
|
||||||
* @version %I%, %G%
|
|
||||||
* @author Arthur van Hoff, Werner Randelshofer
|
|
||||||
*/
|
|
||||||
public interface ServiceTypeListener extends EventListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* A new service type was discovered.
|
|
||||||
*
|
|
||||||
* @param event The service event providing the fully qualified type of
|
|
||||||
* the service.
|
|
||||||
*/
|
|
||||||
void serviceTypeAdded(ServiceEvent event);
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
===============================================================
|
|
||||||
== NOTICE File for JmDNS ==
|
|
||||||
===============================================================
|
|
||||||
|
|
||||||
Java Multicast Domain Name Server (JmDNS)
|
|
||||||
|
|
||||||
This project was originally developed by Arthur van Hoff under the GNU
|
|
||||||
Lesser General Public License as jRendevous. It was moved to Sourceforge
|
|
||||||
by Rick Blair and renamed to JmDNS with the Arthur's kind permission.
|
|
||||||
|
|
||||||
Currently it has been re-released under the Apache License, Version 2.0.
|
|
||||||
|
|
||||||
Details of the Apache License, Version 2.0 can be found at:
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
|
|
||||||
For other details please see the README.txt file.
|
|
|
@ -1,117 +0,0 @@
|
||||||
// %Z%%M%, %I%, %G%
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU Lesser General Public
|
|
||||||
// License as published by the Free Software Foundation; either
|
|
||||||
// version 2.1 of the License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
|
|
||||||
//This library is now licensed under the Apache License Version 2.0 Please
|
|
||||||
//see the file NOTICE.
|
|
||||||
|
|
||||||
|
|
||||||
Arthur van Hoff
|
|
||||||
avh@strangeberry.com
|
|
||||||
|
|
||||||
Rick Blair
|
|
||||||
rickblair@mac.com
|
|
||||||
|
|
||||||
** JmDNS
|
|
||||||
|
|
||||||
This is an implemenation of multi-cast DNS in Java. It currently
|
|
||||||
supports service discovery and service registration. It is fully
|
|
||||||
interoperable with Apple's Rendezvous.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
** Requirements
|
|
||||||
|
|
||||||
jmdns has been tested using the JDK 1.3.1 and JDK 1.4.0
|
|
||||||
on the following platforms:
|
|
||||||
|
|
||||||
Windows 9x, XP, 2000
|
|
||||||
Linux RedHat 7.3-9.0, Mandrake
|
|
||||||
Mac OSX
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
** Running jmdns from the Command Line
|
|
||||||
|
|
||||||
GUI browser:
|
|
||||||
|
|
||||||
java -jar lib/jmdns.jar -browse
|
|
||||||
|
|
||||||
TTY browser for a particular service type:
|
|
||||||
|
|
||||||
java -jar lib/jmdns.jar -bs _http._tcp local.
|
|
||||||
|
|
||||||
Register a service:
|
|
||||||
|
|
||||||
java -jar lib/jmdns.jar -rs foobar _http._tcp local. 1234 path=index.html
|
|
||||||
|
|
||||||
List service types:
|
|
||||||
|
|
||||||
java -jar lib/jmdns.jar -bt
|
|
||||||
|
|
||||||
To print debugging output specify -d as the first argument.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
** Sample Code for Service Registration
|
|
||||||
|
|
||||||
import javax.jmdns.*;
|
|
||||||
|
|
||||||
JmDNS jmdns = new JmDNS();
|
|
||||||
jmdns.registerService(
|
|
||||||
new ServiceInfo("_http._tcp.local.", "foo._http._tcp.local.", 1234, 0, 0, "path=index.html")
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
** Sample code for Serivice Discovery
|
|
||||||
|
|
||||||
import javax.jmdns.*;
|
|
||||||
|
|
||||||
static class SampleListener implements ServiceListener
|
|
||||||
{
|
|
||||||
public void addService(JmDNS jmdns, String type, String name)
|
|
||||||
{
|
|
||||||
System.out.println("ADD: " + jmdns.getServiceInfo(type, name));
|
|
||||||
}
|
|
||||||
public void removeService(JmDNS jmdns, String type, String name)
|
|
||||||
{
|
|
||||||
System.out.println("REMOVE: " + name);
|
|
||||||
}
|
|
||||||
public void resolveService(JmDNS jmdns, String type, String name, ServiceInfo info)
|
|
||||||
{
|
|
||||||
System.out.println("RESOLVED: " + info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JmDNS jmdns = new JmDNS();
|
|
||||||
jmdns.addServiceListener("_http._tcp.local.", new SampleListener());
|
|
||||||
|
|
||||||
|
|
||||||
** Changes since October 2003
|
|
||||||
|
|
||||||
- Renamed package com.strangeberry.rendezvous to javax.jmdns
|
|
||||||
- fixed unicast queries
|
|
||||||
- fixed property handling
|
|
||||||
- use the hostname instead of the service name is address resolution
|
|
||||||
- Added Apache License.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
The activemq-jmdns_1.0 source is derived from http://repo1.maven.org/maven2/jmdns/jmdns/1.0/jmdns-1.0-sources.jar
|
|
||||||
|
|
||||||
Changes to apache activemq version:
|
|
||||||
- renamed package javax.jmdns to org.apache.activemq.jmdns
|
|
||||||
- removed classes with lgpl source headers, leaving only the org.apache.activemq.jmdns package.
|
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
<bundle>mvn:org.apache.httpcomponents/httpcore-osgi/${httpclient-version}</bundle>
|
<bundle>mvn:org.apache.httpcomponents/httpcore-osgi/${httpclient-version}</bundle>
|
||||||
<bundle>mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient-version}</bundle>
|
<bundle>mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient-version}</bundle>
|
||||||
<bundle>mvn:org.springframework/spring-oxm/${spring-version}</bundle>
|
<bundle>mvn:org.springframework/spring-oxm/${spring-version}</bundle>
|
||||||
|
<bundle>mvn:javax.jmdns/jmdns/${jmdns-version}</bundle>
|
||||||
</feature>
|
</feature>
|
||||||
|
|
||||||
<feature name="activemq-camel" version="${activemq-version}" resolver="(obr)">
|
<feature name="activemq-camel" version="${activemq-version}" resolver="(obr)">
|
||||||
|
|
|
@ -158,8 +158,8 @@
|
||||||
<artifactId>jaxp-api</artifactId>
|
<artifactId>jaxp-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>javax.jmdns</groupId>
|
||||||
<artifactId>activemq-jmdns_1.0</artifactId>
|
<artifactId>jmdns</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.thoughtworks.xstream</groupId>
|
<groupId>com.thoughtworks.xstream</groupId>
|
||||||
|
|
|
@ -138,7 +138,6 @@
|
||||||
<include>${pom.groupId}:activemq-xmpp</include>
|
<include>${pom.groupId}:activemq-xmpp</include>
|
||||||
<include>${pom.groupId}:activemq-spring</include>
|
<include>${pom.groupId}:activemq-spring</include>
|
||||||
<include>${pom.groupId}:activeio-core</include>
|
<include>${pom.groupId}:activeio-core</include>
|
||||||
<include>${pom.groupId}:activemq-jmdns_1.0</include>
|
|
||||||
<include>commons-beanutils:commons-beanutils</include>
|
<include>commons-beanutils:commons-beanutils</include>
|
||||||
<include>commons-collections:commons-collections</include>
|
<include>commons-collections:commons-collections</include>
|
||||||
<include>commons-httpclient:commons-httpclient</include>
|
<include>commons-httpclient:commons-httpclient</include>
|
||||||
|
@ -168,6 +167,7 @@
|
||||||
<include>org.apache.velocity:velocity</include>
|
<include>org.apache.velocity:velocity</include>
|
||||||
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.josql</include>
|
<include>org.apache.servicemix.bundles:org.apache.servicemix.bundles.josql</include>
|
||||||
<include>org.jasypt:jasypt</include>
|
<include>org.jasypt:jasypt</include>
|
||||||
|
<include>javax.jmdns:jmdns</include>
|
||||||
<!-- leveldb -->
|
<!-- leveldb -->
|
||||||
<include>org.fusesource.fuse-extra:fusemq-leveldb</include>
|
<include>org.fusesource.fuse-extra:fusemq-leveldb</include>
|
||||||
<include>org.fusesource.hawtbuf:hawtbuf</include>
|
<include>org.fusesource.hawtbuf:hawtbuf</include>
|
||||||
|
|
15
pom.xml
15
pom.xml
|
@ -73,6 +73,7 @@
|
||||||
<jasypt-version>1.9.0</jasypt-version>
|
<jasypt-version>1.9.0</jasypt-version>
|
||||||
<jdom-version>1.0</jdom-version>
|
<jdom-version>1.0</jdom-version>
|
||||||
<jetty-version>7.6.5.v20120716</jetty-version>
|
<jetty-version>7.6.5.v20120716</jetty-version>
|
||||||
|
<jmdns-version>3.4.1</jmdns-version>
|
||||||
<jsp-version>2.1.v20100127</jsp-version>
|
<jsp-version>2.1.v20100127</jsp-version>
|
||||||
<jstl-version>1.1.2</jstl-version>
|
<jstl-version>1.1.2</jstl-version>
|
||||||
<jettison-version>1.3.2</jettison-version>
|
<jettison-version>1.3.2</jettison-version>
|
||||||
|
@ -204,7 +205,6 @@
|
||||||
<module>activemq-web-console</module>
|
<module>activemq-web-console</module>
|
||||||
<module>activemq-xmpp</module>
|
<module>activemq-xmpp</module>
|
||||||
<module>assembly</module>
|
<module>assembly</module>
|
||||||
<module>activemq-jmdns_1.0</module>
|
|
||||||
<module>kahadb</module>
|
<module>kahadb</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
@ -246,11 +246,6 @@
|
||||||
<artifactId>activemq-jaas</artifactId>
|
<artifactId>activemq-jaas</artifactId>
|
||||||
<version>${activemq-version}</version>
|
<version>${activemq-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activemq-jmdns_1.0</artifactId>
|
|
||||||
<version>${activemq-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-pool</artifactId>
|
<artifactId>activemq-pool</artifactId>
|
||||||
|
@ -479,6 +474,14 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- zeroconf transport -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.jmdns</groupId>
|
||||||
|
<artifactId>jmdns</artifactId>
|
||||||
|
<version>${jmdns-version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- For jsvc support -->
|
<!-- For jsvc support -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-daemon</groupId>
|
<groupId>commons-daemon</groupId>
|
||||||
|
|
Loading…
Reference in New Issue