Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

XMPPReconnect doesn't always work correctly #101

Open
sarsonj opened this Issue Aug 20, 2012 · 44 comments

Comments

Projects
None yet

sarsonj commented Aug 20, 2012

Hi,

I have issues with XMPPReconnect - sometimes, when going from 3G to no-signal and back, XMPP didn't reconnect. I tried to simulate this using flight mode and I realized, that XMPPReconnect doesn't handle "no network reachable" event. Because XMPPStream doesn't use timeouts, it can happen, that this "no-signal" state is not detected and when network goes back to 3G, same socket is used. But at least our 3G network doesn't guarantee same IP address, so that socket is not working again. But because of no timeout, application is in state, that it looks like that is connected, but it is not.

I tried to implement experiment, using Apple reachability example and simply disconnect xmppSteam socket when reachability changed and both WLAN and WAN are not available. It fixes this issue and now XMPPReconnect works correctly.

Before I start to change XMPPReconnect I want to discuss, how this should be handled correctly. For example - should be also socket closed and created again with every reachability change? How is this handled now? Is socket closed automaitcally, when for example already connected on WiFi and new WiFi is connected?

Thanks,

Jindrich

Hello,

I also have this problem. Some times the Framework doesnt even connect to the server. I didnt make any investigation on that.

Could you share your fix so I can test it in my implementation?

Yeah I am having the same issue, is there a fix?

YDing commented Aug 29, 2012

I'd like to see the fix as well.

I'm having the same exact problem- does anyone know of a solution?

sarsonj commented Aug 29, 2012

Currently, I implemented "hacky" solution using Rechability example from Apple - http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html

Simply when I detect no network, I close XMPP socket using [asyncSocket disconnect];

The XMPPReconnect plugin then handles connecting correctly.

However, this is quick hack, It should be implemented in XMPPReconnect. Now when it is confirmed as problem of more people, I will look to XMPPReconnect to fix it here.

YDing commented Aug 29, 2012

