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(); user = response.getJid();
serviceName = XmppStringUtils.parseDomain(user); 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(); Session session = new Session();
packetCollector = createPacketCollectorAndSend(new PacketIDFilter(session), session); packetCollector = createPacketCollectorAndSend(new PacketIDFilter(session), session);
packetCollector.nextResultOrThrow(); packetCollector.nextResultOrThrow();
@ -1137,7 +1140,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
streamFeature = Bind.Feature.INSTANCE; streamFeature = Bind.Feature.INSTANCE;
break; break;
case Session.ELEMENT: case Session.ELEMENT:
streamFeature = Session.Feature.INSTANCE; streamFeature = PacketParserUtils.parseSessionFeature(parser);
break; break;
case RosterVer.ELEMENT: case RosterVer.ELEMENT:
if(namespace.equals(RosterVer.NAMESPACE)) { if(namespace.equals(RosterVer.NAMESPACE)) {

View File

@ -17,6 +17,8 @@
package org.jivesoftware.smack.packet; 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> * 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 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 @Override
@ -60,8 +69,16 @@ public class Session extends SimpleIQ {
} }
@Override @Override
public String toXML() { public XmlStringBuilder toXML() {
return SESSION; 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.Packet;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Session;
import org.jivesoftware.smack.packet.StartTls; import org.jivesoftware.smack.packet.StartTls;
import org.jivesoftware.smack.packet.StreamError; import org.jivesoftware.smack.packet.StreamError;
import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.packet.XMPPError;
@ -982,6 +983,32 @@ public class PacketParserUtils {
return new StartTls(required); 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) { private static String getLanguageAttribute(XmlPullParser parser) {
for (int i = 0; i < parser.getAttributeCount(); i++) { for (int i = 0; i < parser.getAttributeCount(); i++) {
String attributeName = parser.getAttributeName(i); String attributeName = parser.getAttributeName(i);