Add support for *optional* session establishment

Don't perform XMPP session binding if the server announced the feature
as optional.

Fixes SMACK-622
This commit is contained in:
Florian Schmaus 2014-12-30 12:37:01 +01:00
parent e6593cb200
commit c5d0fb3c7b
3 changed files with 53 additions and 6 deletions

View File

@ -466,7 +466,10 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
user = response.getJid();
serviceName = XmppStringUtils.parseDomain(user);
if (hasFeature(Session.ELEMENT, Session.NAMESPACE) && !getConfiguration().isLegacySessionDisabled()) {
Session.Feature sessionFeature = getFeature(Session.ELEMENT, Session.NAMESPACE);
// Only bind the session if it's announced as stream feature by the server, is not optional and not disabled
// For more information see http://tools.ietf.org/html/draft-cridland-xmpp-session-01
if (sessionFeature != null && !sessionFeature.isOptional() && !getConfiguration().isLegacySessionDisabled()) {
Session session = new Session();
packetCollector = createPacketCollectorAndSend(new PacketIDFilter(session), session);
packetCollector.nextResultOrThrow();
@ -1137,7 +1140,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
streamFeature = Bind.Feature.INSTANCE;
break;
case Session.ELEMENT:
streamFeature = Session.Feature.INSTANCE;
streamFeature = PacketParserUtils.parseSessionFeature(parser);
break;
case RosterVer.ELEMENT:
if(namespace.equals(RosterVer.NAMESPACE)) {

View File

@ -17,6 +17,8 @@
package org.jivesoftware.smack.packet;
import org.jivesoftware.smack.util.XmlStringBuilder;
/**
* IQ packet that will be sent to the server to establish a session.<p>
*
@ -44,9 +46,16 @@ public class Session extends SimpleIQ {
public static class Feature implements PacketExtension {
public static final Session.Feature INSTANCE = new Feature();
public static final String OPTIONAL_ELEMENT = "optional";
private Feature() {
private final boolean optional;
public Feature(boolean optional) {
this.optional = optional;
}
public boolean isOptional() {
return optional;
}
@Override
@ -60,8 +69,16 @@ public class Session extends SimpleIQ {
}
@Override
public String toXML() {
return SESSION;
public XmlStringBuilder toXML() {
XmlStringBuilder xml = new XmlStringBuilder(this);
if (optional) {
xml.rightAngleBracket();
xml.emptyElement(OPTIONAL_ELEMENT);
xml.closeElement(this);
} else {
xml.closeEmptyElement();
}
return xml;
}
}
}

View File

@ -39,6 +39,7 @@ import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Session;
import org.jivesoftware.smack.packet.StartTls;
import org.jivesoftware.smack.packet.StreamError;
import org.jivesoftware.smack.packet.XMPPError;
@ -982,6 +983,32 @@ public class PacketParserUtils {
return new StartTls(required);
}
public static Session.Feature parseSessionFeature(XmlPullParser parser) throws XmlPullParserException, IOException {
ParserUtils.assertAtStartTag(parser);
final int initialDepth = parser.getDepth();
boolean optional = false;
if (!parser.isEmptyElementTag()) {
outerloop: while(true) {
int event = parser.next();
switch (event) {
case XmlPullParser.START_TAG:
String name = parser.getName();
switch (name) {
case Session.Feature.OPTIONAL_ELEMENT:
optional = true;
break;
}
break;
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
}
}
}
return new Session.Feature(optional);
}
private static String getLanguageAttribute(XmlPullParser parser) {
for (int i = 0; i < parser.getAttributeCount(); i++) {
String attributeName = parser.getAttributeName(i);