Smack V4.2.0-beta3 MessageEventRequestListener implementation requirements

One last issue encountered while porting aTalk to use Smack version 4.2.0 which does not occur in smack 4.1.8. The problem occurred when atalk-android receives a chat message from jitsi-windows. Attached below is the captured smack log. It seems that exceptions are triggered because of the events in the received chat message. There is no problem when jitsi-android sends a chat message to jitsi-windows which contains the same event in the message.

atalk-android has implemented private class JabberMessageEventRequestListener implements MessageEventRequestListener

and has executed the following upon user registration is completed

messageEventManager = MessageEventManager.getInstanceFor(parentProvider.getConnection());
messageEventManager.addMessageEventRequestListener(new JabberMessageEventRequestListener());

What else I need to do to resolve the problem? Appreciate if someone can give me some advice.

Thanking in advance.

===================================================================

12-10 11:39:30.813 10224-10969 D/SMACK: RECV (0): ?OTR:AAMSCCyqcgFBmfQAAAHSDHiKZWR5Fvojo2UMS++oGM7OjEeQ91zPICbN 1rQn1XY6AbrqtM8ylQIxIph+PSItfRgIHzNScFIy/RtpFVT9DgSfhpFvwyq3LFvYjvi0hWjn658Wv4uR Km7I5AP8feRcskDg931EXF64l8pkdoFMsScNwkYC9TfEwPNvmbFYQz9GSCdMHj1jBSUESX0Iu+hGOsnY 6Y7UaQY7d3q8O+Xgq5ccf0PnpOVwAD/FF7Jr9Nz5wWHFmVLZzYRiRJC5q7We+Pj1SQhwXwxpJa/6I2iW 9SJsHUG9OvMrqBD1SpuwxFw4iTxA6YNXh/sJL2mDAPXEBalt+SljchCaF0/aC4IZmzeufeEfnDDHa6qd juiBkrpjJVcx6a86DIauV0md8QLgXdw3F4UOnreXo7T+Q0C31AVxAqAytlOoXzuwEDYLSYU9eObg6j1I 7FARTi5Ke6gpX4IOr740GeE3QPmQM9a7BnixoBJ1sUFfKbPDzJv8b4ZH3nymWasPnTG2t9gpAQnHc+LS +lvqBhbqGKr8vgzMualG/Rj37WRG2TpnGksSNFx1NiePLfT7AJwWzP8oRnkaonCXpwemqQLG62cDVgtM ZCIzAEDe8+6W8XGo/ttIQYLVtZ3165keG69djeFFIA45287w/qCl.w8p7l0</thre ad>

12-10 11:39:30.823 10224-10969 D/SMACK: RECV (0):

12-10 11:39:30.823 10224-10968 D/SMACK: SENT (0):

12-10 11:39:30.833 10224-11011 E/αTalk: [10] org.jivesoftware.smackx.xevent.MessageEventManager.fireMessageEventRequestListe ners() Error while invoking MessageEventRequestListener

java.lang.NoSuchMethodException: composingNotificationRequested [class java.lang.String, class java.lang.String, class org.jivesoftware.smackx.xevent.MessageEventManager]

at java.lang.Class.getDeclaredMethod(Class.java:635)

at org.jivesoftware.smackx.xevent.MessageEventManager.fireMessageEventRequestListe ners(MessageEventManager.java:175)

at org.jivesoftware.smackx.xevent.MessageEventManager.access$000(MessageEventManag er.java:51)

at org.jivesoftware.smackx.xevent.MessageEventManager$1.processPacket(MessageEvent Manager.java:87)

at org.jivesoftware.smack.AbstractXMPPConnection$4.run(AbstractXMPPConnection.java :1138)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)

at java.lang.Thread.run(Thread.java:818)

12-10 11:39:30.833 10224-11011 E/αTalk: [10] org.jivesoftware.smackx.xevent.MessageEventManager.fireMessageEventRequestListe ners() Error while invoking MessageEventRequestListener

java.lang.NoSuchMethodException: offlineNotificationRequested [class java.lang.String, class java.lang.String, class org.jivesoftware.smackx.xevent.MessageEventManager]

at java.lang.Class.getDeclaredMethod(Class.java:635)

at org.jivesoftware.smackx.xevent.MessageEventManager.fireMessageEventRequestListe ners(MessageEventManager.java:175)

at org.jivesoftware.smackx.xevent.MessageEventManager.access$000(MessageEventManag er.java:51)

