FDH2 / UxPlay

AirPlay Unix mirroring server
GNU General Public License v3.0
1.53k stars 78 forks source link

macOS requires ipv6 "zone_id" , now implemented (was: ERROR: raop_ntp error sending request) #296

Closed galvezam closed 4 months ago

galvezam commented 4 months ago

This issue appeared when running UxPlay 1.68.3 on macOS:

Client identified as User-Agent: AirPlay/760.20.1 ERROR: raop_ntp error sending request Accepted IPv6 client on socket 29 Local: fe80:0000:0000:0000:0c61:9b2c:9a74:09b0 Remote: fe80:0000:0000:0000:0cbc:827b:d26e:1c64 raop_rtp_mirror starting mirroring ERROR: *** invalid ntp_time < gst_video_pipeline_base_time 599854.608661 ntp_time

Thoughts on how to fix?

fduncanh commented 4 months ago

yes, confirming that this happens.

For some reason the ntp timing doesnt get set up properly. (it used to work, it would be good to test some older uxplay releases to see when this got broken) (or it could be a macOS change).

fduncanh commented 4 months ago

This is the issue:

*** ERROR: raop_ntp error sending request

need to find out what is causing this (sending timing request to client to fail) on macOS perhaps macOS has started to block some network ports unless they get opened???

the error message says that the timing request could not be sent !!! (sendto( , ...) failed)

from lib/raop_ntp.c:

        // Send request
        uint64_t send_time = raop_ntp_get_local_time(raop_ntp);
        byteutils_put_ntp_timestamp(request, 24, send_time);
        int send_len = sendto(raop_ntp->tsock, (char *)request, sizeof(request), 0,
                              (struct sockaddr *) &raop_ntp->remote_saddr, raop_ntp->remote_saddr_len);
        if (logger_debug) {
            char *str = utils_data_to_string(request, sizeof(request), 16);
            logger_log(raop_ntp->logger, LOGGER_DEBUG, "\nraop_ntp send time type_t=%d packetlen = %d, now = %8.6f\n%s",
                       request[1] &~0x80, sizeof(request), (double) send_time / SECOND_IN_NSECS, str);
            free(str);
        }
        if (send_len < 0) {
            logger_log(raop_ntp->logger, LOGGER_ERR, "raop_ntp error sending request");
        } else {
            // Read response
fduncanh commented 4 months ago

Added extra output to identify error in sendto:

*** ERROR: raop_ntp  sending request
Error Number 65
Error Description: No route to host

?? maybe the timing port is now blocked by macOS unless it is opened somehow? or its an ipv6 issue (ipv6 was recently activated)

fduncanh commented 4 months ago

the latest github uxplay code will show this error code.

If you are able to diagnose why it occurs on macOS that would be a help (otherwise it will investigated here as soon as time permits)

fduncanh commented 4 months ago

when ipv6 was disabled , error goes away. this will allow us to track it down.

thiccaxe commented 4 months ago

Try checking what the builtin ios -> macos mirroring is doing with wireshark. Maybe NTP is over ipv4 even if everything else is over ipv6?

galvezam commented 4 months ago

the latest github uxplay code will show this error code.

If you are able to diagnose why it occurs on macOS that would be a help (otherwise it will investigated here as soon as time permits)

I tried the new code from lib/raop_ntp:c and got this error:

UxPlay 1.68: An Open-Source AirPlay mirroring and audio-streaming server. macOS detected: use -nc option as workaround for GStreamer problem

(:93481): GStreamer-GL-WARNING **: 13:59:17.778: An NSApplication needs to be running on the main thread to ensure correct behaviour on macOS. Use gst_macos_main() or call [NSApplication sharedApplication] in your code before using this element. using system MAC address 3e:33:dc:59:f5:d1 Initialized server socket(s) Accepted IPv6 client on socket 26 Local: fe80:0000:0000:0000:1879:e912:602d:1060 Remote: fe80:0000:0000:0000:0c92:afad:f1b0:27bd connection request from Matthew’s iPhone (2) (iPhone15,2) with deviceID = 90:EC:EA:DB:72:C6

Client identified as User-Agent: AirPlay/760.20.1 ERROR: raop_ntp error sending request Accepted IPv6 client on socket 29 Local: fe80:0000:0000:0000:1879:e912:602d:1060 Remote: fe80:0000:0000:0000:0c92:afad:f1b0:27bd raop_rtp_mirror starting mirroring Begin streaming to GStreamer video pipeline ERROR: raop_ntp error sending request ERROR: raop_ntp error sending request ERROR: raop_rtp_mirror error in select Connection closed for socket 26 Connection closed for socket 29

fduncanh commented 4 months ago

This isnt the latest code (get it with git clone https://github.com/FDH2/UxPlay) because ** ERROR: raop_ntp error sending request is not displaying the error number.

this issue is something in the ipv6 support. If you can't wait for the solution to be discovered you can disable ipv6 by undoing this commit:

https://github.com/FDH2/UxPlay/commit/088f6be0fb05be513089cef6edf9963702a3fa9e

fduncanh commented 4 months ago

The IPV6 support works fine on Linux and Windows with activated. It hadn't been tested on MacOS, we just assumed it worked fine too. Some research on the internet shows ipv6 ihas some extra complications on macOS

e.g. https://github.com/netty/netty/issues/11563

ipv6 by uxplay on macOS has now been disabled by default in the github source, until it is sorted out.

fduncanh commented 4 months ago

@thiccaxe

it seems to be something to do with "zone id's" of link-local ipv6 addresses, that macOS cares about, but linux and windows dont seem to.

https://superuser.com/questions/99746/why-is-there-a-percent-sign-in-the-ipv6-address

https://github.com/netty/netty/issues/11563

https://networkengineering.stackexchange.com/questions/46653/what-is-the-use-of-the-ipv6-scope-id

fduncanh commented 4 months ago

The issue is that when the ipadOS client request a connection with uxplay on macOS with ipv6 enabled, both the local and remote ipv6 addresss are given temporary link-local values fe80::xxxx:xxxx:xxxx:xxxx%en0 (en0 = scope_id 0x0000000f) written into local and remote sockaddr. On linux (and I guess, windows) the full external ipv6 address (with no scope id) is used......

fduncanh commented 4 months ago

Its exactly what all those other reports I found were experiencing.

macOS prefers to use "link local" ipv6 addresses fe80::xxxx:xxxx:xxxx:xxxx%xxxx on a local network, and these need that extra %xxxx "scope_id" postpended to the ipaddress. Its there as a separate entry in the "sockaddr" struct in "receive" when the connection is made, but is no longer in the sockaddr (or set to 0) used when the "sendto" is called. Some copying of the sockaddr that doesnt know to copy the "scope_id" as well must be happening.

fduncanh commented 4 months ago

@galvezam

The macOS ipv6 issue is now solved. (macOS uses "link-local" ipv6 addresses on the local network, and these needed a ipv6 feature called the "zone_id" (interface index n) only needed by link-local (fe80::xxxx:xxxx:xxxx:xxxx%n) ipv6 addresses. Linux and Windows don't use link-local addresses, so they had working ipv6 already).

Thank you for bringing this issue to our attention!