server: add error to OnSessionClose()

This commit is contained in:
aler9
2021-05-04 15:51:35 +02:00
committed by Alessandro Ros
parent 6f749e6ba8
commit 9d42a63102
9 changed files with 99 additions and 79 deletions

View File

@@ -38,7 +38,7 @@ func (sh *serverHandler) OnSessionOpen(ss *gortsplib.ServerSession) {
} }
// called when a session is closed. // called when a session is closed.
func (sh *serverHandler) OnSessionClose(ss *gortsplib.ServerSession) { func (sh *serverHandler) OnSessionClose(ss *gortsplib.ServerSession, err error) {
log.Printf("session closed") log.Printf("session closed")
sh.mutex.Lock() sh.mutex.Lock()

View File

@@ -37,7 +37,7 @@ func (sh *serverHandler) OnSessionOpen(ss *gortsplib.ServerSession) {
} }
// called when a session is closed. // called when a session is closed.
func (sh *serverHandler) OnSessionClose(ss *gortsplib.ServerSession) { func (sh *serverHandler) OnSessionClose(ss *gortsplib.ServerSession, err error) {
log.Printf("session closed") log.Printf("session closed")
sh.mutex.Lock() sh.mutex.Lock()

View File

@@ -7,6 +7,22 @@ import (
"github.com/aler9/gortsplib/pkg/headers" "github.com/aler9/gortsplib/pkg/headers"
) )
// ErrServerTerminated is an error that can be returned by a server.
type ErrServerTerminated struct{}
// Error implements the error interface.
func (e ErrServerTerminated) Error() string {
return "terminated"
}
// ErrServerSessionTimedOut is an error that can be returned by a server.
type ErrServerSessionTimedOut struct{}
// Error implements the error interface.
func (e ErrServerSessionTimedOut) Error() string {
return "timed out"
}
// ErrServerTCPFramesEnable is an error that can be returned by a server. // ErrServerTCPFramesEnable is an error that can be returned by a server.
type ErrServerTCPFramesEnable struct{} type ErrServerTCPFramesEnable struct{}
@@ -192,11 +208,11 @@ func (e ErrServerLinkedToOtherSession) Error() string {
return "connection is linked to another session" return "connection is linked to another session"
} }
// ErrServerTeardown is an error that can be returned by a server. // ErrServerSessionTeardown is an error that can be returned by a server.
type ErrServerTeardown struct{} type ErrServerSessionTeardown struct{}
// Error implements the error interface. // Error implements the error interface.
func (e ErrServerTeardown) Error() string { func (e ErrServerSessionTeardown) Error() string {
return "teardown" return "teardown"
} }

View File

@@ -500,7 +500,7 @@ func TestServerPublish(t *testing.T) {
onSessionOpen: func(ss *ServerSession) { onSessionOpen: func(ss *ServerSession) {
close(sessionOpened) close(sessionOpened)
}, },
onSessionClose: func(ss *ServerSession) { onSessionClose: func(ss *ServerSession, err error) {
close(sessionClosed) close(sessionClosed)
}, },
onAnnounce: func(ctx *ServerHandlerOnAnnounceCtx) (*base.Response, error) { onAnnounce: func(ctx *ServerHandlerOnAnnounceCtx) (*base.Response, error) {
@@ -997,7 +997,7 @@ func TestServerPublishErrorTimeout(t *testing.T) {
s := &Server{ s := &Server{
Handler: &testServerHandler{ Handler: &testServerHandler{
onSessionClose: func(ss *ServerSession) { onSessionClose: func(ss *ServerSession, err error) {
close(sessionClosed) close(sessionClosed)
}, },
onAnnounce: func(ctx *ServerHandlerOnAnnounceCtx) (*base.Response, error) { onAnnounce: func(ctx *ServerHandlerOnAnnounceCtx) (*base.Response, error) {

View File

@@ -288,7 +288,7 @@ func TestServerRead(t *testing.T) {
onSessionOpen: func(ss *ServerSession) { onSessionOpen: func(ss *ServerSession) {
close(sessionOpened) close(sessionOpened)
}, },
onSessionClose: func(ss *ServerSession) { onSessionClose: func(ss *ServerSession, err error) {
close(sessionClosed) close(sessionClosed)
}, },
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) {

View File

@@ -19,7 +19,7 @@ type testServerHandler struct {
onConnOpen func(*ServerConn) onConnOpen func(*ServerConn)
onConnClose func(*ServerConn, error) onConnClose func(*ServerConn, error)
onSessionOpen func(*ServerSession) onSessionOpen func(*ServerSession)
onSessionClose func(*ServerSession) onSessionClose func(*ServerSession, error)
onDescribe func(*ServerHandlerOnDescribeCtx) (*base.Response, []byte, error) onDescribe func(*ServerHandlerOnDescribeCtx) (*base.Response, []byte, error)
onAnnounce func(*ServerHandlerOnAnnounceCtx) (*base.Response, error) onAnnounce func(*ServerHandlerOnAnnounceCtx) (*base.Response, error)
onSetup func(*ServerHandlerOnSetupCtx) (*base.Response, error) onSetup func(*ServerHandlerOnSetupCtx) (*base.Response, error)
@@ -49,9 +49,9 @@ func (sh *testServerHandler) OnSessionOpen(ss *ServerSession) {
} }
} }
func (sh *testServerHandler) OnSessionClose(ss *ServerSession) { func (sh *testServerHandler) OnSessionClose(ss *ServerSession, err error) {
if sh.onSessionClose != nil { if sh.onSessionClose != nil {
sh.onSessionClose(ss) sh.onSessionClose(ss, err)
} }
} }
@@ -211,7 +211,7 @@ func TestServerHighLevelPublishRead(t *testing.T) {
s := &Server{ s := &Server{
Handler: &testServerHandler{ Handler: &testServerHandler{
onSessionClose: func(ss *ServerSession) { onSessionClose: func(ss *ServerSession, err error) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()

View File

@@ -168,9 +168,9 @@ func (sc *ServerConn) run() {
}() }()
}() }()
var err error err := func() error {
select { select {
case err = <-readDone: case err := <-readDone:
if sc.tcpFrameEnabled { if sc.tcpFrameEnabled {
sc.tcpFrameWriteBuffer.Close() sc.tcpFrameWriteBuffer.Close()
<-sc.tcpFrameBackgroundWriteDone <-sc.tcpFrameBackgroundWriteDone
@@ -178,6 +178,7 @@ func (sc *ServerConn) run() {
sc.nconn.Close() sc.nconn.Close()
sc.s.connClose <- sc sc.s.connClose <- sc
<-sc.terminate <-sc.terminate
return err
case <-sc.terminate: case <-sc.terminate:
if sc.tcpFrameEnabled { if sc.tcpFrameEnabled {
@@ -185,8 +186,10 @@ func (sc *ServerConn) run() {
<-sc.tcpFrameBackgroundWriteDone <-sc.tcpFrameBackgroundWriteDone
} }
sc.nconn.Close() sc.nconn.Close()
err = <-readDone <-readDone
return liberrors.ErrServerTerminated{}
} }
}()
if sc.tcpFrameEnabled { if sc.tcpFrameEnabled {
sc.s.sessionClose <- sc.tcpFrameLinkedSession sc.s.sessionClose <- sc.tcpFrameLinkedSession

View File

@@ -26,7 +26,7 @@ type ServerHandlerOnSessionOpen interface {
// ServerHandlerOnSessionClose can be implemented by a ServerHandler. // ServerHandlerOnSessionClose can be implemented by a ServerHandler.
type ServerHandlerOnSessionClose interface { type ServerHandlerOnSessionClose interface {
OnSessionClose(*ServerSession) OnSessionClose(*ServerSession, error)
} }
// ServerHandlerOnRequest can be implemented by a ServerHandler. // ServerHandlerOnRequest can be implemented by a ServerHandler.

View File

@@ -210,7 +210,7 @@ func (ss *ServerSession) run() {
receiverReportTicker := time.NewTicker(ss.s.receiverReportPeriod) receiverReportTicker := time.NewTicker(ss.s.receiverReportPeriod)
defer receiverReportTicker.Stop() defer receiverReportTicker.Stop()
outer: err := func() error {
for { for {
select { select {
case req := <-ss.request: case req := <-ss.request:
@@ -225,9 +225,9 @@ outer:
res.Header["Session"] = base.HeaderValue{ss.id} res.Header["Session"] = base.HeaderValue{ss.id}
} }
if _, ok := err.(liberrors.ErrServerTeardown); ok { if _, ok := err.(liberrors.ErrServerSessionTeardown); ok {
req.res <- requestRes{res, nil} req.res <- requestRes{res, nil}
break outer return liberrors.ErrServerSessionTeardown{}
} }
req.res <- requestRes{res, err} req.res <- requestRes{res, err}
@@ -239,7 +239,7 @@ outer:
now := time.Now() now := time.Now()
lft := atomic.LoadInt64(ss.udpLastFrameTime) lft := atomic.LoadInt64(ss.udpLastFrameTime)
if now.Sub(time.Unix(lft, 0)) >= ss.s.ReadTimeout { if now.Sub(time.Unix(lft, 0)) >= ss.s.ReadTimeout {
break outer return liberrors.ErrServerSessionTimedOut{}
} }
// in case there's a linked TCP connection, timeout is handled in the connection // in case there's a linked TCP connection, timeout is handled in the connection
@@ -249,7 +249,7 @@ outer:
default: default:
now := time.Now() now := time.Now()
if now.Sub(ss.lastRequestTime) >= serverSessionCloseAfterNoRequestsFor { if now.Sub(ss.lastRequestTime) >= serverSessionCloseAfterNoRequestsFor {
break outer return liberrors.ErrServerSessionTimedOut{}
} }
} }
@@ -265,9 +265,10 @@ outer:
} }
case <-ss.terminate: case <-ss.terminate:
break outer return liberrors.ErrServerTerminated{}
} }
} }
}()
go func() { go func() {
for req := range ss.request { for req := range ss.request {
@@ -298,7 +299,7 @@ outer:
close(ss.request) close(ss.request)
if h, ok := ss.s.Handler.(ServerHandlerOnSessionClose); ok { if h, ok := ss.s.Handler.(ServerHandlerOnSessionClose); ok {
h.OnSessionClose(ss) h.OnSessionClose(ss, err)
} }
} }
@@ -758,7 +759,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
return &base.Response{ return &base.Response{
StatusCode: base.StatusOK, StatusCode: base.StatusOK,
}, liberrors.ErrServerTeardown{} }, liberrors.ErrServerSessionTeardown{}
case base.GetParameter: case base.GetParameter:
if h, ok := sc.s.Handler.(ServerHandlerOnGetParameter); ok { if h, ok := sc.s.Handler.(ServerHandlerOnGetParameter); ok {