at org.jivesoftware.smackx.xevent.MessageEventManager$1.processPacket(MessageEvent Manager.java:87)

at org.jivesoftware.smack.AbstractXMPPConnection$4.run(AbstractXMPPConnection.java :1138)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)

at java.lang.Thread.run(Thread.java:818)

Attached is the class implementation for JabberMessageEventRequestListener

not sure if this is correct.

/**

  • Listens for incoming request for typing info
    */
    private class JabberMessageEventRequestListener implements MessageEventRequestListener
    {
    public void deliveredNotificationRequested(Jid from, String packetID,
    MessageEventManager messageEventManager)
    {
    try {
    messageEventManager.sendDeliveredNotification(from, packetID);
    }
    catch (NotConnectedException | InterruptedException e) {
    e.printStackTrace();
    }
    }

    public void displayedNotificationRequested(Jid from, String packetID,
    MessageEventManager messageEventManager)
    {
    try {
    messageEventManager.sendDisplayedNotification(from, packetID);
    }
    catch (NotConnectedException | InterruptedException e) {
    e.printStackTrace();
    }
    }

    public void composingNotificationRequested(Jid from, String packetID,
    MessageEventManager messageEventManager)
    {
    try {
    messageEventManager.sendComposingNotification(from, packetID);
    }
    catch (NotConnectedException | InterruptedException e) {
    e.printStackTrace();
    }
    }

    public void offlineNotificationRequested(Jid from, String packetID,
    MessageEventManager messageEventManager)
    {
    try {
    messageEventManager.sendCancelledNotification(from, packetID);
    }
    catch (NotConnectedException | InterruptedException e) {
    e.printStackTrace();
    }
    }
    }

Appears to be a bug in MessageEventManager, as for some strange reason, it uses reflection. One disadvantage of using reflection is that if you refactor your code, then the compilation will not fail if your reflective code makes an wrong assumption about e.g. types. I’ll eventually fix MessageEventManager, but please not that XEP-0022: Message Events is obsolete. As XEP-0022 tells you, you should use XEP-0085 instead.

Should be fixed with Fix MessageEventManager.fireMessageEvent…() · igniterealtime/Smack@3a221f2 · GitHub

Thanks for your quick response.

I saw you also realize that the same patch needs also to apply to private void fireMessageEventRequestListeners

method as seen from your checked in source.

Yes, the patch fixes the chat message event sending between atalk-anroid and jitsi-windows.

Thank for the information that XEP-0085 is now superseded XEP-0022. I will implement the new XEP-0085 in atalk.

Some clarifications:

Does it means atalk needs to keep XEP-0022 and implement the new XEP-0085 in order to be compatible with other clients like jitsi-windows? What is the common practice for other application developers to handle in this case?

Similar situation is also applying to XEP-0153 and XEP-0084 which I am in the mid of implementing.

Thanks again for your help.

Actually Jitsi implements XEP-0085 but has stray left over from the previous XEP-0022 implementation. This has led to the earlier reported problem.

aTalk-android, a fork from jitsi-android, hence inherited the same problem. Need to do a clean up and make correction to the problem.

While doing implementation for XEP-0085, I observed the following strange behaviour from Smack ChatStateManager. It repeatedly sending “composing” chat state upon requested by atalk while the user is composing a long message; actually the event is triggered from aTalk which I need to look at it to prevent this repetition. But the strange thing is that the ChatStateManager code has a built-in mechanism to prevent repetition, but why it still happen.

Section 5.3 Repetition of XEP-0085 clearing stated not repetition even user is composing a long message.

===================================================

12-13 10:06:29.972 18465-3559/org.atalk.android I/αTalk: [13] impl.protocol.jabber.OperationSetChatStateNotificationsJabberImpl.sendChatState Notification().135 Sending Chat State: inactive

12-13 10:06:29.972 18465-19124/org.atalk.android D/SMACK: SENT (0): bad38d43-c944-4fb5-9450-42cf71d33e3b

12-13 10:06:29.982 18465-19125/org.atalk.android D/SMACK: RECV (0):

12-13 10:06:30.792 18465-18465/org.atalk.android I/αTalk: [1] impl.protocol.jabber.OperationSetChatStateNotificationsJabberImpl.sendChatState Notification().135 Sending Chat State: composing

12-13 10:06:30.792 18465-19124/org.atalk.android D/SMACK: SENT (0): 4aa76d53-a579-4212-a3db-9e6245943f7d

12-13 10:06:30.802 18465-19125/org.atalk.android D/SMACK: RECV (0):

