mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-10 17:49:38 +02:00
Add support for XEP-0198: Stream Management
- De-duplicate code by moving it into AbstractXMPPConnection - Introduce TopLevelStreamElement as superclass for all XMPP stream elements. - Add SynchronizationPoint, ParserUtils - Add ParserUtils Fixes SMACK-333 and SMACK-521
This commit is contained in:
parent
07c10a7444
commit
fc51f3df48
69 changed files with 3277 additions and 1083 deletions
|
@ -20,9 +20,8 @@ package org.jivesoftware.smack.bosh;
|
|||
import java.io.StringReader;
|
||||
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.sasl.packet.SaslStanzas.Challenge;
|
||||
import org.jivesoftware.smack.sasl.packet.SaslStanzas.SASLFailure;
|
||||
import org.jivesoftware.smack.sasl.packet.SaslStanzas.Success;
|
||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
|
||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Success;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.jivesoftware.smack.XMPPException.StreamErrorException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
@ -86,8 +85,6 @@ public class BOSHPacketReader implements BOSHClientResponseListener {
|
|||
final String challengeData = parser.nextText();
|
||||
connection.getSASLAuthentication()
|
||||
.challengeReceived(challengeData);
|
||||
connection.processPacket(new Challenge(
|
||||
challengeData));
|
||||
} else if (parser.getName().equals("success")) {
|
||||
connection.send(ComposableBody.builder()
|
||||
.setNamespaceDefinition("xmpp", XMPPBOSHConnection.XMPP_BOSH_NS)
|
||||
|
@ -100,14 +97,12 @@ public class BOSHPacketReader implements BOSHClientResponseListener {
|
|||
.build());
|
||||
Success success = new Success(parser.nextText());
|
||||
connection.getSASLAuthentication().authenticated(success);
|
||||
connection.processPacket(success);
|
||||
} else if (parser.getName().equals("features")) {
|
||||
parseFeatures(parser);
|
||||
} else if (parser.getName().equals("failure")) {
|
||||
if ("urn:ietf:params:xml:ns:xmpp-sasl".equals(parser.getNamespace(null))) {
|
||||
final SASLFailure failure = PacketParserUtils.parseSASLFailure(parser);
|
||||
connection.getSASLAuthentication().authenticationFailed(failure);
|
||||
connection.processPacket(failure);
|
||||
}
|
||||
} else if (parser.getName().equals("error")) {
|
||||
throw new StreamErrorException(PacketParserUtils.parseStreamError(parser));
|
||||
|
@ -123,41 +118,7 @@ public class BOSHPacketReader implements BOSHClientResponseListener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and setup the XML stream features.
|
||||
*
|
||||
* @param parser the XML parser, positioned at the start of a message packet.
|
||||
* @throws Exception if an exception occurs while parsing the packet.
|
||||
*/
|
||||
private void parseFeatures(XmlPullParser parser) throws Exception {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
int eventType = parser.next();
|
||||
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
if (parser.getName().equals("mechanisms")) {
|
||||
// The server is reporting available SASL mechanisms. Store
|
||||
// this information
|
||||
// which will be used later while logging (i.e.
|
||||
// authenticating) into
|
||||
// the server
|
||||
connection.getSASLAuthentication().setAvailableSASLMethods(
|
||||
PacketParserUtils.parseMechanisms(parser));
|
||||
} else if (parser.getName().equals("bind")) {
|
||||
// The server requires the client to bind a resource to the
|
||||
// stream
|
||||
connection.serverRequiresBinding();
|
||||
} else if (parser.getName().equals("session")) {
|
||||
// The server supports sessions
|
||||
connection.serverSupportsSession();
|
||||
} else if (parser.getName().equals("register")) {
|
||||
connection.serverSupportsAccountCreation();
|
||||
}
|
||||
} else if (eventType == XmlPullParser.END_TAG) {
|
||||
if (parser.getName().equals("features")) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
connection.parseFeatures0(parser);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,9 +38,12 @@ import org.jivesoftware.smack.ConnectionCreationListener;
|
|||
import org.jivesoftware.smack.ConnectionListener;
|
||||
import org.jivesoftware.smack.Roster;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.packet.Element;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.PlainStreamElement;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.packet.Presence.Type;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.igniterealtime.jbosh.BOSHClient;
|
||||
import org.igniterealtime.jbosh.BOSHClientConfig;
|
||||
import org.igniterealtime.jbosh.BOSHClientConnEvent;
|
||||
|
@ -85,7 +88,6 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
// Some flags which provides some info about the current state.
|
||||
private boolean connected = false;
|
||||
private boolean authenticated = false;
|
||||
private boolean anonymous = false;
|
||||
private boolean isFirstInitialization = true;
|
||||
private boolean wasAuthenticated = false;
|
||||
private boolean done = false;
|
||||
|
@ -104,11 +106,6 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
*/
|
||||
protected String sessionID = null;
|
||||
|
||||
/**
|
||||
* The full JID of the authenticated user.
|
||||
*/
|
||||
private String user = null;
|
||||
|
||||
/**
|
||||
* Create a HTTP Binding connection to a XMPP server.
|
||||
*
|
||||
|
@ -220,10 +217,6 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
return user;
|
||||
}
|
||||
|
||||
public boolean isAnonymous() {
|
||||
return anonymous;
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
return authenticated;
|
||||
}
|
||||
|
@ -250,6 +243,10 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
if (authenticated) {
|
||||
throw new AlreadyLoggedInException();
|
||||
}
|
||||
|
||||
// Wait with SASL auth until the SASL mechanisms have been received
|
||||
saslFeatureReceived.checkIfSuccessOrWaitOrThrow();
|
||||
|
||||
// Do partial version of nameprep on the username.
|
||||
username = username.toLowerCase(Locale.US).trim();
|
||||
|
||||
|
@ -264,41 +261,11 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
throw new SaslException("No non-anonymous SASL authentication mechanism available");
|
||||
}
|
||||
|
||||
String response = bindResourceAndEstablishSession(resource);
|
||||
// Set the user.
|
||||
if (response != null) {
|
||||
this.user = response;
|
||||
// Update the serviceName with the one returned by the server
|
||||
setServiceName(response);
|
||||
} else {
|
||||
this.user = username + "@" + getServiceName();
|
||||
if (resource != null) {
|
||||
this.user += "/" + resource;
|
||||
}
|
||||
}
|
||||
bindResourceAndEstablishSession(resource);
|
||||
|
||||
// Indicate that we're now authenticated.
|
||||
authenticated = true;
|
||||
anonymous = false;
|
||||
|
||||
// Stores the autentication for future reconnection
|
||||
// Stores the authentication for future reconnection
|
||||
setLoginInfo(username, password, resource);
|
||||
|
||||
// If debugging is enabled, change the the debug window title to include
|
||||
// the
|
||||
// name we are now logged-in as.l
|
||||
if (config.isDebuggerEnabled() && debugger != null) {
|
||||
debugger.userHasLogged(user);
|
||||
}
|
||||
callConnectionAuthenticatedListener();
|
||||
|
||||
// Set presence to online. It is important that this is done after
|
||||
// callConnectionAuthenticatedListener(), as this call will also
|
||||
// eventually load the roster. And we should load the roster before we
|
||||
// send the initial presence.
|
||||
if (config.isSendPresence()) {
|
||||
sendPacket(new Presence(Presence.Type.available));
|
||||
}
|
||||
afterSuccessfulLogin(false, false);
|
||||
}
|
||||
|
||||
public void loginAnonymously() throws XMPPException, SmackException, IOException {
|
||||
|
@ -309,6 +276,9 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
throw new AlreadyLoggedInException();
|
||||
}
|
||||
|
||||
// Wait with SASL auth until the SASL mechanisms have been received
|
||||
saslFeatureReceived.checkIfSuccessOrWaitOrThrow();
|
||||
|
||||
if (saslAuthentication.hasAnonymousAuthentication()) {
|
||||
saslAuthentication.authenticateAnonymously();
|
||||
}
|
||||
|
@ -317,38 +287,27 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
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
|
||||
setServiceName(response);
|
||||
bindResourceAndEstablishSession(null);
|
||||
|
||||
// Set presence to online.
|
||||
if (config.isSendPresence()) {
|
||||
sendPacket(new Presence(Presence.Type.available));
|
||||
afterSuccessfulLogin(true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(PlainStreamElement element) throws NotConnectedException {
|
||||
if (done) {
|
||||
throw new NotConnectedException();
|
||||
}
|
||||
|
||||
// Indicate that we're now authenticated.
|
||||
authenticated = true;
|
||||
anonymous = true;
|
||||
|
||||
// If debugging is enabled, change the the debug window title to include the
|
||||
// name we are now logged-in as.
|
||||
// If DEBUG_ENABLED was set to true AFTER the connection was created the debugger
|
||||
// will be null
|
||||
if (config.isDebuggerEnabled() && debugger != null) {
|
||||
debugger.userHasLogged(user);
|
||||
}
|
||||
callConnectionAuthenticatedListener();
|
||||
sendElement(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendPacketInternal(Packet packet) throws NotConnectedException {
|
||||
if (done) {
|
||||
throw new NotConnectedException();
|
||||
}
|
||||
sendElement(packet);
|
||||
}
|
||||
|
||||
private void sendElement(Element element) {
|
||||
try {
|
||||
send(ComposableBody.builder().setPayloadXML(packet.toXML().toString()).build());
|
||||
send(ComposableBody.builder().setPayloadXML(element.toXML().toString()).build());
|
||||
}
|
||||
catch (BOSHException e) {
|
||||
LOGGER.log(Level.SEVERE, "BOSHException in sendPacketInternal", e);
|
||||
|
@ -524,19 +483,8 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
|||
return super.getSASLAuthentication();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void serverRequiresBinding() {
|
||||
super.serverRequiresBinding();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void serverSupportsSession() {
|
||||
super.serverSupportsSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void serverSupportsAccountCreation() {
|
||||
super.serverSupportsAccountCreation();
|
||||
void parseFeatures0(XmlPullParser parser) throws Exception {
|
||||
parseFeatures(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue