Get Presence of Multiple JIDs at once XMPP - xmpp

I am developing a XMPP application and will be doing a global shared roster so that I don't have to do presence subscription requests. I also need to get the presence of a certain range of JabberIDs and not the entire global roster. We do not want to do single directed presence stanzas, since that would require up to 15 presence calls each page load. Is there a method within XMPP for me to get presence of multiple, but specific JIDs at once?
Something like:
<presence from="user1#domain.tld,user2#domain.tld,user3#domain.tld" to="user4#domain.tld" />
Thanks in advance!

You could create a pubsub node where each item is about a user. The id would be the users bare JID, and the contents could be a dataform stating whether they are online or not.
A bot or xmpp module listens out for presence messages and then updates the pubsub node appropriately.
The clients can then query the pubsub node using whatever method they like: subscribe and get live updates, or query and use requests

Related

Multi Device support in XMPP Smack Chat Application

I am developing Android Chat Application.
My requirement is to deliver messages to multiple devices.
Consider this scenario between two users User A and User B:
User A logs in and sends message to User B.
User B logs in from Device 1 and receives message from User A.
User B logs in from Device 2 but does not get message from User A.
According to my requirement User B should get message from User A in Device 2 as well.
How can I achieve this?
Thanks.
In XMPP, the message are only delivered in a single go either:
to the online resources sharing the highest priority,
to the first client that connect through offline message delivery.
However, if you want other clients to resync, you should rely on XEP-0313: Message Archive Management. This specifications describe how a client can access a message history and resync its state.
You can for example query the message archive for all messages after a given time. This will allow the client that connect to get all the messages it missed since it was last online:
<iq type='set' id='juliet1'>
<query xmlns='urn:xmpp:mam:0'>
<x xmlns='jabber:x:data'>
<field var='FORM_TYPE'>
<value>urn:xmpp:mam:0</value>
</field>
<field var='start'>
<value>2010-08-07T00:00:00Z</value>
</field>
</x>
</query>
</iq>
In addition to Mickael's answer, you should be aware of a few things. If you specify a full JID as your to address, then the message will only be delivered to that single endpoint.
Message deliver to multiple resources for the same user will only occur if
The to address is the bare JID
All connections have the same priority
The server is configured to deliver to multiple endpoints.
That last point is crucial. According to the specification, the server can handle messages sent to the bare JID in 2 ways.
Send to one of the connections with the highest priority. Which one is determined by the server, it could be the first one connected, the last one, or a random choice if there are multiple connections with the same priority.
Send to all of the connections with the highest priority.
So, unless you know your server supports and is configured to allow the second choice, you can't accomplish what you are trying to do anyway.
In order to participate in the instant messaging and presence activities, a client (i.e device) should establish a session on the server.
As given in XMPP Documentation
If there is already an active resource of the same name, the server
MUST either (1) terminate the active resource and allow the
newly-requested session, or (2) disallow the newly-requested session
and maintain the active resource. Which of these the server does is up
to the implementation, although it is RECOMMENDED to implement case #1. In case #1, the server SHOULD send a stream error to the active resource, terminate the XML stream and underlying TCP
connection for the active resource, and return a IQ stanza of type
"result" (indicating success) to the newly-requested session. In case #2, the server SHOULD send a stanza error to the newly-requested session but maintain the XML stream for that
connection so that the newly-requested session has an opportunity to
negotiate a non-conflicting resource identifier before sending another
request for session establishment.
(https://www.rfc-editor.org/rfc/rfc6120#section-7.7.2.2)
Therefore you should first decide the way you are going to handle the sessions, according to the app requirement.
Now since you are using Ejabberd you can configure it by defining the option resource_conflict
However, if you still want to use multiple sessions you can use Message Archive Management - XEP-0313
So you can store chat history on the server and then retrieve. This can be configured in ejabberd by using the option mod_mam

Delivering messages to offline users in a multi-user chat (ejabberd)

Actually we are using ejabberd server for one of our client's Chat application. Everything is working well except for Group chat.
We are using MUC for Group chat but it is not sending Messages to the member whenever uses is offline. Is there any alternative plugin or something where we can make that working?
Or any one can suggest about how to receive offline messages for that user from Group chat history.
Thanks in advance
That's because there's no such concept for multi-user chat rooms. In fact, if you'll think about this a bit more you'll understand why:
Potentially unbound number of participants might be present in a room at any given time.
So exactly for which users not currently present in the MUC room should the server store the messages in the offline storage? I mean, in the generic case, the server does not know all the users who could ever possibly chat in a given room it hosts.
(Well, if this would be the only problem, it could possibly work for members-only rooms, I must admit.)
MUC rooms are not "local server only": a potentially unbound number of users from any number of other servers might join the room, and messages to those users will be delivered by routing them via their respective servers.
Obviously, this is another reason why such an idea of "MUC room offline storage" has no sense.
MUC rooms are by definition transient: when a user is offline, they're not in any room— (re-)joninig a room is an explicit action.
This is in fact the most important reason for not supporting offline storage.
As you can see, XMPP MUC rooms are much like IRC chats on steroids.
So what you really want is "room history"—a part of the XMPP-0045 extension which allows the client to explicitly ask the room for the message history they missed. In a sense, instead of storing offline message for each user, the room might be configured to store just a certain number of the most recent messages sent to it (or all such messages for a given period of time). Then the room supports querying these messages by the joined users.
There's another possibility which you might explore: "multicast addressing" of XEP-0033 ("Extended stanza addressing"). Basically it allows a client to use a special multicast service to send their message to multiple recipients at once. The upside is that offline storage is there again. The downside is that I doubt such a multicast service is supported out of the box in ejabberd, and it seems like that extension leaves much details about how it could be implemented unspecified.
I faced your issue as I sought to implement groupchats for my chatting app. I faced the same problem of MUC not storing offline messages for each recipient. And I did not want to retrieve MUC history which requires the user to rejoin every MUC to update his messages database. What I wanted is for the server to save offline messages by recipient, and for the recipient to get all MUC messages when he gets online (without having to join each MUC).
The way I did it is through pubsub. Using pubsub will force the server to store offline message per recipient. When the user reconnects, he gets all the offline messages including the pubsub messages which are sent as normal messages - that is it. One issue I had with pubsub over MUC though is that it is hard to get the list of subscribers. So when my app creates a groupchat, it creates a pubsub node for messages, invite all participants to subscribe (including self) to the pubsub and my app also creates a MUC and makes every participant an owner of that MUC. This way the list of the groupchat participants can be retrieved by checking the list of owners of the MUC. The only purposes of the MUC are to hold the list of participants as well as the name of the groupchat. Everything else is handled by the pubsub node.
Anything unclear please let me know.
ADDITIONAL DETAILS:
Essentially when the user wants to create a groupchat, our app creates a pubsub node as well as a MUC. You need to be familiar with both concepts. For the pubsub node, you need to set an option to allow any subscriber to post. When a user sends a message, he actually publishes on the node, and ejabberd will send the message to all subscribers as if it were a regular message (except it comes from pubsub.yourdomain.com). Therefore if a recipient is offline, ejabberd will store this message as any other regular message.
This is not how ejabberd handles MUC messages. Those are only sent to people CURRENTLY in the chatroom. History of messages can be stored by ejabberd however, but for a recipient to get the history he will need to join the MUC. Which means that everytime the app reconnects, it would have to join all the user's existing MUCs. We found this was not practical.
We also use a MUC for the same groupchat, but this is only to store participants so that a user can get the list at any time (no way to do it with pubsub).
An additional benefit of using pubsub over MUC is that the way ejabberd stores pubsub data is way more efficient. I have not studied this in depth, but I expect much better performance from pubsub.
New ejabberd server at 16.09 version have improvements for multi-user chat - MUC Sub:
The goal of MUC Sub is to try to rely as much as possible on existing MUC specification, while making the smallest possible change that make mobile group conversation client easy.
The feature is enabled by default. To use it, just make sure you set the new parameter “Allow subscription” in the room on which you want to use it.
Here is link to documentation: https://docs.ejabberd.im/developer/proposed-extensions/muc-sub/
More info here: https://blog.process-one.net/xmpp-mobile-groupchat-introducing-muc-subscription/

Tracking MUC room list with XMPP (ejabberd)

I'd like to allow a client to keep track of the list of rooms on a multi-user chat service provided by ejabberd. This would require receiving notifications of room creation/destruction and presence events for all rooms on the server.
Is there a way to subscribe to receive notifications about such events without sending a presence event to, and therefore joining the roster of all rooms?
FWIW, I've found out how to send a request for the room list (http://xmpp.org/extensions/xep-0045.html#disco-rooms) and I've been trying to make sense of the pubsub system (http://xmpp.org/extensions/xep-0060.html#glossary) in hope that I'd find a solution there but nothing seems obvious.
What's the right(TM) way to do this in XMPP land?
Ubuntu 10.04 + ejabberd 2.1.5-3+squeeze1 + Strophe.js & BOSH & jQuery
You need to develop custom code for that, especially to trigger packets sending on the event you are interested.

Send XMPP message without starting a chat

I am basically writing a XMPP client to automatically reply to "specific" chat messages.
My setup is like this:
I have pidgin running on my machine configured to run with an account x#xyz.com.
I have my own jabber client configured to run with the same account x#xyz.com.
There could be other XMPP clients .
Here is my requirement:
I am trying to automate certain kind of messages that I receive on gtalk. So whenever I receive a specific message eg: "How are you" , my own XMPP client should reply automatically with say "fine". How are you". All messages sent (before and after my client replies) to x#xyz.com but should be received by all clients (my own client does not have a UI and can only respond to specific messages.).
Now I have already coded my client to reply automatically. This works fine. But the problem I am facing is that as soon as I reply (I use the smack library), all subsequent messages that are sent to x#xyz.com are received only by my XMPP client. This is obviously a problem as my own client is quite dump and does not have a UI, so I don't get to see the rest of the messages sent to me, thereby making me "lose" messages.
I have observed the same behavior with other XMPP clients as well. Now the question is, is this is a requirement of XMPP (I am sorry but I haven't read XMPP protocol too well). Is it possible to code an XMPP client to send a reply to a user and still be able to receive all subsequent messages in all clients currently listening for messages? Making my client a full fledged XMPP client is a solution, but I don't want to go that route.
I hope my question is clear.
You may have to set a negative presence priority for your bot..
First thing to know is that in XMPP protocol every client is supposed to have a full JID. This is a bare JID - in your case x#xyz.com with a resource in the end e.g. x#xyz.com/pidgin or x#xyz.com/home (where /pidgin and /home are the resource). This is a part of how routing messages to different clients is supposed to be achieved.
Then there are the presence stanzas. When going online a client usually sends a presence stanza to the server. This informs about e.g. if the client is available for chat or away for lunch. Along with this information can be sent a priority. When there are more than one clients connected the one with the highest priority will receive the messages sent to the bare JID (e.g. ClientA(prio=50) and ClientB(prio=60) -> ClientB receives the messages sent to x#xyz.com). But there are also negative priorities. A priority less than 0 states that this client should never be sent any messages. Such a stanza might look like this
<presence from="x#xyz.com/bot">
<priority>-1</priority>
</presence>
This may fit your case. Please keep in mind it also depends on the XMPP server where your account is located, which may or may have not fully implemented this part of the protocol.
So to summarize: I recommend you to look through the Smack API how to set a presence and set the priority to <0 for your bot client right after it connected.

Does xmpp Resource Change?

I'm writing an app which communicates with clients via XMPP. I want to be able to use the users existing xmpp account (they all have google ID's) but I don't want my messages to appear in their regular IM stream.
I'm thinking that when my client pairs with the server it could use a custom resource id eg Fred.Bloggs#gmail.com/MYCUSTOMID then I can always send messages to that ID with the resource tag.
Is this the best approach, are Resource ID's tied to a specific install of a client or should they change on a per session basis?
Google will modify any resource you give it by adding a random identifier to the end.
If you're writing both the sender and the receiver, try using an XMPP extension:
<message to="fred.bloggs#gmail.com">
<x xmlns='http://my.domain.example.com/my_extension'>stuff</x>
</message>
If you need to be able to tell which of the resources is your client, try XEP-0115.