1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-17 00:44:50 +02:00

Synchronize bindingRequired

Right after PacketReader receives the 'success' stanza, indicating
successful SASL authentication, it opens a new stream. The login
process continues in another thread and checks for bindingRequired,
which may not have been set a this point yet.

bindResourceAndEstablishSession() now waits until either the binding
feature stanza is parsed or the default packet timeout occurs.
This commit is contained in:
Florian Schmaus 2014-04-30 12:28:56 +02:00
parent fd532be9b6
commit ed8b80c2ff

View file

@ -35,6 +35,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -215,7 +216,15 @@ public abstract class XMPPConnection {
*/ */
private int port; private int port;
private boolean bindingRequired; /**
* Set to true if the server requires the connection to be binded in order to continue.
* <p>
* Note that we use AtomicBoolean here because it allows us to set the Boolean *object*, which
* we also use as synchronization object. A plain non-atomic Boolean object would be newly created
* for every change of the boolean value, which makes it useless as object for wait()/notify().
*/
private AtomicBoolean bindingRequired = new AtomicBoolean(false);
private boolean sessionSupported; private boolean sessionSupported;
/** /**
@ -358,7 +367,7 @@ public abstract class XMPPConnection {
*/ */
public void connect() throws SmackException, IOException, XMPPException { public void connect() throws SmackException, IOException, XMPPException {
saslAuthentication.init(); saslAuthentication.init();
bindingRequired = false; bindingRequired.set(false);
sessionSupported = false; sessionSupported = false;
connectionException = null; connectionException = null;
connectInternal(); connectInternal();
@ -457,7 +466,10 @@ public abstract class XMPPConnection {
* resource to the stream. * resource to the stream.
*/ */
void serverRequiresBinding() { void serverRequiresBinding() {
bindingRequired = true; synchronized (bindingRequired) {
bindingRequired.set(true);
bindingRequired.notify();
}
} }
/** /**
@ -472,11 +484,22 @@ public abstract class XMPPConnection {
String bindResourceAndEstablishSession(String resource) throws XMPPErrorException, String bindResourceAndEstablishSession(String resource) throws XMPPErrorException,
ResourceBindingNotOfferedException, NoResponseException, NotConnectedException { ResourceBindingNotOfferedException, NoResponseException, NotConnectedException {
if (!bindingRequired) { synchronized (bindingRequired) {
// Server never offered resource binding, which is REQURIED in XMPP client and server if (!bindingRequired.get()) {
try {
bindingRequired.wait(getPacketReplyTimeout());
}
catch (InterruptedException e) {
// Ignore
}
if (!bindingRequired.get()) {
// Server never offered resource binding, which is REQURIED in XMPP client and
// server
// implementations as per RFC6120 7.2 // implementations as per RFC6120 7.2
throw new ResourceBindingNotOfferedException(); throw new ResourceBindingNotOfferedException();
} }
}
}
Bind bindResource = new Bind(); Bind bindResource = new Bind();
bindResource.setResource(resource); bindResource.setResource(resource);