Not logged in. · Lost password · Register
Forum: MatriX and XmppDotNet RSS
Avatar
Stei #1
Member since Oct 2016 · 31 posts
Group memberships: Members
Show profile · Link to this post
Subject: Can't receive messages after disconnecting from internet
Hello, here is my scenario.

I have two cell phones that are running a chat app that have Matrix XMPP. When both phones are connected to the internet, everything works fine. But here is the problem I found:

1) Turn off Phone A's internet connection
2) Send message from Phone B to Phone A
3) Turn on Phone A's internet connection

However, the message sent from Phone B is not received on Phone A after it is reconnected to the internet. Although I can send messages between the two phones normally again.

My app is built using C#. I have an event handler that is triggered when the device's internet connection turns on or off. I notice that when I turn the internet off, the event handler is triggered, however it still says that the XMPPClient.StreamActive = true.

Then if I wait about 10 or 15 seconds (with the internet connection still turned off), I get these messages from the OnError event:

A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

and sometimes:

An existing connection was forcibly closed by the remote host.

So, I am wondering what the best way to handle this is. After the internet is disconnected, should I call XMPPClient.Close()? And when it is reconnected, should I call XMPPClient.Resume() or XMPPClient.Open()?

Like I said, right now I am using a different event handler to check on the connection status; should I only rely on XMPP's events to check for internet status?
Avatar
Alex #2
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
When you loose the internet connection MatriX will throw an OnClose event whenever it detects the loss.
MatriX can only detect the loss once it gets notified by the underlying network stack (sockets), which can take a while (seconds up to 2 minutes depending on your configuration).

You cannot call Open() on a XmppClient object before you got the OnClose(). If you want to reconnect before you even got the OnClose then please create a complete new XmppClient. of course you have to setup all your events again and unsubscribe the old XmppClient events.

  1. xmppClient = new XmppClient();

When you send a message to a full Jid while a user is offline the server should return an error message to you.
When the user if offline and you send the message to the users bare Jid then teh server will store it offline and deliver as soon as he comes online again.

So I assume you send to a full Jid and ignore the error message which comes back. This is why you may loose the message.
Also when user A goes offline then user B gets an offline presence. Once you get this presence you know that this specific resource is offline and should not send any messages to the full Jid.
Avatar
Stei #3
Member since Oct 2016 · 31 posts
Group memberships: Members
Show profile · Link to this post
Thank you for the fast response. You are right, I was calling Open() before I got the OnClose().

Would this code work?

  1. public void OnConnectionChanged(object sender, EventArgs e)
  2. {
  3.     if (InternetIsConnected)
  4.     {
  5.         // Internet is back online
  6.         Connect(_domain, _port, _username, _password); // set up new XMPPClient()
  7.     }
  8.     else
  9.     {
  10.         // internet is offline
  11.         UnRegisterDefaultEventHandlers(); // unsubscribe event handlers
  12.         _xmppClient.Close();
  13.     }
  14. }
This post was edited on 2016-10-27, 14:16 by Alex.
Avatar
Stei #4
Member since Oct 2016 · 31 posts
Group memberships: Members
Show profile · Link to this post
Here is a more detailed example of what I am experiencing:

Two phones, Phone A and Phone B

1) Phone A and B are both online
2) Send message from A to B "msg1" at 8:30:02
3) Message received on Phone B
4) Turn off Phone B's internet at 8:30:10
5) Send message from A to B "msg2" at 8:30:15
6) Send message from A to B "msg3" at 8:30:17
7) Send message from A to B "msg4" at 8:30:19
8) Send message from A to B "msg5" at 8:30:21
9) Send message from A to B "msg6" at 8:30:23
10) Send message from A to B "msg7" at 8:30:25
11) Send message from A to B "msg8" at 8:30:27
12) Send message from A to B "msg9" at 8:30:29
13) Turn On Phone B's internet at 8:30:31
14) Phone B receives messages "msg7", "msg8", "msg9". But "msg2" to "msg6" are not received.


However, I tried a similar scenario, but kept the internet offline just for a few seconds:
1) Phone A and B are both online
2) Send message from A to B "msg1" at 8:40:10
3) Message received on Phone B
4) Turn off Phone B's internet at 8:40:12
5) Send message from A to B "msg2" at 8:40:15
6) Send message from A to B "msg3" at 8:40:17
7) Turn on Phone B's internet at 8:40:20
8) Phone B receives "msg2" and "msg3", so no messages were lost
Avatar
Alex #5
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
In reply to post #3
yes the above code should work
Avatar
Alex #6
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
In reply to post #4
Quote by Stei:
Here is a more detailed example of what I am experiencing:

