From 1c507795981ece94c8b66658563d799b11bcb81f Mon Sep 17 00:00:00 2001 From: Nils Zottmann <44364366+nzottmann@users.noreply.github.com> Date: Mon, 13 Feb 2023 13:22:38 +0100 Subject: [PATCH] Allow RTCP packets for keepalive also in state PLAY (#185) (#186) * Allow RTCP packets for keepalive also in state PLAY (#185) * use sessionTimeout instead of ReadTimeout * reset udpLastPacketTime before PLAY and RECORD * change error message in case of timeouts * fix comment --------- Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com> --- pkg/liberrors/server.go | 16 ++++------------ server_session.go | 20 +++++++++++++------- server_session_media.go | 3 +++ 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/pkg/liberrors/server.go b/pkg/liberrors/server.go index 4f19606e..d0049f3a 100644 --- a/pkg/liberrors/server.go +++ b/pkg/liberrors/server.go @@ -24,20 +24,12 @@ func (e ErrServerSessionNotFound) Error() string { return "session not found" } -// ErrServerNoUDPPacketsInAWhile is an error that can be returned by a server. -type ErrServerNoUDPPacketsInAWhile struct{} +// ErrServerSessionTimedOut is an error that can be returned by a server. +type ErrServerSessionTimedOut struct{} // Error implements the error interface. -func (e ErrServerNoUDPPacketsInAWhile) Error() string { - return "no UDP packets received in a while" -} - -// ErrServerNoRTSPRequestsInAWhile is an error that can be returned by a server. -type ErrServerNoRTSPRequestsInAWhile struct{} - -// Error implements the error interface. -func (e ErrServerNoRTSPRequestsInAWhile) Error() string { - return "no RTSP requests received in a while" +func (e ErrServerSessionTimedOut) Error() string { + return "session timed out" } // ErrServerCSeqMissing is an error that can be returned by a server. diff --git a/server_session.go b/server_session.go index fd42cddd..8614056c 100644 --- a/server_session.go +++ b/server_session.go @@ -412,16 +412,18 @@ func (ss *ServerSession) runInner() error { case <-ss.udpCheckStreamTimer.C: now := time.Now() + lft := atomic.LoadInt64(ss.udpLastPacketTime) + // in case of RECORD, timeout happens when no RTP or RTCP packets are being received if ss.state == ServerSessionStateRecord { - lft := atomic.LoadInt64(ss.udpLastPacketTime) if now.Sub(time.Unix(lft, 0)) >= ss.s.ReadTimeout { - return liberrors.ErrServerNoUDPPacketsInAWhile{} + return liberrors.ErrServerSessionTimedOut{} } - // in case of PLAY, timeout happens when no RTSP keepalives are being received - } else if now.Sub(ss.lastRequestTime) >= ss.s.sessionTimeout { - return liberrors.ErrServerNoRTSPRequestsInAWhile{} + // in case of PLAY, timeout happens when no RTSP keepalives and no RTCP packets are being received + } else if now.Sub(ss.lastRequestTime) >= ss.s.sessionTimeout && + now.Sub(time.Unix(lft, 0)) >= ss.s.sessionTimeout { + return liberrors.ErrServerSessionTimedOut{} } ss.udpCheckStreamTimer = time.NewTimer(ss.s.checkStreamPeriod) @@ -573,8 +575,6 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base ss.setuppedQuery = query ss.announcedMedias = medias - v := time.Now().Unix() - ss.udpLastPacketTime = &v return res, err case base.Setup: @@ -860,6 +860,9 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base ss.state = ServerSessionStatePlay + v := time.Now().Unix() + ss.udpLastPacketTime = &v + for _, sm := range ss.setuppedMedias { sm.start() } @@ -949,6 +952,9 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base ss.state = ServerSessionStateRecord + v := time.Now().Unix() + ss.udpLastPacketTime = &v + for _, sm := range ss.setuppedMedias { sm.start() } diff --git a/server_session_media.go b/server_session_media.go index 41796531..ff996946 100644 --- a/server_session_media.go +++ b/server_session_media.go @@ -165,6 +165,9 @@ func (sm *serverSessionMedia) readRTCPUDPPlay(payload []byte) error { return nil } + now := time.Now() + atomic.StoreInt64(sm.ss.udpLastPacketTime, now.Unix()) + for _, pkt := range packets { sm.onPacketRTCP(pkt) }