XMPP receive messages sent to different resource - xmpp

How do I receive XMPP chat messages that are sent to a different resource?
E.g. my message listener receives messages fine, until that message gets replied to from another resource (like Gmail Google Talk). From that point on the messages are sent to that client resource and not my listener.
I'm using the Smack library for Java (well, actually asmack which is a port for Android)
After connecting to the service (Google Talk server), I add a listener like this:
connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
Log.i(TAG, "processPacket: chat");
Message message = (Message) packet;
Log.d(TAG, "Message: " + message.toXML());
if (message.getBody() != null) {
String fromName = StringUtils.parseBareAddress(message.getFrom());
Log.i(TAG, "Got text [" +
message.getBody() +
"] from [" +
fromName +
"]");
}
}
}, filter);
This works fine initially, I receive messages from Google Talk. These messages actually get sent to multiple clients, my desktop Google Talk, the Google Talk app an Android, and my implementation.
But when I reply to a message, say in the desktop application, all subsequent messages get sent to the desktop application resource, and I get nothing received in my implementation.
So I'm not sure how to also receive these messages. The Google Talk application seems to do this. It doesn't appear as a new message like it does initially (before it's replied to), but it does get updated in the Google Talk application thread.
Any help would be great!

If I've understood you right, you are logged in with the same user on different applications (resources). You receive messages from contacts in your roster, but when you reply from one place, it creates a dialogue just between those two nodes?
This is implementation specific. Most clients follow the recommended behaviour in RFC 3921, which is to reply to a full JID (user#domain/resource) if the message received was from a full JID. You are free to reply using your from as your bare JID (user#domain), so that a future response in sequence will be sent to your bare JID, resulting in all your available resources (assuming priority is equal) receiving it.
From your example where you reply from your desktop application, it's likely that the application is setting its 'From' header to the full JID, and the other party whom receives the reply from your desktop application is then using that value as the 'To' header for its response. This of course means only that unique resource will get the messages.
So it's got nothing to do with your code. It's to do with the code in that desktop application, working in conjunction with the code at the other endpoint (the buddy you're talking to), that is cutting your implementation out of the loop.

I think you should look up priority settings for that problem in xmpp. there is a priority settings that needs to be set so as to receive messages across different resources !
with multiple connection you need to control the message flow and so need to set priorities: Here are the basic rules for priorities: The resource with the highest priority at any given time will be the one which receives incoming messages. If two or more resources have the same priority, all resources with said priority will receive incoming messages. If all connected resources have a negative priority, incoming messages will be queued server-side until one of the resources resets priority to be positive.
source:http://blog.roobix.net/2010/02/jabber-xmpp-resources-and-priorities.html

Related

Ejabberd Message delivery while application is terminated

I am developing a chat app using ejabberd server for both IOS and Android. I also wrote a module for ejabberd to get the offline messages sent to my own server api .
my own server api will send notifications to the IOS/Android platforms using FCM.
On the client side , if the application is in the foreground or the background , it will stay connected to ejabberd and if the client receives the message then ejabberd will send the message delivery status.
I am facing an issue while the app is terminated ( service is not running ) which means it is not connected to ejabberd (offline) . if i send a message to this app while it is not terminated , it will receive a notification but the message still undelivered . how can mark the messages as delivered when receiving the notification while the app is terminated.
to explain it more , the same functionality is working fine with whatsapp :
device A has whatsapp installed and whatsapp was turned off (terminated)
Device B has whatsapp running
Device B sends a message to device A
Device A receives a whatsapp notification
Without doing anything on Device A , the message status on Device B is marked as delivered .
How can I implement this scenario with ejabberd ?
In case someone went into this issue , here is the solution that I implemented with help of #Mickaël Rémond from his answer.
I configured ejabberd to send the offline messages to an http service ( your own server) please refer to this link for further on how to do it
your server should catch the above call and generate a notification message (FCM ) in my case and send it to recipient device
recipient device will catch the notification which includes the message
recipient device will call http service (your own server backend)that responsible for sending the deliver ack to the original sender . you need to pass from, to , stanzaId , vhost with this call
backend server will use ejabberd-api (set of exposed apis to manage ejabberd through rest apis calls) to send delivery message using this api
please note the following notes also :
sending the delivery message from your own server to ejabberd will not delete them from ejabberd database
if the user re-connected to the ejabberd server then the recipient will receive the message again from ejabberd .
It is probably too complex for a simple Stack Overflow question, as you need to integrate several moving part on client and server:
You need to execute code in background when receiving push notifications on iOS (you need that property set on your app in your app provisioning profile and have code to handle that). The client will initiate an HTTPS query to let the server know that the message was delivered.
You need to have an endpoint that will get the delivered HTTPS calls and generate either a message ack or a chat marker on behalf of the user and route it in ejabberd.
In real world, this is not enough if you want to take into account the fact that you can only have 1 push in the queue on APNS. If you have several messages sent while the device is not on the network, you will need to have the device check all received messages while offline on the server, otherwise you will lose messaging.
You need to rely on XMPP Message Archive Management (MAM) to handle that history.
As you see, this is not a simple few tens of line of codes but need real design and involved work.

How to check if Siebel has successfully delivered an email?

We send a lot of email messages from our Siebel 7.8 application, and we'd like to determine whether they have been successfully delivered or not.
According to the Bookshelf, if the SMTP server is down, the Communications Outbound Manager retries to send the message later, so that's not a problem. However, there are still plenty of issues which could cause an email to not be delivered, such as a typo in the address, the receiver having reached its storage quota, etc.
We send our messages this way:
var ps = TheApplication().NewPropertySet();
ps.SetProperty("ActivityId", outboundEmailActivityId);
ps.SetProperty("CommProfile", commProfile);
ps.SetProperty("ProcessMode", "Local");
var bs = TheApplication().GetService("Outbound Communications Manager");
bs.InvokeMethod("SendMessage", ps, psOut);
Using ProcessMode = Local allows us to detect a few errors. For example, if we try to send a message to a non-existant account in the same domain of our SMTP server, it returns 550 Unknown user and then 503 Must have sender and recipient first. The Outbound Communications Manager raises an exception, and we capture and handle it.
However, if we send a message to a non-existant account in a different domain, our SMTP server can't know that it will fail, and therefore it returns 250 Queued, and our code completes successfully. Later (it can range from seconds to a few hours later), we will receive a "Message undeliverable" error message, but at this point we only know that an outbound message failed, we don't know which one.
Is there any way in which Siebel can handle these 'Message undeliverable' notifications automatically?
We are thinking of writing our own process for that, but it seems like a huge task: we'd have to parse the delivery failure notification, identify the failing recipient, search for all the recent messages sent to that address, and somehow, guess which one failed (based on the Message-Id if we are lucky and can read it within Siebel, or on the Subject otherwise).
The problem is that SMTP is by its nature neither a synchronous nor reliable protocol (i.e. in the sense of "engineered for guaranteed delivery"). Your Siebel app server will connect to its assigned SMTP server and ask it to accept a message for delivery and at that time there are a few high level validations that can be perform (some of which you've mentioned but which can also include policy enforcement such as checking whether your (possibly anonymous) identity is authorized for relaying messages to external domains). Once that conversation ends, there is not much else you can reliably do because again, everything from that point is asynchronous and not guaranteed for delivery (any number of intermediate relay agents can be involved, each with their own potential for outages with or without retry, each with the ability to honor or ignore requests for delivery or read receipts or to report invalid recipients, throwing your message in a junk folder or not, etc.). Certainly you can attempt to work with any bounce notifications you do happen to get to try to correlate them back to the sender but that would be outside the context of your sending code.

Message send to JID is only received on one connected device of possible multiple

Same user logged in three device(User name "A"), if a message is send to
this user(User name "A") from another user(User name: "B") only one
devices is receiving the messages other two devices are not receiving.
Kindly provide me a solution.
User A's clients and user A's server should implement XEP-0280, which does exactly that: it makes sure every connected client gets every received and sent message.
In case the message is sent to the full JID (i.e. user#domain/resource) there is no way to make other devices of the same user (but with a different resources) to receive the same message. This could be only possible if the XEP-0280 aka "Message Carbons" is implemented (this is what xnyhps suggested).
In case when the messages is sent to the bare JID (i.e. user#domain), it's usually sent based on presence priorities (f.e. it's true for Ejabberd), if all devices have the same presence priority the message will be sent to all the devices. It could not be true for your server, RFC 6121 says only about delivering to the "most available" resource, so everything depends on implementation:
delivering 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" (M)
If you develop your custom client and aren't going to use any 3rd-party clients in your chat-system, it could be ok to not use carbons and just stick to the default server option of the message delivery. At least for the first time.

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,

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.