1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2025-09-10 18:59:41 +02:00

Remove resource binding out of sasl auth

Follow XEP-170 recommendations: Resource binding *after* compression.

Fixes also a bunch of race conditions related to the wait()/notify()
pattern used in the early stages of a Connection where
createPacketCollectorAndSend(Packet).nextResultOrThrow() can not be
used. Those wait()/notify() patterns are currently
- SASL authentication
- compression
- resource binding

Fixes SMACK-454
This commit is contained in:
Florian Schmaus 2014-04-27 12:27:12 +02:00
parent d17f64ed9a
commit 874a22489e
7 changed files with 188 additions and 165 deletions

View file

@ -308,7 +308,7 @@ class PacketReader {
}
else if (parser.getName().equals("bind")) {
// The server requires the client to bind a resource to the stream
connection.getSASLAuthentication().bindingRequired();
connection.serverRequiresBinding();
}
// Set the entity caps node for the server if one is send
// See http://xmpp.org/extensions/xep-0115.html#stream
@ -325,7 +325,7 @@ class PacketReader {
}
else if (parser.getName().equals("session")) {
// The server supports sessions
connection.getSASLAuthentication().sessionsSupported();
connection.serverSupportsSession();
}
else if (parser.getName().equals("ver")) {
if (parser.getNamespace().equals("urn:xmpp:features:rosterver")) {

View file

@ -108,6 +108,10 @@ public class XMPPTCPConnection extends XMPPConnection {
*/
private boolean serverAckdCompression = false;
/**
* Lock for the wait()/notify() pattern for the compression negotiation
*/
private final Object compressionLock = new Object();
/**
* Creates a new connection to the specified XMPP server. A DNS SRV lookup will be
@ -230,20 +234,26 @@ public class XMPPTCPConnection extends XMPPConnection {
// Do partial version of nameprep on the username.
username = username.toLowerCase(Locale.US).trim();
String response;
if (saslAuthentication.hasNonAnonymousAuthentication()) {
// Authenticate using SASL
if (password != null) {
response = saslAuthentication.authenticate(username, password, resource);
saslAuthentication.authenticate(username, password, resource);
}
else {
response = saslAuthentication.authenticate(resource, config.getCallbackHandler());
saslAuthentication.authenticate(resource, config.getCallbackHandler());
}
} else {
throw new SaslException("No non-anonymous SASL authentication mechanism available");
}
// If compression is enabled then request the server to use stream compression. XEP-170
// recommends to perform stream compression before resource binding.
if (config.isCompressionEnabled()) {
useCompression();
}
// Set the user.
String response = bindResourceAndEstablishSession(resource);
if (response != null) {
this.user = response;
// Update the serviceName with the one returned by the server
@ -256,11 +266,6 @@ public class XMPPTCPConnection extends XMPPConnection {
}
}
// If compression is enabled then request the server to use stream compression
if (config.isCompressionEnabled()) {
useCompression();
}
// Indicate that we're now authenticated.
authenticated = true;
anonymous = false;
@ -292,14 +297,14 @@ public class XMPPTCPConnection extends XMPPConnection {
throw new AlreadyLoggedInException();
}
String response;
if (saslAuthentication.hasAnonymousAuthentication()) {
response = saslAuthentication.authenticateAnonymously();
saslAuthentication.authenticateAnonymously();
}
else {
throw new SaslException("No anonymous SASL authentication mechanism available");
}
String response = bindResourceAndEstablishSession(null);
// Set the user value.
this.user = response;
// Update the serviceName with the one returned by the server
@ -396,8 +401,6 @@ public class XMPPTCPConnection extends XMPPConnection {
reader = null;
writer = null;
saslAuthentication.init();
}
public synchronized void disconnect(Presence unavailablePresence) {
@ -786,11 +789,11 @@ public class XMPPTCPConnection extends XMPPConnection {
}
if ((compressionHandler = maybeGetCompressionHandler()) != null) {
synchronized (this) {
synchronized (compressionLock) {
requestStreamCompression(compressionHandler.getCompressionMethod());
// Wait until compression is being used or a timeout happened
try {
wait(getPacketReplyTimeout());
compressionLock.wait(getPacketReplyTimeout());
}
catch (InterruptedException e) {
// Ignore.
@ -835,8 +838,10 @@ public class XMPPTCPConnection extends XMPPConnection {
* Notifies the XMPP connection that stream compression negotiation is done so that the
* connection process can proceed.
*/
synchronized void streamCompressionNegotiationDone() {
this.notify();
void streamCompressionNegotiationDone() {
synchronized (compressionLock) {
compressionLock.notify();
}
}
/**
@ -851,7 +856,8 @@ public class XMPPTCPConnection extends XMPPConnection {
* @throws SmackException
* @throws IOException
*/
public void connect() throws SmackException, IOException, XMPPException {
@Override
void connectInternal() throws SmackException, IOException, XMPPException {
// Establishes the connection, readers and writers
connectUsingConfiguration(config);
// TODO is there a case where connectUsing.. does not throw an exception but connected is