With bb8dcc9874 the concept if IQ request
handlers was introduced in Smack. This doesn't allow packet/stanza
collectors/listeners to filter for incoming IQ requests. Unfortunately
the file transfer code relied on this being able, so it broke with the
change.
There were two places where the file transfer code was listening for
incoming IQ requests:
- InitationListener(s)
- Negotiator(s)
With this change, we let the InitiationListener signal the existence of
an incoming initation request, send by an IQ of type 'set', using the
newly created EventManager utility.
The negotiator waits for those events to arrive and proceedes as it would
have done when the packet collector was used.
the combination with concurrencyLevel and LinkedBlockingQueue never
worked as intented. The idea was that the cachedExecutorService would
spawn new threads until maximumPoolSize (=concurrencyLevel) is reached,
and then start queing the Runnables.
But this was not the case, since ThreadPoolExecutor does not take into
consideration if the worker threads is busy, i.e. executing a Runnable,
or idle, i.e. waiting for a Runnable.
This means that if a busy Worker would execute a Runnable, which would
block, because it's waiting for an event (e.g. an incoming IQ
request), then the handling of those incoming IQ request would be
queued by ThreadPoolExecutor, because no fewer threads then corePoolSize
are running and the task can be queued (since the LinkedBlockingQueue is
unbounded).
Using the term 'enabled' was a terriable choice from a security
perspective, as it gives the user the impression that the security is
"enabled". In fact this setting is only slightly better then
"disabled".
Make that fact clear in the javadoc too.
The XMPPConnection interface does not define methods to manipulate the
connection state (e.g. connect(), disconnect()). The example should use
the connection type as declared type.
Since e6045c6593 the cached executor
services maximum pool size is limited to concurrencyLevel (was
previously Integer.MAX_VALUE). In order to prevent
RejectExecutionException we need to use an queue which max size is
greater than 1 (i.e. nont an SynchronousQueue).
Connection closed with error java.util.concurrent.RejectedExecutionException: Task org.jivesoftware.smack.tcp.XMPPTCPConnection$2@41dce200 rejected from java.util.concurrent.ThreadPoolExecutor@41d59150[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 4]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2011)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:793)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1339)
at org.jivesoftware.smack.AbstractXMPPConnection.asyncGo(AbstractXMPPConnection.java:1583)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.processHandledCount(XMPPTCPConnection.java:1655)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$2300(XMPPTCPConnection.java:137)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1083)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPConnection.java:896)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:911)
at java.lang.Thread.run(Thread.java:841)
and remove getConnectionID().
Also make streamId a field of AbstractXMPPConnection. Most XMPP
connection types have a streamId, it appears to be optional when BOSH
is used though.
RFC 6121 § 5.2.2:
"""
If an application receives a message with no 'type' attribute or the
application does not understand the value of the 'type' attribute
provided, it MUST consider the message to be of type "normal" (i.e.,
"normal" is the default).
"""
Otherwise we may get an NPE if the key was cached:
Connection closed with error java.lang.NullPointerException: Attempt to get length of null array
at org.jivesoftware.smack.util.stringencoder.Base64.encodeToString(Base64.java:43)
at org.jivesoftware.smack.sasl.core.SCRAMSHA1Mechanism.evaluateChallenge(SCRAMSHA1Mechanism.java:201)
at org.jivesoftware.smack.sasl.SASLMechanism.challengeReceived(SASLMechanism.java:230)
at org.jivesoftware.smack.SASLAuthentication.challengeReceived(SASLAuthentication.java:328)
at org.jivesoftware.smack.SASLAuthentication.authenticated(SASLAuthentication.java:347)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPConnection.java:894)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:909)
at java.lang.Thread.run(Thread.java:818)
instead of just logging a warning if the XMPP domain has no DNS SRV
lookups, create the failedAddresses list now within DNSUtil and add the
information that the SRV lookup failed.
In initConnection, only initReaderAndWriter() throws IOException.
connectUsingConfiguration doesn't need to take an argument.
PacketReader.init does not throw a SmackException.
Use Async.go() in PacketWriter, just like it's already done in PacketReader.
Also limit the max pool size of the remove callbacks service and use the
same keep alive time for idle threads as the cached executor service
uses.
Note that it would be possible to merge those two. But this could lead
to tasks from the cached executor service blocking the removal of
callbacks, which we don't want.
Make 'order' an long
Parse fall-through case's child elements (message, iq, presence-in,
presence-out)
Remove
privacy.addExtension(new DefaultPacketExtension(parser.getName(), parser.getNamespace()));
at the beginning of PrivacyProvider. Was there since day one for an
unknown reason.
since this method is not only used to determine the key for the
presence map, but also for the 'entries' map.
The logic is in both cases the same: If somehow an entry with an
resourcepart went into the roster (RFC 6121 does not explicity forbid
JIDs with an resourcepart in the roster), then use the full JID as
key, otherwise use the bare JID.
See also SMACK-19.
add a new AutoReceiptMode enum that specifies how delivery receipt
requests are handled. Default is to send receipts if the requstor is
subscribed to the user's presence.
Also make sure that messages contain an id if a receipt request is
added to it.
instead of getMessage(), because some Exceptions, e.g. Android's
NetworkOnMainThreadException, will return null on
getMessage(). Exception.toString() does what we want, i.e. returns
- the exception class name
- and the return value of getLocalizedMessage()
from o.jsmack.tcp.sm, as XEP-198 Stream Management is not an "XMPP over
TCP" exclusive feature. It could also be use together with the Websocket
binding of XMPP, so we may have a smack-streammangement in the
future. This change prepares for that by moving the SM code out of the
XMPP TCP package namespace.
if connect() was not previously called. Previously calling login() with
arguments would not check for the preconditions.
The check to throw needs to be performed in AbstractXMPPConnection
before every 'abstract login(Non)Anonymously()' call. That's the two
lines that check the preconditions are duplicated.
Also fix NPE in
XMPPTCPConnection.throwNotConnectedExceptionIfAppropriate() when
packetWrite is null (i.e. if the connection was never connected before).
(yeah, I know)
Sometimes "a friend" has setup an XMPP service which uses a self-signed
cert. While we can get a decent amount of security by using techniques
like e.g. the MemorizingTrustManager, there's still a pitfall. If the
service's TLS certificates contains no or the wrong service/hostname
information, Smack will throw an CertificateException. Therefore provide
an API call to disable hostname verification.
This is useful for cases where a result set is requested, as it's the
case in XEP-13 and XEP-313.
Also adds
XMPPConnection.createPacketCollector(PacketCollector.Configuration).
InterruptedExceptions should be treated as the users intention to
'cancel' the current thread's task. There is no such thing as a
spurious interrupt (not to be confused with "spurious wakeups").
after at most 12 hours.
Also set a keep alive time for the removeCallbacksService to 30 seconds
and add AbstractXMPPConnection.schedule(Runnable, long, TimeUnit).
isAnonymous() is now a bit weakened since it also considers
allowNullorEmptyUsername.
SaslExternalMechanism of smack-sasl-provided now also doesn't throw an
UnsupportedOperationException.
Follow up on 7e4e3699a1
to avoid confusion between the IQ element 'iq' and the IQs child
element. ELEMENT defined in an IQ sublcass should contain the *child*
element.
Add element to StreamInitation and fix FileTransferManager which still
used a packet listener instead of an IQ request handler to handle
incoming stream initiation requests.
to ConnectionConfiguration.Builder().
And prepare SASL EXTERNAL for empty or null usernames.
Also clarify some parts regarding the user field.
Fixes SMACK-627
This also moves the logic to send error IQ replies from "when there is
no IQ provider registerd" to "when there is no IQ request handler
registered". Which has for example the advantage that IQ parsing no
longer asks for a connection instance.
It's important to know if the stream was resumed. authenticated() is the
ideal callback for Managers to reset their state (e.g. cached values of
the connection state). But if the stream was resumed, the cached values
don't have to be reset.
notably add a cache for the active and default privacy list to avoid
IQ get/response round-trips.
Also add a few methods to PrivacyListManager to get the privacy list
names. The already existing methods always returned the whole list
together with the name, which caused two round-trips.
Simplified some code.
Properly escape Privacy XML.
Differentiate between asynchronous and synchronous ones. Asynchronous
are the ones where the invocation order may not be the same as the order
in which the stanzas arrived.
Since it's no longer guaranteed that when a unit test calls
processPacket(stanza)
the stanza will be completely processed when the call returns, it was
necessary to extend the unit tests (mostly Roster and ChatManager) with
a packet listener that waits for his invocation. Since we now also use
LinkedHashMaps as Map for the packet listeners (SMACK-531, SMACK-424),
adding a packet listeners as last also means that it will be called as
last. We exploit this behavior change now in the unit tests.
Rename 'recvListeners' to 'syncRecvListeners' in AbstractXMPPConnection.
Rename 'rosterInitialized' to 'loaded' in Roster.
Add Roster.isLoaded().
Reset 'loaded' to false in
Roster.setOfflinePresencesAndResetLoaded() (was setOfflinePresences()).
Fixes SMACK-583, SMACK-532, SMACK-424
on package layer instead of Declarative Service (DS) approach.
Restructuring and cleanup of initialization process to ensure that all
internal config files are found by the corresponding bundle
classloaders.
SMACK-343
- HeadersExtension.getHeaders() now returns a List instead of a
Collection
- Use XmlStringBuilder in Header and HeadersExtension toXML()
- Add HeadersProviderTest
- Use Smack formatting
Also remove duplicate parsing code regarding SHIM from HOXT
implementation.
- Change method modifiers keyword order to JLS
- Use attributecount when creating the HashMap
- Rename 'tag' to event'
- Use diamond operator
- Use Smack formatting style
Data Forms Validation are a part of Data Fields and implemented as
extensions, added to a Datafield.
Data validation extensions are validated before adding to the message,
using the consistency rules as described in the XEP.
Fixes SMACK-621.
Minor modifications done by Florian Schmaus <flo@geekplace.eu>
Those were broken since 9e797c1b17 as they
always used the basic PubSub namespace, i.e. without a fragment. Which
resulted in e.g. delete requests look like
<iq to="pubsub.ec-xmpp" id="2GAeW-75" type="set">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<delete node="2e92d38c-9e90-47f6-8e26-330d25ebe96b"/>
</pubsub>
</iq>
when the namespace should be in fact
http://jabber.org/protocol/pubsub#owner
since most JUL implementations do not print log messages of level
FINE (or lower) per default. Therefore the debugging output is not seen
by the user who wants to debug and a second step is required to
configure JUL to also log FINE or lower log messages to the console.
This fixes e.g. IllegalArgumentException "'conflict' can not contain a
condition text", when receiving elements like
<stream:error>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-streams'></conflict>
<text xml:lang='' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>
Replaced by new connection
</text>
</sream:error>
(ejabberd does this)
This simplifies code as there is no longer a distinction between
"normal" providers and introspection providers in ProviderManager
necessary.
It's also easier to get an idea where introspection is used for parsing.
Introduce AbstractError, change 'Conditions' to enums. Because of
AbstractError, it was necessary that PlainStreamElement and
TopLevelStreamElement becomes an interface. Thus the implementation of
TopLevelStreamElement.toString() had to be removed.
This adds
- policy-violation
- unexpected-request
to XMPPError.Condition, and removes the
- payment-required
- remote-server-error
- unexpected-condition
- request-timeout
Conditions
The file transfer code does now no longer throw XMPPErrorExceptions, but
SmackExceptions.
Fixes SMACK-608. Makes it possible to resolves SMACK-386.
there was a lot of duplicate code in ConsoleDebugger and
AndroidDebugger, which resides now in AbstractDebugger. Those two and
the new JulDebugger subclass AbstractDebugger.