To make it clear that this will either return if the condition is
true *or* if a connection exception happened.
Also introduce waitFor(), which is deliberately not named
waitForCondition() because it carries a different semantic.
Synchronize notifyConnectionError() so that only one exception is
handled and remove the ASYNC_BUT_ORDERED usage here. The
ASYNC_BUT_ORDERED was added with 7d2c3ac9f ("Do not call synchronized
methods in reader/writer thread"), but is no longer necessary, since
the Semaphores where replaced with conditions in the previous commit.
This continues the design started with e98d42790 ("SmackReactor/NIO,
Java8/Android19, Pretty print XML, FSM connections"), where the
exceptions that caused an operation to fail, are not recorded within
SynchronizationPoint but within the connection instance itself.
Since d65f2c932 ("Bump Error Prone version to 2.3.4 and fix new bug
patterns") the channel selected callback is no longer a final field of
the connection instance, hence it may be come null even if the
connection instance is still strongly referenced. Also the
ConnectionAttemptState class uses simply a lambda as callback, which
is also not strongly referenced otherwise.
The "channel selected" callback was wrapped in weak reference, so that
connection instances could get gc'ed if they are still connected but
the user lost all references to them. In this case, the weak reference
to the connection instance would become 'null' and
selectionKey.cancel() would be called.
This change means that a socket and its selection key of a "leaked"
connected connection instance continues to be part of the reactor. But
this may not be that bad: first, users are expected to manager their
connection instances, and disconnect them before they are
discarded. And secondly, at some point the connection likely will get
disconnected, and in this case, the socket and its selection key will
be removed from the reactor.
This moves the logic in AbstractXMPPConnection.getSmackTlsContext()
into the ConnectionConfiguration constructor.
Also introduce SslContextFactory and use it in
ConnectionConfiguration.
The field XMPPInputOutputStream.flushMethod was not initialized, which
could cause an NPE in the "switch (flushMethod)" found in
Java7ZlibInputOutputStream.getOutputStream().
Apply builder pattern to form fields and replace getVariable() with
getFieldName(). Refer to the field name as "field name" instead of
"variable" everyone, just as XEP-0004 does.
Improve the high-level form API: introduce FilledForm and FillableForm
which perform stronger validation and consistency checks.
Also add FormFieldRegistry to enable processing of 'submit' forms
where the form field types are omitted.
Smack also now does omit the form field type declaration on 'submit'
type forms, as it is allowed by XEP-0004.
The initState() method is also called in disconnect(). And if we reset
the closingStreamReceived sync point at disconnect, it will break the
WaitForClosingStreamElementTest integration test.
Return false as soon as the hashed value does not match. This is
sound, since every class that implements equals(Object) should also
implement hashCode().
This method was removed with 07da9ffb4 ("Do not have
Stanza.getExtension(String, String) return a generic type"). In order
to aide migration to the newer API, this commit re-adds the method and
marks it as deprecated.
Ensure that he returned extension element is actually of the correct
type. It should not be common, but in theory, Smack's provider
architecture would allow for different types to be returned than the
ones one may expect.
Returning a generic would allow for
List<ExtensionElement> list = stanza.getExtension("foo", "bar");
to compile (Note the we are calling getExtension(), not
getExtension*s*()).
Users are encouraged to use the type safe getExtension(Class<? extends
ExtensionElement) variant instead.
Fixes SMACK-825.
This is a complete redesign of what was previously
XmppNioTcpConnection. The new architecture allows to extend an XMPP
client to server (c2s) connection with new transport bindings and
other extensions.
Instead of marking the handle as not running by setting the handler's
value in the map to false, we now remove simply the key if there is no
handler running. This also means we no longer need to use a weak hash
map for this.
Also reduce the size of the synchronized blocks, mainly by scheduling
the handler outside of the synchronized(threadActiveMap) block.
Make some code better readable and add some more comments. Also do
start a new handler thread if the task threw.
If we do not peek at the scheduled actions in the reactors
synchronized block, then there is a kind of lost-update problem. While
Ractor.schedule() will call wakeup() on the selector, a thread could
have already determined the value of selectWait, while being blocked
at the start of the synchronized reactor section. Once it is able to
enter the section, it will use an outdated selectWait value.
This leads to scheduled actions not being executed on time.
Thanks to Eng ChongMeng for reporting this and suggesting the fix.
Besides the way the transport handles the stream after SASL
<success/>, the SASL logic is independend from the underlying
transport (BOSH, TCP, …). Hence move it up into
AbstractXMPPConnection.
This also has the benefit that we can make some more methods private
or package-private.
Also introduce XmlStringBuilder.optTextChild(), which causes some
associated changes.
Thanks to PolFW, who writes:
A SASLErrorException is thrown before we have received the "<success
xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>". This is because
SASLAuthentication is keeping a reference to a "saslException" so to
clear that after a authentication failure we have to invoke again
connect on the xmpptcpconnection to initialize again the
saslAuthentication. But it doesn't solve the issue because an
AlreadyConnectedException is thrown before the initialisation of the
"this.saslAuthentication.init();"
Note that the user uses one time tokens for authentication.