1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-09 17:19:39 +02:00

Smack 4.2.0-rc2

-----BEGIN PGP SIGNATURE-----
 
 iQF8BAABCgBmBQJYe7kjXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25zLm9w
 ZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQ5Nzc1MDU5RjNBMjFEQ0UxNkJFNEZCQUUy
 MjM5QTdFOEY1ODUyMDUyAAoJECI5p+j1hSBSuGkH/1mU66MNR0/ywbdZ2RKcb9MK
 WTHBBOuD/KaqkQOQQ5Fud+ktyahmDd9Nk4TbchIJ56PlEPqJbhnwP8txh1gU+8Zz
 jpRHYYQiTEuLSblToVL3afrfd/IQnOrh7VbwkG7S1wkWmOFKCv94wlv/OgZFaICc
 RHHJyJbJ0TTuavEkJ141ruNYmq/qYjUjdLmFrqhT3hv3iuiHCT1PK1787wEB0EWS
 ciwkw2j/j/2i27XNQRwu7QaLsmUGk8rLnr2/AsYpmsBsjAMqMbNEQEPbIgO9MVef
 7dt/GWoqHjH1opVcOw+rRz/cynMii2sSTXiqRVTEZsWlx3uYYz5eKsuiuckZcBs=
 =yqh1
 -----END PGP SIGNATURE-----

Merge tag '4.2.0-rc2'

Smack 4.2.0-rc2
This commit is contained in:
Florian Schmaus 2017-01-15 19:03:32 +01:00
commit 382ed9d871
53 changed files with 797 additions and 182 deletions

View file

@ -169,9 +169,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
protected String streamId;
/**
*
* The timeout to wait for a reply in milliseconds.
*/
private long packetReplyTimeout = SmackConfiguration.getDefaultPacketReplyTimeout();
private long replyTimeout = SmackConfiguration.getDefaultReplyTimeout();
/**
* The SmackDebugger allows to log and debug XML traffic.
@ -188,6 +188,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
*/
protected Writer writer;
protected final SynchronizationPoint<SmackException> tlsHandled = new SynchronizationPoint<>(this, "establishing TLS");
/**
* Set to success if the last features stanza from the server has been parsed. A XMPP connection
* handshake can invoke multiple features stanzas, e.g. when TLS is activated a second feature
@ -198,9 +200,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
AbstractXMPPConnection.this, "last stream features received from server");
/**
* Set to success if the sasl feature has been received.
* Set to success if the SASL feature has been received.
*/
protected final SynchronizationPoint<SmackException> saslFeatureReceived = new SynchronizationPoint<SmackException>(
protected final SynchronizationPoint<XMPPException> saslFeatureReceived = new SynchronizationPoint<>(
AbstractXMPPConnection.this, "SASL mechanisms stream feature from server");
/**
@ -368,11 +370,15 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
saslAuthentication.init();
saslFeatureReceived.init();
lastFeaturesReceived.init();
tlsHandled.init();
streamId = null;
// Perform the actual connection to the XMPP service
connectInternal();
// TLS handled will be successful either if TLS was established, or if it was not mandatory.
tlsHandled.checkIfSuccessOrWaitOrThrow();
// Wait with SASL auth until the SASL mechanisms have been received
saslFeatureReceived.checkIfSuccessOrWaitOrThrow();
@ -596,7 +602,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
protected List<HostAddress> hostAddresses;
/**
* Populates {@link #hostAddresses} with at least one host address.
* Populates {@link #hostAddresses} with the resolved addresses or with the configured host address. If no host
* address was configured and all lookups failed, for example with NX_DOMAIN, then {@link #hostAddresses} will be
* populated with the empty list.
*
* @return a list of host addresses where DNS (SRV) RR resolution failed.
*/
@ -610,14 +618,15 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
else if (config.host != null) {
hostAddresses = new ArrayList<HostAddress>(1);
HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
hostAddresses.add(hostAddress);
if (hostAddress != null) {
hostAddresses.add(hostAddress);
}
} else {
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
}
// If we reach this, then hostAddresses *must not* be empty, i.e. there is at least one host added, either the
// config.host one or the host representing the service name by DNSUtil
assert(!hostAddresses.isEmpty());
// Either the populated host addresses are not empty *or* there must be at least one failed address.
assert(!hostAddresses.isEmpty() || !failedAddresses.isEmpty());
return failedAddresses;
}
@ -960,14 +969,26 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
}
}
@SuppressWarnings("deprecation")
@Override
public long getPacketReplyTimeout() {
return packetReplyTimeout;
return getReplyTimeout();
}
@SuppressWarnings("deprecation")
@Override
public void setPacketReplyTimeout(long timeout) {
setReplyTimeout(timeout);
}
@Override
public void setPacketReplyTimeout(long timeout) {
packetReplyTimeout = timeout;
public long getReplyTimeout() {
return replyTimeout;
}
@Override
public void setReplyTimeout(long timeout) {
replyTimeout = timeout;
}
private static boolean replyToUnknownIqDefault = true;
@ -1407,6 +1428,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
// Only proceed with SASL auth if TLS is disabled or if the server doesn't announce it
if (!hasFeature(StartTls.ELEMENT, StartTls.NAMESPACE)
|| config.getSecurityMode() == SecurityMode.disabled) {
tlsHandled.reportSuccess();
saslFeatureReceived.reportSuccess();
}
}
@ -1456,7 +1478,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
StanzaListener callback, ExceptionCallback exceptionCallback)
throws NotConnectedException, InterruptedException {
sendStanzaWithResponseCallback(stanza, replyFilter, callback, exceptionCallback,
getPacketReplyTimeout());
getReplyTimeout());
}
@Override
@ -1517,7 +1539,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
@Override
public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback,
ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException {
sendIqWithResponseCallback(iqRequest, callback, exceptionCallback, getPacketReplyTimeout());
sendIqWithResponseCallback(iqRequest, callback, exceptionCallback, getReplyTimeout());
}
@Override
@ -1546,7 +1568,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
public void run() {
removeSyncStanzaListener(packetListener);
}
}, getPacketReplyTimeout(), TimeUnit.MILLISECONDS);
}, getReplyTimeout(), TimeUnit.MILLISECONDS);
}
@Override

