FDH2 / UxPlay

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

Gracefully reset Uxplay if network close from iOS/Mac device #181

Closed malikAr closed 1 year ago

malikAr commented 1 year ago

Hi Team,

I am facing issue if mirroring is running and if we close the network from either mac or iOS , uxplay window stuck and not resetting itself.

Any help or suggestion.

fduncanh commented 1 year ago

please give details about the mac. (model, operating system etc.) (new or old)

if you stop mirroring on iOS the mac window remains open, but is available for a new connection.

This is an old workaround for an issue.

at line 1296 of uxplay.cpp there is this :

#if __APPLE__
    /* force use of -nc option on macOS */
    LOGI("macOS detected: use -nc option as workaround for GStreamer problem");
    new_window_closing_behavior = false;
#endif

try commenting this out and report back

(without the fix you probably get a segfault when you stop mirroring on iOS)

(This is a problem that needs a fix, it hasn't been looked at for a long time). EDIT: this is a gstreamer issue, please give details about which gstreamer version you are using,

malikAr commented 1 year ago

@fduncanh, Actually my uxplay running on fedora 18.0 and when we present from iOS mirroring works fine on the Linux system. Then if we forcefully switch off iPhone wifi the, mirroring widow is stuck and not closed gracefully.

Hope now the issue is clear.

fduncanh commented 1 year ago

OK: If I now understand correctly: There is nothing special about macOS clients: iOS and macOS clients behave similarly you say

  1. UxPlay is running on Fedora 18.0
  2. when you connect from iOS device (iPhone) no problem when you stop mirroring, window closes.
  3. when you just disconnect the iphone from the network, so it "disappears", the window remains open

Yes, this is what was supposed to happen. The window remains open in case the client manages to recover the network connection and reconnect. Do you propose a different solution? Maybe a timeout after which the window on the server closes? Or an option that users with a bad network need to select? This was put in place to deal with a user's mysterious problem which turned out to be a bad router.

The "Troubleshooting" section of the README says:

  1. Mirror screen freezes:

This can happen if the TCP video stream from the client stops arriving at the server, probably because of network problems (the UDP audio stream may continue to arrive). At 3-second intervals, UxPlay checks that the client is still connected by sending it a request for a NTP time signal. If a reply is not received from the client within a 0.3 sec time-window, an "ntp timeout" is registered. If a certain number (currently 5) of consecutive ntp timeouts occur, UxPlay assumes that the client is "dead", and resets the connection, becoming available for connection to a new client, or reconnection to the previous one. Sometimes the connection may recover before the timeout limit is reached, and if the default limit is not right for your network, it can be modified using the option "-reset n", where n is the desired timeout-limit value (n = 0 means "no limit"). If the connection starts to recover after ntp timeouts, a corrupt video packet from before the timeout may trigger a "connection reset by peer" error, which also causes UxPlay to reset the connection. When the connection is reset, the "frozen" mirror screen of the previous connection is left in place, and will be taken over by a new client connection when it is made.

fduncanh commented 1 year ago

To be clear.

In normal use, uxplay is locked to a client until it disconnects. (There is a -nohold option to change this)

If the client just "vanishes" from the network, the lock is removed after an interval (15 secs by default), but the mirror window is not closed.

A different client is able to connect after the lock is removed.

fduncanh commented 1 year ago

The behavior you don't like can be got rid of by commenting out the line 1017 of uxplay.cp "close_window = reset video" (see below).

The idea of it was to preserve the screen someone reconnects after a lost connection. Maybe this is not the right thing to do? It is easy to change

extern "C" void conn_reset (void *cls, int timeouts, bool reset_video) {
    LOGI("***ERROR lost connection with client (network problem?)");
    if (timeouts) {
        LOGI("   Client no-response limit of %d timeouts (%d seconds) reached:", timeouts, 3*timeouts);
        LOGI("   Sometimes the network connection may recover after a longer delay:\n"
             "   the default timeout limit n = %d can be changed with the \"-reset n\" option", NTP_TIMEOUT_LIMIT);
    }
    printf("reset_video %d\n",(int) reset_video);
    close_window = reset_video;    /* leave "frozen" window open if reset_video is false */  <=========HERE (line 107)
    raop_stop(raop);
    reset_loop = true;
}
malikAr commented 1 year ago

@fduncanh so can I use -nohold option, then its works fine.

fduncanh commented 1 year ago

I dont think you need -nohold, I tested (on Fedora 38)

But maybe your issue is different from what I thought (the lost connection timeout) In that case you would see (on the uxplay terminal)

raop_ntp receive timeout 2 (limit 5) (request sent 55094-05-11 )    <(-I see a recent change has messed up dates here)
raop_ntp receive timeout 3 (limit 5) (request sent 55094-05-11 )
raop_ntp receive timeout 4 (limit 5) (request sent 55094-05-11 )
raop_ntp receive timeout 5 (limit 5) (request sent 55094-05-11 )
***ERROR lost connection with client (network problem?)
   Client no-response limit of 5 timeouts (15 seconds) reached:
   Sometimes the network connection may recover after a longer delay:
   the default timeout limit n = 5 can be changed with the "-reset n" option
reset_video 0
Removing connection for socket 24
raop_rtp_mirror->running is no longer true
Removing connection for socket 26
Initialized server socket(s)
fduncanh commented 1 year ago

seems done