AIR-Mobile-UDP-Extension icon indicating copy to clipboard operation
AIR-Mobile-UDP-Extension copied to clipboard

Un-bind socket?

Open perholmes opened this issue 11 years ago • 9 comments

Hi,

I'm having some trouble with UDP sockets getting un-bound by iOS when the device goes to sleep and comes back on, or if the network substantially changes.

Is there are right way to handle this? The desktop DatagramSocket has a .bound property, but I don't know how to test the mobile UDP socket class for whether it's bound or not.

If this is missing, I'd love to do some sponsored development. I don't know what the rules on GitHub are, so hopefully I'm not suggesting something wrong. But I think that this is a valuable class, and I'd love to see you also make something from it.

Best,

Per

perholmes avatar Apr 17 '13 13:04 perholmes

I'll take a look at this, this isn't implemented yet, but I can figure that it would be a nice add-on. I'll put it on my weekend to-do list :)

wouterverweirder avatar Apr 18 '13 17:04 wouterverweirder

Hi Wouter,

The issue mainly is that I've had some crashed that had to do with coming in and out of sleep, or with the network changing, and I wasn't sure how the ANE intends to handle it. For example, what happens to the bind if WiFi disappears, or you get a new IP address. I haven't seen these crashes lately, but I also haven't stress tested my app with changing the network a lot, and I've stopped responding to NetworkInfoChange events from NetworkInfo if the IP address ends up being the same.

But basically, it would be great to know what the correct way is to respond to a changing network. I've also had the feeling that iOS sometimes forcibly unbinds the socket, and then the app crashes because it thinks it's still bound. It's a feeling, not scientific.

Thanks!

Per

perholmes avatar Apr 18 '13 17:04 perholmes

Hi,

Yes, just to confirm the issue, the port seems to get unbound when iOS suspends the app. This doesn't necessarily happen just because you switch out of it, it happens later, presumably when iOS decides the app is no longer used.

So even though I could switch in and out of the app last night and put the device to sleep, when I opened up both my iPads this morning and used any function in the app that wanted to send UDP, the app immediately crashed.

I have global exception handling in the app, so had it been a code error, It would have been trapped. Instead, the app immediately crashed and disappeared the immediately millisecond I used a network function.

This tells me that the OS is unbinding the port, but the ANE doesn't know it.

If you have a way of testing if the bind is still valid in your connection to the OS, I propose either of the following solutions:

  • An event that fires when a port is unbound by the OS.
  • A way to test if you're bound (e.g. IsBound()). Then I can call that before any desired network activity.
  • A flag to auto-rebind, which is selected when you called bind().

I'm not distinguishing between inbound and outbound data here, because I never got outbound data to work unless I was always bound on the receiving socket. I don't know how these are distinguished internally.

So in reality, it seems you need to both be able to detect if sending is still possible, as well as whether the receiving port is still bound.

Best,

Per

perholmes avatar Apr 20 '13 07:04 perholmes

Been working on it, have to redo the iOS code to use ARC, to be able to use the latest version of the UDP socket library. I'm now able to send out a close event when the OS closes the socket. Will need to do some android refactoring as well before I push to github

wouterverweirder avatar Apr 21 '13 19:04 wouterverweirder

This is excellent! Please let me donate, I'm using this professionally, and I value your work.

Best,

Per

perholmes avatar Apr 21 '13 19:04 perholmes

I pushed support for the "close" event. This is iOS 6+ atm, will look into supporting lower iOS versions later. Let me know how this works atm. Android is on my todo as well.

wouterverweirder avatar Apr 22 '13 14:04 wouterverweirder

Great! I don't think it's important to support earlier versions of iOS, but that's just for my personal purposes.

One thing occurred to me: If the forced unbind is event-based, what are the chances that my app will try to fire an UDP transmission before receiving the event that the port has been unbound? If the ANE has awareness of this, perhaps it would also be a good idea to save the status and implement an IsBound() function that can be called immediately before trying to use the port? Then the event is more to detect that listening has stopped and then deal with it appropriately.

In my particular app, the UDP packets are used to synchronize devices for something time-critical, and I actually use audio-timers in order to not rely on EnterFrame and getTimer(), because the jitter is upwards of 40 ms. This means that if I return from suspension, there's a chance that the audio-timer events will run even before the unbind event or even Activate() for the app. In this case, I'm worried that the app will still crash because I receive the unbind event 1 millisecond too late. I don't control which order events execute in, and when the app is running, I need to fire the UDP sync events on a very regular schedule.

So I think that if you'd be able to save the bind status, with an IsBound() function to read it, it would be safer.

Best,

Per

perholmes avatar Apr 22 '13 15:04 perholmes

Okay - I am facing a problem which might be related to this issue - for some reason I suddenly cannot bind() anymore (might have been that the app had crashed or I force-closed it). Even reinstalling the app does not help. So now I wonder what I can do to release that port.

Quasimondo avatar Apr 23 '13 16:04 Quasimondo

Sounds strange. iOS / Android? How about rebooting device, test with latest ane (which fixes a crash in android)? Can you tell me the steps to reconstruct this issue?

wouterverweirder avatar Apr 23 '13 17:04 wouterverweirder