From b46e06fcf1b289bb6a3b2307c10e1a7274c5f3b5 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 1 May 2020 19:25:24 -0700 Subject: [PATCH] Terminate the connection if video isn't received for 10 seconds --- src/ControlStream.c | 2 +- src/Limelight.h | 11 +++++++++++ src/VideoStream.c | 12 ++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/ControlStream.c b/src/ControlStream.c index 0f8957f..d34a2ae 100644 --- a/src/ControlStream.c +++ b/src/ControlStream.c @@ -564,7 +564,7 @@ static void controlReceiveThreadFunc(void* context) { // SERVER_TERMINATED_INTENDED if (terminationReason == 0x0100) { // Pass error code 0 to notify the client that this was not an error - terminationErrorCode = 0; + terminationErrorCode = ML_ERROR_GRACEFUL_TERMINATION; } else { // Otherwise pass the reason unmodified diff --git a/src/Limelight.h b/src/Limelight.h index d2053b5..a76df91 100644 --- a/src/Limelight.h +++ b/src/Limelight.h @@ -352,6 +352,17 @@ typedef void(*ConnListenerConnectionStarted)(void); // to LiStopConnection() or LiInterruptConnection(). typedef void(*ConnListenerConnectionTerminated)(int errorCode); +// This error code is passed to ConnListenerConnectionTerminated() when the stream +// is being gracefully terminated by the host. It usually means the app on the host +// PC has exited. +#define ML_ERROR_GRACEFUL_TERMINATION 0 + +// This error is passed to ConnListenerConnectionTerminated() if no video data +// was ever received for this connection after waiting several seconds. It likely +// indicates a problem with traffic on UDP 47998 due to missing or incorrect +// firewall or port forwarding rules. +#define ML_ERROR_NO_VIDEO_TRAFFIC -100 + // This callback is invoked to log debug message typedef void(*ConnListenerLogMessage)(const char* format, ...); diff --git a/src/VideoStream.c b/src/VideoStream.c index c557b71..856de60 100644 --- a/src/VideoStream.c +++ b/src/VideoStream.c @@ -75,6 +75,7 @@ static void ReceiveThreadProc(void* context) { char* buffer; int queueStatus; int useSelect; + int waitingForVideoMs; receiveSize = StreamConfig.packetSize + MAX_RTP_HEADER_SIZE; bufferSize = receiveSize + sizeof(RTPFEC_QUEUE_ENTRY); @@ -89,6 +90,7 @@ static void ReceiveThreadProc(void* context) { useSelect = 0; } + waitingForVideoMs = 0; while (!PltIsThreadInterrupted(&receiveThread)) { PRTP_PACKET packet; @@ -108,6 +110,16 @@ static void ReceiveThreadProc(void* context) { break; } else if (err == 0) { + if (!receivedDataFromPeer) { + // If we wait many seconds without ever receiving a video packet, + // assume something is broken and terminate the connection. + waitingForVideoMs += UDP_RECV_POLL_TIMEOUT_MS; + if (waitingForVideoMs >= FIRST_FRAME_TIMEOUT_SEC * 1000) { + ListenerCallbacks.connectionTerminated(ML_ERROR_NO_VIDEO_TRAFFIC); + break; + } + } + // Receive timed out; try again continue; }