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 530bf7b11..fa76f780d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -2243,7 +2243,10 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { StreamOpen streamOpen = new StreamOpen(to, from, id, config.getXmlLang(), StreamOpen.StreamContentNamespace.client); sendNonza(streamOpen); + updateOutgoingStreamXmlEnvironmentOnStreamOpen(streamOpen); + } + protected void updateOutgoingStreamXmlEnvironmentOnStreamOpen(StreamOpen streamOpen) { XmlEnvironment.Builder xmlEnvironmentBuilder = XmlEnvironment.builder(); xmlEnvironmentBuilder.with(streamOpen); outgoingStreamXmlEnvironment = xmlEnvironmentBuilder.build(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java index 5bc020c46..25351cc45 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java @@ -68,6 +68,7 @@ import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StreamClose; import org.jivesoftware.smack.packet.StreamError; +import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.TopLevelStreamElement; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.parsing.SmackParsingException; @@ -81,7 +82,9 @@ import org.jivesoftware.smack.util.Supplier; import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.parts.Resourcepart; +import org.jxmpp.util.XmppStringUtils; public final class ModularXmppClientToServerConnection extends AbstractXMPPConnection { @@ -560,10 +563,26 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne protected void newStreamOpenWaitForFeaturesSequence(String waitFor) throws InterruptedException, SmackException, XMPPException { prepareToWaitForFeaturesReceived(); - sendStreamOpen(); + + // Create StreamOpen from StreamOpenAndCloseFactory via underlying transport. + StreamOpenAndCloseFactory streamOpenAndCloseFactory = activeTransport.getStreamOpenAndCloseFactory(); + CharSequence from = null; + CharSequence localpart = connectionInternal.connection.getConfiguration().getUsername(); + DomainBareJid xmppServiceDomain = getXMPPServiceDomain(); + if (localpart != null) { + from = XmppStringUtils.completeJidFrom(localpart, xmppServiceDomain); + } + StreamOpen streamOpen = streamOpenAndCloseFactory.createStreamOpen(xmppServiceDomain, from, getStreamId(), getConfiguration().getXmlLang()); + sendStreamOpen(streamOpen); + waitForFeaturesReceived(waitFor); } + private void sendStreamOpen(StreamOpen streamOpen) throws NotConnectedException, InterruptedException { + sendNonza(streamOpen); + updateOutgoingStreamXmlEnvironmentOnStreamOpen(streamOpen); + } + public static class DisconnectedStateDescriptor extends StateDescriptor { protected DisconnectedStateDescriptor() { super(DisconnectedState.class, StateDescriptor.Property.finalState); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/c2s/StreamOpenAndCloseFactory.java b/smack-core/src/main/java/org/jivesoftware/smack/c2s/StreamOpenAndCloseFactory.java new file mode 100644 index 000000000..250fedfce --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/c2s/StreamOpenAndCloseFactory.java @@ -0,0 +1,26 @@ +/** + * + * Copyright 2020 Aditya Borikar. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.c2s; + +import org.jivesoftware.smack.packet.StreamClose; +import org.jivesoftware.smack.packet.StreamOpen; + +public interface StreamOpenAndCloseFactory { + StreamOpen createStreamOpen(CharSequence to, CharSequence from, String id, String lang); + + StreamClose createStreamClose(); +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/c2s/XmppClientToServerTransport.java b/smack-core/src/main/java/org/jivesoftware/smack/c2s/XmppClientToServerTransport.java index d68440fc3..4bedb51b6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/c2s/XmppClientToServerTransport.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/c2s/XmppClientToServerTransport.java @@ -58,6 +58,8 @@ public abstract class XmppClientToServerTransport { return getSslSession() != null; } + public abstract StreamOpenAndCloseFactory getStreamOpenAndCloseFactory(); + public abstract Stats getStats(); public abstract static class Stats { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractStreamClose.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractStreamClose.java new file mode 100644 index 000000000..c938c7e9e --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractStreamClose.java @@ -0,0 +1,20 @@ +/** + * + * Copyright 2020 Aditya Borikar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.packet; + +public abstract class AbstractStreamClose implements Nonza { +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractStreamOpen.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractStreamOpen.java new file mode 100644 index 000000000..36f0dc760 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractStreamOpen.java @@ -0,0 +1,79 @@ +/** + * + * Copyright 2020 Aditya Borikar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smack.packet; + +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.packet.StreamOpen.StreamContentNamespace; +import org.jivesoftware.smack.util.StringUtils; + +/** + * AbstractStreamOpen is actually a {@link TopLevelStreamElement}, however we + * implement {@link Nonza} here. This is because, {@link XMPPConnection} doesn't + * yet support sending {@link TopLevelStreamElement} directly and the same can only + * be achieved through {@link XMPPConnection#sendNonza(Nonza)}. + */ +public abstract class AbstractStreamOpen implements Nonza { + public static final String CLIENT_NAMESPACE = "jabber:client"; + public static final String SERVER_NAMESPACE = "jabber:server"; + + /** + * RFC 6120 § 4.7.5. + */ + public static final String VERSION = "1.0"; + + /** + * RFC 6120 § 4.7.1. + */ + protected final String from; + + /** + * RFC 6120 § 4.7.2. + */ + protected final String to; + + /** + * RFC 6120 § 4.7.3. + */ + protected final String id; + + /** + * RFC 6120 § 4.7.4. + */ + protected final String lang; + + /** + * RFC 6120 § 4.8.2. + */ + protected final String contentNamespace; + + public AbstractStreamOpen(CharSequence to, CharSequence from, String id, String lang, StreamContentNamespace ns) { + this.to = StringUtils.maybeToString(to); + this.from = StringUtils.maybeToString(from); + this.id = id; + this.lang = lang; + switch (ns) { + case client: + this.contentNamespace = CLIENT_NAMESPACE; + break; + case server: + this.contentNamespace = SERVER_NAMESPACE; + break; + default: + throw new IllegalStateException(); + } + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamClose.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamClose.java index 377e6c616..fd284a2e5 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamClose.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamClose.java @@ -16,7 +16,7 @@ */ package org.jivesoftware.smack.packet; -public final class StreamClose implements Nonza { +public final class StreamClose extends AbstractStreamClose { public static final StreamClose INSTANCE = new StreamClose(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamOpen.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamOpen.java index 6ef368b63..f4b59db4b 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamOpen.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamOpen.java @@ -17,49 +17,14 @@ package org.jivesoftware.smack.packet; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.XmlStringBuilder; /** * The stream open tag. */ -public class StreamOpen implements Nonza { - +public final class StreamOpen extends AbstractStreamOpen { public static final String ELEMENT = "stream:stream"; - public static final String CLIENT_NAMESPACE = "jabber:client"; - public static final String SERVER_NAMESPACE = "jabber:server"; - - /** - * RFC 6120 § 4.7.5. - */ - public static final String VERSION = "1.0"; - - /** - * RFC 6120 § 4.7.1. - */ - private final String from; - - /** - * RFC 6120 § 4.7.2. - */ - private final String to; - - /** - * RFC 6120 § 4.7.3. - */ - private final String id; - - /** - * RFC 6120 § 4.7.4. - */ - private final String lang; - - /** - * RFC 6120 § 4.8.2. - */ - private final String contentNamespace; - public StreamOpen(CharSequence to) { this(to, null, null, null, StreamContentNamespace.client); } @@ -69,20 +34,7 @@ public class StreamOpen implements Nonza { } public StreamOpen(CharSequence to, CharSequence from, String id, String lang, StreamContentNamespace ns) { - this.to = StringUtils.maybeToString(to); - this.from = StringUtils.maybeToString(from); - this.id = id; - this.lang = lang; - switch (ns) { - case client: - this.contentNamespace = CLIENT_NAMESPACE; - break; - case server: - this.contentNamespace = SERVER_NAMESPACE; - break; - default: - throw new IllegalStateException(); - } + super(to, from, id, lang, ns); } @Override diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java index 946eb4a1a..ca003ca8d 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java @@ -58,6 +58,7 @@ import org.jivesoftware.smack.XmppInputOutputFilter; import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection.ConnectedButUnauthenticatedStateDescriptor; import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection.LookupRemoteConnectionEndpointsStateDescriptor; import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionModule; +import org.jivesoftware.smack.c2s.StreamOpenAndCloseFactory; import org.jivesoftware.smack.c2s.XmppClientToServerTransport; import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal; import org.jivesoftware.smack.c2s.internal.WalkStateGraphContext; @@ -68,6 +69,7 @@ import org.jivesoftware.smack.fsm.StateTransitionResult; import org.jivesoftware.smack.internal.SmackTlsContext; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StartTls; +import org.jivesoftware.smack.packet.StreamClose; import org.jivesoftware.smack.packet.StreamOpen; import org.jivesoftware.smack.packet.TlsFailure; import org.jivesoftware.smack.packet.TlsProceed; @@ -580,6 +582,22 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM super(connectionInternal); } + @Override + public StreamOpenAndCloseFactory getStreamOpenAndCloseFactory() { + return new StreamOpenAndCloseFactory() { + @Override + public StreamOpen createStreamOpen(CharSequence to, CharSequence from, String id, String lang) { + String xmlLang = connectionInternal.connection.getConfiguration().getXmlLang(); + StreamOpen streamOpen = new StreamOpen(to, from, id, xmlLang, StreamOpen.StreamContentNamespace.client); + return streamOpen; + } + @Override + public StreamClose createStreamClose() { + return StreamClose.INSTANCE; + } + }; + } + @Override protected void resetDiscoveredConnectionEndpoints() { discoveredTcpEndpoints = null;