karlheyes / icecast-kh

KH branch of icecast
GNU General Public License v2.0
298 stars 107 forks source link

now-playing info in icecast > kh17 broken on iOS devices #441

Open dicksnippe opened 10 months ago

dicksnippe commented 10 months ago

Hello,

recently it was brought to our attention that the now-playing info in our icecast streams was missing in our icecast streams on iOS devices. E.g. on the RadioNED, myTuner and NederlandFM apps on iOS for the NPO Radio 1-5 stations.

As it turns out this is because of a better handling of range requests in icecast versions >kh17. My guess is that all these apps use the same SDK or mediaplayer, probably the default, apple provided one. The way the iOS mediaplayer works is that it first sends a range requests for bytes 0-1 and if that succeeds (HTTP 206) it sends a second range request for bytes 0-1073741822 However! on this second range request iOS appears to "forget" to send the Icy-MetaData header, so the server doesn't provide any metadata, hence now-playing doesn't work anymore.

If the response to the initial range request is a HTTP 200 (as opposed to a HTTP 206). iOS does a regular HTTP GET (i.e. without range header), but with Icy-MetaData header and all is well.

Now, the question is imo: "How to go about this (stupid) behaviour. I wrote a very simple patch that I intend to roll out on our platform, to simply revert back to the older, pre-kh17 behaviour. However, that obvously kills the range request functionality. So maybe it should be a config option? Or may be looking at the User-Agent ? That appears to be AppleCoreMedia/<version> on the apps that I tested.

For the record, this is my braindead patch:

diff -Nurp icecast-tls-2.4.0-kh22.cs8_64.org/src/format.c icecast-tls-2.4.0-kh22.cs8_64/src/format.c
--- icecast-tls-2.4.0-kh22.cs8_64.org/src/format.c      2023-07-04 22:36:53.000000000 +0200
+++ icecast-tls-2.4.0-kh22.cs8_64/src/format.c  2023-11-23 16:00:55.500052866 +0100
@@ -435,7 +435,7 @@ static int apply_client_tweaks (ice_http
         uint64_t range = client->connection.discon.sent;
         char total_size [32] = "*";

-        if (range == 0 || (fs == NULL && range > (1<<30)))
+        if (range == 0 || (fs == NULL))
         {       // ignore most range requests on streams, treat as full
             client->connection.discon.sent = 0;
             client->intro_offset = 0;
biosmatrix123 commented 8 months ago

I've just changed from Icecast 2.4.4 -> Icecast 2.4.0-kh22 and noticed this issue - I'll be re-compiling with your patch, hopefully it fixes it - thanks!

Question: What's the benefit of range requests?

voidzero commented 8 months ago

Thanks for this solution. Hope @karlheyes will be able to address it, I'm about to move over to some new systems, and would really like to use -kh.

dicksnippe commented 8 months ago

@biosmatrix123 : IOS devices use range requests, because it allows them to switch more easily between networks. Suppose a classical single HTTP request were used and suppose that the client changed network (from wifi to 4G or somesuch) then the connection would stall, because the new network connection is associated with a different IP address. Range requests allow mobile devices to overcome this problem. Instead of doing 1 big request, the device does a number of smaller requests (maybe 5-10 seconds each or something like that). And now when the device switches network, ideally there's no drop or stall at all, because the newer requests are done using the new network.