Two phones, Phone A and Phone B

1) Phone A and B are both online
2) Send message from A to B "msg1" at 8:30:02
3) Message received on Phone B
4) Turn off Phone B's internet at 8:30:10

you can send messages only once you are online and your session is ready (First OnPresence event received).
It looks to me like you are sending messages when you are not supposed to send them.

Alex
Avatar
Stei #7
Member since Oct 2016 · 31 posts
Group memberships: Members
Show profile · Link to this post
In the above test, I only send messages from the phone that is online, not from the phone that is offline.

I've been testing the code I posted above, and it still has a small issue. When I call xmppClient.Close(), the OnClose() event does not get triggered until after 10 or 15 seconds. I find that if the phone is offline, any messages sent to the offline phone within this 10 or 15 second timeframe do not get received. However, messags sent to the phone after OnClose() is triggered will get received when the phone comes back online.

Is this because the online phone is sending the message to the offline phone's Full JID instead of the bare JID?

Edit: actually, the message is being sent to the bare jid. When I view the messageevent args in OnMessageReceived, the to property in the <message> tag is to the bare jid
This post was edited on 2016-10-27, 15:43 by Stei.
Avatar
Alex #8
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Quote by Stei:
Is this because the online phone is sending the message to the offline phone's Full JID instead of the bare JID?

you have not posted an Xml log, so I don't know if you send to a full or bare Jid.
Also your connection can break while you are in process of sending messages. To make sure no messages are lost you need implement something like message receipts for example when you are on unreliable connections.
There are many threads about this here in the forum. Please use the forum search for this.
Avatar
Alex #9
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
In reply to post #7
Quote by Stei:
I've been testing the code I posted above, and it still has a small issue. When I call xmppClient.Close(), the OnClose() event does not get triggered until after 10 or 15 seconds. I find that if the phone is offline, any messages sent to the offline phone within this 10 or 15 second timeframe do not get received.

this is by design and how it works. MatriX has to wait until it gets the socket exceptions as has to do some other cleanup.
As I said before, if you create a complete new XmppClient you don't have to worry about the OnClose event if you don't want to wait.
Avatar
Stei #10
Member since Oct 2016 · 31 posts
Group memberships: Members
Show profile · Link to this post
Quote by Alex:
Quote by Stei:
I've been testing the code I posted above, and it still has a small issue. When I call xmppClient.Close(), the OnClose() event does not get triggered until after 10 or 15 seconds. I find that if the phone is offline, any messages sent to the offline phone within this 10 or 15 second timeframe do not get received.

this is by design and how it works. MatriX has to wait until it gets the socket exceptions as has to do some other cleanup.
As I said before, if you create a complete new XmppClient you don't have to worry about the OnClose event if you don't want to wait.
So does that mean I should not call OnClose() event when the connection is offline? Instead I should just wait for it to come online, and then create the new client?

Also, I already have receipts implemented. Well, I receive the receipts but I do not do anything with them right now. But I will look into handling them appropriately.
Avatar
Alex #11
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Quote by Stei:
So does that mean I should not call OnClose() event when the connection is offline? Instead I should just wait for it to come online, and then create the new client?

When you create a new XmppClient then I think the Close() call is unnecessary. Because when you are offline already it cannot close the XmppStream properly anyway.
Avatar
Stei #12
Member since Oct 2016 · 31 posts
Group memberships: Members
Show profile · Link to this post
Is it normal for the OnStreamStart() event to be fired twice after connecting?

Also I just realized that I am not doing anything with Rosters. Because I am not adding my friends to my roster, would this be causing an issue? Would my friend not see my offline presence after the internet connection goes down?
This post was edited on 2016-10-28, 12:15 by Stei.
Avatar
Alex #13
Member since Feb 2003 · 4449 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Quote by Stei:
Is it normal for the OnStreamStart() event to be fired twice after connecting?

yes, there are stream restarts required in XMPP. eg. after Tls and after authentication.

Quote by Stei:
Also I just realized that I am not doing anything with Rosters. Because I am not adding my friends to my roster, would this be causing an issue? Would my friend not see my offline presence after the internet connection goes down?
Presence requires you to be subscribed to your contacts and have them on your roster. Roster and subscriptions are persistent. So you do it once and the server stores the state.
Avatar
Stei #14
Member since Oct 2016 · 31 posts
Group memberships: Members
Show profile · Link to this post
Ok, I think I have a good understanding of what I need to do now. Thank you for your time Alex, I really appreciate the help
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters: