diff --git a/source/org/jivesoftware/smack/PacketReader.java b/source/org/jivesoftware/smack/PacketReader.java
index ee9d36449..ca075e991 100644
--- a/source/org/jivesoftware/smack/PacketReader.java
+++ b/source/org/jivesoftware/smack/PacketReader.java
@@ -22,6 +22,9 @@ package org.jivesoftware.smack;
import org.jivesoftware.smack.Connection.ListenerWrapper;
import org.jivesoftware.smack.packet.*;
+import org.jivesoftware.smack.sasl.SASLMechanism.Challenge;
+import org.jivesoftware.smack.sasl.SASLMechanism.Failure;
+import org.jivesoftware.smack.sasl.SASLMechanism.Success;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
@@ -281,14 +284,28 @@ class PacketReader {
else {
// SASL authentication has failed. The server may close the connection
// depending on the number of retries
+ final Failure failure = PacketParserUtils.parseSASLFailure(parser);
+ processPacket(failure);
connection.getSASLAuthentication().authenticationFailed();
}
}
else if (parser.getName().equals("challenge")) {
// The server is challenging the SASL authentication made by the client
- connection.getSASLAuthentication().challengeReceived(parser.nextText());
+ String challengeData = parser.nextText();
+ processPacket(new Challenge(challengeData));
+ connection.getSASLAuthentication().challengeReceived(challengeData);
}
else if (parser.getName().equals("success")) {
+ processPacket(new Success(parser.nextText()));
+ // We now need to bind a resource for the connection
+ // Open a new stream and wait for the response
+ connection.packetWriter.openStream();
+ // Reset the state of the parser since a new stream element is going
+ // to be sent by the server
+ resetParser();
+ // The SASL authentication with the server was successful. The next step
+ // will be to bind the resource
+ connection.getSASLAuthentication().authenticated();
}
else if (parser.getName().equals("compressed")) {
// Server confirmed that it's possible to use stream compression. Start
@@ -304,17 +321,6 @@ class PacketReader {
// Disconnect the connection
connection.disconnect();
}
- else if (parser.getName().equals("success")) {
- // We now need to bind a resource for the connection
- // Open a new stream and wait for the response
- connection.packetWriter.openStream();
- // Reset the state of the parser since a new stream element is going
- // to be sent by the server
- resetParser();
- // The SASL authentication with the server was successful. The next step
- // will be to bind the resource
- connection.getSASLAuthentication().authenticated();
- }
}
eventType = parser.next();
} while (!done && eventType != XmlPullParser.END_DOCUMENT && thread == readerThread);
diff --git a/source/org/jivesoftware/smack/sasl/SASLMechanism.java b/source/org/jivesoftware/smack/sasl/SASLMechanism.java
index 42b2670f0..8a5767740 100644
--- a/source/org/jivesoftware/smack/sasl/SASLMechanism.java
+++ b/source/org/jivesoftware/smack/sasl/SASLMechanism.java
@@ -216,6 +216,28 @@ public abstract class SASLMechanism implements CallbackHandler {
}
}
+ /**
+ * A SASL challenge stanza.
+ */
+ public static class Challenge extends Packet {
+ final private String data;
+
+ public Challenge(String data) {
+ this.data = data;
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("");
+ if (data != null &&
+ data.trim().length() > 0) {
+ stanza.append(data);
+ }
+ stanza.append("");
+ return stanza.toString();
+ }
+ }
+
/**
* A SASL response stanza.
*/
@@ -248,4 +270,57 @@ public abstract class SASLMechanism implements CallbackHandler {
return stanza.toString();
}
}
+
+ /**
+ * A SASL success stanza.
+ */
+ public static class Success extends Packet {
+ final private String data;
+
+ public Success(String data) {
+ this.data = data;
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("");
+ if (data != null &&
+ data.trim().length() > 0) {
+ stanza.append(data);
+ }
+ stanza.append("");
+ return stanza.toString();
+ }
+ }
+
+ /**
+ * A SASL failure stanza.
+ */
+ public static class Failure extends Packet {
+ final private String condition;
+
+ public Failure(String condition) {
+ this.condition = condition;
+ }
+
+ /**
+ * Get the SASL related error condition.
+ *
+ * @return the SASL related error condition.
+ */
+ public String getCondition() {
+ return condition;
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("");
+ if (condition != null &&
+ condition.trim().length() > 0) {
+ stanza.append("<").append(condition).append("/>");
+ }
+ stanza.append("");
+ return stanza.toString();
+ }
+ }
}
diff --git a/source/org/jivesoftware/smack/util/PacketParserUtils.java b/source/org/jivesoftware/smack/util/PacketParserUtils.java
index d76b60417..83cffb7ba 100644
--- a/source/org/jivesoftware/smack/util/PacketParserUtils.java
+++ b/source/org/jivesoftware/smack/util/PacketParserUtils.java
@@ -25,6 +25,7 @@ import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.provider.ProviderManager;
+import org.jivesoftware.smack.sasl.SASLMechanism.Failure;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -590,6 +591,33 @@ public class PacketParserUtils {
return properties;
}
+ /**
+ * Parses SASL authentication error packets.
+ *
+ * @param parser the XML parser.
+ * @return a SASL Failure packet.
+ * @throws Exception if an exception occurs while parsing the packet.
+ */
+ public static Failure parseSASLFailure(XmlPullParser parser) throws Exception {
+ String condition = null;
+ boolean done = false;
+ while (!done) {
+ int eventType = parser.next();
+
+ if (eventType == XmlPullParser.START_TAG) {
+ if (!parser.getName().equals("failure")) {
+ condition = parser.getName();
+ }
+ }
+ else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals("failure")) {
+ done = true;
+ }
+ }
+ }
+ return new Failure(condition);
+ }
+
/**
* Parses stream error packets.
*