Skip to content
Commits on Source (6)
jmdns (3.5.4-1) unstable; urgency=medium
* Team upload.
* New upstream release
* Standards-Version updated to 4.2.1
* Switch to debhelper level 11
* Use salsa.debian.org Vcs-* URLs
-- Emmanuel Bourg <ebourg@apache.org> Fri, 19 Oct 2018 15:29:20 +0200
jmdns (3.5.3-1) unstable; urgency=medium
* Team upload.
......
......@@ -4,7 +4,7 @@ Priority: optional
Maintainer: Debian Java Maintainers <pkg-java-maintainers@lists.alioth.debian.org>
Uploaders: James Page <james.page@ubuntu.com>
Build-Depends:
debhelper (>= 10),
debhelper (>= 11),
default-jdk,
junit4,
libeasymock-java,
......@@ -12,9 +12,9 @@ Build-Depends:
libmaven-javadoc-plugin-java,
libslf4j-java,
maven-debian-helper
Standards-Version: 4.1.1
Vcs-Git: https://anonscm.debian.org/git/pkg-java/jmdns.git
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/jmdns.git
Standards-Version: 4.2.1
Vcs-Git: https://salsa.debian.org/java-team/jmdns.git
Vcs-Browser: https://salsa.debian.org/java-team/jmdns
Homepage: https://github.com/jmdns/jmdns
Package: libjmdns-java
......
......@@ -2,6 +2,3 @@
%:
dh $@ --buildsystem=maven
get-orig-source:
uscan --download-current-version --force-download --rename --repack --compression xz
version=3
version=4
opts=repack,compression=xz \
https://github.com/jmdns/jmdns/tags .*/archive/jmdns-([\d\.]+).tar.gz
<feature
id="org.jmdns.feature"
label="JmDNS"
version="3.5.3.qualifier"
version="3.5.4"
provider-name="JmDNS.org">
<description>
......@@ -9,7 +9,7 @@
</description>
<copyright>
Copyright (C) 2017 JmDNS.org and others
Copyright (C) 2018 JmDNS.org and others
</copyright>
<license url="%licenseURL">
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>org.jmdns.p2</groupId>
<artifactId>features</artifactId>
<version>3.5.3-SNAPSHOT</version>
<version>3.5.4</version>
</parent>
<artifactId>org.jmdns.feature</artifactId>
......
......@@ -7,7 +7,7 @@
<parent>
<groupId>org.jmdns.p2</groupId>
<artifactId>pom</artifactId>
<version>3.5.3-SNAPSHOT</version>
<version>3.5.4</version>
</parent>
<artifactId>features</artifactId>
......
......@@ -6,7 +6,7 @@
<groupId>org.jmdns.p2</groupId>
<artifactId>pom</artifactId>
<version>3.5.3-SNAPSHOT</version>
<version>3.5.4</version>
<packaging>pom</packaging>
<name>JmDNS p2</name>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>org.jmdns.p2</groupId>
<artifactId>pom</artifactId>
<version>3.5.3-SNAPSHOT</version>
<version>3.5.4</version>
</parent>
<artifactId>org.jmdns.repository</artifactId>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>org.jmdns.p2</groupId>
<artifactId>pom</artifactId>
<version>3.4.3</version>
<version>3.5.4</version>
</parent>
<artifactId>targetplatform</artifactId>
......
......@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.jmdns</groupId>
<artifactId>jmdns</artifactId>
<version>3.5.3</version>
<version>3.5.4</version>
<name>JmDNS</name>
<packaging>jar</packaging>
<description>JmDNS is a Java implementation of multi-cast DNS and can be used for service registration and discovery in local area networks. JmDNS is fully compatible with Apple's Bonjour.
......@@ -52,7 +52,7 @@ The project was originally started in December 2002 by Arthur van Hoff at Strang
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.16</version>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>junit</groupId>
......
......@@ -672,6 +672,7 @@ public abstract class DNSRecord extends DNSEntry {
final String text = ByteWrangler.readUTF(_text);
if (text != null) {
// if the text is longer than 20 characters cut it to 17 chars
// and add "..." at the end
if (20 < text.length()) {
......@@ -679,6 +680,7 @@ public abstract class DNSRecord extends DNSEntry {
} else {
sb.append(text);
}
}
sb.append('\'');
}
......@@ -1078,4 +1080,9 @@ public abstract class DNSRecord extends DNSEntry {
public int getTTL() {
return _ttl;
}
public long getCreated() {
return this._created;
}
}
......@@ -464,6 +464,7 @@ public class JmDNSImpl extends JmDNS implements DNSStatefulObject, DNSTaskStarte
_socket = new MulticastSocket(DNSConstants.MDNS_PORT);
if ((hostInfo != null) && (hostInfo.getInterface() != null)) {
final SocketAddress multicastAddr = new InetSocketAddress(_group, DNSConstants.MDNS_PORT);
_socket.setNetworkInterface(hostInfo.getInterface());
logger.trace("Trying to joinGroup({}, {})", multicastAddr, hostInfo.getInterface());
......@@ -1346,13 +1347,21 @@ public class JmDNSImpl extends JmDNS implements DNSStatefulObject, DNSTaskStarte
final boolean unique = newRecord.isUnique();
final DNSRecord cachedRecord = (DNSRecord) this.getCache().getDNSEntry(newRecord);
logger.debug("{} handle response cached record: {}", this.getName(), cachedRecord);
// RFC 6762, section 10.2 Announcements to Flush Outdated Cache Entries
// https://tools.ietf.org/html/rfc6762#section-10.2
// if (cache-flush a.k.a unique), remove all existing records matching these criterias :--
// 1. same name
// 2. same record type
// 3. same record class
// 4. record is older than 1 second.
if (unique) {
for (DNSEntry entry : this.getCache().getDNSEntryList(newRecord.getKey())) {
if ( newRecord.getRecordType().equals(entry.getRecordType()) &&
newRecord.getRecordClass().equals(entry.getRecordClass()) &&
(entry != cachedRecord)
isOlderThanOneSecond( (DNSRecord)entry, now )
) {
logger.trace("setWillExpireSoon() on: {}", entry);
// this set ttl to 1 second,
((DNSRecord) entry).setWillExpireSoon(now);
}
}
......@@ -1426,6 +1435,16 @@ public class JmDNSImpl extends JmDNS implements DNSStatefulObject, DNSTaskStarte
}
/**
*
* @param dnsRecord
* @param timeToCompare a given times for comparison
* @return true if dnsRecord create time is older than 1 second, relative to the given time; false otherwise
*/
private boolean isOlderThanOneSecond(DNSRecord dnsRecord, long timeToCompare) {
return (dnsRecord.getCreated() < (timeToCompare - DNSConstants.FLUSH_RECORD_OLDER_THAN_1_SECOND*1000));
}
/**
* Handle an incoming response. Cache answers, and pass them on to the appropriate questions.
*
......
......@@ -795,6 +795,7 @@ public class ServiceInfoImpl extends ServiceInfo implements DNSListener, DNSStat
// flag for changes
boolean serviceChanged = false;
// When a record is soon to be expired, i.e. ttl=1, consider that as expired too.
if (record.isExpired(now)) {
// remove data
serviceChanged = handleExpiredRecord(record);
......@@ -813,7 +814,18 @@ public class ServiceInfoImpl extends ServiceInfo implements DNSListener, DNSStat
// ServiceEvent event = ((DNSRecord) rec).getServiceEvent(dns);
// event = new ServiceEventImpl(dns, event.getType(), event.getName(), this);
// Failure to resolve services - ID: 3517826
ServiceEvent event = new ServiceEventImpl(dns, this.getType(), this.getName(), this);
//
// There is a timing/ concurrency issue here. The ServiceInfo object is subject to concurrent change.
// e.g. when a device announce a new IP, the old IP has TTL=1.
//
// The listeners runs on different threads concurrently. When they start and read the event,
// the ServiceInfo is already removed/ changed.
//
// The simple solution is to clone the ServiceInfo. Therefore, future changes to ServiceInfo
// will not be seen by the listeners.
//
// Fixes ListenerStatus warning "Service Resolved called for an unresolved event: {}"
ServiceEvent event = new ServiceEventImpl(dns, this.getType(), this.getName(), this.clone());
dns.handleServiceResolved(event);
}
} else {
......
......@@ -53,6 +53,7 @@ public final class DNSConstants {
public static final int RECORD_EXPIRY_DELAY = 1; // This is 1s delay used in ttl and therefore in seconds
public static final int KNOWN_ANSWER_TTL = 120;
public static final int ANNOUNCED_RENEWAL_TTL_INTERVAL = DNS_TTL * 500; // 50% of the TTL in milliseconds
public static final int FLUSH_RECORD_OLDER_THAN_1_SECOND = 1; // rfc6762, section 10.2 Flush outdated cache (older than 1 second)
public static final int STALE_REFRESH_INCREMENT = 5;
public static final int STALE_REFRESH_STARTING_PERCENTAGE = 80;
......
......@@ -3,8 +3,11 @@ package javax.jmdns.impl.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class contains all the byte shifting
......@@ -13,6 +16,7 @@ import java.util.Map;
*
*/
public class ByteWrangler {
private static Logger logger = LoggerFactory.getLogger(ByteWrangler.class.getName());
/**
* Maximum number of bytes a value can consist of.
......@@ -39,79 +43,35 @@ public class ByteWrangler {
public final static byte[] EMPTY_TXT = new byte[] { 0 };
/**
* Write a UTF string with a length to a stream.
* Name for charset used to convert Strings to/from wire bytes: {@value #CHARSET_NAME}.
*/
public final static String CHARSET_NAME = "UTF-8";
/**
* Charset used to convert Strings to/from wire bytes: {@value #CHARSET_NAME}.
*/
private final static Charset CHARSET_UTF_8 = Charset.forName(CHARSET_NAME);
/**
* Write a String as {@value #CHARSET_NAME} encoded bytes to a stream.
*/
public static void writeUTF(final OutputStream out, final String str) throws IOException {
final int len = str.length();
for (int i = 0; i < len; i++) {
final 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));
}
}
}
final byte[] utf8Bytes = str.getBytes(CHARSET_UTF_8);
out.write(utf8Bytes);
}
/**
* Read data bytes as UTF-8 to a String.
* Read data bytes as {@value #CHARSET_NAME} to String.
*/
public static String readUTF(final byte data[]) {
return readUTF(data, 0, data.length);
}
/**
* Read data bytes as UTF-8 to a String.
* Read data bytes as {@value #CHARSET_NAME} to String.
*/
public static String readUTF(final byte data[], final int off, final int len) {
int offset = off;
final StringBuilder sb = new StringBuilder();
for (final int end = offset + len; offset < end;) {
int ch = data[offset++] & 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 (offset >= len) {
return null;
}
// 110x xxxx 10xx xxxx
ch = ((ch & 0x1F) << 6) | (data[offset++] & 0x3F);
break;
case 14:
if (offset + 2 >= len) {
return null;
}
// 1110 xxxx 10xx xxxx 10xx xxxx
ch = ((ch & 0x0f) << 12) | ((data[offset++] & 0x3F) << 6) | (data[offset++] & 0x3F);
break;
default:
if (offset + 1 >= len) {
return null;
}
// 10xx xxxx, 1111 xxxx
ch = ((ch & 0x3F) << 4) | (data[offset++] & 0x0f);
break;
}
sb.append((char) ch);
}
return sb.toString();
return new String(data, off, len, CHARSET_UTF_8);
}
public static void readProperties(final Map<String, byte[]> properties, final byte[] textBytes) throws Exception {
......@@ -181,7 +141,8 @@ public class ByteWrangler {
}
byte data[] = out2.toByteArray();
if (data.length > MAX_VALUE_LENGTH) {
throw new IOException("Cannot have individual values larger that 255 chars. Offending value: " + key + (val != null ? "" : "=" + val));
logger.warn("Cannot have individual values larger that 255 chars. Offending value: {}", key + (val == null ? "" : "=" + val));
return EMPTY_TXT;
}
out.write((byte) data.length);
out.write(data, 0, data.length);
......@@ -201,7 +162,8 @@ public class ByteWrangler {
writeUTF(out2, text);
final byte data[] = out2.toByteArray();
if (data.length > MAX_VALUE_LENGTH) {
throw new IOException("Cannot have individual values larger that 255 chars. Offending value: " + text);
logger.warn("Cannot have individual values larger that 255 chars. Offending value: {}", text);
return EMPTY_TXT;
}
out.write((byte) data.length);
out.write(data, 0, data.length);
......