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:
parent
d17f64ed9a
commit
874a22489e
7 changed files with 188 additions and 165 deletions
|
@ -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")) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue