This also lifts a bunch of logic from smack-websocket-okhttp into
smack-websocket. Furthermore, the following subprojects require now
Java 11:
- smack-integration-test
- smack-omemo-signal-integration-test
- smack-repl
- smack-websocket-java11
Related tracking issue: SMACK-835
This also resulted in a refactoring of the Providers and parsing
Exceptions. NumberFormatException and ParseException can now be thrown
directly, the wrapping in a SmackParsingException is down at a higher
layer, i.e. in AbstractProvider.
Assume the element
<foo:bar xmlns='namespace' xmlns:foo='foo-namespace'/>
then the <bar/> element's namespace is 'foo-namespace', but the
default namespace is 'namespace'. And this is the namespace that
scopes into inner elements.
aTalk shows the following exception:
2020-12-14 12:11:13.704 7370-30976/org.atalk.android E/AndroidRuntime: FATAL EXCEPTION: AccountManager.loadStoredAccounts
Process: org.atalk.android, PID: 7370
java.lang.AssertionError: Element type 'EE' is neither of type Class or ParameterizedType
at org.jivesoftware.smack.provider.AbstractProvider.<init>(AbstractProvider.java:46)
at org.jivesoftware.smack.provider.Provider.<init>(Provider.java:40)
at org.jivesoftware.smack.provider.ExtensionElementProvider.<init>(ExtensionElementProvider.java:29)
at org.xmpp.extensions.DefaultExtensionElementProvider.<init>(DefaultExtensionElementProvider.java:43)
at org.xmpp.extensions.coin.CoinIQProvider.<init>(CoinIQProvider.java:46)
at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.initialize(ProtocolProviderServiceJabberImpl.java:2091)
at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderFactoryJabberImpl.createService(ProtocolProviderFactoryJabberImpl.java:121)
at net.java.sip.communicator.service.protocol.ProtocolProviderFactory.loadAccount(ProtocolProviderFactory.java:934)
at net.java.sip.communicator.service.protocol.AccountManager.doLoadStoredAccounts(AccountManager.java:139)
at net.java.sip.communicator.service.protocol.AccountManager.loadStoredAccounts(AccountManager.java:294)
at net.java.sip.communicator.service.protocol.AccountManager.runInLoadStoredAccountsThread(AccountManager.java:394)
at net.java.sip.communicator.service.protocol.AccountManager.access$000(AccountManager.java:36)
at
net.java.sip.communicator.service.protocol.AccountManager$1.run(AccountManager.java:329)
where CoinIQProvider line 46-47 [1] reads
private final DefaultExtensionElementProvider<URIsExtension> urisProvider
= new
DefaultExtensionElementProvider<>(URIsExtension.class);
This fixes SMACK-898.
1: f61f264312/aTalk/src/main/java/org/xmpp/extensions/coin/CoinIQProvider.java (L47)
Do net put an ack to the queue if it has already been shutdown. Some
servers, like ejabberd, like to request an ack even after we have send
a stream close (and hance the queue was shutdown). If we would not
check here, then the ack would dangle around in the queue, and be send
on the next re-connection attempt even before the stream open.
See the following trace of the MUC bookmarks integration test. The
fact that it is a MUC test does not matter, but this test does
disconnect the connection and reconnect it. Not how the server,
ejabberd in this case, requests an SM ack by sending an <r/> even
though we already send the </stream:stream>:
22:22:05 SENT (4):
<iq id='MD4UC-61' type='set'>
<query xmlns='jabber:iq:private'>
<storage xmlns='storage:bookmarks'>
<conference name='Smack Inttest: 7in7j' autojoin='true' jid='y9jcn5@conference.salem.geekplace.eu'>
<nick>
Nick-P2VXD7
</nick>
</conference>
</storage>
</query>
</iq>
22:22:05 RECV (4):
<r xmlns='urn:xmpp:sm:3'/>
22:22:05 SENT (4):
<a xmlns='urn:xmpp:sm:3' h='29'/>
22:22:05 RECV (4):
<message to='sinttest-7in7j-4@salem.geekplace.eu' from='sinttest-7in7j-4@salem.geekplace.eu' type='headline'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='storage:bookmarks'>
<item id='current'>
<storage xmlns='storage:bookmarks'>
<conference name='Smack Inttest: 7in7j' autojoin='true' jid='y9jcn5@conference.salem.geekplace.eu'>
<nick>
Nick-P2VXD7
</nick>
</conference>
</storage>
</item>
</items>
</event>
<addresses xmlns='http://jabber.org/protocol/address'>
<address jid='sinttest-7in7j-4@salem.geekplace.eu/1415073683806426185213090' type='replyto'/>
</addresses>
</message>
22:22:05 RECV (4):
<iq xml:lang='en-US' to='sinttest-7in7j-4@salem.geekplace.eu/1415073683806426185213090' from='sinttest-7in7j-4@salem.geekplace.eu' type='result' id='MD4UC-61'/>
22:22:05 SENT (4):
<presence id='6MS6J-20' type='unavailable'/>
<a xmlns='urn:xmpp:sm:3' h='31'/>
<!-- We have closed the stream -->
</stream:stream>
<!-- But the server still requests an SM ack -->
22:22:05 RECV (4):
<r xmlns='urn:xmpp:sm:3'/>
22:22:05 RECV (4):
</stream:stream>
22:22:05 XMPPConnection closed (XMPPTCPConnection[sinttest-7in7j-4@salem.geekplace.eu/1415073683806426185213090] (4))
22:22:05 SENT (4):
<a xmlns='urn:xmpp:sm:3' h='31'/>
22:22:05 SENT (4):
<stream:stream xmlns='jabber:client' to='salem.geekplace.eu' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' from='sinttest-7in7j-4@salem.geekplace.eu' xml:lang='en-US'>
22:22:05 RECV (4): ?xml version='1.0'?>
<stream:stream id='3379123514446782311' ver
22:22:05 RECV (4): sion='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'>
<stream:error>
<invalid-xml xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
</stream:error>
</stream:stream>
22:22:05 XMPPConnection closed due to an exception (XMPPTCPConnection[sinttest-7in7j-4@salem.geekplace.eu/1415073683806426185213090] (4))
org.jivesoftware.smack.XMPPException$StreamErrorException: invalid-xml You can read more about the meaning of this stream error at http://xmpp.org/rfcs/rfc6120.html#streams-error-conditions
<stream:error><invalid-xml xmlns='urn:ietf:params:xml:ns:xmpp-streams'/></stream:error>
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:981)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:913)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:936)
at java.base/java.lang.Thread.run(Thread.java:834)
Smack currently does unnecessary escaping of XML text, where it
escapes e.g. '"' to '"'. This bloats the stanza size, especially
if JSON payloads are involved.
Fixes SMACK-892 (although there are probably still places where
XmlStringBuilder.escape() is used when XmlStringBuild.text() could
have been used).
This means that users get now exceptions with helpful error messages
instead of the dreaded ClassCastException, like
java.lang.ClassCastException: org.jivesoftware.smack.packet.StandardExtensionElement cannot be cast to org.jivesoftware.smackx.mam.element.MamElements$MamResultExtension
at
when StanzaView.getExtension(Class) is used to retrieve the extension.
When sending a stream-open-like element, it depends on the actual used
transport which element is send. For example, RFC6120-style TCP uses
<stream>, whereas the Websocket binding for XMPP uses <open/>.
Most of the times when we construct a stream-open-like element, we
want the jabber:client namespace. Hence add a constructor that does
select the namespace implicitly.
Before the existence of AbstractStreamOpen, StreamOpen sufficed our need
during sending an open stream element. Since the intention behind
introducing AbstractStreamOpen is to allow underlying transports provide
transport specific opening streams, these changes will further support
the cause.
This commit will allow us to send transport specific open element
which should be inherited from AbstractStreamOpen.
This PR aims to provide parseXrdLinkReferencesFor() method the ability
to parse forward to the first START_ELEMENT tag.The HttpLookupMethodTest
tests the HttpLookupMethod class by parsing String. This makes use of
PacketParserUtils.getParserFor(String), which already does forward
winding to reach START_ELEMENT. However when fetching endpoints from a
remote host meta data, PacketParserUtils.getParserFor(InputStream) is
used which doesn't do winding in any form. And thus, even though
HttpLookupMethodTest tests pass, this implementation would crash while
parsing remote host-meta.
We previously only set 'connected' after connectInternal()
returned. This could lead to notifyConnectionError() ignoring stream
error exceptions, e.g. when establishing TLS which happens also in
connectInternal(), because 'connected' was still 'false'.
2020-08-06 13:08:06.265 19830-20423/org.atalk.android D/SMACK: SENT (0):
<stream:stream xmlns='jabber:client' to='atalk.sytes.net' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
2020-08-06 13:08:06.333 19830-20424/org.atalk.android D/SMACK: RECV (0): ?xml version='1.0'?>
<stream:stream id='16420577292739412012' version='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net' xmlns='jabber:client'>
<stream:error>
<policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
<text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>
Too many (20) failed authentications from this IP address (::ffff:42.60.7.13). The address will be unblocked at 05:15:34 06.08.2020 UTC
</text>
</stream:error>
</stream:stream>
2020-08-06 13:08:06.346 19830-20424/org.atalk.android I/aTalk: [241896] org.jivesoftware.smack.AbstractXMPPConnection.notifyConnectionError() Connection was already disconnected when attempting to handle org.jivesoftware.smack.XMPPException$StreamErrorException: policy-violation You can read more about the meaning of this stream error at http://xmpp.org/rfcs/rfc6120.html#streams-error-conditions
<stream:error><policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en'>Too many (20) failed authentications from this IP address (::ffff:42.60.7.13). The address will be unblocked at 05:15:34 06.08.2020 UTC</text></stream:error>
org.jivesoftware.smack.XMPPException$StreamErrorException: policy-violation You can read more about the meaning of this stream error at http://xmpp.org/rfcs/rfc6120.html#streams-error-conditions
<stream:error><policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en'>Too many (20) failed authentications from this IP address (::ffff:42.60.7.13). The address will be unblocked at 05:15:34 06.08.2020 UTC</text></stream:error>
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:966)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921)
at java.lang.Thread.run(Thread.java:919)
Which eventually leads to a NoResponseException
org.jivesoftware.smack.SmackException$NoResponseException: No response
received within reply timeout. Timeout was 30000ms (~30s). While
waiting for establishing TLS
[XMPPTCPConnection[not-authenticated] (4)]
We now set 'connected' to 'true' as soon as the transport (e.g. TCP,
BOSH, …) is connected. While this is in other ways also sensible, it
also allows notifyConnectionError() to handle exceptions in the early
connection stage.
Thanks to Eng Chong Meng for reporting this.