Losing messages over lost connection xmpp - ios

i went through this question
Lost messages over XMPP on device disconnected
but there is no answer.
When a connection is lost due to some network issue then the server is not able to recognize it and keeps on sending messages to disconnected receiver which are permanently lost.
I have a workaround in which i ping the client from server and when the client gets disconnected server is able to recognize it after 10 sec and save further messages in queue preventing them from being lost.
my question is can 100% fail save message delivery be achieved by using some other way i know psi and many other xmpp client are doing it.
on ios side i am using xmppframework

One way is to employ the Advanced Message Processing (AMP) on your server; another one is to employ the Message Delivery Receipts on your clients.
The former one requires an AMP-enabled server implementation and the initiating client has to be able to tell the server what kind of delivery status reports it wants (it wants an error to be returned if the delivery is not possible). Note that this is not bullet-proof anyway as there is a window between the moment the target client losts its connectivity with the server and the moment the TCP stack on the server's machine detects this and tells the server about it: during this window, everything sent to the client is considered by the server to be sent okay because there's no concept of message boundaries in the TCP layer and hence if the server process managed to stuff a message stanza's XML into the system buffers of its TCP connection, it considers that stanza to be sent—there's no way for it to know which bits of its stream did not get to the receiver once the TCP stack says the connection is lost.
The latter one is bullet-proof as the clients rely on explicit notifications about message reception. This does increase chattiness though. In return, no server support for this feature is required—it's implemented solely in the clients.

go with XEP-0198 and enjoy...
http://xmpp.org/extensions/xep-0198.html

For a XMPP client I'm working on, the following mechanism is used:
Add Reachability to the project, to detect quickly when the phone is having connectivity problems.
Use a modified version of XEP-0198, adding a confirmation sent by the server. So, the client sends a message, the server confirms with a receipt. Later on, the receiving user will also confirm with a receipt. For each message you send, you get two confirmations, one from the server, one from the client. This requires modifications on the server of course.
When the app is not connected to the XMPP server, messages are queued.
When the app is logged in again to the XMPP server, the app takes all messages which were not confirmed by the server and sends them again.
For this to work, you have to locally store the messages in the app with three possible states: "Not sent", "Confirmed by server", "Confirmed by user"

Related

Suave runs out of sockets when receiving messages from AWS' SNS service

This is linked to question: Suave stops responding with "Socket failed to accept a client" error
When I first started to use Suave, I was taking commands from a 3rd party service pushing messages and I would have an out of socket situation.
There is now more understanding of the problem:
I am receiving messages that are posted to the SNS service on AWS (it's just a queue). SNS will forward me each message it receives through a HTTP connection, as a POST message.
If I reply with Ok, I will run out of sockets. So this means that Suave is trying to keep the connection open and AWS is somehow initiating a new connection every time.
If I reply with CLOSE, the AWS' delivery starts to become odd and messages get delivered in batches followed by periods of nothing.
Since AWS will not change their system for me, I'm wondering if I can reply Ok but then somehow close the connection in Suave to not run out of sockets. Is it possible?
Or, is there a better way to handle this?

NodeMCU resest with mqtt.client:close()), or mqtt.client:connect()

I have an application that uses mqtt for communication between modules and with a mobile terminal.
In some situations when the messages do not arrive, the node performs a self test of MQTT (sending a msg to itself), and when the selftest fails, tries to reconnect to the broker (mqtt offline not always arrives). And then two problems may arise:
If I perform a mqtt.client:close() to assure that the client is closed (to avoid the second problem) and the client is already closed, the node resets.
If I perform a mqtt.client:connect() and the client is still connected, an exception and a restet occurs.
is there a way to know if the mqtt client is connected or not?
Thanks for your comment. I am going to describe what I am doing, to see if you can help me:
I have two independent system, a master and a slave. The master publish a test message every 10 minutes. If there is no answer from the slave. it publish a test message to itself. If this self test does not arrive, a disconnection from the broker is assumed, and a reconnection is initiated.
And here is where the problem comes, sometimes the client is disconnected and everything go well, but sometimes it is still connected but unresponsive, and the node resets with an exception "already connected".
Performing a mqtt:close() previously to the reconnection, should be safe, but if I send it and the client is truly disconnected, the node resets without any reason (known to me).
All this is happening without receiving any offline message.
Instead of waiting for messages manually sent by the master client (which could fail to send for various reasons, leading a listening device to the wrong conclusion about the state of its connection to the broker), I recommend using MQTT's built-in connection management.
First, you can make sure that each client's initial connection has succeeded by including an error handler in :connect(). If the client really opens, nothing in the NodeMCU documentation indicates that it will close itself; it may go offline.
Once connected, the client only knows that something is wrong when it sends a message and does not receive a response. It sounds like you are not calling :publish() much (which would otherwise let you know by returning false), so pinging may be best. If you expect to receive a message from the broker every n seconds, set a keepalive time slightly higher than that on the client.
Then, failure to get a response to those messages should trigger an event that you can respond to. That might be something like the following (not tested, may work better called outside the callback):
m:on("offline", function(client) m:close() end)

