processone / ejabberd

Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
https://www.process-one.net/en/ejabberd/
Other
6k stars 1.5k forks source link

Mucsub subscription messages are not receiving when create a new group in a other xmpp connection. #4206

Open vietnguyen87 opened 2 months ago

vietnguyen87 commented 2 months ago

Environment

ejabberd version: 24.2.40 Using the ejabberd/ecs docker container

Configuration

  mod_muc:
    host: "conference.localhost"
    history_size: 1000
    max_users: 256
    max_user_conferences: 1000
    access_create: all ## all, local or none
    access_admin: muc_admin
    access_mam: always
    default_room_options:
      mam: true
      max_users: 1000000
      members_by_default: true
      members_only: false
      password_protected: false
      persistent: true
      public: true
      allow_user_invites: true
      moderated: false
      anonymous: false
      ## https://www.process-one.net/blog/xmpp-mobile-groupchat-introducing-muc-subscription/
      ## Create room and allow subscription. No need to send invitation.
      allow_subscription: true

  mod_muc_admin: {}
  mod_offline:
    access_max_user_messages: max_user_offline_messages
    ## Offline Storage
    db_type: sql
    store_groupchat: true
    use_mam_for_storage: true

Architecture

image

Description

I have Chat SSE Server uses ejabberd server, App/Web client connect to by SSE( Server send event). and Chat APIs Server uses ejabberd to call admin apis to send message, create groups...

I'm using https://github.com/xmppo/go-xmpp library for which I'm using MUC plugin to send join presence to specific chat room. That code is working and I'm able to receive all new messages in real time by call send message to ejabberd (admin apis) type "groupchat".

But i have an issue when client call Chat APIs Server ==> ejabberd (admin apis) to create group with all events :

{
          "name": "subscribers",
          "value": "user1@localhost:user1:messages:presence:subscribers:affiliations:subject,user2@localhost:user2:messages:presence:subscribers:affiliations,user3@localhost:user3:messages:presence:subscribers:affiliations"
        }

after that user1 call Chat APIs Server ==> ejabberd (admin apis) to send message to room i just created. And this time user2 has already connected with Chat SSE Server can not received the message.

I did a look at the documentation and there is a mention which I think is related to that issue:

If a user wants to be present in the room, they just have to join the room as defined in XEP-0045.

A subscriber MAY decide to join a conference (in the XEP-0045 sense). In this case a conference MUST behave as described in XEP-0045 7.2 Entering a Room. A conference MUST process events as described under XEP-0045 7.1 Order of Events except it MUST not send room history. When a subscriber is joined, a conference MUST stop sending subscription events and MUST switch to a regular groupchat protocol (as described in XEP-0045) until a subscriber leaves.

Do you have any ideas how to resolve that issue which I'm facing? How can users connected to Chat SSE Server still receive messages?

vietnguyen87 commented 2 months ago

@prefiks, @badlop Please help.!

prefiks commented 2 months ago

So in other words you created room with create_room_with_opts with subscribers and then when you sent message to a room using command (what exactly command?), that didn't get delivered to subscriber from create command, yes? I am just trying to see what i need to do to reproduce it.

vietnguyen87 commented 2 months ago

yup, @prefiks i used two ways:

  1. I use admin api https://docs.ejabberd.im/developer/ejabberd-api/admin-api/#send-message
  2. I use XMPP send stanza
    <message to='room3@conference.localhost' type='groupchat' id='e23ff0a35b4e9150' xml:lang='en'><body>testing </body></message>
    image
prefiks commented 2 months ago

It's working in my tests, you are aware that mucsub will not send regular groupchat message, but event with wrapped message like this:

<message to='prefiks@localhost' from='sub2@conference.localhost' id='1713861977424826' xmlns='jabber:client'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='urn:xmpp:mucsub:nodes:messages'>
      <item id='1713861977424826'>
        <message to='prefiks@localhost' from='sub2@conference.localhost/p2' type='groupchat' id='10483677060557293314' xmlns='jabber:client'><body>test</body>
        </message>
      </item>
    </items>
  </event>
</message>
vietnguyen87 commented 2 months ago

hi @prefiks, i call Admin Api send-stanza https://docs.ejabberd.im/developer/ejabberd-api/admin-api/#send-stanza

<message to='7214252@localhost' from='room3@conference.localhost' id='1713865884466642' xmlns='jabber:client'><event xmlns='http://jabber.org/protocol/pubsub#event'><items node='urn:xmpp:mucsub:nodes:messages'><item id='1713865884466642'><message to='7214252@localhost' from='room3@conference.localhost/7238854' type='groupchat' id='1713865884466642' xmlns='jabber:client'><body>test</body></message></item></items></event></message>

but it did not work. I can't receive the message at SSE connection. Data has stored at db.

image

prefiks commented 2 months ago

So that message that i showed in previous message was a result of calling

ejabberdctl send_message groupchat user@localhost sub2@conference.localhost "" test

and that resulted in sending that event to subscribers in a room.

I think your ejabberd sends event like this too, but your SSE server doesn't recognize it. Are you able to see all traffic that your code receive?

