Fix: TCP connections never send a keepalive, causing periodic disconnects - #416
Open
Fimeg wants to merge 1 commit into
Open
Fix: TCP connections never send a keepalive, causing periodic disconnects#416Fimeg wants to merge 1 commit into
Fimeg wants to merge 1 commit into
Conversation
TCP-connected cameras drop their Baichuan session after a few minutes of otherwise-idle traffic, forcing a reconnect that surfaces as a periodic blip in downstream consumers (Frigate, etc.). UDP sessions are kept alive by the camera itself, which sends MSG_ID_UDP_KEEP_ALIVE and which we acknowledge; TCP had no equivalent, so nothing kept the session warm. Send a periodic MSG_ID_PING on TCP connections to hold the session open. The ping is fire-and-forget and any reply is ignored.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Cameras connected over TCP (the common case —
address = "ip:9000", as opposed touid = "..."over UDP) silently drop their Baichuan session after a few minutes of otherwise-idle traffic, then reconnect. The reconnect is automatic, but it surfaces as a periodic blip in downstream consumers (Frigate, etc.), which is disruptive for continuous recording and motion detection.Root cause
UDP sessions are kept alive by the camera itself: it sends
MSG_ID_UDP_KEEP_ALIVE, which neolink acknowledges inBcCamera::keepalive(). TCP has no equivalent — nothing flows during idle periods — so the camera times the session out. There is aBcCamera::ping()(MSG_ID_PING) that looks purpose-built for this, but it is currently dead code (no call sites).Fix
Send a fire-and-forget
MSG_ID_PINGevery 60s on TCP connections only, to hold the session open. UDP is left untouched, since it already keeps itself alive.BcCamera::new()now tracks whether the transport is UDP and, for TCP, spawns a task that sendsMSG_ID_PINGon an interval. The task ends on its own once the connection goes away (the send returns an error).BcConnection::sendis widened frompub(super)topub(crate)so the keepalive can be sent without subscribing for a reply.Validation
The same approach (a periodic
MSG_ID_PINGon TCP) has been running in production on TCP/Baichuan cameras (port 9000) where it eliminated reconnects that previously recurred every few minutes without fail. This PR ports that fix to currentmaster.