Multi Device support in XMPP Smack Chat Application - xmpp

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

Related

How to allow Ejabberd external XMPP component to send presence packets on behalf of a user

I wrote an external component for Ejabberd, but when trying to send presence stanzas on behalf of a user i get a 400 error.
The component's name is bot.domain.com and the host name in Ejabberd is domain.com and I have set the "check_from" flag to false for my component.
Below is an example of a presence stanza I am trying to send from the component on behalf of a user:
<presence from="user#domain.com">
<status>Test status</status>
<show>dnd</show>
</presence>
And this is the error message that is returned by Ejabberd:
<presence type="error" to="user#domain.com">
<status>Test status</status>
<show>dnd</show>
<error code="400" type="modify">
<bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
</presence>
If I add to="user2#domain.com" in the package I'm sending, the destination user actually receives the package.
If I add to="domain.com", I don't get the 400 error anymore, but the presence is not broadcast to anyone in the user's roster.
The actual problem seems to be that Ejabberd is not broadcasting the presence packet to everyone in the user's roster.
Any ideas what I might be missing or why I get the 400 error when not specifying the "to" field?
You cannot broadcast roster presence on behalf of a user from a component. Component service does not load the user roster. Only the ejabberd_c2s is taking care of loading roster to broadcast presence. It also takes care of checking privacy list and many important features of XMPP.
As a side note, I do not know what you expect to do with that approach, but you can split presence from user session in XMPP. A user is online first because he has a session open on XMPP and only secondarily because he sent a presence. By faking presence sending from component for a users, you are not guaranteed that that user will have a session opened. In that case, the overall behaviour will certainly not the one you expect.

How does Google Talk replicate messages across devices?

I'm wondering how (official) GTalk clients manage to show all messages received - even if it was originally consumed by another client. For example: I'm logged into GTalk on gmail.com on my laptop and, at the same time, via the official GTalk app on my Android device. A friend sends me a message, which is displayed on both the gmail.com client and the Android client. (I think it's originally only forwarded to one of either clients, but the second client fetches the message later on)
I recently found out that there's a very similar XMPP feature, called Carbons. However, after a quick service discovery request Google's servers didn't advertise this feature. XEP-0313 and XEP-0136 look good too, but the servers don't advertise them either.
Possibly related question: Deliver Google Talk message to all logged in clients using XMPPPY
When you initiate a new chat then you should send the first message to the users bare Jid. This is what most clients are doing. When the GTalk server retrieves a chat message to a bare Jid it routes the message to all available resources. For all following messages in this conversation the clients normally pick up the Resource and send them to full Jids. The messages should not be replicated then.
Many other servers don't route message to bare Jids to all resources, but to the most available resource which is the client with the highest priority.
Here is a quote form the RFC:
If there is more than one resource with a non-negative presence priority then the
server MUST either
(a) deliver the message to the "most available" resource or
resources (according to the server's implementation-specific algorithm, e.g., treating
the resource or resources with the highest presence priority as "most available") or
(b) deliver the message to all of the non-negative resources.
XEP-0280 defines this. As I understand, it defines the mechanism to notify all the resources from same user when one of them sends a message to anyone. I mean, Alice/pda sends a message to Bob, so Alice/mobile and Alice/PC will receive a copy of the message sent be Alice/pda.
Hope it helps. I am currently looking for a server that implements this, and also for a client library. If not, I will implement it by myself in both jabberd2 and gloox xmpp library.
Cheers,

How does the persistence work in XMPP?

I'm trying to understand the differences between AMQP and XMPP and among other things I don't really understand if XMPP works like it had Queues.
When you send a message to various clients what happen if one of them is down? The server enqueues the message up to the client is up again or how does it work?
Thanks
It depends on the XMPP server implementation how messages and iq's are handeld when the JID is offline. Section 11.1 of RFC 3921:
Else if the JID is of the form and there are no
available resources associated with the user, how the stanza is
handled depends on the stanza type:
...
For message stanzas, the server MAY choose to store the stanza on
behalf of the user and deliver it when the user next becomes
available, or forward the message to the user via some other means
(e.g., to the user's email account). However, if offline message
storage or message forwarding is not enabled, the server MUST return
to the sender a stanza error. (Note: Offline
message storage and message forwarding are not defined in XMPP, since
they are strictly a matter of implementation and service
provisioning.)
For IQ stanzas, the server itself MUST reply on behalf of the user
with either an IQ result or an IQ error. Specifically, if the
semantics of the qualifying namespace define a reply that the server
can provide, the server MUST reply to the stanza on behalf of the
user; if not, the server MUST reply with a
stanza error.

Get Presence of Multiple JIDs at once 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

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.