Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ class SrtStreamClient(
srtClient.setLogs(enabled)
}

/**
* Report a connection failure if the server sends nothing for [millis] (0 = disabled).
* See [com.pedro.srt.srt.SrtClient.setServerSilenceTimeout].
*/
fun setServerSilenceTimeout(millis: Long) {
srtClient.setServerSilenceTimeout(millis)
}

override fun setCheckServerAlive(enabled: Boolean) {
srtClient.setCheckServerAlive(enabled)
}
Expand Down
23 changes: 23 additions & 0 deletions srt/src/main/java/com/pedro/srt/srt/SrtClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.pedro.common.ConnectionFailed
import com.pedro.common.UrlParser
import com.pedro.common.VideoCodec
import com.pedro.common.frame.MediaFrame
import com.pedro.common.TimeUtils
import com.pedro.common.onMainThread
import com.pedro.common.socket.base.SocketType
import com.pedro.common.socket.base.StreamSocket
Expand Down Expand Up @@ -80,6 +81,7 @@ class SrtClient(private val connectChecker: ConnectChecker) {
private var jobRetry: Job? = null

private var checkServerAlive = false
private var serverSilenceTimeoutMs = 0L
@Volatile
var isStreaming = false
private set
Expand Down Expand Up @@ -169,6 +171,19 @@ class SrtClient(private val connectChecker: ConnectChecker) {
checkServerAlive = enabled
}

/**
* Report onConnectionFailed("No response from server") if no packet is received from the
* server for [millis]. While data is being published, the server acknowledges it with ACK
* packets (typically every 10 ms), so a long silence means the path is dead even if sending
* does not fail (for example, packets silently dropped by the network).
* Unlike [setCheckServerAlive] it needs no ICMP/Echo, which firewalls often block.
* Servers only acknowledge received data, so use a value well above the longest pause in
* which no media is sent. 0 (default) disables the check.
*/
fun setServerSilenceTimeout(millis: Long) {
serverSilenceTimeoutMs = millis
}

fun setReTries(reTries: Int) {
numRetry = reTries
this.reTries = reTries
Expand Down Expand Up @@ -333,11 +348,13 @@ class SrtClient(private val connectChecker: ConnectChecker) {

@Throws(IOException::class)
private suspend fun handleServerPackets() {
var lastServerPacketTs = TimeUtils.getCurrentTimeMillis()
while (scope.isActive && isStreaming) {
val error = runCatching {
if (isAlive()) {
//ignore packet after connect if tunneled to avoid spam idle
handleMessages()
lastServerPacketTs = TimeUtils.getCurrentTimeMillis()
} else {
onMainThread {
connectChecker.onConnectionFailed("No response from server")
Expand All @@ -347,6 +364,12 @@ class SrtClient(private val connectChecker: ConnectChecker) {
}.exceptionOrNull()
if (error != null && ConnectionFailed.parse(error.validMessage()) != ConnectionFailed.TIMEOUT) {
scope.cancel()
} else if (error != null && serverSilenceTimeoutMs > 0 &&
TimeUtils.getCurrentTimeMillis() - lastServerPacketTs >= serverSilenceTimeoutMs) {
onMainThread {
connectChecker.onConnectionFailed("No response from server")
}
scope.cancel()
}
}
}
Expand Down
Loading