View file

@ -200,7 +200,7 @@ public final class SASLAuthentication {
else {
currentMechanism.authenticate(username, host, xmppServiceDomain, password, authzid, sslSession);
}
final long deadline = System.currentTimeMillis() + connection.getPacketReplyTimeout();
final long deadline = System.currentTimeMillis() + connection.getReplyTimeout();
while (!authenticationSuccessful && saslException == null) {
final long now = System.currentTimeMillis();
if (now >= deadline) break;

View file

@ -101,8 +101,32 @@ public final class SmackConfiguration {
* the server. The default value is 5000 ms.
*
* @return the milliseconds to wait for a response from the server
* @deprecated use {@link #getDefaultReplyTimeout()} instead.
*/
@Deprecated
public static int getDefaultPacketReplyTimeout() {
return getDefaultReplyTimeout();
}
/**
* Sets the number of milliseconds to wait for a response from
* the server.
*
* @param timeout the milliseconds to wait for a response from the server
* @deprecated use {@link #setDefaultReplyTimeout(int)} instead.
*/
@Deprecated
public static void setDefaultPacketReplyTimeout(int timeout) {
setDefaultReplyTimeout(timeout);
}
/**
* Returns the number of milliseconds to wait for a response from
* the server. The default value is 5000 ms.
*
* @return the milliseconds to wait for a response from the server
*/
public static int getDefaultReplyTimeout() {
// The timeout value must be greater than 0 otherwise we will answer the default value
if (defaultPacketReplyTimeout <= 0) {
defaultPacketReplyTimeout = 5000;
@ -116,7 +140,7 @@ public final class SmackConfiguration {
*
* @param timeout the milliseconds to wait for a response from the server
*/
public static void setDefaultPacketReplyTimeout(int timeout) {
public static void setDefaultReplyTimeout(int timeout) {
if (timeout <= 0) {
throw new IllegalArgumentException();
}

View file

@ -58,7 +58,7 @@ public class SmackException extends Exception {
/**
* Exception thrown always when there was no response to an request within the stanza(/packet) reply timeout of the used
* connection instance. You can modify (e.g. increase) the stanza(/packet) reply timeout with
* {@link XMPPConnection#setPacketReplyTimeout(long)}.
* {@link XMPPConnection#setReplyTimeout(long)}.
*/
public static final class NoResponseException extends SmackException {
/**
@ -111,7 +111,7 @@ public class SmackException extends Exception {
}
private static StringBuilder getWaitingFor(XMPPConnection connection) {
final long replyTimeout = connection.getPacketReplyTimeout();
final long replyTimeout = connection.getReplyTimeout();
final StringBuilder sb = new StringBuilder(256);
sb.append("No response received within reply timeout. Timeout was "
+ replyTimeout + "ms (~"

View file

@ -161,7 +161,7 @@ public class StanzaCollector {
* @throws InterruptedException
*/
public <P extends Stanza> P nextResult() throws InterruptedException {
return nextResult(connection.getPacketReplyTimeout());
return nextResult(connection.getReplyTimeout());
}
private volatile long waitStart;
@ -205,7 +205,7 @@ public class StanzaCollector {
*/
public <P extends Stanza> P nextResultOrThrow() throws NoResponseException, XMPPErrorException,
InterruptedException, NotConnectedException {
return nextResultOrThrow(connection.getPacketReplyTimeout());
return nextResultOrThrow(connection.getReplyTimeout());
}
/**

View file

@ -234,7 +234,7 @@ public class SynchronizationPoint<E extends Exception> {
* @throws InterruptedException
*/
private void waitForConditionOrTimeout() throws InterruptedException {
long remainingWait = TimeUnit.MILLISECONDS.toNanos(connection.getPacketReplyTimeout());
long remainingWait = TimeUnit.MILLISECONDS.toNanos(connection.getReplyTimeout());
while (state == State.RequestSent || state == State.Initial) {
if (remainingWait <= 0) {
state = State.NoResponse;

View file

@ -410,7 +410,9 @@ public interface XMPPConnection {
* XMPPConnection instance.
*
* @return the stanza(/packet) reply timeout in milliseconds
* @deprecated use {@link #getReplyTimeout()} instead.
*/
@Deprecated
public long getPacketReplyTimeout();
/**
@ -418,9 +420,27 @@ public interface XMPPConnection {
* {@link NoResponseException} if no reply to a request was received within the timeout period.
*
* @param timeout the stanza(/packet) reply timeout in milliseconds
* @deprecated use {@link #setReplyTimeout(long)} instead.
*/
@Deprecated
public void setPacketReplyTimeout(long timeout);
/**
* Returns the current value of the reply timeout in milliseconds for request for this
* XMPPConnection instance.
*
* @return the reply timeout in milliseconds
*/
public long getReplyTimeout();
/**
* Set the stanza(/packet) reply timeout in milliseconds. In most cases, Smack will throw a
* {@link NoResponseException} if no reply to a request was received within the timeout period.
*
* @param timeout for a reply in milliseconds
*/
public void setReplyTimeout(long timeout);
/**
* Get the connection counter of this XMPPConnection instance. Those can be used as ID to
* identify the connection, but beware that the ID may not be unique if you create more then

View file

@ -0,0 +1,62 @@
/**
*
* Copyright 2017 Florian Schmaus.
*
* Licensed 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.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza;
import org.jxmpp.jid.Jid;
public abstract class AbstractJidTypeFilter implements StanzaFilter {
protected enum JidType {
entityFull,
entityBare,
domainFull,
domainBare,
;
}
private final JidType jidType;
protected AbstractJidTypeFilter(JidType jidType) {
this.jidType = jidType;
}
protected abstract Jid getJidToInspect(Stanza stanza);
@Override
public final boolean accept(Stanza stanza) {
final Jid jid = stanza.getFrom();
if (jid == null) {
return false;
}
switch (jidType) {
case entityFull:
return jid.isEntityFullJid();
case entityBare:
return jid.isEntityBareJid();
case domainFull:
return jid.isDomainFullJid();
case domainBare:
return jid.isDomainBareJid();
default:
throw new AssertionError();
}
}
}

View file

@ -0,0 +1,38 @@
/**
*
* Copyright 2017 Florian Schmaus.
*
* Licensed 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.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza;
import org.jxmpp.jid.Jid;
public final class FromTypeFilter extends AbstractJidTypeFilter {
public static final FromTypeFilter ENTITY_FULL_JID = new FromTypeFilter(JidType.entityFull);
public static final FromTypeFilter ENTITY_BARE_JID = new FromTypeFilter(JidType.entityBare);
public static final FromTypeFilter DOMAIN_FULL_JID = new FromTypeFilter(JidType.domainFull);
public static final FromTypeFilter DOMAIN_BARE_JID = new FromTypeFilter(JidType.domainBare);
private FromTypeFilter(JidType jidType) {
super(jidType);
}
@Override
protected Jid getJidToInspect(Stanza stanza) {
return stanza.getFrom();
}
}

View file

@ -0,0 +1,40 @@
/**
*
* Copyright 2017 Florian Schmaus.
*
* Licensed 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.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza;
import org.jxmpp.jid.Jid;
public final class ToTypeFilter extends AbstractJidTypeFilter {
public static final ToTypeFilter ENTITY_FULL_JID = new ToTypeFilter(JidType.entityFull);
public static final ToTypeFilter ENTITY_BARE_JID = new ToTypeFilter(JidType.entityBare);
public static final ToTypeFilter DOMAIN_FULL_JID = new ToTypeFilter(JidType.domainFull);
public static final ToTypeFilter DOMAIN_BARE_JID = new ToTypeFilter(JidType.domainBare);
public static final StanzaFilter ENTITY_FULL_OR_BARE_JID = new OrFilter(ENTITY_FULL_JID, ENTITY_BARE_JID);
private ToTypeFilter(JidType jidType) {
super(jidType);
}
@Override
protected Jid getJidToInspect(Stanza stanza) {
return stanza.getTo();
}
}

View file

@ -250,14 +250,16 @@ public class DNSUtil {
List<SRVRecord> bucket = buckets.get(priority);
int bucketSize;
while ((bucketSize = bucket.size()) > 0) {
int[] totals = new int[bucket.size()];
int[] totals = new int[bucketSize];
int running_total = 0;
int count = 0;
int zeroWeight = 1;
for (SRVRecord r : bucket) {
if (r.getWeight() > 0)
if (r.getWeight() > 0) {
zeroWeight = 0;
break;
}
}
for (SRVRecord r : bucket) {

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2013-2016 Florian Schmaus
* Copyright 2013-2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -50,7 +50,7 @@ public abstract class DNSResolver {
public final HostAddress lookupHostAddress(String name, int port, List<HostAddress> failedAddresses, DnssecMode dnssecMode) {
checkIfDnssecRequestedAndSupported(dnssecMode);
List<InetAddress> inetAddresses = lookupHostAddress0(name, failedAddresses, dnssecMode);
if (inetAddresses == null) {
if (inetAddresses == null || inetAddresses.isEmpty()) {
return null;
}
return new HostAddress(name, port, inetAddresses);

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2013-2016 Florian Schmaus
* Copyright © 2013-2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,7 +25,7 @@ import java.util.Map;
import java.util.Map.Entry;
import org.jivesoftware.smack.SmackException.ConnectionException;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils;
public class HostAddress {
private final String fqdn;
@ -34,18 +34,17 @@ public class HostAddress {
private final List<InetAddress> inetAddresses;
/**
* Creates a new HostAddress with the given FQDN. The port will be set to the default XMPP client port: 5222
* Creates a new HostAddress with the given FQDN.
*
* @param fqdn Fully qualified domain name.
* @param fqdn the optional fully qualified domain name (FQDN).
* @param port The port to connect on.
* @throws IllegalArgumentException If the fqdn is null or port is out of valid range (0 - 65535).
* @throws IllegalArgumentException If the port is out of valid range (0 - 65535).
*/
public HostAddress(String fqdn, int port, List<InetAddress> inetAddresses) {
Objects.requireNonNull(fqdn, "FQDN is null");
if (port < 0 || port > 65535)
throw new IllegalArgumentException(
"Port must be a 16-bit unsiged integer (i.e. between 0-65535. Port was: " + port);
if (fqdn.charAt(fqdn.length() - 1) == '.') {
if (StringUtils.isNotEmpty(fqdn) && fqdn.charAt(fqdn.length() - 1) == '.') {
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
}
else {
@ -59,7 +58,7 @@ public class HostAddress {
}
public HostAddress(int port, InetAddress hostAddress) {
this("", port, Collections.singletonList(hostAddress));
this(null, port, Collections.singletonList(hostAddress));
}
/**

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2013-2016 Florian Schmaus
* Copyright 2013-2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,6 +19,8 @@ package org.jivesoftware.smack.util.dns;
import java.net.InetAddress;
import java.util.List;
import org.jivesoftware.smack.util.StringUtils;
/**
* A DNS SRV RR.
*
@ -43,6 +45,7 @@ public class SRVRecord extends HostAddress implements Comparable<SRVRecord> {
*/
public SRVRecord(String fqdn, int port, int priority, int weight, List<InetAddress> inetAddresses) {
super(fqdn, port, inetAddresses);
StringUtils.requireNotNullOrEmpty(fqdn, "The FQDN must not be null");
if (weight < 0 || weight > 65535)
throw new IllegalArgumentException(
"DNS SRV records weight must be a 16-bit unsiged integer (i.e. between 0-65535. Weight was: "

View file

@ -91,6 +91,7 @@ public class DummyConnection extends AbstractXMPPConnection {
protected void connectInternal() {
connected = true;
saslFeatureReceived.reportSuccess();
tlsHandled.reportSuccess();
streamId = "dummy-" + new Random(new Date().getTime()).nextInt();
if (reconnect) {

View file

@ -28,7 +28,7 @@ public class SmackConfigurationTest {
@Test
public void testSmackConfiguration() {
try {
SmackConfiguration.getDefaultPacketReplyTimeout();
SmackConfiguration.getDefaultReplyTimeout();
} catch (Throwable t) {
fail("SmackConfiguration threw Throwable");
}
@ -40,7 +40,7 @@ public class SmackConfigurationTest {
@Ignore
@Test
public void smackConfigurationShouldNotCauseInitializationTest() {
SmackConfiguration.getDefaultPacketReplyTimeout();
SmackConfiguration.getDefaultReplyTimeout();
// Only a call to SmackConfiguration.getVersion() should cause Smack to become initialized.
assertFalse(SmackConfiguration.isSmackInitialized());