Browse Source

fix multiple freezes during shutdown of components

pull/483/head
aler9 5 years ago
parent
commit
de6e9589b8
  1. 17
      internal/core/hls_remuxer.go
  2. 8
      internal/core/hls_server.go
  3. 31
      internal/core/path.go
  4. 86
      internal/core/path_manager.go
  5. 6
      internal/core/read_publisher.go
  6. 34
      internal/core/rtmp_conn.go
  7. 1
      internal/core/rtmp_server.go
  8. 9
      internal/core/rtmp_source.go
  9. 127
      internal/core/rtsp_conn.go
  10. 48
      internal/core/rtsp_session.go
  11. 9
      internal/core/rtsp_source.go

17
internal/core/hls_remuxer.go

@ -204,27 +204,19 @@ func (r *hlsRemuxer) run() { @@ -204,27 +204,19 @@ func (r *hlsRemuxer) run() {
r.ctxCancel()
if r.path != nil {
res := make(chan struct{})
r.path.OnReadPublisherRemove(readPublisherRemoveReq{
Author: r,
Res: res,
})
<-res
r.path.OnReadPublisherRemove(readPublisherRemoveReq{Author: r})
}
r.parent.OnRemuxerClose(r)
}
func (r *hlsRemuxer) runInner(innerCtx context.Context) error {
pres := make(chan readPublisherSetupPlayRes)
r.pathManager.OnReadPublisherSetupPlay(readPublisherSetupPlayReq{
res := r.pathManager.OnReadPublisherSetupPlay(readPublisherSetupPlayReq{
Author: r,
PathName: r.pathName,
IP: nil,
ValidateCredentials: nil,
Res: pres,
})
res := <-pres
if res.Err != nil {
return res.Err
@ -308,12 +300,9 @@ func (r *hlsRemuxer) runInner(innerCtx context.Context) error { @@ -308,12 +300,9 @@ func (r *hlsRemuxer) runInner(innerCtx context.Context) error {
r.ringBuffer = ringbuffer.New(uint64(r.readBufferCount))
resc := make(chan readPublisherPlayRes)
r.path.OnReadPublisherPlay(readPublisherPlayReq{
Author: r,
Res: resc,
})
<-resc
writerDone := make(chan error)
go func() {
@ -490,7 +479,7 @@ func (r *hlsRemuxer) runRequestHandler(terminate chan struct{}, done chan struct @@ -490,7 +479,7 @@ func (r *hlsRemuxer) runRequestHandler(terminate chan struct{}, done chan struct
}
}
// OnRequest is called by hlsserver.Server.
// OnRequest is called by hlsserver.Server (forwarded from ServeHTTP).
func (r *hlsRemuxer) OnRequest(req hlsRemuxerRequest) {
select {
case r.request <- req:

8
internal/core/hls_server.go

@ -107,11 +107,11 @@ outer: @@ -107,11 +107,11 @@ outer:
select {
case pa := <-s.pathSourceReady:
if s.hlsAlwaysRemux {
s.createRemuxer(pa.Name())
s.findOrCreateRemuxer(pa.Name())
}
case req := <-s.request:
r := s.createRemuxer(req.Dir)
r := s.findOrCreateRemuxer(req.Dir)
r.OnRequest(req)
case c := <-s.connClose:
@ -146,7 +146,7 @@ func (s *hlsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -146,7 +146,7 @@ func (s *hlsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Access-Control-Allow-Origin", s.hlsAllowOrigin)
w.Header().Add("Access-Control-Allow-Credentials", "true")
if r.Method == "OPTIONS" {
if r.Method == http.MethodOptions {
w.Header().Add("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Add("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers"))
w.WriteHeader(http.StatusOK)
@ -207,7 +207,7 @@ func (s *hlsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -207,7 +207,7 @@ func (s *hlsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
func (s *hlsServer) createRemuxer(pathName string) *hlsRemuxer {
func (s *hlsServer) findOrCreateRemuxer(pathName string) *hlsRemuxer {
r, ok := s.remuxers[pathName]
if !ok {
r = newHLSRemuxer(

31
internal/core/path.go

@ -619,7 +619,7 @@ func (pa *path) onReadPublisherPlay(req readPublisherPlayReq) { @@ -619,7 +619,7 @@ func (pa *path) onReadPublisherPlay(req readPublisherPlayReq) {
req.Author.OnReaderAccepted()
req.Res <- readPublisherPlayRes{}
close(req.Res)
}
func (pa *path) onReadPublisherAnnounce(req readPublisherAnnounceReq) {
@ -771,23 +771,25 @@ func (pa *path) Name() string { @@ -771,23 +771,25 @@ func (pa *path) Name() string {
// OnSourceExternalSetReady is called by an external source.
func (pa *path) OnSourceExternalSetReady(req sourceExtSetReadyReq) {
req.Res = make(chan sourceExtSetReadyRes)
select {
case pa.extSourceSetReady <- req:
<-req.Res
case <-pa.ctx.Done():
close(req.Res)
}
}
// OnSourceExternalSetNotReady is called by an external source.
func (pa *path) OnSourceExternalSetNotReady(req sourceExtSetNotReadyReq) {
req.Res = make(chan struct{})
select {
case pa.extSourceSetNotReady <- req:
<-req.Res
case <-pa.ctx.Done():
close(req.Res)
}
}
// OnPathManDescribe is called by pathManager.
// OnPathManDescribe is called by pathManager (forwarded from a readPublisher).
func (pa *path) OnPathManDescribe(req readPublisherDescribeReq) {
select {
case pa.describeReq <- req:
@ -796,7 +798,7 @@ func (pa *path) OnPathManDescribe(req readPublisherDescribeReq) { @@ -796,7 +798,7 @@ func (pa *path) OnPathManDescribe(req readPublisherDescribeReq) {
}
}
// OnPathManSetupPlay is called by pathManager.
// OnPathManSetupPlay is called by pathManager (forwarded from a readPublisher).
func (pa *path) OnPathManSetupPlay(req readPublisherSetupPlayReq) {
select {
case pa.setupPlayReq <- req:
@ -805,7 +807,7 @@ func (pa *path) OnPathManSetupPlay(req readPublisherSetupPlayReq) { @@ -805,7 +807,7 @@ func (pa *path) OnPathManSetupPlay(req readPublisherSetupPlayReq) {
}
}
// OnPathManAnnounce is called by pathManager.
// OnPathManAnnounce is called by pathManager (forwarded from a readPublisher).
func (pa *path) OnPathManAnnounce(req readPublisherAnnounceReq) {
select {
case pa.announceReq <- req:
@ -816,43 +818,50 @@ func (pa *path) OnPathManAnnounce(req readPublisherAnnounceReq) { @@ -816,43 +818,50 @@ func (pa *path) OnPathManAnnounce(req readPublisherAnnounceReq) {
// OnReadPublisherPlay is called by a readPublisher.
func (pa *path) OnReadPublisherPlay(req readPublisherPlayReq) {
req.Res = make(chan struct{})
select {
case pa.playReq <- req:
<-req.Res
case <-pa.ctx.Done():
close(req.Res)
}
}
// OnReadPublisherRecord is called by a readPublisher.
func (pa *path) OnReadPublisherRecord(req readPublisherRecordReq) {
func (pa *path) OnReadPublisherRecord(req readPublisherRecordReq) readPublisherRecordRes {
req.Res = make(chan readPublisherRecordRes)
select {
case pa.recordReq <- req:
return <-req.Res
case <-pa.ctx.Done():
close(req.Res)
return readPublisherRecordRes{Err: fmt.Errorf("terminated")}
}
}
// OnReadPublisherPause is called by a readPublisher.
func (pa *path) OnReadPublisherPause(req readPublisherPauseReq) {
req.Res = make(chan struct{})
select {
case pa.pauseReq <- req:
<-req.Res
case <-pa.ctx.Done():
close(req.Res)
}
}
// OnReadPublisherRemove is called by a readPublisher.
func (pa *path) OnReadPublisherRemove(req readPublisherRemoveReq) {
req.Res = make(chan struct{})
select {
case pa.removeReq <- req:
<-req.Res
case <-pa.ctx.Done():
close(req.Res)
}
}
// OnFrame is called by a source.
func (pa *path) OnSourceFrame(trackID int, streamType gortsplib.StreamType, payload []byte) {
// forward to RTSP readers
pa.sourceStream.WriteFrame(trackID, streamType, payload)
// forward to non-RTSP readers
pa.nonRTSPReaders.forwardFrame(trackID, streamType, payload)
}

86
internal/core/path_manager.go

@ -287,6 +287,37 @@ func (pm *pathManager) findPathConf(name string) (string, *conf.PathConf, error) @@ -287,6 +287,37 @@ func (pm *pathManager) findPathConf(name string) (string, *conf.PathConf, error)
return "", nil, fmt.Errorf("unable to find a valid configuration for path '%s'", name)
}
func (pm *pathManager) authenticate(
ip net.IP,
validateCredentials func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error,
pathName string,
pathIPs []interface{},
pathUser string,
pathPass string,
) error {
// validate ip
if pathIPs != nil && ip != nil {
if !ipEqualOrInRange(ip, pathIPs) {
return readPublisherErrAuthCritical{
Message: fmt.Sprintf("IP '%s' not allowed", ip),
Response: &base.Response{
StatusCode: base.StatusUnauthorized,
},
}
}
}
// validate user
if pathUser != "" && validateCredentials != nil {
err := validateCredentials(pm.authMethods, pathUser, pathPass)
if err != nil {
return err
}
}
return nil
}
// OnConfReload is called by core.
func (pm *pathManager) OnConfReload(pathConfs map[string]*conf.PathConf) {
select {
@ -311,30 +342,36 @@ func (pm *pathManager) OnPathClose(pa *path) { @@ -311,30 +342,36 @@ func (pm *pathManager) OnPathClose(pa *path) {
}
}
// OnReadPublisherDescribe is called by a ReadPublisher.
func (pm *pathManager) OnReadPublisherDescribe(req readPublisherDescribeReq) {
// OnReadPublisherDescribe is called by a readPublisher.
func (pm *pathManager) OnReadPublisherDescribe(req readPublisherDescribeReq) readPublisherDescribeRes {
req.Res = make(chan readPublisherDescribeRes)
select {
case pm.rpDescribe <- req:
return <-req.Res
case <-pm.ctx.Done():
req.Res <- readPublisherDescribeRes{Err: fmt.Errorf("terminated")}
return readPublisherDescribeRes{Err: fmt.Errorf("terminated")}
}
}
// OnReadPublisherAnnounce is called by a ReadPublisher.
func (pm *pathManager) OnReadPublisherAnnounce(req readPublisherAnnounceReq) {
// OnReadPublisherAnnounce is called by a readPublisher.
func (pm *pathManager) OnReadPublisherAnnounce(req readPublisherAnnounceReq) readPublisherAnnounceRes {
req.Res = make(chan readPublisherAnnounceRes)
select {
case pm.rpAnnounce <- req:
return <-req.Res
case <-pm.ctx.Done():
req.Res <- readPublisherAnnounceRes{Err: fmt.Errorf("terminated")}
return readPublisherAnnounceRes{Err: fmt.Errorf("terminated")}
}
}
// OnReadPublisherSetupPlay is called by a ReadPublisher.
func (pm *pathManager) OnReadPublisherSetupPlay(req readPublisherSetupPlayReq) {
// OnReadPublisherSetupPlay is called by a readPublisher.
func (pm *pathManager) OnReadPublisherSetupPlay(req readPublisherSetupPlayReq) readPublisherSetupPlayRes {
req.Res = make(chan readPublisherSetupPlayRes)
select {
case pm.rpSetupPlay <- req:
return <-req.Res
case <-pm.ctx.Done():
req.Res <- readPublisherSetupPlayRes{Err: fmt.Errorf("terminated")}
return readPublisherSetupPlayRes{Err: fmt.Errorf("terminated")}
}
}
@ -345,34 +382,3 @@ func (pm *pathManager) OnHLSServer(s *hlsServer) { @@ -345,34 +382,3 @@ func (pm *pathManager) OnHLSServer(s *hlsServer) {
case <-pm.ctx.Done():
}
}
func (pm *pathManager) authenticate(
ip net.IP,
validateCredentials func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error,
pathName string,
pathIPs []interface{},
pathUser string,
pathPass string,
) error {
// validate ip
if pathIPs != nil && ip != nil {
if !ipEqualOrInRange(ip, pathIPs) {
return readPublisherErrAuthCritical{
Message: fmt.Sprintf("IP '%s' not allowed", ip),
Response: &base.Response{
StatusCode: base.StatusUnauthorized,
},
}
}
}
// validate user
if pathUser != "" && validateCredentials != nil {
err := validateCredentials(pm.authMethods, pathUser, pathPass)
if err != nil {
return err
}
}
return nil
}

6
internal/core/read_publisher.go

@ -16,7 +16,7 @@ type readPublisherPath interface { @@ -16,7 +16,7 @@ type readPublisherPath interface {
Conf() *conf.PathConf
OnReadPublisherRemove(readPublisherRemoveReq)
OnReadPublisherPlay(readPublisherPlayReq)
OnReadPublisherRecord(readPublisherRecordReq)
OnReadPublisherRecord(readPublisherRecordReq) readPublisherRecordRes
OnReadPublisherPause(readPublisherPauseReq)
OnSourceFrame(int, gortsplib.StreamType, []byte)
}
@ -105,11 +105,9 @@ type readPublisherRemoveReq struct { @@ -105,11 +105,9 @@ type readPublisherRemoveReq struct {
Res chan struct{}
}
type readPublisherPlayRes struct{}
type readPublisherPlayReq struct {
Author readPublisher
Res chan readPublisherPlayRes
Res chan struct{}
}
type readPublisherRecordRes struct {

34
internal/core/rtmp_conn.go

@ -48,11 +48,6 @@ type rtmpConnTrackIDPayloadPair struct { @@ -48,11 +48,6 @@ type rtmpConnTrackIDPayloadPair struct {
buf []byte
}
type rtmpConnPathMan interface {
OnReadPublisherSetupPlay(readPublisherSetupPlayReq)
OnReadPublisherAnnounce(readPublisherAnnounceReq)
}
type rtmpConnParent interface {
Log(logger.Level, string, ...interface{})
OnConnClose(*rtmpConn)
@ -68,7 +63,7 @@ type rtmpConn struct { @@ -68,7 +63,7 @@ type rtmpConn struct {
wg *sync.WaitGroup
stats *stats
conn *rtmp.Conn
pathManager rtmpConnPathMan
pathManager *pathManager
parent rtmpConnParent
ctx context.Context
@ -88,7 +83,7 @@ func newRTMPConn( @@ -88,7 +83,7 @@ func newRTMPConn(
wg *sync.WaitGroup,
stats *stats,
nconn net.Conn,
pathManager rtmpConnPathMan,
pathManager *pathManager,
parent rtmpConnParent) *rtmpConn {
ctx, ctxCancel := context.WithCancel(parentCtx)
@ -174,12 +169,7 @@ func (c *rtmpConn) run() { @@ -174,12 +169,7 @@ func (c *rtmpConn) run() {
c.ctxCancel()
if c.path != nil {
res := make(chan struct{})
c.path.OnReadPublisherRemove(readPublisherRemoveReq{
Author: c,
Res: res,
})
<-res
c.path.OnReadPublisherRemove(readPublisherRemoveReq{Author: c})
}
c.parent.OnConnClose(c)
@ -207,17 +197,14 @@ func (c *rtmpConn) runInner(ctx context.Context) error { @@ -207,17 +197,14 @@ func (c *rtmpConn) runInner(ctx context.Context) error {
func (c *rtmpConn) runRead(ctx context.Context) error {
pathName, query := pathNameAndQuery(c.conn.URL())
sres := make(chan readPublisherSetupPlayRes)
c.pathManager.OnReadPublisherSetupPlay(readPublisherSetupPlayReq{
res := c.pathManager.OnReadPublisherSetupPlay(readPublisherSetupPlayReq{
Author: c,
PathName: pathName,
IP: c.ip(),
ValidateCredentials: func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error {
return c.validateCredentials(pathUser, pathPass, query)
},
Res: sres,
})
res := <-sres
if res.Err != nil {
if terr, ok := res.Err.(readPublisherErrAuthCritical); ok {
@ -274,12 +261,9 @@ func (c *rtmpConn) runRead(ctx context.Context) error { @@ -274,12 +261,9 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
c.ringBuffer.Close()
}()
pres := make(chan readPublisherPlayRes)
c.path.OnReadPublisherPlay(readPublisherPlayReq{
Author: c,
Res: pres,
})
<-pres
// disable read deadline
c.conn.NetConn().SetReadDeadline(time.Time{})
@ -405,8 +389,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error { @@ -405,8 +389,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
pathName, query := pathNameAndQuery(c.conn.URL())
resc := make(chan readPublisherAnnounceRes)
c.pathManager.OnReadPublisherAnnounce(readPublisherAnnounceReq{
res := c.pathManager.OnReadPublisherAnnounce(readPublisherAnnounceReq{
Author: c,
PathName: pathName,
Tracks: tracks,
@ -414,9 +397,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error { @@ -414,9 +397,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
ValidateCredentials: func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error {
return c.validateCredentials(pathUser, pathPass, query)
},
Res: resc,
})
res := <-resc
if res.Err != nil {
if terr, ok := res.Err.(readPublisherErrAuthCritical); ok {
@ -432,10 +413,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error { @@ -432,10 +413,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
// disable write deadline
c.conn.NetConn().SetWriteDeadline(time.Time{})
rresc := make(chan readPublisherRecordRes)
c.path.OnReadPublisherRecord(readPublisherRecordReq{Author: c, Res: rresc})
rres := <-rresc
rres := c.path.OnReadPublisherRecord(readPublisherRecordReq{Author: c})
if rres.Err != nil {
return rres.Err
}

1
internal/core/rtmp_server.go

@ -165,6 +165,7 @@ func (s *rtmpServer) doConnClose(c *rtmpConn) { @@ -165,6 +165,7 @@ func (s *rtmpServer) doConnClose(c *rtmpConn) {
c.Close()
}
// OnConnClose is called by rtmpConn.
func (s *rtmpServer) OnConnClose(c *rtmpConn) {
select {
case s.connClose <- c:

9
internal/core/rtmp_source.go

@ -168,19 +168,12 @@ func (s *rtmpSource) runInner() bool { @@ -168,19 +168,12 @@ func (s *rtmpSource) runInner() bool {
s.log(logger.Info, "ready")
cres := make(chan sourceExtSetReadyRes)
s.parent.OnSourceExternalSetReady(sourceExtSetReadyReq{
Tracks: tracks,
Res: cres,
})
<-cres
defer func() {
res := make(chan struct{})
s.parent.OnSourceExternalSetNotReady(sourceExtSetNotReadyReq{
Res: res,
})
<-res
s.parent.OnSourceExternalSetNotReady(sourceExtSetNotReadyReq{})
}()
rtcpSenders := rtcpsenderset.New(tracks, s.parent.OnSourceFrame)

127
internal/core/rtsp_conn.go

@ -30,10 +30,6 @@ func isTerminatedErr(err error) bool { @@ -30,10 +30,6 @@ func isTerminatedErr(err error) bool {
return ok
}
type rtspConnPathMan interface {
OnReadPublisherDescribe(readPublisherDescribeReq)
}
type rtspConnParent interface {
Log(logger.Level, string, ...interface{})
}
@ -43,7 +39,7 @@ type rtspConn struct { @@ -43,7 +39,7 @@ type rtspConn struct {
readTimeout time.Duration
runOnConnect string
runOnConnectRestart bool
pathManager rtspConnPathMan
pathManager *pathManager
stats *stats
conn *gortsplib.ServerConn
parent rtspConnParent
@ -60,7 +56,7 @@ func newRTSPConn( @@ -60,7 +56,7 @@ func newRTSPConn(
readTimeout time.Duration,
runOnConnect string,
runOnConnectRestart bool,
pathManager rtspConnPathMan,
pathManager *pathManager,
stats *stats,
conn *gortsplib.ServerConn,
parent rtspConnParent) *rtspConn {
@ -114,67 +110,6 @@ func (c *rtspConn) ip() net.IP { @@ -114,67 +110,6 @@ func (c *rtspConn) ip() net.IP {
return c.conn.NetConn().RemoteAddr().(*net.TCPAddr).IP
}
// OnRequest is called by rtspServer.
func (c *rtspConn) OnRequest(req *base.Request) {
c.log(logger.Debug, "[c->s] %v", req)
}
// OnResponse is called by rtspServer.
func (c *rtspConn) OnResponse(res *base.Response) {
c.log(logger.Debug, "[s->c] %v", res)
}
// OnDescribe is called by rtspServer.
func (c *rtspConn) OnDescribe(ctx *gortsplib.ServerHandlerOnDescribeCtx) (*base.Response, *gortsplib.ServerStream, error) {
resc := make(chan readPublisherDescribeRes)
c.pathManager.OnReadPublisherDescribe(readPublisherDescribeReq{
PathName: ctx.Path,
URL: ctx.Req.URL,
IP: c.ip(),
ValidateCredentials: func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error {
return c.validateCredentials(authMethods, pathUser, pathPass, ctx.Path, ctx.Req)
},
Res: resc,
})
res := <-resc
if res.Err != nil {
switch terr := res.Err.(type) {
case readPublisherErrAuthNotCritical:
return terr.Response, nil, nil
case readPublisherErrAuthCritical:
// wait some seconds to stop brute force attacks
<-time.After(rtspConnPauseAfterAuthError)
return terr.Response, nil, errors.New(terr.Message)
case readPublisherErrNoOnePublishing:
return &base.Response{
StatusCode: base.StatusNotFound,
}, nil, res.Err
default:
return &base.Response{
StatusCode: base.StatusBadRequest,
}, nil, res.Err
}
}
if res.Redirect != "" {
return &base.Response{
StatusCode: base.StatusMovedPermanently,
Header: base.Header{
"Location": base.HeaderValue{res.Redirect},
},
}, nil, nil
}
return &base.Response{
StatusCode: base.StatusOK,
}, res.Stream, nil
}
func (c *rtspConn) validateCredentials(
authMethods []headers.AuthMethod,
pathUser string,
@ -240,3 +175,61 @@ func (c *rtspConn) validateCredentials( @@ -240,3 +175,61 @@ func (c *rtspConn) validateCredentials(
return nil
}
// OnRequest is called by rtspServer.
func (c *rtspConn) OnRequest(req *base.Request) {
c.log(logger.Debug, "[c->s] %v", req)
}
// OnResponse is called by rtspServer.
func (c *rtspConn) OnResponse(res *base.Response) {
c.log(logger.Debug, "[s->c] %v", res)
}
// OnDescribe is called by rtspServer.
func (c *rtspConn) OnDescribe(ctx *gortsplib.ServerHandlerOnDescribeCtx) (*base.Response, *gortsplib.ServerStream, error) {
res := c.pathManager.OnReadPublisherDescribe(readPublisherDescribeReq{
PathName: ctx.Path,
URL: ctx.Req.URL,
IP: c.ip(),
ValidateCredentials: func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error {
return c.validateCredentials(authMethods, pathUser, pathPass, ctx.Path, ctx.Req)
},
})
if res.Err != nil {
switch terr := res.Err.(type) {
case readPublisherErrAuthNotCritical:
return terr.Response, nil, nil
case readPublisherErrAuthCritical:
// wait some seconds to stop brute force attacks
<-time.After(rtspConnPauseAfterAuthError)
return terr.Response, nil, errors.New(terr.Message)
case readPublisherErrNoOnePublishing:
return &base.Response{
StatusCode: base.StatusNotFound,
}, nil, res.Err
default:
return &base.Response{
StatusCode: base.StatusBadRequest,
}, nil, res.Err
}
}
if res.Redirect != "" {
return &base.Response{
StatusCode: base.StatusMovedPermanently,
Header: base.Header{
"Location": base.HeaderValue{res.Redirect},
},
}, nil, nil
}
return &base.Response{
StatusCode: base.StatusOK,
}, res.Stream, nil
}

48
internal/core/rtsp_session.go

@ -19,11 +19,6 @@ const ( @@ -19,11 +19,6 @@ const (
pauseAfterAuthError = 2 * time.Second
)
type rtspSessionPathMan interface {
OnReadPublisherSetupPlay(readPublisherSetupPlayReq)
OnReadPublisherAnnounce(readPublisherAnnounceReq)
}
type rtspSessionParent interface {
Log(logger.Level, string, ...interface{})
}
@ -33,7 +28,7 @@ type rtspSession struct { @@ -33,7 +28,7 @@ type rtspSession struct {
protocols map[conf.Protocol]struct{}
visualID string
ss *gortsplib.ServerSession
pathManager rtspSessionPathMan
pathManager *pathManager
parent rtspSessionParent
path readPublisherPath
@ -47,7 +42,7 @@ func newRTSPSession( @@ -47,7 +42,7 @@ func newRTSPSession(
visualID string,
ss *gortsplib.ServerSession,
sc *gortsplib.ServerConn,
pathManager rtspSessionPathMan,
pathManager *pathManager,
parent rtspSessionParent) *rtspSession {
s := &rtspSession{
rtspAddress: rtspAddress,
@ -72,12 +67,7 @@ func (s *rtspSession) ParentClose() { @@ -72,12 +67,7 @@ func (s *rtspSession) ParentClose() {
}
if s.path != nil {
res := make(chan struct{})
s.path.OnReadPublisherRemove(readPublisherRemoveReq{
Author: s,
Res: res,
})
<-res
s.path.OnReadPublisherRemove(readPublisherRemoveReq{Author: s})
s.path = nil
}
@ -116,8 +106,7 @@ func (s *rtspSession) log(level logger.Level, format string, args ...interface{} @@ -116,8 +106,7 @@ func (s *rtspSession) log(level logger.Level, format string, args ...interface{}
// OnAnnounce is called by rtspServer.
func (s *rtspSession) OnAnnounce(c *rtspConn, ctx *gortsplib.ServerHandlerOnAnnounceCtx) (*base.Response, error) {
resc := make(chan readPublisherAnnounceRes)
s.pathManager.OnReadPublisherAnnounce(readPublisherAnnounceReq{
res := s.pathManager.OnReadPublisherAnnounce(readPublisherAnnounceReq{
Author: s,
PathName: ctx.Path,
Tracks: ctx.Tracks,
@ -125,9 +114,7 @@ func (s *rtspSession) OnAnnounce(c *rtspConn, ctx *gortsplib.ServerHandlerOnAnno @@ -125,9 +114,7 @@ func (s *rtspSession) OnAnnounce(c *rtspConn, ctx *gortsplib.ServerHandlerOnAnno
ValidateCredentials: func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error {
return c.validateCredentials(authMethods, pathUser, pathPass, ctx.Path, ctx.Req)
},
Res: resc,
})
res := <-resc
if res.Err != nil {
switch terr := res.Err.(type) {
@ -178,17 +165,14 @@ func (s *rtspSession) OnSetup(c *rtspConn, ctx *gortsplib.ServerHandlerOnSetupCt @@ -178,17 +165,14 @@ func (s *rtspSession) OnSetup(c *rtspConn, ctx *gortsplib.ServerHandlerOnSetupCt
switch s.ss.State() {
case gortsplib.ServerSessionStateInitial, gortsplib.ServerSessionStatePrePlay: // play
resc := make(chan readPublisherSetupPlayRes)
s.pathManager.OnReadPublisherSetupPlay(readPublisherSetupPlayReq{
res := s.pathManager.OnReadPublisherSetupPlay(readPublisherSetupPlayReq{
Author: s,
PathName: ctx.Path,
IP: ctx.Conn.NetConn().RemoteAddr().(*net.TCPAddr).IP,
ValidateCredentials: func(authMethods []headers.AuthMethod, pathUser string, pathPass string) error {
return c.validateCredentials(authMethods, pathUser, pathPass, ctx.Path, ctx.Req)
},
Res: resc,
})
res := <-resc
if res.Err != nil {
switch terr := res.Err.(type) {
@ -248,12 +232,9 @@ func (s *rtspSession) OnPlay(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Respo @@ -248,12 +232,9 @@ func (s *rtspSession) OnPlay(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Respo
}, fmt.Errorf("path has changed, was '%s', now is '%s'", s.path.Name(), ctx.Path)
}
resc := make(chan readPublisherPlayRes)
s.path.OnReadPublisherPlay(readPublisherPlayReq{
Author: s,
Res: resc,
})
<-resc
if s.path.Conf().RunOnRead != "" {
_, port, _ := net.SplitHostPort(s.rtspAddress)
@ -278,10 +259,7 @@ func (s *rtspSession) OnRecord(ctx *gortsplib.ServerHandlerOnRecordCtx) (*base.R @@ -278,10 +259,7 @@ func (s *rtspSession) OnRecord(ctx *gortsplib.ServerHandlerOnRecordCtx) (*base.R
}, fmt.Errorf("path has changed, was '%s', now is '%s'", s.path.Name(), ctx.Path)
}
resc := make(chan readPublisherRecordRes)
s.path.OnReadPublisherRecord(readPublisherRecordReq{Author: s, Res: resc})
res := <-resc
res := s.path.OnReadPublisherRecord(readPublisherRecordReq{Author: s})
if res.Err != nil {
return &base.Response{
StatusCode: base.StatusBadRequest,
@ -301,20 +279,10 @@ func (s *rtspSession) OnPause(ctx *gortsplib.ServerHandlerOnPauseCtx) (*base.Res @@ -301,20 +279,10 @@ func (s *rtspSession) OnPause(ctx *gortsplib.ServerHandlerOnPauseCtx) (*base.Res
s.onReadCmd.Close()
}
res := make(chan struct{})
s.path.OnReadPublisherPause(readPublisherPauseReq{
Author: s,
Res: res,
})
<-res
s.path.OnReadPublisherPause(readPublisherPauseReq{Author: s})
case gortsplib.ServerSessionStateRecord:
res := make(chan struct{})
s.path.OnReadPublisherPause(readPublisherPauseReq{
Author: s,
Res: res,
})
<-res
s.path.OnReadPublisherPause(readPublisherPauseReq{Author: s})
}
return &base.Response{

9
internal/core/rtsp_source.go

@ -187,19 +187,12 @@ func (s *rtspSource) runInner() bool { @@ -187,19 +187,12 @@ func (s *rtspSource) runInner() bool {
s.log(logger.Info, "ready")
cres := make(chan sourceExtSetReadyRes)
s.parent.OnSourceExternalSetReady(sourceExtSetReadyReq{
Tracks: conn.Tracks(),
Res: cres,
})
<-cres
defer func() {
res := make(chan struct{})
s.parent.OnSourceExternalSetNotReady(sourceExtSetNotReadyReq{
Res: res,
})
<-res
s.parent.OnSourceExternalSetNotReady(sourceExtSetNotReadyReq{})
}()
readErr := make(chan error)

Loading…
Cancel
Save