MUC mediated invitations usually have the form
<message
from='coven@chat.shakespeare.lit'
id='nzd143v8'
to='hecate@shakespeare.lit'>
<x xmlns='http://jabber.org/protocol/muc#user'>
<invite from='crone1@shakespeare.lit/desktop'>
<reason>
Hey Hecate, this is the place for all good witches!
</reason>
</invite>
<password>cauldronburn</password>
</x>
</message>
(source: XEP-0045 Example 57.)
However, previous versions of XEP-0045 specified an additional <x
xmlns='jabber❌conference'> element to be included (see
implementation note in XEP-0045). Therefore, a legacy implementation
may emit a mediated invitations in the form of
<message
from="smack-inttest-mediated-invite-from-8ta77-hw9igz@conference.example.org"
to="smack-inttest-two-8ta77@example.org">
<x xmlns="http://jabber.org/protocol/muc#user">
<invite from="smack-inttest-one-8ta77@example.org"/>
</x>
<x xmlns="jabber❌conference" jid="smack-inttest-mediated-invite-from-8ta77-hw9igz@conference.example.org"/>
</message>
Unfortunately, this matches
MultiUserChatManager.DIRECT_INVITATION_FILTER because
GroupChatInvitation matches <x xmlns="jabber❌conference"/>. However
the message is not a direct invitation but a mediated one. Besides
this invoking the wrong listeners (direct vs. medidated) the value for
'inviter' that's used to invoke that listener will be false.
To fix this, extend DIRECT_INVITATION_FILTER with
NotFilter.of(MUCUser.class) to avoid matching those legacy mediated
invitations.
Fixes SMACK-943
Co-authored-by: Florian Schmaus <flo@geekplace.eu>
When Smack requests a subject change of a MUC, an error returned by
the server (eg: 'forbidden') should be propagated (as suggested by the
pre-existing javadoc).
Reported-by: Guus der Kinderen <guus@goodbytes.nl>
When the incoming unavailable presence is signalling a nickname
change (303), then do not invoke userHasLeft(), because the user
actually does not leave but instead just changes its nickname.
Note that this would also have had fixed SMACK-942, as it would
resolve the deadlock. However, using a dedicated lock for
changeNickname() still seems sensible, and if its just to avoid a bit
of lock contention.
What this also fixes is that a MultiUserChat does no longer invoke its
listener-based callbacks after a nickname change, as previously, after
a nickname change, the userHasLeft() would have been invoked, which
tears down the listeners. This issue was found with
MultiUserChatOccupantIntegrationTest.mucChangeNicknameInformationTest().
Using this method used to result in a deadlock, as shown by these two threads
"main" #1 prio=5 os_prio=0 cpu=926.39ms elapsed=21.00s tid=0x00007f463802c800 nid=0x5a691 in Object.wait() [0x00007f463f323000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(java.base@11.0.23/Native Method)
- waiting on <0x0000000622e82fd8> (a org.jivesoftware.smack.StanzaCollector)
at org.jivesoftware.smack.StanzaCollector.nextResult(StanzaCollector.java:206)
- waiting to re-lock in wait() <0x0000000622e82fd8> (a org.jivesoftware.smack.StanzaCollector)
at org.jivesoftware.smack.StanzaCollector.nextResultOrThrow(StanzaCollector.java:270)
at org.jivesoftware.smack.StanzaCollector.nextResultOrThrow(StanzaCollector.java:228)
at org.jivesoftware.smackx.muc.MultiUserChat.changeNickname(MultiUserChat.java:1314)
- locked <0x0000000622e19700> (a org.jivesoftware.smackx.muc.MultiUserChat)
at org.jivesoftware.smackx.muc.MultiUserChatOccupantIntegrationTest.mucChangeNicknameInformationTest(MultiUserChatOccupantIntegrationTest.java:981)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@11.0.23/Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@11.0.23/NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@11.0.23/DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(java.base@11.0.23/Method.java:566)
at org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.lambda$runTests$0(SmackIntegrationTestFramework.java:476)
at org.igniterealtime.smack.inttest.SmackIntegrationTestFramework$$Lambda$141/0x000000084026e040.execute(Unknown Source)
at org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.runConcreteTest(SmackIntegrationTestFramework.java:551)
at org.igniterealtime.smack.inttest.SmackIntegrationTestFramework$PreparedTest.run(SmackIntegrationTestFramework.java:759)
at org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.runTests(SmackIntegrationTestFramework.java:539)
at org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.run(SmackIntegrationTestFramework.java:277)
- locked <0x000000062d191318> (a org.igniterealtime.smack.inttest.SmackIntegrationTestFramework)
at
org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.main(SmackIntegrationTestFramework.java:115)
"Smack Cached Executor" #19 daemon prio=5 os_prio=0 cpu=7.85ms elapsed=20.48s tid=0x00007f4638a42800 nid=0x5a6b2 waiting for monitor entry [0x00007f46023fe000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.jivesoftware.smackx.muc.MultiUserChat.userHasLeft(MultiUserChat.java:2281)
- waiting to lock <0x0000000622e19700> (a org.jivesoftware.smackx.muc.MultiUserChat)
at org.jivesoftware.smackx.muc.MultiUserChat.access$800(MultiUserChat.java:117)
at org.jivesoftware.smackx.muc.MultiUserChat$3.processStanza(MultiUserChat.java:263)
at org.jivesoftware.smack.AbstractXMPPConnection.lambda$invokeStanzaCollectorsAndNotifyRecvListeners$8(AbstractXMPPConnection.java:1654)
at org.jivesoftware.smack.AbstractXMPPConnection$$Lambda$127/0x000000084022f440.run(Unknown Source)
at org.jivesoftware.smack.AbstractXMPPConnection$10.run(AbstractXMPPConnection.java:2213)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.23/ThreadPoolExecutor.java:1128)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.23/ThreadPoolExecutor.java:628)
at java.lang.Thread.run(java.base@11.0.23/Thread.java:829)
The changeNickname() method was synchronized and is userHasLeft(),
this caused a deadlock since changeNickname() awaits the presence that
is send as result of the nickname change. But this presence is also
processed in a listener which invokes userHasLeft(). However, this
invocation blocks as userHasLeft() is waiting on the montior currently
hold by the thread invoking changeNickname().
To fix this, we change changeNickname() to not take the MultiUserChat
monitor, but instead use a dedicate lock.
Fixes SMACK-942.
Calling write() in FillableForm's constructor causes a NPE because
write() makes use of requiredFields which has not been set at this
time. Furthermore, write() makes use of missingRequiredFields, which
is also populated in that loop. Therefore, we have to delay the
invocation of write() until requiredFields got set.
Thanks to Dan Caseley for reporting this.
Reported-by: Dan Caseley <dan@caseley.me.uk>
Calling write() in FillableForm's constructor causes a NPE because
write() makes use of requiredFields which has not been set at this
time. Furthermore, write() makes use of missingRequiredFields, which
is also populated in that loop. Therefore, we have to delay the
invocation of write() until requiredFields got set.
Thanks to Dan Caseley for reporting this.
Reported-by: Dan Caseley <dan@caseley.me.uk>
This is a follow-up on 198c51356d ("Add initial support for XEP-0103
and XEP-0104: URL Address Information"), which
1. adds the entries to the support XEPs table
2. registers the provider
3. renames the package from url_address_information to urldata (aka.
the shortname of XEP-0130).
The default local address is often just "the first address found in the list of addresses read from the OS" and this might mean an internal IP address that cannot reach external servers. So wherever possible use the same IP address being used to connect to the XMPP server because this local address has a better chance of being suitable.
This MR adds the above behaviour, and two UTs to test that we use the local XMPP connection IP when connected, and the previous behaviour when not.
Exposes a method for a MUC to invite a user to the room, and adds a listener to the MultiUserChat listener to inform users of direct invitations they have received.
Fixes SMACK-932.
While markdown is easier to write, Smack's markdown documentation was
never tightly coupled with the source. For example, the markdown
documentation never provided links to the actual Java classes and
methods. This poses the risk that the documentation and the code
diverge over time. Furthermore, javadoc is constantly improving (for
example @snippet annotations) and I expect that one will be able to
write javadoc in markdown.
Fixes SMACK-928.
Set started with Smack 4.4 to set myRoomJid to null, introduced by
ab2822be3e ("muc: also set myRoomJid to null if we have left the
room"), however the code comment still states that we "do not reset
nickname here" (and myRoomJid contains the nickname as its
resourcepart).
Reported-by: Damian Minkov <damencho@jitsi.org>
On dinamically remove the last existed presence interceptor
we also should to remove the MUC's main presence interceptor from the connection.
Fixes: 60fee7b ("[muc] Fix Presence interceptors")
The lambda we schedule in 25ms captures a strong reference to the
XMPPConnection. However the lambda is part of the scheduled action,
which we save in the renewEntityCapsScheduledAction field. This causes
a memory leak, since the ServiceDiscoveryManager now holds a strong
reference to its XMPPConnection.
Fix this by obtaining the strong reference to the XMPPConnection, if
one still exists, within the lambda.
Fixes SMACK-926.
Reported-by: Damian Minkov <damencho@jitsi.org>
Presence interceptors where hooked into stanza sending listeners,
which are called *after* the stanza has been put on the wire, i.e., to
late for interceptors that any modifications, they may perform, to
take effect.
Fixes SMACK-925.
We now also dynamically add the MUC's main presence interceptor to the
connection.
Reported-by: Damian Minkov <damencho@jitsi.org>