12-13 10:06:36.122 18465-3777/org.atalk.android I/αTalk: [14] impl.protocol.jabber.OperationSetChatStateNotificationsJabberImpl.sendChatState Notification().135 Sending Chat State: composing

12-13 10:06:36.122 18465-19124/org.atalk.android D/SMACK: SENT (0): d45a68ec-5eb1-4a4a-9304-2e985f2bc16a

12-13 10:06:36.132 18465-19125/org.atalk.android D/SMACK: RECV (0):

12-13 10:06:41.362 18465-3777/org.atalk.android I/αTalk: [14] impl.protocol.jabber.OperationSetChatStateNotificationsJabberImpl.sendChatState Notification().135 Sending Chat State: composing

12-13 10:06:41.362 18465-19124/org.atalk.android D/SMACK: SENT (0): e0d1030e-c298-4edb-b95b-af24b17a735f

12-13 10:06:41.362 18465-19125/org.atalk.android D/SMACK: RECV (0):

12-13 10:06:44.042 18465-3777/org.atalk.android I/αTalk: [14] impl.protocol.jabber.OperationSetChatStateNotificationsJabberImpl.sendChatState Notification().135 Sending Chat State: paused

12-13 10:06:44.062 18465-19124/org.atalk.android D/SMACK: SENT (0): 70763ddd-1501-40dc-8f21-fc8e8f435c71

12-13 10:06:44.082 18465-19125/org.atalk.android D/SMACK: RECV (0):

12-13 10:06:47.052 18465-3777/org.atalk.android I/αTalk: [14] impl.protocol.jabber.OperationSetChatStateNotificationsJabberImpl.sendChatState Notification().135 Sending Chat State: inactive

12-13 10:06:47.062 18465-19124/org.atalk.android D/SMACK: SENT (0): 246af504-5b00-40a7-a3bb-dd7f16f39167

12-13 10:06:47.082 18465-19125/org.atalk.android D/SMACK: RECV (0):

Sorry is my mistake. I sent in a new chat instant each time I setCurrentState(…).

Finally completed the full implementation of XEP-0085 for atalk. I use Gajim for testing as it is the only client that I found that has correctly implemented the protocol. However I have some ambiguities in the implementation, hopefully somebody can share his thought on this.

In XEP-0085 specifications, section 5.1:

In the absence of explicit discovery or negotiation, the User MAY implicitly request and discover the use of chat state notifications in a one-to-one chat session by adhering to the following business rules:

  1. If the User desires chat state notifications, the message(s) that it sends to the Contact before receiving a reply MUST contain a chat state notification extension, which SHOULD be .
  2. If the Contact replies but does not include a chat state notification extension, the User MUST NOT send subsequent chat state notifications to the Contact.
  3. If the Contact replies and includes an notification (or sends a standalone notification to the User), the User and Contact SHOULD send subsequent notifications for supported chat states (as specified in the next subsection) by including an notification in each content message and sending standalone notifications for the chat states they support (at a minimum, the state).

I found that Gajim strictly binded by section 4 of the document to assume an entity support XEP-0085 if it is advertised in the entitycaps feature.

4. Determining Support

If an entity supports the Chat State Notifications protocol, it MUST advertise that fact in its responses to Service Discovery (XEP-0030) [3] information (“disco#info”) requests by returning a feature of “http://jabber.org/protocol/chatstates”:

In the absence of an explicit chat state feature advertised in disco#info, any occurrence of event in section 5.1.3, will be ignored by Gajim, and not sending any chat state in all subsequent response.

Q1. What should be the correct implementation?

aTalk has implemented as describes in the document, but I likeGajim implementation as it is cleaner.

I am not sure if I have actually incorrectly interpreted the XEP-0085 document requirements.

If the sender is required to response with chat state notifications when a contains extension; irrespective of features advertised in EntityCaps, I assume that the reverse situation will also warrant the similar action. i.e. feature is being advertised in a client EntityCaps, but the notification is absent from all its sending messages; for reason that the user has disabled and decided not to send his chat state notification to his recipient after logged in. Under this case, I support the sender should stop sending notifications in all subsequent messages being sent, until the client has re-triggered and send the notification again.

As for the case in Gajim implementation, the client will have to send an update of the EntityCaps when user enable / disable the ChatState Notifications sending.

In Smack v4.2.0, the ChatStateManager Implementation is such that once the protocol is enabled, the user must log out and re-login to disable it.

Should Smack ChatStateManager implementation supports the dynamic disabling of the protocol?