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

Merge branch '4.1'

Conflicts:
	smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java
	smack-core/src/main/java/org/jivesoftware/smack/PacketCollector.java
	smack-core/src/main/java/org/jivesoftware/smack/PacketListener.java
	smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java
	smack-core/src/main/java/org/jivesoftware/smack/debugger/SmackDebugger.java
	smack-core/src/main/java/org/jivesoftware/smack/packet/Packet.java
	smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java
	smack-core/src/test/java/org/jivesoftware/smack/ThreadedDummyConnection.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/address/provider/MultipleAddressesProvider.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FaultTolerantNegotiator.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/LeafNode.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/packet/PubSub.java
	smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java
	smack-extensions/src/test/java/org/jivesoftware/smackx/receipts/DeliveryReceiptTest.java
	smack-im/src/main/java/org/jivesoftware/smack/chat/ChatManager.java
	smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java
	smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleProvider.java
	smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/UserID.java
	smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/provider/RosterExchangeProvider.java
	smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java
	version.gradle
This commit is contained in:
Florian Schmaus 2015-03-04 22:42:36 +01:00
commit 701aa7d9c4
298 changed files with 2402 additions and 1562 deletions

View file

@ -17,14 +17,14 @@
package org.jivesoftware.smack.sm.packet;
import org.jivesoftware.smack.packet.FullStreamElement;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.XmlStringBuilder;
public class StreamManagement {
public static final String NAMESPACE = "urn:xmpp:sm:3";
public static class StreamManagementFeature implements PacketExtension {
public static class StreamManagementFeature implements ExtensionElement {
public static final String ELEMENT = "sm";
public static final StreamManagementFeature INSTANCE = new StreamManagementFeature();

View file

@ -16,10 +16,10 @@
*/
package org.jivesoftware.smack.sm.predicates;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Stanza;
public class AfterXStanzas implements PacketFilter {
public class AfterXStanzas implements StanzaFilter {
final int count;
int currentCount;

View file

@ -16,11 +16,11 @@
*/
package org.jivesoftware.smack.sm.predicates;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
public class ForEveryMessage implements PacketFilter {
public class ForEveryMessage implements StanzaFilter {
public static final ForEveryMessage INSTANCE = new ForEveryMessage();

View file

@ -16,10 +16,10 @@
*/
package org.jivesoftware.smack.sm.predicates;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Stanza;
public class ForEveryStanza implements PacketFilter {
public class ForEveryStanza implements StanzaFilter {
public static final ForEveryStanza INSTANCE = new ForEveryStanza();

View file

@ -16,15 +16,15 @@
*/
package org.jivesoftware.smack.sm.predicates;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Stanza;
public class ForMatchingPredicateOrAfterXStanzas implements PacketFilter {
public class ForMatchingPredicateOrAfterXStanzas implements StanzaFilter {
private final PacketFilter predicate;
private final StanzaFilter predicate;
private final AfterXStanzas afterXStanzas;
public ForMatchingPredicateOrAfterXStanzas(PacketFilter predicate, int count) {
public ForMatchingPredicateOrAfterXStanzas(StanzaFilter predicate, int count) {
this.predicate = predicate;
this.afterXStanzas = new AfterXStanzas(count);
}

View file

@ -16,18 +16,18 @@
*/
package org.jivesoftware.smack.sm.predicates;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.util.StringUtils;
public class OnceForThisStanza implements PacketFilter {
public class OnceForThisStanza implements StanzaFilter {
private final String id;
private final XMPPTCPConnection connection;
public static void setup(XMPPTCPConnection connection, Stanza packet) {
PacketFilter packetFilter = new OnceForThisStanza(connection, packet);
StanzaFilter packetFilter = new OnceForThisStanza(connection, packet);
connection.addRequestAckPredicate(packetFilter);
}

View file

@ -16,11 +16,11 @@
*/
package org.jivesoftware.smack.sm.predicates;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
public class Predicate {
public static PacketFilter forMessagesOrAfter5Stanzas() {
public static StanzaFilter forMessagesOrAfter5Stanzas() {
return new ForMatchingPredicateOrAfterXStanzas(ForEveryMessage.INSTANCE, 5);
}

View file

@ -20,31 +20,31 @@ import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Stanza;
public class ShortcutPredicates implements PacketFilter {
public class ShortcutPredicates implements StanzaFilter {
private final Set<PacketFilter> predicates = new LinkedHashSet<PacketFilter>();
private final Set<StanzaFilter> predicates = new LinkedHashSet<StanzaFilter>();
public ShortcutPredicates() {
}
public ShortcutPredicates(Collection<? extends PacketFilter> predicates) {
public ShortcutPredicates(Collection<? extends StanzaFilter> predicates) {
this.predicates.addAll(predicates);
}
public boolean addPredicate(PacketFilter predicate) {
public boolean addPredicate(StanzaFilter predicate) {
return predicates.add(predicate);
}
public boolean removePredicate(PacketFilter prediacte) {
public boolean removePredicate(StanzaFilter prediacte) {
return predicates.remove(prediacte);
}
@Override
public boolean accept(Stanza packet) {
for (PacketFilter predicate : predicates) {
for (StanzaFilter predicate : predicates) {
if (predicate.accept(packet)) {
return true;
}

View file

@ -16,11 +16,11 @@
*/
package org.jivesoftware.smack.sm.provider;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.sm.packet.StreamManagement.StreamManagementFeature;
import org.xmlpull.v1.XmlPullParser;
public class StreamManagementStreamFeatureProvider extends PacketExtensionProvider<StreamManagementFeature> {
public class StreamManagementStreamFeatureProvider extends ExtensionElementProvider<StreamManagementFeature> {
@Override
public StreamManagementFeature parse(XmlPullParser parser,

View file

@ -27,6 +27,14 @@ public class BundleAndDefer {
this.isStopped = isStopped;
}
/**
* Stop the bundle and defer mechanism that was started when this instance of {@link BundleAndDefer} was emitted by
* Smack.
* <p>
* It is possible that the defer period already expired when this is invoked. In this case this method is basically
* a no-op.
* </p>
*/
public void stopCurrentBundleAndDefer() {
synchronized (isStopped) {
if (isStopped.get()) {

View file

@ -20,7 +20,7 @@ package org.jivesoftware.smack.tcp;
* This callback is used to get the current value of the period in which Smack does bundle and defer
* outgoing stanzas.
* <p>
* Smack will bundle and defer stanzas if the connection is authenticated, the send queue is empty
* Smack will bundle and defer stanzas if the connection is authenticated
* and if a bundle and defer callback is set, either via
* {@link XMPPTCPConnection#setDefaultBundleAndDeferCallback(BundleAndDeferCallback)} or
* {@link XMPPTCPConnection#setBundleandDeferCallback(BundleAndDeferCallback)}, and

View file

@ -20,7 +20,7 @@ import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.AlreadyConnectedException;
@ -38,7 +38,7 @@ import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.compress.packet.Compressed;
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.compress.packet.Compress;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.IQ;
@ -187,8 +187,19 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
private final SynchronizationPoint<XMPPException> compressSyncPoint = new SynchronizationPoint<XMPPException>(
this);
/**
* The default bundle and defer callback, used for new connections.
* @see bundleAndDeferCallback
*/
private static BundleAndDeferCallback defaultBundleAndDeferCallback;
/**
* The used bundle and defer callback.
* <p>
* Although this field may be set concurrently, the 'volatile' keyword was deliberately not added, in order to avoid
* having a 'volatile' read within the writer threads loop.
* </p>
*/
private BundleAndDeferCallback bundleAndDeferCallback = defaultBundleAndDeferCallback;
private static boolean useSmDefault = false;
@ -255,13 +266,13 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* themselves after they have been invoked.
* </p>
*/
private final Collection<PacketListener> stanzaAcknowledgedListeners = new ConcurrentLinkedQueue<PacketListener>();
private final Collection<StanzaListener> stanzaAcknowledgedListeners = new ConcurrentLinkedQueue<StanzaListener>();
/**
* This listeners are invoked for a acknowledged stanza that has the given stanza ID. They will
* only be invoked once and automatically removed after that.
*/
private final Map<String, PacketListener> stanzaIdAcknowledgedListeners = new ConcurrentHashMap<String, PacketListener>();
private final Map<String, StanzaListener> stanzaIdAcknowledgedListeners = new ConcurrentHashMap<String, StanzaListener>();
/**
* Predicates that determine if an stream management ack should be requested from the server.
@ -270,7 +281,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* order in which they are invoked in order to determine if an ack request should be send or not.
* </p>
*/
private final Set<PacketFilter> requestAckPredicates = new LinkedHashSet<PacketFilter>();
private final Set<StanzaFilter> requestAckPredicates = new LinkedHashSet<StanzaFilter>();
private final XMPPTCPConnectionConfiguration config;
@ -390,10 +401,15 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
// There was a previous connection with SM enabled but that was either not resumable or
// failed to resume. Make sure that we (re-)send the unacknowledged stanzas.
unacknowledgedStanzas.drainTo(previouslyUnackedStanzas);
// Reset unacknowledged stanzas to 'null' to signal that we never send 'enable' in this
// XMPP session (There maybe was an enabled in a previous XMPP session of this
// connection instance though). This is used in writePackets to decide if stanzas should
// be added to the unacknowledged stanzas queue, because they have to be added right
// after the 'enable' stream element has been sent.
unacknowledgedStanzas = null;
}
if (isSmAvailable() && useSm) {
// Remove what is maybe left from previously stream managed sessions
unacknowledgedStanzas = new ArrayBlockingQueue<Stanza>(QUEUE_SIZE);
serverHandledStanzasCount = 0;
// XEP-198 3. Enabling Stream Management. If the server response to 'Enable' is 'Failed'
// then this is a non recoverable error and we therefore throw an exception.
@ -409,7 +425,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
}
// (Re-)send the stanzas *after* we tried to enable SM
for (Stanza stanza : previouslyUnackedStanzas) {
sendPacketInternal(stanza);
sendStanzaInternal(stanza);
}
afterSuccessfulLogin(false);
@ -496,7 +512,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
setWasAuthenticated();
// If we are able to resume the stream, then don't set
// connected/authenticated/usingTLS to false since we like behave like we are still
// connected (e.g. sendPacket should not throw a NotConnectedException).
// connected (e.g. sendStanza should not throw a NotConnectedException).
if (isSmResumptionPossible() && instant) {
disconnectedButResumeable = true;
} else {
@ -524,10 +540,10 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
}
@Override
protected void sendPacketInternal(Stanza packet) throws NotConnectedException, InterruptedException {
protected void sendStanzaInternal(Stanza packet) throws NotConnectedException, InterruptedException {
packetWriter.sendStreamElement(packet);
if (isSmEnabled()) {
for (PacketFilter requestAckPredicate : requestAckPredicates) {
for (StanzaFilter requestAckPredicate : requestAckPredicates) {
if (requestAckPredicate.accept(packet)) {
requestSmAcknowledgementInternal();
break;
@ -606,7 +622,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
// If debugging is enabled, we should start the thread that will listen for
// all packets and then log them.
if (config.isDebuggerEnabled()) {
addAsyncPacketListener(debugger.getReaderListener(), null);
addAsyncStanzaListener(debugger.getReaderListener(), null);
if (debugger.getWriterListener() != null) {
addPacketSendingListener(debugger.getWriterListener(), null);
}
@ -1173,6 +1189,16 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
private volatile boolean instantShutdown;
/**
* True if some preconditions are given to start the bundle and defer mechanism.
* <p>
* This will likely get set to true right after the start of the writer thread, because
* {@link #nextStreamElement()} will check if {@link queue} is empty, which is probably the case, and then set
* this field to true.
* </p>
*/
private boolean shouldBundleAndDefer;
/**
* Initializes the writer in order to be used. It is called at the first connection and also
* is invoked if the connection is disconnected by an error.
@ -1243,7 +1269,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
shutdownDone.checkIfSuccessOrWait();
}
catch (NoResponseException e) {
LOGGER.log(Level.WARNING, "NoResponseException", e);
LOGGER.log(Level.WARNING, "shutdownDone was not marked as successful by the writer thread", e);
}
}
@ -1255,6 +1281,10 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @return the next element for writing or null.
*/
private Element nextStreamElement() {
// It is important the we check if the queue is empty before removing an element from it
if (queue.isEmpty()) {
shouldBundleAndDefer = true;
}
Element packet = null;
try {
packet = queue.take();
@ -1285,7 +1315,10 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
// If the preconditions are given (e.g. bundleAndDefer callback is set, queue is
// empty), then we could wait a bit for further stanzas attempting to decrease
// our energy consumption
if (localBundleAndDeferCallback != null && isAuthenticated() && queue.isEmpty()) {
if (localBundleAndDeferCallback != null && isAuthenticated() && shouldBundleAndDefer) {
// Reset shouldBundleAndDefer to false, nextStreamElement() will set it to true once the
// queue is empty again.
shouldBundleAndDefer = false;
final AtomicBoolean bundlingAndDeferringStopped = new AtomicBoolean();
final int bundleAndDeferMillis = localBundleAndDeferCallback.getBundleAndDeferMillis(new BundleAndDefer(
bundlingAndDeferringStopped));
@ -1306,11 +1339,17 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
if (element instanceof Stanza) {
packet = (Stanza) element;
}
else if (element instanceof Enable) {
// The client needs to add messages to the unacknowledged stanzas queue
// right after it sent 'enabled'. Stanza will be added once
// unacknowledgedStanzas is not null.
unacknowledgedStanzas = new ArrayBlockingQueue<>(QUEUE_SIZE);
}
// Check if the stream element should be put to the unacknowledgedStanza
// queue. Note that we can not do the put() in sendPacketInternal() and the
// packet order is not stable at this point (sendPacketInternal() can be
// queue. Note that we can not do the put() in sendStanzaInternal() and the
// packet order is not stable at this point (sendStanzaInternal() can be
// called concurrently).
if (isSmEnabled() && packet != null) {
if (unacknowledgedStanzas != null && packet != null) {
// If the unacknowledgedStanza queue is nearly full, request an new ack
// from the server in order to drain it
if (unacknowledgedStanzas.size() == 0.8 * XMPPTCPConnection.QUEUE_SIZE) {
@ -1382,6 +1421,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
LOGGER.log(Level.FINE, "Ignoring Exception in writePackets()", e);
}
} finally {
LOGGER.fine("Reporting shutdownDone success in writer thread");
shutdownDone.reportSuccess();
}
}
@ -1462,7 +1502,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @param predicate the predicate to add.
* @return if the predicate was not already active.
*/
public boolean addRequestAckPredicate(PacketFilter predicate) {
public boolean addRequestAckPredicate(StanzaFilter predicate) {
synchronized (requestAckPredicates) {
return requestAckPredicates.add(predicate);
}
@ -1473,7 +1513,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @param predicate the predicate to remove.
* @return true if the predicate was removed.
*/
public boolean removeRequestAckPredicate(PacketFilter predicate) {
public boolean removeRequestAckPredicate(StanzaFilter predicate) {
synchronized (requestAckPredicates) {
return requestAckPredicates.remove(predicate);
}
@ -1533,13 +1573,13 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* Add a Stanza acknowledged listener.
* <p>
* Those listeners will be invoked every time a Stanza has been acknowledged by the server. The will not get
* automatically removed. Consider using {@link #addStanzaIdAcknowledgedListener(String, PacketListener)} when
* automatically removed. Consider using {@link #addStanzaIdAcknowledgedListener(String, StanzaListener)} when
* possible.
* </p>
*
* @param listener the listener to add.
*/
public void addStanzaAcknowledgedListener(PacketListener listener) {
public void addStanzaAcknowledgedListener(StanzaListener listener) {
stanzaAcknowledgedListeners.add(listener);
}
@ -1549,7 +1589,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @param listener the listener.
* @return true if the listener was removed.
*/
public boolean removeStanzaAcknowledgedListener(PacketListener listener) {
public boolean removeStanzaAcknowledgedListener(StanzaListener listener) {
return stanzaAcknowledgedListeners.remove(listener);
}
@ -1572,7 +1612,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @return the previous listener for this stanza ID or null.
* @throws StreamManagementNotEnabledException if Stream Management is not enabled.
*/
public PacketListener addStanzaIdAcknowledgedListener(final String id, PacketListener listener) throws StreamManagementNotEnabledException {
public StanzaListener addStanzaIdAcknowledgedListener(final String id, StanzaListener listener) throws StreamManagementNotEnabledException {
// Prevent users from adding callbacks that will never get removed
if (!smWasEnabledAtLeastOnce) {
throw new StreamManagementException.StreamManagementNotEnabledException();
@ -1594,7 +1634,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @param id the stanza ID.
* @return true if the listener was found and removed, false otherwise.
*/
public PacketListener removeStanzaIdAcknowledgedListener(String id) {
public StanzaListener removeStanzaIdAcknowledgedListener(String id) {
return stanzaIdAcknowledgedListeners.remove(id);
}
@ -1716,7 +1756,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
@Override
public void run() {
for (Stanza ackedStanza : ackedStanzas) {
for (PacketListener listener : stanzaAcknowledgedListeners) {
for (StanzaListener listener : stanzaAcknowledgedListeners) {
try {
listener.processPacket(ackedStanza);
}
@ -1728,7 +1768,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
if (StringUtils.isNullOrEmpty(id)) {
continue;
}
PacketListener listener = stanzaIdAcknowledgedListeners.remove(id);
StanzaListener listener = stanzaIdAcknowledgedListeners.remove(id);
if (listener != null) {
try {
listener.processPacket(ackedStanza);

View file

@ -36,7 +36,7 @@ public class PacketWriterTest {
/**
* Make sure that packet writer does block once the queue reaches
* {@link PacketWriter#QUEUE_SIZE} and that
* {@link PacketWriter#sendPacket(org.jivesoftware.smack.tcp.packet.Packet)} does unblock after the
* {@link PacketWriter#sendStanza(org.jivesoftware.smack.tcp.packet.Packet)} does unblock after the
* interrupt.
*
* @throws InterruptedException
@ -86,7 +86,7 @@ public class PacketWriterTest {
// will block before we call shutdown. Otherwise we may get false positives (which is still
// better then false negatives).
barrier.await();
// Not really cool, but may increases the chances for 't' to block in sendPacket.
// Not really cool, but may increases the chances for 't' to block in sendStanza.
Thread.sleep(250);
// Set to true for testing purposes, so that shutdown() won't wait packet writer