iOS: Unable to fetch Offline messages for XMPP Chat

I am facing an issue with the presence status, following the documentation and XMPPframework example code. I have written a chat application.
Problem : When the user 1 & 2 are online I get the status successfully and they can chat with each other. However when the user 2 goes physically offline via (Wifi OFF / 3G Off) User 1 is not getting the offline status from XMPP and hence what ever messages are sent from that instant of time are lost when the user 2 comes online.
It seems since the user 2 is not notified or stored as offline in XMPP and hence its not storing the offline messages to push back to user 2 when it comes online.
I have tried to resolve this by explicitly writing a [goOffline] call to XMPP, however the call is shown in 'SEND log' for 'user 2' but not received in 'RECV log' in user 1 from XMPP, due to which the message are lost in between.
Also tried with other sources replies.
Set status for presence available and send XMPP
priority changed with values non-negative
XMPPArchiving work but this is not what I wanted.
Server side Mod_zero push enables but get only first message push notification sometimes.
Setting limit on ejabberd.cfg file for users and offline message limit.
request for offline message pull.
Can anyone help me with this?
This is very typical situation where client losses network but server can't detect that it is offline.
To detect status of each client, server need to send PING packets to every client and wait for response.
If client responds then fine otherwise server will mark that client as offline and every other online client will be informed automatically.
Here is PING Module implementation for ejabberd XMPP Server (hope you are using ejabberd server):
mod_ping:
send_pings: true
ping_interval: 10
timeout_action: kill
ping_ack_timeout: 10
This has to be written in ejabberd.yml configuration file.
At client side also we need to enable ping module to respond to server pings as:
private var xmppPing: XMPPPing?
xmppPing = XMPPPing()
xmppPing!.activate(xmppStream!)
This code has to be written while we setupStream() for iOS.
For detailed info, please go through mod_ping documentations.
Sounds like your problem is at server level. The server thinks that the user is online so it sends the message but nobody gets it. This does not really have a simple solution.
1.
The best solution would be delivery receipts. Where basically when the message is sent to your client, your client returns a confirmation of delivery receipt. If the server does not get that receipt it would resend the message every n time. Depending on your XMPP server you might find a already made solution, of not you would have to roll out your own.
2.
A possible hack would be to have your server always store and deliver last 10 messages and then at client side you discard repeated... This also depends on your server implementation. XMPP MUC and PubSub have resources along these lines.
For a long term scalable solution, you'll need to deal with this both at server and client level.

XMPP client network failure and Openfire offline message

I have configured XMPP client (iOS) and Openfire , everything works just fine except that i am not able to handle the following situation.
iOS client disconnects because of network failure.
User is still logged in on the server because there is no way to disconnect(no network).
Further messages are not stored in server because server thinks that the user is still logged in. Hence the messages are lost.
Unable to send push notification by sender because the receiver(User) status is still online ( no network to send presence ).
How can i solve this issue?
I found a solution, not sure if it is efficient.
In Openfire admin portal, under Client Connection Settings->Idle Connections Policy, there is an option to disconnect the client if it is idle for x seconds. By default it is 360 seconds, i have changed it to 5 seconds so that the messages won't get lost.
I am not sure if its a good idea to ping the clients every 5 seconds.

Chat between two iphones

I am looking to create a chat app so that two iphones/mobile can chat with each other.
Can someone please head me in the right direction ?
1. Should I try to connect two devices directly using HTTP or TCP
2. Or should the communication pass through a server i.e. one phone sends the message to the server and server then push the message to other phone ?
If you can tell me any libraries/api that I should use, that would be greatly helpful too.
Or should the communication pass through a server i.e. one phone sends the message to
the server and server then push the message to other phone ?
That's the usual approach. A server with a known address is easy to find; mobile phones that move from one network to another and frequently change their addresses are not. Also, you can keep a server running all the time, so that when one device sends a message, the server receives it and stores it until the other device becomes available. If you were to try to run your chat program on the phones all the time, you'd quickly deplete the batteries.

Resources