Smack/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java

623 lines
23 KiB
Java
Raw Permalink Normal View History

2014-02-19 20:06:30 +01:00
/**
*
* Copyright 2009 Jive Software.
*
* 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.bosh;
2014-02-19 20:06:30 +01:00
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
2014-02-19 20:06:30 +01:00
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.GenericConnectionException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
2022-06-02 15:55:24 +02:00
import org.jivesoftware.smack.SmackException.OutgoingQueueFullException;
import org.jivesoftware.smack.SmackException.SmackWrappedException;
2014-03-10 09:45:50 +01:00
import org.jivesoftware.smack.XMPPConnection;
2014-02-19 20:06:30 +01:00
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.StreamErrorException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
2014-02-19 20:06:30 +01:00
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaError;
2022-06-02 15:55:24 +02:00
import org.jivesoftware.smack.packet.TopLevelStreamElement;
import org.jivesoftware.smack.util.ArrayBlockingQueueWithShutdown;
import org.jivesoftware.smack.util.Async;
2018-08-15 17:25:22 +02:00
import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.igniterealtime.jbosh.AbstractBody;
2014-02-19 20:06:30 +01:00
import org.igniterealtime.jbosh.BOSHClient;
import org.igniterealtime.jbosh.BOSHClientConfig;
import org.igniterealtime.jbosh.BOSHClientConnEvent;
import org.igniterealtime.jbosh.BOSHClientConnListener;
import org.igniterealtime.jbosh.BOSHClientRequestListener;
import org.igniterealtime.jbosh.BOSHClientResponseListener;
import org.igniterealtime.jbosh.BOSHException;
import org.igniterealtime.jbosh.BOSHMessageEvent;
import org.igniterealtime.jbosh.BodyQName;
import org.igniterealtime.jbosh.ComposableBody;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.parts.Resourcepart;
2014-02-19 20:06:30 +01:00
/**
2015-02-12 12:13:19 +01:00
* Creates a connection to an XMPP server via HTTP binding.
2014-02-19 20:06:30 +01:00
* This is specified in the XEP-0206: XMPP Over BOSH.
*
2014-03-10 09:45:50 +01:00
* @see XMPPConnection
2014-02-19 20:06:30 +01:00
* @author Guenther Niess
*/
public class XMPPBOSHConnection extends AbstractXMPPConnection {
private static final Logger LOGGER = Logger.getLogger(XMPPBOSHConnection.class.getName());
2014-02-19 20:06:30 +01:00
/**
* The XMPP Over Bosh namespace.
*/
public static final String XMPP_BOSH_NS = "urn:xmpp:xbosh";
/**
* The BOSH namespace from XEP-0124.
*/
public static final String BOSH_URI = "http://jabber.org/protocol/httpbind";
/**
* The used BOSH client from the jbosh library.
*/
private BOSHClient client;
/**
* Holds the initial configuration used while creating the connection.
*/
2018-03-28 15:56:04 +02:00
@SuppressWarnings("HidingField")
2014-02-19 20:06:30 +01:00
private final BOSHConfiguration config;
2022-06-02 15:55:24 +02:00
private final ArrayBlockingQueueWithShutdown<TopLevelStreamElement> outgoingQueue = new ArrayBlockingQueueWithShutdown<>(100, true);
private Thread writerThread;
2014-02-19 20:06:30 +01:00
// Some flags which provides some info about the current state.
private boolean isFirstInitialization = true;
private boolean done = false;
// The readerPipe and consumer thread are used for the debugger.
private PipedWriter readerPipe;
private Thread readerConsumer;
/**
* The session ID for the BOSH session with the connection manager.
*/
protected String sessionID = null;
private boolean notified;
2014-02-19 20:06:30 +01:00
/**
2015-02-12 12:13:19 +01:00
* Create a HTTP Binding connection to an XMPP server.
*
* @param username the username to use.
* @param password the password to use.
2014-02-19 20:06:30 +01:00
* @param https true if you want to use SSL
* (e.g. false for http://domain.lt:7070/http-bind).
* @param host the hostname or IP address of the connection manager
* (e.g. domain.lt for http://domain.lt:7070/http-bind).
* @param port the port of the connection manager
* (e.g. 7070 for http://domain.lt:7070/http-bind).
* @param filePath the file which is described by the URL
* (e.g. /http-bind for http://domain.lt:7070/http-bind).
* @param xmppServiceDomain the XMPP service name
2014-02-19 20:06:30 +01:00
* (e.g. domain.lt for the user alice@domain.lt)
*/
public XMPPBOSHConnection(String username, String password, boolean https, String host, int port, String filePath, DomainBareJid xmppServiceDomain) {
this(BOSHConfiguration.builder().setUseHttps(https).setHost(host)
.setPort(port).setFile(filePath).setXmppDomain(xmppServiceDomain)
.setUsernameAndPassword(username, password).build());
2014-02-19 20:06:30 +01:00
}
/**
2015-02-12 12:13:19 +01:00
* Create a HTTP Binding connection to an XMPP server.
*
2014-02-19 20:06:30 +01:00
* @param config The configuration which is used for this connection.
*/
public XMPPBOSHConnection(BOSHConfiguration config) {
2014-02-19 20:06:30 +01:00
super(config);
this.config = config;
}
@SuppressWarnings("deprecation")
@Override
protected void connectInternal() throws SmackException, InterruptedException {
2014-02-19 20:06:30 +01:00
done = false;
notified = false;
2014-02-19 20:06:30 +01:00
try {
// Ensure a clean starting state
if (client != null) {
client.close();
client = null;
}
sessionID = null;
// Initialize BOSH client
BOSHClientConfig.Builder cfgBuilder = BOSHClientConfig.Builder
.create(config.getURI(), config.getXMPPServiceDomain().toString());
2014-02-19 20:06:30 +01:00
if (config.isProxyEnabled()) {
cfgBuilder.setProxy(config.getProxyAddress(), config.getProxyPort());
}
2019-03-22 21:56:15 +01:00
cfgBuilder.setCompressionEnabled(config.isCompressionEnabled());
for (Map.Entry<String, String> h : config.getHttpHeaders().entrySet()) {
cfgBuilder.addHttpHeader(h.getKey(), h.getValue());
}
2019-03-22 21:56:15 +01:00
2014-02-19 20:06:30 +01:00
client = BOSHClient.create(cfgBuilder.build());
[bosh] Fix BOSH debug send message not shown Following logcat are captured with various PR fixes implemented: // ===== Without any of the PR fixes ===== // All the sent stanza are missing; fixed by ``` // Fix all BOSH sent debug messages not shown writer.flush(); ``` ``` 2023-12-11 12:25:33.548 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='4867162268865181478' xmlns='http://jabber.org/protocol/httpbind' sid='53e66759d21e128cc1cba8d00aacb7421f1ea960' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:25:33.748 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'/> 2023-12-11 12:25:33.925 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1DI2QjJHE7JVs6LzElInQnPDhaK3JLMTUzPCtPVicvXmNuV204ei9kV1UzT1lsdCtzRW1ZTkE9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:25:33.939 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1saEFrUzVKMFRBMEJVbTg1djd5dE4xTUpZaE09 </success> </body> ``` // ===== With only PR fixes: writer.flush(); readerConsumer = null; but withoug the following fixes ===== // // Initialize the debugger before addBOSHClientResponseListener(new BOSHPacketReader()); // BOSHPacketReader may hold and send response prior to display of the request i.e. \<response/> before \<challenge/> ``` 2023-12-11 12:33:54.915 6162-6310/org.atalk.android D/SMACK: SENT (0): <body ver='1.8' wait='60' xmpp:version='1.0' rid='6195788493952909' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.198 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='1477509259581416251' xmlns='http://jabber.org/protocol/httpbind' sid='796ae552c9fea53ff10a1979429396d19745d430' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:33:55.301 6162-6310/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952910' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPUJwMTZzKG9dd0xmb1lnN0haRkAjKko7PiReIXhbKiou </auth> </body> 2023-12-11 12:33:55.534 6162-6313/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952911' ack='6195788493952909' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxwPVZlT3pkVzExN0tMc3k4THZpQWJZWDlpcW84az0= </response> </body> 2023-12-11 12:33:55.538 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:33:55.558 6162-6310/org.atalk.android D/SMACK: SENT (0): <body xmpp:restart='true' rid='6195788493952912' xmlns:xmpp='urn:xmpp:xbosh' sid='796ae552c9fea53ff10a1979429396d19745d430' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.560 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1mcFdSekE1SXltdTBrNys4K1hML3JncTVEd2s9 </success> </body> ``` // ===== With the full PR fixes ===== // ``` 2023-12-11 12:21:16.435 4703-5344/org.atalk.android D/SMACK: SENT (4): <body ver='1.8' wait='60' xmpp:version='1.0' rid='949729322134413' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:21:16.637 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmpp:version='1.0' authid='1761920914298566866' xmlns='http://jabber.org/protocol/httpbind' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:21:16.667 4703-5344/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134414' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPTdiSVxeVnVMU0ZoWT8zVVlSa2psdkVMeks/e3BaQUwp </auth> </body> 2023-12-11 12:21:16.683 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:21:16.689 4703-5347/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134415' ack='949729322134413' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxwPXdNb2c5N3UzQktON1FHaFVQRzQ3MHVjZXdldz0= </response> </body> 2023-12-11 12:21:16.702 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj0yTzRqVzJXWHdEUDdvNjdJSkdNU3Rmc0NMTkk9 </success> </body> 2023-12-11 12:21:16.704 4703-5344/org.atalk.android D/SMACK: SENT (4): <body xmpp:restart='true' rid='949729322134416' xmlns:xmpp='urn:xmpp:xbosh' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> ``` Link: https://github.com/igniterealtime/Smack/pull/554
2023-02-20 02:49:10 +01:00
// Initialize the debugger before addBOSHClientResponseListener(new BOSHPacketReader());
// BOSHPacketReader may hold and send response prior to display of the request i.e. <response/> before <challenge/>
if (debugger != null) {
2014-02-19 20:06:30 +01:00
initDebugger();
}
[bosh] Fix BOSH debug send message not shown Following logcat are captured with various PR fixes implemented: // ===== Without any of the PR fixes ===== // All the sent stanza are missing; fixed by ``` // Fix all BOSH sent debug messages not shown writer.flush(); ``` ``` 2023-12-11 12:25:33.548 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='4867162268865181478' xmlns='http://jabber.org/protocol/httpbind' sid='53e66759d21e128cc1cba8d00aacb7421f1ea960' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:25:33.748 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'/> 2023-12-11 12:25:33.925 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1DI2QjJHE7JVs6LzElInQnPDhaK3JLMTUzPCtPVicvXmNuV204ei9kV1UzT1lsdCtzRW1ZTkE9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:25:33.939 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1saEFrUzVKMFRBMEJVbTg1djd5dE4xTUpZaE09 </success> </body> ``` // ===== With only PR fixes: writer.flush(); readerConsumer = null; but withoug the following fixes ===== // // Initialize the debugger before addBOSHClientResponseListener(new BOSHPacketReader()); // BOSHPacketReader may hold and send response prior to display of the request i.e. \<response/> before \<challenge/> ``` 2023-12-11 12:33:54.915 6162-6310/org.atalk.android D/SMACK: SENT (0): <body ver='1.8' wait='60' xmpp:version='1.0' rid='6195788493952909' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.198 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='1477509259581416251' xmlns='http://jabber.org/protocol/httpbind' sid='796ae552c9fea53ff10a1979429396d19745d430' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:33:55.301 6162-6310/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952910' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPUJwMTZzKG9dd0xmb1lnN0haRkAjKko7PiReIXhbKiou </auth> </body> 2023-12-11 12:33:55.534 6162-6313/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952911' ack='6195788493952909' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxwPVZlT3pkVzExN0tMc3k4THZpQWJZWDlpcW84az0= </response> </body> 2023-12-11 12:33:55.538 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:33:55.558 6162-6310/org.atalk.android D/SMACK: SENT (0): <body xmpp:restart='true' rid='6195788493952912' xmlns:xmpp='urn:xmpp:xbosh' sid='796ae552c9fea53ff10a1979429396d19745d430' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.560 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1mcFdSekE1SXltdTBrNys4K1hML3JncTVEd2s9 </success> </body> ``` // ===== With the full PR fixes ===== // ``` 2023-12-11 12:21:16.435 4703-5344/org.atalk.android D/SMACK: SENT (4): <body ver='1.8' wait='60' xmpp:version='1.0' rid='949729322134413' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:21:16.637 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmpp:version='1.0' authid='1761920914298566866' xmlns='http://jabber.org/protocol/httpbind' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:21:16.667 4703-5344/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134414' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPTdiSVxeVnVMU0ZoWT8zVVlSa2psdkVMeks/e3BaQUwp </auth> </body> 2023-12-11 12:21:16.683 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:21:16.689 4703-5347/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134415' ack='949729322134413' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxwPXdNb2c5N3UzQktON1FHaFVQRzQ3MHVjZXdldz0= </response> </body> 2023-12-11 12:21:16.702 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj0yTzRqVzJXWHdEUDdvNjdJSkdNU3Rmc0NMTkk9 </success> </body> 2023-12-11 12:21:16.704 4703-5344/org.atalk.android D/SMACK: SENT (4): <body xmpp:restart='true' rid='949729322134416' xmlns:xmpp='urn:xmpp:xbosh' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> ``` Link: https://github.com/igniterealtime/Smack/pull/554
2023-02-20 02:49:10 +01:00
client.addBOSHClientConnListener(new BOSHConnectionListener());
client.addBOSHClientResponseListener(new BOSHPacketReader());
2014-02-19 20:06:30 +01:00
// Send the session creation request
client.send(ComposableBody.builder()
.setNamespaceDefinition("xmpp", XMPP_BOSH_NS)
.setAttribute(BodyQName.createWithPrefix(XMPP_BOSH_NS, "version", "xmpp"), "1.0")
.build());
} catch (Exception e) {
throw new GenericConnectionException(e);
2014-02-19 20:06:30 +01:00
}
// Wait for the response from the server
synchronized (this) {
if (!connected) {
final long deadline = System.currentTimeMillis() + getReplyTimeout();
while (!notified) {
final long now = System.currentTimeMillis();
if (now >= deadline) break;
wait(deadline - now);
2014-02-19 20:06:30 +01:00
}
}
}
2022-06-02 15:55:24 +02:00
assert writerThread == null || !writerThread.isAlive();
outgoingQueue.start();
writerThread = Async.go(this::writeElements, this + " Writer");
2014-02-19 20:06:30 +01:00
// If there is no feedback, throw an remote server timeout error
if (!connected && !done) {
done = true;
String errorMessage = "Timeout reached for the connection to "
2014-02-19 20:06:30 +01:00
+ getHost() + ":" + getPort() + ".";
2022-06-02 15:55:24 +02:00
instantShutdown();
2019-02-10 21:39:48 +01:00
throw new SmackException.SmackMessageException(errorMessage);
2014-02-19 20:06:30 +01:00
}
try {
XmlPullParser parser = PacketParserUtils.getParserFor(
"<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'/>");
onStreamOpen(parser);
} catch (XmlPullParserException | IOException e) {
2022-06-02 15:55:24 +02:00
instantShutdown();
throw new AssertionError("Failed to setup stream environment", e);
}
2014-02-19 20:06:30 +01:00
}
@Override
2014-02-19 20:06:30 +01:00
public boolean isSecureConnection() {
return config.isUsingHTTPS();
2014-02-19 20:06:30 +01:00
}
@Override
2014-02-19 20:06:30 +01:00
public boolean isUsingCompression() {
// TODO: Implement compression
return false;
}
@Override
protected void loginInternal(String username, String password, Resourcepart resource) throws XMPPException,
SmackException, IOException, InterruptedException {
// Authenticate using SASL
authenticate(username, password, config.getAuthzid(), null);
2014-02-19 20:06:30 +01:00
bindResourceAndEstablishSession(resource);
2014-02-19 20:06:30 +01:00
afterSuccessfulLogin(false);
2014-02-19 20:06:30 +01:00
}
2022-06-02 15:55:24 +02:00
private volatile boolean writerThreadRunning;
private void writeElements() {
writerThreadRunning = true;
try {
while (true) {
TopLevelStreamElement element;
try {
element = outgoingQueue.take();
} catch (InterruptedException e) {
LOGGER.log(Level.FINE,
"Writer thread exiting: Outgoing queue was shutdown as signalled by interrupted exception",
e);
return;
}
String xmlPayload = element.toXML(BOSH_URI).toString();
ComposableBody.Builder composableBodyBuilder = ComposableBody.builder().setPayloadXML(xmlPayload);
if (sessionID != null) {
BodyQName qName = BodyQName.create(BOSH_URI, "sid");
composableBodyBuilder.setAttribute(qName, sessionID);
}
ComposableBody composableBody = composableBodyBuilder.build();
try {
client.send(composableBody);
} catch (BOSHException e) {
LOGGER.log(Level.WARNING, this + " received BOSHException in writer thread, connection broke!", e);
// TODO: Signal the user that there was an unexpected exception.
return;
}
if (element instanceof Stanza) {
Stanza stanza = (Stanza) element;
firePacketSendingListeners(stanza);
}
}
} catch (Exception exception) {
LOGGER.log(Level.WARNING, "BOSH writer thread threw", exception);
} finally {
writerThreadRunning = false;
notifyWaitingThreads();
}
}
@Override
2022-06-02 15:55:24 +02:00
protected void sendInternal(TopLevelStreamElement element) throws NotConnectedException, InterruptedException {
throwNotConnectedExceptionIfAppropriate();
try {
2022-06-02 15:55:24 +02:00
outgoingQueue.put(element);
} catch (InterruptedException e) {
throwNotConnectedExceptionIfAppropriate();
// If the method above did not throw, then the sending thread was interrupted
throw e;
}
2022-06-02 15:55:24 +02:00
}
@Override
protected void sendNonBlockingInternal(TopLevelStreamElement element)
throws NotConnectedException, OutgoingQueueFullException {
throwNotConnectedExceptionIfAppropriate();
boolean enqueued = outgoingQueue.offer(element);
if (!enqueued) {
throwNotConnectedExceptionIfAppropriate();
throw new OutgoingQueueFullException();
2014-02-19 20:06:30 +01:00
}
}
@Override
public InetAddress getLocalAddress() {
return null;
}
@Override
protected void shutdown() {
2022-06-02 15:55:24 +02:00
instantShutdown();
}
@Override
public void instantShutdown() {
outgoingQueue.shutdown();
try {
boolean writerThreadTerminated = waitFor(() -> !writerThreadRunning);
if (!writerThreadTerminated) {
LOGGER.severe("Writer thread of " + this + " did not terminate timely");
}
} catch (InterruptedException e) {
LOGGER.log(Level.FINE, "Interrupted while waiting for writer thread to terminate", e);
}
if (client != null) {
try {
client.disconnect();
} catch (Exception e) {
LOGGER.log(Level.WARNING, "shutdown", e);
}
}
setWasAuthenticated();
2014-02-19 20:06:30 +01:00
sessionID = null;
done = true;
authenticated = false;
connected = false;
isFirstInitialization = false;
2022-06-02 15:55:24 +02:00
client = null;
2014-02-19 20:06:30 +01:00
// Close down the readers and writers.
2018-08-15 17:25:22 +02:00
CloseableUtil.maybeClose(readerPipe, LOGGER);
CloseableUtil.maybeClose(reader, LOGGER);
CloseableUtil.maybeClose(writer, LOGGER);
2014-02-19 20:06:30 +01:00
[bosh] Fix BOSH debug send message not shown Following logcat are captured with various PR fixes implemented: // ===== Without any of the PR fixes ===== // All the sent stanza are missing; fixed by ``` // Fix all BOSH sent debug messages not shown writer.flush(); ``` ``` 2023-12-11 12:25:33.548 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='4867162268865181478' xmlns='http://jabber.org/protocol/httpbind' sid='53e66759d21e128cc1cba8d00aacb7421f1ea960' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:25:33.748 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'/> 2023-12-11 12:25:33.925 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1DI2QjJHE7JVs6LzElInQnPDhaK3JLMTUzPCtPVicvXmNuV204ei9kV1UzT1lsdCtzRW1ZTkE9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:25:33.939 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1saEFrUzVKMFRBMEJVbTg1djd5dE4xTUpZaE09 </success> </body> ``` // ===== With only PR fixes: writer.flush(); readerConsumer = null; but withoug the following fixes ===== // // Initialize the debugger before addBOSHClientResponseListener(new BOSHPacketReader()); // BOSHPacketReader may hold and send response prior to display of the request i.e. \<response/> before \<challenge/> ``` 2023-12-11 12:33:54.915 6162-6310/org.atalk.android D/SMACK: SENT (0): <body ver='1.8' wait='60' xmpp:version='1.0' rid='6195788493952909' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.198 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='1477509259581416251' xmlns='http://jabber.org/protocol/httpbind' sid='796ae552c9fea53ff10a1979429396d19745d430' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:33:55.301 6162-6310/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952910' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPUJwMTZzKG9dd0xmb1lnN0haRkAjKko7PiReIXhbKiou </auth> </body> 2023-12-11 12:33:55.534 6162-6313/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952911' ack='6195788493952909' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxwPVZlT3pkVzExN0tMc3k4THZpQWJZWDlpcW84az0= </response> </body> 2023-12-11 12:33:55.538 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:33:55.558 6162-6310/org.atalk.android D/SMACK: SENT (0): <body xmpp:restart='true' rid='6195788493952912' xmlns:xmpp='urn:xmpp:xbosh' sid='796ae552c9fea53ff10a1979429396d19745d430' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.560 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1mcFdSekE1SXltdTBrNys4K1hML3JncTVEd2s9 </success> </body> ``` // ===== With the full PR fixes ===== // ``` 2023-12-11 12:21:16.435 4703-5344/org.atalk.android D/SMACK: SENT (4): <body ver='1.8' wait='60' xmpp:version='1.0' rid='949729322134413' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:21:16.637 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmpp:version='1.0' authid='1761920914298566866' xmlns='http://jabber.org/protocol/httpbind' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:21:16.667 4703-5344/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134414' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPTdiSVxeVnVMU0ZoWT8zVVlSa2psdkVMeks/e3BaQUwp </auth> </body> 2023-12-11 12:21:16.683 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:21:16.689 4703-5347/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134415' ack='949729322134413' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxwPXdNb2c5N3UzQktON1FHaFVQRzQ3MHVjZXdldz0= </response> </body> 2023-12-11 12:21:16.702 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj0yTzRqVzJXWHdEUDdvNjdJSkdNU3Rmc0NMTkk9 </success> </body> 2023-12-11 12:21:16.704 4703-5344/org.atalk.android D/SMACK: SENT (4): <body xmpp:restart='true' rid='949729322134416' xmlns:xmpp='urn:xmpp:xbosh' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> ``` Link: https://github.com/igniterealtime/Smack/pull/554
2023-02-20 02:49:10 +01:00
// set readerConsumer = null before reader to avoid NPE reference
readerConsumer = null;
2018-08-15 17:25:22 +02:00
readerPipe = null;
reader = null;
writer = null;
2014-02-19 20:06:30 +01:00
}
/**
* Send a HTTP request to the connection manager with the provided body element.
*
2014-02-19 20:06:30 +01:00
* @param body the body which will be sent.
* @throws BOSHException if an BOSH (Bidirectional-streams Over Synchronous HTTP, XEP-0124) related error occurs
2014-02-19 20:06:30 +01:00
*/
protected void send(ComposableBody body) throws BOSHException {
if (!connected) {
throw new IllegalStateException("Not connected to a server!");
}
if (body == null) {
throw new NullPointerException("Body mustn't be null!");
}
if (sessionID != null) {
body = body.rebuild().setAttribute(
BodyQName.create(BOSH_URI, "sid"), sessionID).build();
}
client.send(body);
}
/**
* Initialize the SmackDebugger which allows to log and debug XML traffic.
*/
@Override
2014-02-19 20:06:30 +01:00
protected void initDebugger() {
// TODO: Maybe we want to extend the SmackDebugger for simplification
// and a performance boost.
// Initialize a empty writer which discards all data.
writer = new Writer() {
@Override
public void write(char[] cbuf, int off, int len) {
/* ignore */ }
@Override
public void close() {
/* ignore */ }
@Override
public void flush() {
/* ignore */ }
};
2014-02-19 20:06:30 +01:00
// Initialize a pipe for received raw data.
try {
readerPipe = new PipedWriter();
reader = new PipedReader(readerPipe);
}
catch (IOException e) {
// Ignore
}
// Call the method from the parent class which initializes the debugger.
super.initDebugger();
// Add listeners for the received and sent raw data.
client.addBOSHClientResponseListener(new BOSHClientResponseListener() {
@Override
2014-02-19 20:06:30 +01:00
public void responseReceived(BOSHMessageEvent event) {
if (event.getBody() != null) {
try {
readerPipe.write(event.getBody().toXML());
readerPipe.flush();
} catch (Exception e) {
// Ignore
}
}
}
});
client.addBOSHClientRequestListener(new BOSHClientRequestListener() {
@Override
2014-02-19 20:06:30 +01:00
public void requestSent(BOSHMessageEvent event) {
if (event.getBody() != null) {
try {
writer.write(event.getBody().toXML());
[bosh] Fix BOSH debug send message not shown Following logcat are captured with various PR fixes implemented: // ===== Without any of the PR fixes ===== // All the sent stanza are missing; fixed by ``` // Fix all BOSH sent debug messages not shown writer.flush(); ``` ``` 2023-12-11 12:25:33.548 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='4867162268865181478' xmlns='http://jabber.org/protocol/httpbind' sid='53e66759d21e128cc1cba8d00aacb7421f1ea960' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:25:33.748 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'/> 2023-12-11 12:25:33.925 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1DI2QjJHE7JVs6LzElInQnPDhaK3JLMTUzPCtPVicvXmNuV204ei9kV1UzT1lsdCtzRW1ZTkE9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:25:33.939 5470-5636/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1saEFrUzVKMFRBMEJVbTg1djd5dE4xTUpZaE09 </success> </body> ``` // ===== With only PR fixes: writer.flush(); readerConsumer = null; but withoug the following fixes ===== // // Initialize the debugger before addBOSHClientResponseListener(new BOSHPacketReader()); // BOSHPacketReader may hold and send response prior to display of the request i.e. \<response/> before \<challenge/> ``` 2023-12-11 12:33:54.915 6162-6310/org.atalk.android D/SMACK: SENT (0): <body ver='1.8' wait='60' xmpp:version='1.0' rid='6195788493952909' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.198 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmpp:version='1.0' authid='1477509259581416251' xmlns='http://jabber.org/protocol/httpbind' sid='796ae552c9fea53ff10a1979429396d19745d430' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:33:55.301 6162-6310/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952910' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPUJwMTZzKG9dd0xmb1lnN0haRkAjKko7PiReIXhbKiou </auth> </body> 2023-12-11 12:33:55.534 6162-6313/org.atalk.android D/SMACK: SENT (0): <body rid='6195788493952911' ack='6195788493952909' sid='796ae552c9fea53ff10a1979429396d19745d430' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxwPVZlT3pkVzExN0tMc3k4THZpQWJZWDlpcW84az0= </response> </body> 2023-12-11 12:33:55.538 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj1CcDE2cyhvXXdMZm9ZZzdIWkZAIypKOz4kXiF4WyoqLlV4eTcvUVBCQUNKbjg1TWdRZHhjQnc9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:33:55.558 6162-6310/org.atalk.android D/SMACK: SENT (0): <body xmpp:restart='true' rid='6195788493952912' xmlns:xmpp='urn:xmpp:xbosh' sid='796ae552c9fea53ff10a1979429396d19745d430' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:33:55.560 6162-6314/org.atalk.android D/SMACK: RECV (0): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1mcFdSekE1SXltdTBrNys4K1hML3JncTVEd2s9 </success> </body> ``` // ===== With the full PR fixes ===== // ``` 2023-12-11 12:21:16.435 4703-5344/org.atalk.android D/SMACK: SENT (4): <body ver='1.8' wait='60' xmpp:version='1.0' rid='949729322134413' xmlns:xmpp='urn:xmpp:xbosh' hold='1' xml:lang='en' ack='1' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> 2023-12-11 12:21:16.637 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmpp:version='1.0' authid='1761920914298566866' xmlns='http://jabber.org/protocol/httpbind' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' wait='60' ver='1.11' polling='2' inactivity='30' hold='1' xmpp:restartlogic='true' requests='2' secure='true' maxpause='120' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism> PLAIN </mechanism> <mechanism> SCRAM-SHA-1 </mechanism> <mechanism> X-OAUTH2 </mechanism> </mechanisms> <register xmlns='http://jabber.org/features/iq-register'/> </stream:features> </body> 2023-12-11 12:21:16.667 4703-5344/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134414' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'> bixhPXN3YW5AYXRhbGsuc3l0ZXMubmV0LG49c3dhbixyPTdiSVxeVnVMU0ZoWT8zVVlSa2psdkVMeks/e3BaQUwp </auth> </body> 2023-12-11 12:21:16.683 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> cj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxzPTdjNktCSnNaTHdTYjNZSytqdVRXb2c9PSxpPTQwOTY= </challenge> </body> 2023-12-11 12:21:16.689 4703-5347/org.atalk.android D/SMACK: SENT (4): <body rid='949729322134415' ack='949729322134413' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' xmlns='http://jabber.org/protocol/httpbind'> <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> Yz1iaXhoUFhOM1lXNUFZWFJoYkdzdWMzbDBaWE11Ym1WMExBPT0scj03YklcXlZ1TFNGaFk/M1VZUmtqbHZFTHpLP3twWkFMKUhqVjVlVFUvdzJFaW9yQjlGdHh3T3c9PSxwPXdNb2c5N3UzQktON1FHaFVQRzQ3MHVjZXdldz0= </response> </body> 2023-12-11 12:21:16.702 4703-5348/org.atalk.android D/SMACK: RECV (4): <body xmlns='http://jabber.org/protocol/httpbind'> <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj0yTzRqVzJXWHdEUDdvNjdJSkdNU3Rmc0NMTkk9 </success> </body> 2023-12-11 12:21:16.704 4703-5344/org.atalk.android D/SMACK: SENT (4): <body xmpp:restart='true' rid='949729322134416' xmlns:xmpp='urn:xmpp:xbosh' sid='25ba67c4b943796418a2b7c064085327ab9c35ac' to='atalk.sytes.net' xmlns='http://jabber.org/protocol/httpbind'> </body> ``` Link: https://github.com/igniterealtime/Smack/pull/554
2023-02-20 02:49:10 +01:00
// Fix all BOSH sent debug messages not shown
writer.flush();
2014-02-19 20:06:30 +01:00
} catch (Exception e) {
// Ignore
}
}
}
});
// Create and start a thread which discards all read data.
readerConsumer = new Thread() {
private Thread thread = this;
private int bufferLength = 1024;
@Override
2014-02-19 20:06:30 +01:00
public void run() {
try {
char[] cbuf = new char[bufferLength];
while (readerConsumer == thread && !done) {
reader.read(cbuf, 0, bufferLength);
}
} catch (IOException e) {
// Ignore
}
}
};
readerConsumer.setDaemon(true);
readerConsumer.start();
}
@Override
protected void afterSaslAuthenticationSuccess()
throws NotConnectedException, InterruptedException, SmackWrappedException {
// XMPP over BOSH is unusual when it comes to SASL authentication: Instead of sending a new stream open, it
// requires a special XML element ot be send after successful SASL authentication.
// See XEP-0206 § 5., especially the following is example 5 of XEP-0206.
2022-06-02 15:55:24 +02:00
ComposableBody composeableBody = ComposableBody.builder()
.setNamespaceDefinition("xmpp", XMPPBOSHConnection.XMPP_BOSH_NS)
.setAttribute(BodyQName.createWithPrefix(XMPPBOSHConnection.XMPP_BOSH_NS, "restart", "xmpp"), "true")
.setAttribute(BodyQName.create(XMPPBOSHConnection.BOSH_URI, "to"), getXMPPServiceDomain().toString())
.setAttribute(BodyQName.create(BOSH_URI, "sid"), sessionID)
.build();
try {
2022-06-02 15:55:24 +02:00
client.send(composeableBody);
} catch (BOSHException e) {
// jbosh's exception API does not really match the one of Smack.
throw new SmackException.SmackWrappedException(e);
}
}
2014-02-19 20:06:30 +01:00
/**
* A listener class which listen for a successfully established connection
* and connection errors and notifies the BOSHConnection.
*
2014-02-19 20:06:30 +01:00
* @author Guenther Niess
*/
private class BOSHConnectionListener implements BOSHClientConnListener {
/**
* Notify the BOSHConnection about connection state changes.
* Process the connection listeners and try to login if the
* connection was formerly authenticated and is now reconnected.
*/
@Override
2014-02-19 20:06:30 +01:00
public void connectionEvent(BOSHClientConnEvent connEvent) {
try {
if (connEvent.isConnected()) {
connected = true;
if (isFirstInitialization) {
isFirstInitialization = false;
}
else {
if (wasAuthenticated) {
try {
login();
}
catch (Exception e) {
throw new RuntimeException(e);
}
2014-02-19 20:06:30 +01:00
}
}
}
else {
if (connEvent.isError()) {
// TODO Check why jbosh's getCause returns Throwable here. This is very
// unusual and should be avoided if possible
Throwable cause = connEvent.getCause();
Exception e;
if (cause instanceof Exception) {
e = (Exception) cause;
} else {
e = new Exception(cause);
2014-02-19 20:06:30 +01:00
}
notifyConnectionError(e);
2014-02-19 20:06:30 +01:00
}
connected = false;
}
}
finally {
notified = true;
synchronized (XMPPBOSHConnection.this) {
XMPPBOSHConnection.this.notifyAll();
2014-02-19 20:06:30 +01:00
}
}
}
}
/**
* Listens for XML traffic from the BOSH connection manager and parses it into
2018-03-31 14:17:30 +02:00
* stanza objects.
*
* @author Guenther Niess
*/
private class BOSHPacketReader implements BOSHClientResponseListener {
/**
* Parse the received packets and notify the corresponding connection.
*
* @param event the BOSH client response which includes the received packet.
*/
@Override
public void responseReceived(BOSHMessageEvent event) {
AbstractBody body = event.getBody();
if (body != null) {
try {
if (sessionID == null) {
sessionID = body.getAttribute(BodyQName.create(XMPPBOSHConnection.BOSH_URI, "sid"));
}
if (streamId == null) {
streamId = body.getAttribute(BodyQName.create(XMPPBOSHConnection.BOSH_URI, "authid"));
}
final XmlPullParser parser = PacketParserUtils.getParserFor(body.toXML());
XmlPullParser.Event eventType = parser.getEventType();
do {
eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
String name = parser.getName();
switch (name) {
case Message.ELEMENT:
case IQ.IQ_ELEMENT:
case Presence.ELEMENT:
parseAndProcessStanza(parser);
break;
case "features":
parseFeaturesAndNotify(parser);
break;
case "error":
// Some BOSH error isn't stream error.
2017-02-27 13:14:04 +01:00
if ("urn:ietf:params:xml:ns:xmpp-streams".equals(parser.getNamespace(null))) {
throw new StreamErrorException(PacketParserUtils.parseStreamError(parser));
} else {
StanzaError stanzaError = PacketParserUtils.parseError(parser);
throw new XMPPException.XMPPErrorException(null, stanzaError);
2017-02-27 13:14:04 +01:00
}
default:
parseAndProcessNonza(parser);
break;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
while (eventType != XmlPullParser.Event.END_DOCUMENT);
}
catch (Exception e) {
if (isConnected()) {
notifyConnectionError(e);
}
}
}
}
}
2014-02-19 20:06:30 +01:00
}