sarsonj, I tried your solution, but it doesn't seem to fix my problem. Here's how I'm reproducing the issue:

  1. Start with app open, XMPP is connected.
  2. Background the app
  3. Turn on airplane mode (or turn off the AirPort if you're running on the simulator)
  4. Turn off airplane mode (or turn the AirPort back on)
  5. Bring app back to foreground.
  6. Look for the reconnection...

2012-08-29 01:54:47.540 medigram[48306:c07] -[MGXMPPManager xmppStream:socketDidConnect:] [Line 243] XMPP Stream Socket did connect
2012-08-29 01:54:47.768 medigram[48306:c07] -[MGXMPPManager xmppStream:willSecureWithSettings:] [Line 250] XMPP Stream willSecureWithSettings:{
}
2012-08-29 01:54:48.109 medigram[48306:c07] -[MGXMPPManager xmppStreamDidSecure:] [Line 302] XMPPStream Did secure
2012-08-29 01:54:48.186 medigram[48306:c07] -[MGXMPPManager xmppStreamDidConnect:] [Line 307] XMPP Stream Did Connect
2012-08-29 01:54:48.186 medigram[48306:c07] -[MGXMPPManager xmppStreamDidConnect:] [Line 315] Error authenticating with password: xxxxxx : Error Domain=XMPPStreamErrorDomain Code=1 "Please wait until the stream is connected." UserInfo=0x8514d70 {NSLocalizedDescription=Please wait until the stream is connected.}

The interesting thing is that xmppstream thinks it's not connected, even though the authenticatewithpassword function is being called from the xmppStreamDidConnect delegate function.

yding did you try without using the secure method?

It could be a bug with the secure feature that is not setting all the variables correctly.

YDing commented Aug 30, 2012

jonasman, we ended up fixing it with sarsonj's method. Changing the security didn't seem to help.

Can you provide the code you have implemented?

any news in this topic?

It seems that the rechability is the way to go, what about the integration with that class and XMPPStream/reconnect or even in the async socket?

asendra commented Oct 21, 2012

I'm having the same problems. When leaving the app for a long time, or even in the background, It sometimes randomly loses the connection and can't reconnect. What's the best way to force a reconnection?

I think the problem is with the async socket that doesn't care about the reachability at all.

so, was there any development in this case or should I use sarsonj's workaround?

Ok, the workaround does help when app is activated, but when it's in background it still doesn't reconnect.

basants commented Feb 5, 2013

I have tested whats app for ios. Even that wont connect in background once
the internet connectivity is gone and comes back. However KIK messenger
does connect. Weird problem.

On Tue, Feb 5, 2013 at 7:07 PM, misha2400 notifications@github.com wrote:

Ok, the workaround does help when app is activated, but when it's in
background it still doesn't reconnect.


Reply to this email directly or view it on GitHubhttps://github.com/robbiehanson/XMPPFramework/issues/101#issuecomment-13129364.

Contributor

paulmelnikow commented Feb 5, 2013

What code do you run when you enter background?

No code at all in AppDelegate's applicationDidEnterBackground, should I have something specific there?
I just keep being connected to xmpp server and listening for messages.

Contributor

paulmelnikow commented Feb 5, 2013

I think you need to request permission to keep running while in the background, or else your app is suspended shortly after. This is Apple's documentation on background execution.

I have "Location" and "VoIP" in required background modes in Info.plist, I thought this is enough.
Application runs for hours in background without any problem when there's uninterrupted access to data network. It's only when the network is temporary unavailable that it has problem reconnecting in background.
Is it possible that once app is disconnected, it automatically stops to qualify being "VoIP" and is suspended by iOS?

Contributor

paulmelnikow commented Feb 5, 2013

Just did some digging, and it looks like you might also have to enable VOIP for the socket. There's a method -[GCDAsyncSocket enableBackgroundingOnSocketWithCaveat:] which does this but it doesn't look like it's used by the framework. You could try modifying XMPPStream to invoke that method and seeing if that makes a difference.

I'll try that, thanks. I also found that I may need to implement setKeepAliveTimeout and, possibly, use beginBackgroundTaskWithExpirationHandler. Will try all that later.

basants commented Feb 5, 2013

[GCDAsyncSocket enableBackgroundingOnSocketWithCaveat:] method is
called by enableBackgroundingOnSocket
which we are setting to true. Also i didn't find nay method with the name
of beginBackgroundTaskWithExpirationHandler. setKeepAliveTimeout looks
promising, will test tomorrow when i have a device.

Apple says the backgrounding of voip will work only when the socket is
connected. Will dig the link and share.

On Wed, Feb 6, 2013 at 12:06 AM, misha2400 notifications@github.com wrote:

I'll try that, thanks. I also found that I may need to implement
setKeepAliveTimeout and, possibly, use
beginBackgroundTaskWithExpirationHandler. Will try all that later.


Reply to this email directly or view it on GitHubhttps://github.com/robbiehanson/XMPPFramework/issues/101#issuecomment-13144113.

The other observation that I have is that when I turn on location updates, application seems to recover nicely from airplane mode, so I guess the problem is indeed related to app being suspended by OS.

basants commented Feb 5, 2013

Turn on location updates ? Like setting some property in plist or general
location updates of iOS device from settings ?

I wonder when we are able to receive messages when the app is in
background, why wont it reconnect automatically. I have tested my app, it
was kept for almost 24 hours in background and there wasn't any internet
disruption, it was working fine (able to receive messages). So the normal
backgrounding is not an issue, the main issue is when the socket has been
disconnected due to internet disconnection and the app is in background.

On Wed, Feb 6, 2013 at 12:27 AM, misha2400 notifications@github.com wrote:

The other observation that I have is that when I turn on location updates,
application seems to recover nicely from airplane mode, so I guess the
problem is indeed related to app being suspended by OS.


Reply to this email directly or view it on GitHubhttps://github.com/robbiehanson/XMPPFramework/issues/101#issuecomment-13145218.

Here's how I understand it: when your app is in background mode, there's only certain events that can "wake it up" to do some processing - for VoIP this event would be some incoming traffic on the socket, for location app - some update in location. But when VoIP socket is closed, there's no way it can receive incoming traffic, so there's nothing that can "wake up" your app. If location update comes and wakes it up, it has a chance to restore the socket, that's why it recovers.
Now, setKeepAliveTimeout supposedly also can wake up your app for, like, 10 sec, so if you manage to connect to server during that time and return from the handler - you're ok, if not - your app is suspended until you bring it to front manually. However beginBackgroundTaskWithExpirationHandler can, supposedly, increase that time interval to 10 minutes.

basants commented Feb 5, 2013

Thats correct because I tried but calling a function using NSTimer when the
app was in background, and it didn't work. Will try with
beginBackgroundTaskWithExpirationHandler once I have the device tomorrow.

On Wed, Feb 6, 2013 at 12:56 AM, misha2400 notifications@github.com wrote:

Here's how I understand it: when your app is in background mode, there's
only certain events that can "wake it up" to do some processing - for VoIP
this event would be some incoming traffic on the socket, for location app -
some update in location. But when VoIP socket is closed, there's no way it
can receive incoming traffic, so there's nothing that can "wake up" your
app. If location update comes and wakes it up, it has a chance to restore
the socket, that's why it recovers.
Now, setKeepAliveTimeout supposedly also can wake up your app for, like,
10 sec, so if you manage to connect to server during that time and return
from the handler - you're ok, if not - your app is suspended until you
bring it to front manually. However
beginBackgroundTaskWithExpirationHandler can, supposedly, increase that
time interval to 10 minutes.


Reply to this email directly or view it on GitHubhttps://github.com/robbiehanson/XMPPFramework/issues/101#issuecomment-13146803.

Contributor

paulmelnikow commented Feb 5, 2013

You know, another thing to try is to register for the connection-related notifications when entering background – the ones which XMPPReconnect needs.

Do you mean Reachability? Did that, don't get notified.
I do get notified when data connection is lost, but never when it's restored, unless I bring the app back into foreground mode. I guess it's not meant for background mode at all.

jonasman commented Feb 5, 2013

You wont get anything via rechability, because you loose the callbacks when the reconnect module asks for them.

The bug in in the cgd async socket.
I tried to debug it but i couldnt find anything.

Enviado do meu iPhone

No dia 05/02/2013, às 21:54, "misha2400" notifications@github.com escreveu:

Do you mean Reachability? Did that, don't get notified.
I do get notified when data connection is lost, but never when it's restored, unless I bring the app back into foreground mode.


Reply to this email directly or view it on GitHub.

basants commented Feb 6, 2013

Reachability doesn't work in background, so that cant be used.

On Wed, Feb 6, 2013 at 1:26 AM, jonasman notifications@github.com wrote:

You wont get anything via rechability, because you loose the callbacks
when the reconnect module asks for them.

The bug in in the cgd async socket.
I tried to debug it but i couldnt find anything.

Enviado do meu iPhone

No dia 05/02/2013, às 21:54, "misha2400" notifications@github.com
escreveu:

Do you mean Reachability? Did that, don't get notified.
I do get notified when data connection is lost, but never when it's
restored, unless I bring the app back into foreground mode.


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHubhttps://github.com/robbiehanson/XMPPFramework/issues/101#issuecomment-13148481.

Update: setKeepAliveTimeout helped, it connects me back to the server within 10 minutes. This is ok for me, if you want to connect immediately once data network is available, you will need to find another solution. That solution definitely exists, because I can see VoIP programs restore their connection in background within seconds after device comes back from Airplane Mode.

bluemoon commented Feb 7, 2013

What do you have your timeout set to?

Actually I just looked at my logs and I see the interval between keepAlive handler calls varies and sometimes it's less than 10 minutes and sometimes it's several hours. So, I guess I still have no idea how it actually works, but it definitely keeps my client connected to server, which is all I care about.

basants commented Feb 8, 2013

So if we set the setKeepAliveTimeout, our client will be connected as soon
as the internet is back and our app is in the background ? (if network is
up within 10 mins)

And yes skype does connect in background, so does KIK messenger, so there
has to be a solution for that. Thanks for the update though.

We had our QA firm look at the issue, it appears that when the user is changing connections we have the most issues.

basants commented Feb 14, 2013

Just an update, Skype uses push notification, so does KIK messenger to
reconnect in background.

How we tested it ? Log into KIK messenger, kill it and send messages, you
will still receive them. Skype uses push only for incoming voice calls.
This basically leaves us with integrating push notification with openfire
server if we want the auto reconnect functionality in background.

On Thu, Feb 14, 2013 at 4:17 AM, Bradford Toney notifications@github.comwrote:

We had our QA firm look at the issue, it appears that when the user is
changing connections we have the most issues.


Reply to this email directly or view it on GitHubhttps://github.com/robbiehanson/XMPPFramework/issues/101#issuecomment-13523036.

After a significant amount of digging, I think i've narrowed it down to a specific issue in CocoaAsyncSocket. robbiehanson/CocoaAsyncSocket#131

yeah, i have been telling that the bug is for sure in the Asyncsocket.
Now to find the solution it is not that easy

In my case i remade the module and adjusted it to my case.
In short:

I added the rechability code from apple. And keep it running all the time instead of when there is a disconnect.

My logic:
Try reconnect with timer when connection fails. After authenticated stop timer.
When stream error, start reconnect.
If wlan/3g changes, disconnect and reconnect.
if no iternet, stop the reconnect timer until the internet comes back, when it comes back start the reconnect again.

With this logic change i was able to cover all of the reconnect problems and internet problems.

jonasman, how do you keep reachability running when the program is in the background mode? In my tests reachability doesn't wake your program up when network status changes.

I dont use background mode.
I only use the background task ( beginBackgroundTaskWithExpirationHandler ). In this case it works.
But I dont keep my app running forever, I just use it to complete tasks or other small things.

I am working on chat app using xmpp framework. I am facing connection issue on 3G network when network goes off or i put the device on airplane mode the application does not connect again it try to reconnect but connection never goes successful. I had tried all the options mention in the post buy unfortunately none of them is working in my case.

the application is working fine on WiFi network automatically reconnect on network failure, when network come again.

Kindly help me out to fix the reconnection issue on 3G network.
Looking for kind help

Regards,
Chauhan

So any luck to make XMPP stream connected to server, while application is in background. I got the app disconnected after 3 mins and no mechanism helped that can make the application alive other then calling it to foreground.

Regards,
Tarun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment