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 358d65778..6854b8fc6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -42,6 +42,7 @@ import org.jivesoftware.smack.compression.XMPPInputOutputStream; import org.jivesoftware.smack.debugger.SmackDebugger; import org.jivesoftware.smack.filter.IQReplyFilter; import org.jivesoftware.smack.filter.PacketFilter; +import org.jivesoftware.smack.filter.PacketIDFilter; import org.jivesoftware.smack.packet.Bind; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Packet; @@ -431,15 +432,30 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } } - Bind bindResource = new Bind(); - bindResource.setResource(resource); - - Bind response = (Bind) createPacketCollectorAndSend(bindResource).nextResultOrThrow(); + // Resource binding, see RFC6120 7. + // Note that we can not use IQReplyFilter here, since the users full JID is not yet + // available. It will become available right after the resource has been successfully bound. + Bind bindResource = Bind.newSet(resource); + PacketCollector packetCollector = createPacketCollector(new PacketIDFilter(bindResource)); + try { + sendPacket(bindResource); + } catch (NotConnectedException e) { + packetCollector.cancel(); + throw e; + } + Bind response = packetCollector.nextResultOrThrow(); String userJID = response.getJid(); if (sessionSupported && !getConfiguration().isLegacySessionDisabled()) { Session session = new Session(); - createPacketCollectorAndSend(session).nextResultOrThrow(); + packetCollector = createPacketCollector(new PacketIDFilter(session)); + try { + sendPacket(session); + } catch (NotConnectedException e) { + packetCollector.cancel(); + throw e; + } + packetCollector.nextResultOrThrow(); } return userJID; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/PacketCollector.java b/smack-core/src/main/java/org/jivesoftware/smack/PacketCollector.java index d402f6db0..fd952d687 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/PacketCollector.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/PacketCollector.java @@ -139,9 +139,10 @@ public class PacketCollector { * * @return the next available packet. */ - public Packet nextResult(long timeout) { + @SuppressWarnings("unchecked") + public

P nextResult(long timeout) { try { - return resultQueue.poll(timeout, TimeUnit.MILLISECONDS); + return (P) resultQueue.poll(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new RuntimeException(e); @@ -157,7 +158,7 @@ public class PacketCollector { * @throws XMPPErrorException in case an error response. * @throws NoResponseException if there was no response from the server. */ - public Packet nextResultOrThrow() throws NoResponseException, XMPPErrorException { + public

P nextResultOrThrow() throws NoResponseException, XMPPErrorException { return nextResultOrThrow(connection.getPacketReplyTimeout()); } @@ -170,8 +171,8 @@ public class PacketCollector { * @throws NoResponseException if there was no response from the server. * @throws XMPPErrorException in case an error response. */ - public Packet nextResultOrThrow(long timeout) throws NoResponseException, XMPPErrorException { - Packet result = nextResult(timeout); + public

P nextResultOrThrow(long timeout) throws NoResponseException, XMPPErrorException { + P result = nextResult(timeout); cancel(); if (result == null) { throw new NoResponseException(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/filter/IQReplyFilter.java b/smack-core/src/main/java/org/jivesoftware/smack/filter/IQReplyFilter.java index 124f38c90..3f7cb1127 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/filter/IQReplyFilter.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/filter/IQReplyFilter.java @@ -81,14 +81,13 @@ public class IQReplyFilter implements PacketFilter { * @param iqPacket An IQ request. Filter for replies to this packet. */ public IQReplyFilter(IQ iqPacket, XMPPConnection conn) { - to = iqPacket.getTo(); - if (conn.getUser() == null) { - // We have not yet been assigned a username, this can happen if the connection is - // in an early stage, i.e. when performing the SASL auth. - local = null; + if (iqPacket.getTo() != null) { + to = iqPacket.getTo().toLowerCase(Locale.US); } else { - local = conn.getUser().toLowerCase(Locale.US); + to = null; } + local = conn.getUser().toLowerCase(Locale.US); + server = conn.getServiceName().toLowerCase(Locale.US); packetId = iqPacket.getPacketID(); @@ -98,11 +97,10 @@ public class IQReplyFilter implements PacketFilter { fromFilter = new OrFilter(); fromFilter.addFilter(FromMatchesFilter.createFull(to)); if (to == null) { - if (local != null) - fromFilter.addFilter(FromMatchesFilter.createBare(local)); + fromFilter.addFilter(FromMatchesFilter.createBare(local)); fromFilter.addFilter(FromMatchesFilter.createFull(server)); } - else if (local != null && to.toLowerCase(Locale.US).equals(XmppStringUtils.parseBareAddress(local))) { + else if (to.equals(XmppStringUtils.parseBareAddress(local))) { fromFilter.addFilter(FromMatchesFilter.createFull(null)); } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java index 3c0546d5b..f9a9b4f71 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java @@ -32,39 +32,44 @@ import org.jivesoftware.smack.util.XmlStringBuilder; */ public class Bind extends IQ { - private String resource = null; - private String jid = null; + public static final String ELEMENT = "bind"; + public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-bind"; - public Bind() { - setType(IQ.Type.set); + private final String resource; + private final String jid; + + public Bind(String resource, String jid) { + this.resource = resource; + this.jid = null; } public String getResource() { return resource; } - public void setResource(String resource) { - this.resource = resource; - } - public String getJid() { return jid; } - public void setJid(String jid) { - this.jid = jid; - } - @Override - public CharSequence getChildElementXML() { + public XmlStringBuilder getChildElementXML() { XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement("bind"); - xml.xmlnsAttribute("urn:ietf:params:xml:ns:xmpp-bind"); - xml.rightAngelBracket(); + + xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngelBracket(); xml.optElement("resource", resource); xml.optElement("jid", jid); - xml.closeElement("bind"); + xml.closeElement(ELEMENT); return xml; } + + public static Bind newSet(String resource) { + Bind bind = new Bind(resource, null); + bind.setType(IQ.Type.set); + return bind; + } + + public static Bind newResult(String jid) { + return new Bind(null, jid); + } } 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 882292650..d7d8ea535 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 @@ -654,24 +654,23 @@ public class PacketParserUtils { private static Bind parseResourceBinding(XmlPullParser parser) throws IOException, XmlPullParserException { - Bind bind = new Bind(); + Bind bind = null; boolean done = false; while (!done) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG) { if (parser.getName().equals("resource")) { - bind.setResource(parser.nextText()); + bind = Bind.newSet(parser.nextText()); } else if (parser.getName().equals("jid")) { - bind.setJid(parser.nextText()); + bind = Bind.newResult(parser.nextText()); } } else if (eventType == XmlPullParser.END_TAG) { - if (parser.getName().equals("bind")) { + if (parser.getName().equals(Bind.ELEMENT)) { done = true; } } } - return bind; }