vietnguyen87 commented 2 months ago

hi @prefiks, i can see the traffic come ejabberd server. I think SSE server doesn't recognize it because it's not auto join when a new group created. When i reconnect SSE and join all group that user subscribe then message receive.

ejabberdctl send_message groupchat 7238854@localhost room2@conference.localhost "" TestBody
image
vietnguyen87 commented 2 months ago

Hi @prefiks,

Even if I reuse the xmpp client id in the call flow through the Chat APIs Server to join the room i created.

image

I also did not receive the message when I sent it.

send_message groupchat 7238854@localhost room4@conference.localhost "" TestBody

From admin website no any users join the room image

prefiks commented 2 months ago

So about send_message not sending message to a room, user that you use in 'from' must be room subscriber or muc admin, only those two classes can send message without joining room first.

vietnguyen87 commented 2 months ago

hi @prefiks, Are these users who subscribe to the room?

image

When i created the room. all users are become subscriber.

prefiks commented 2 months ago

Yes that list of room subscribers.

vietnguyen87 commented 2 months ago

yeah, and i using 7238854@localhost 7238854 is a room subscriber to sending message to the room. But all other subscribers don't receive messages.

If i'm not join the room, i'm not receive the history message. I don't know if I did something wrong? Please help.

prefiks commented 2 months ago

I don't know, do you have anything logged by server when you call that?

vietnguyen87 commented 2 months ago

yes, when i call send_message

send_message groupchat 7238854@localhost room3@conference.localhost "" "TestBody no join group"

and log by server image

log from ejabberd image

prefiks commented 2 months ago

So it seems that part is working.

vietnguyen87 commented 2 months ago

ok @prefiks, let's me check again. But. i can't receive history message if i don't join group. in case user disconnected, the SSE connection lost. Currently, when user reconnect SSE, i join all group user subscribe.

prefiks commented 2 months ago

Messages with event are stored in both user archive and offline storage (so they will be redelivered when user comes online). So those are two ways you can get older mesages.

vietnguyen87 commented 2 months ago

in case user login on the other devices. I will get the messages history from api?

vietnguyen87 commented 2 months ago

Hi @prefiks, I received data from ejabberd with type xmpp.PubsubEvent, parsing xml and received the message.

image
{
  "Node": "urn:xmpp:mucsub:nodes:messages",
  "Items": [
    {
      "ID": "1713956108027223",
      "InnerXML": "PG1lc3NhZ2UgdG89JzcyMTQyNTJAbG9jYWxob3N0JyBmcm9tPSdyb29tMUBjb25mZXJlbmNlLmxvY2FsaG9zdC83MjM4ODU0JyB0eXBlPSdncm91cGNoYXQnIGlkPScxMjE4OTA1NjA4NjQ4ODIyMTgzMicgeG1sbnM9J2phYmJlcjpjbGllbnQnPjxhcmNoaXZlZCBieT0ncm9vbTFAY29uZmVyZW5jZS5sb2NhbGhvc3QnIGlkPScxNzEzOTU2MTA4MDI3MjIzJyB4bWxucz0ndXJuOnhtcHA6bWFtOnRtcCcvPjxzdGFuemEtaWQgYnk9J3Jvb20xQGNvbmZlcmVuY2UubG9jYWxob3N0JyBpZD0nMTcxMzk1NjEwODAyNzIyMycgeG1sbnM9J3Vybjp4bXBwOnNpZDowJy8+PGJvZHk+aGFoYWhhaGEgPzwvYm9keT48L21lc3NhZ2U+"
    }
  ]
}

InnerXML after parse

<message to='7214252@localhost' from='room1@conference.localhost/7238854' type='groupchat' id='12189056086488221832' xmlns='jabber:client'><archived by='room1@conference.localhost' id='1713956108027223' xmlns='urn:xmpp:mam:tmp'/><stanza-id by='room1@conference.localhost' id='1713956108027223' xmlns='urn:xmpp:sid:0'/><body>hahahaha ?</body></message>

So what is the difference between muc and mucsub?

  1. Mucsub, I can get the subscriber list to display, right?
  2. For both modules, do I have to call the api to get message history when the user logs in on another device?

Please help me understand them clearly.!

prefiks commented 2 months ago

Regular muc: you must be online, and explicitly join room to receive messages, when you go offline, you automatically leave room and messages stop arrive.

Mucsub: after subscribing room you will get event for every message until you unsubscribe from room. Messages will also arrive when you are offline, so with mod_offline enabled, they will be delivered to you after you reconnect.

vietnguyen87 commented 2 months ago

Yeah, I understand clearly.! Thanks so much @prefiks. You save my day.! :D

vietnguyen87 commented 2 months ago

Messages with event are stored in both user archive and offline storage (so they will be redelivered when user comes online). So those are two ways you can get older mesages.

Hi @prefiks, with MUCSUB when user online. If user don't join the room, will the message be automatically deliver? What is the best practice for returning history messages to users?

vietnguyen87 commented 2 months ago

How to know if a subscriber is online in a room @prefiks ?