[BUG] Airplay client handling creates race conditions
#1
Sorry if this is the wrong place to post this, you guys should probably put a link up on the github repo since I saw you don't use GH issues to track bugs (sad panda).

Kodi handling only one client at a time (https://github.com/xbmc/xbmc/blob/7f627f...r.cpp#L447) for it's Airtunes server causes some really nasty race conditions and contention errors...

Steps to reproduce:

Scenario 1-
1. Start Airplay-ing from laptop
2. Close lid/quit itunes/stop playback by any means except manually disconnecting from Kodi via the iTunes airplay selector
3. Attempt to Airplay from any other device
4a. [rare] Airplay will either connect and register as playing on device while Kodi will not show any sort of airplay connection (or)
4b. [most common] Airplay will refuse to connect on second device

Scenario 2-
1. Start Airplay-ing from laptop
2. Stop playback with pause
3. without manually disconnecting from Kodi via the iTunes airplay selector
3. Attempt to Airplay from any other device
4. Airplay works
5. Simply open up laptop/restart iTunes (don't restart playback!)
6. iTunes' more robust Airplay connection management will attempt to re-handshake
7a. Secondary device playback will drop on Kodi (but not the device!)
7b. Secondary device will get a pause command and refuse to restart playback ("Unknown error" in 3rd party iOS 8 apps, iTunes app on iOS 8 will simply silently fail to restart playback)

Odd sidenote: Sometimes after client restarts (iOS is the main culprit here) Airplay will work again, but the album art displayed on Kodi will be from the previous song from when I was attempting to stream pre-restart, so Kodi is definitely getting the data somehow.

Tested using: RaspberryPi B+, last version of raspbmc (before they moved to "osmc"... this bug might be the impetus for me to upgrade though), iPhone 6 w/ latest iOS 8, and MacbookPro w/ OSX 10.10.2 (14C1514)

I believe the correct behavior here should be handling of up to N clients (say 10 for argument's sake) and simply choosing a stream to play based on the last device to issue a command (essentially embracing the inherent race conditions as a feature and allowing the clients to manage scheduling instead of the server). This is how I believe Apple's implementation works.

At the very least the server should at least cleanly and transparently kill the client connection (or maybe just simulate a server failure if apple clients don't have that logic) when it switches clients, this bug wouldn't be so terribly frustrating if my client devices didn't register as streaming/playing as if everything's fine while Kodi acts like Airplay doesn't exist (this is probably some sort of hung connection that's not being realized on the client side).

As a side note, I've been seriously considering and researching building a standalone Airplay/Airtunes server in Go and have the general stuff down but my C++ isn't good enough to grok the protocol specifics that y'all figured out... did you guys just reverse engineer from scratch or is there anywhere that has some specifics/documentation laid out?
Reply
#2
We rely on the thrid party library for airtunes (which is the music streaming part of airplay).

https://github.com/juhovh/shairplay

It should handle multiple connections - but i am sure that the kodi side of the code might not handle it well. There are multiple problems. First of all as far as i know airtunes is unidirectional - there is no possibility to talk to the client and say "go off my roof and disconnect". Second problem is that the tcp connections are handled inside of libshairplay and we only get some callbacks.

To track the issue down it would be helpfull to see a debug log (wiki) with airtunes component logging turned on (somewhere in settings->system->debug). And then some easy scenario which doesn't produce so much log spam (like what you described first).

Just in case you are able to look into it (you posted in the developer section and seem to be a developer indeed):

This is the kodi part of the airtunes implementation which interfaces with libshairplay.

https://github.com/xbmc/xbmc/blob/master...Server.cpp

From my side this has low priority (because i don't have much spare time atm for kodi at all and have to maintain some other vital parts of the project). But if you have time to track down a solution i am willing to help to bring it into mainline (or answer any questions of course).

PS: Normal use case i know of is only to use one client at a time (and properly disconnecton client side when switching clients) - i am sure thats nothing you wanna hear Wink
AppleTV4/iPhone/iPod/iPad: HowTo find debug logs and everything else which the devs like so much: click here
HowTo setup NFS for Kodi: NFS (wiki)
HowTo configure avahi (zeroconf): Avahi_Zeroconf (wiki)
READ THE IOS FAQ!: iOS FAQ (wiki)
Reply
#3
Drat, yeah that's definitely not what I wanted to hear. I know it's basically RTSP but I had hoped Apple would add some goodies to it that would make it easier to handle unreliable device connections.

I found the logs already and didn't find anything unusual in them, but I'll try to reproduce and get you a copy. No worries about the priority, I'll live. Thanks for the shairport links as well!
Reply

Logout Mark Read Team Forum Stats Members Help
[BUG] Airplay client handling creates race conditions0