diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/ArrayBlockingQueueWithShutdown.java b/smack-core/src/main/java/org/jivesoftware/smack/util/ArrayBlockingQueueWithShutdown.java index 01938c43c..da61c4724 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/ArrayBlockingQueueWithShutdown.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/ArrayBlockingQueueWithShutdown.java @@ -293,6 +293,30 @@ public class ArrayBlockingQueueWithShutdown extends AbstractQueue implemen } } + /** + * Put if the queue has not been shutdown yet. + * + * @param e the element to put into the queue. + * @return true if the element has been put into the queue, false if the queue was shutdown. + * @throws InterruptedException if the calling thread was interrupted. + * @since 4.4 + */ + public boolean putIfNotShutdown(E e) throws InterruptedException { + checkNotNull(e); + lock.lockInterruptibly(); + + try { + if (isShutdown) { + return false; + } + + putInternal(e, true); + return true; + } finally { + lock.unlock(); + } + } + public void putAll(Collection elements) throws InterruptedException { checkNotNull(elements); lock.lockInterruptibly(); diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index 2d283d802..aeb9d109b 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -1592,7 +1592,12 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { } private void sendSmAcknowledgementInternal() throws NotConnectedException, InterruptedException { - packetWriter.sendStreamElement(new AckAnswer(clientHandledStanzasCount)); + AckAnswer ackAnswer = new AckAnswer(clientHandledStanzasCount); + // Do net put an ack to the queue if it has already been shutdown. Some servers, like ejabberd, like to request + // an ack even after we have send a stream close (and hance the queue was shutdown). If we would not check here, + // then the ack would dangle around in the queue, and be send on the next re-connection attempt even before the + // stream open. + packetWriter.queue.putIfNotShutdown(ackAnswer); } /**