diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index caad497b2..b95e1d1ad 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -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)) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java index 2b2ac49ed..4ce84dba2 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java @@ -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.

* @@ -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; } } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java index 288af9192..cf79cbc41 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java @@ -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);