@ -380,112 +380,85 @@ func (pa *path) runInner() error {
@@ -380,112 +380,85 @@ func (pa *path) runInner() error {
for {
select {
case <- pa . onDemandStaticSourceReadyTimer . C :
for _ , req := range pa . describeRequestsOnHold {
req . res <- pathDescribeRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . describeRequestsOnHold = nil
for _ , req := range pa . readerAddRequestsOnHold {
req . res <- pathAddReaderRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . readerAddRequestsOnHold = nil
pa . onDemandStaticSourceStop ( )
pa . doOnDemandStaticSourceReadyTimer ( )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case <- pa . onDemandStaticSourceCloseTimer . C :
pa . setNotReady ( )
pa . onDemandStaticSourceStop ( )
pa . doOnDemandStaticSourceCloseTimer ( )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case <- pa . onDemandPublisherReadyTimer . C :
for _ , req := range pa . describeRequestsOnHold {
req . res <- pathDescribeRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . describeRequestsOnHold = nil
for _ , req := range pa . readerAddRequestsOnHold {
req . res <- pathAddReaderRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . readerAddRequestsOnHold = nil
pa . onDemandStopPublisher ( )
pa . doOnDemandPublisherReadyTimer ( )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case <- pa . onDemandPublisherCloseTimer . C :
pa . onDemandStop Publisher ( )
pa . doOnDemandPublisherCloseTimer ( )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case newConf := <- pa . chReloadConf :
if pa . conf . HasStaticSource ( ) {
go pa . source . ( * sourceStatic ) . reloadConf ( newConf )
}
pa . confMutex . Lock ( )
pa . conf = newConf
pa . confMutex . Unlock ( )
pa . doReloadConf ( newConf )
case req := <- pa . chSourceStaticSetReady :
pa . handle SourceStaticSetReady( req )
pa . doSourceStaticSetReady ( req )
case req := <- pa . chSourceStaticSetNotReady :
pa . handle SourceStaticSetNotReady( req )
pa . doSourceStaticSetNotReady ( req )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case req := <- pa . chDescribe :
pa . handle Describe( req )
pa . do Describe( req )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case req := <- pa . chRemovePublisher :
pa . handle RemovePublisher( req )
pa . do RemovePublisher( req )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case req := <- pa . chAddPublisher :
pa . handle AddPublisher( req )
pa . do AddPublisher( req )
case req := <- pa . chStartPublisher :
pa . handle StartPublisher( req )
pa . do StartPublisher( req )
case req := <- pa . chStopPublisher :
pa . handle StopPublisher( req )
pa . do StopPublisher( req )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case req := <- pa . chAddReader :
pa . handle AddReader( req )
pa . do AddReader( req )
if pa . shouldClose ( ) {
return fmt . Errorf ( "not in use" )
}
case req := <- pa . chRemoveReader :
pa . handle RemoveReader( req )
pa . do RemoveReader( req )
case req := <- pa . chAPIPathsGet :
pa . handle APIPathsGet( req )
pa . do APIPathsGet( req )
case <- pa . ctx . Done ( ) :
return fmt . Errorf ( "terminated" )
@ -493,167 +466,54 @@ func (pa *path) runInner() error {
@@ -493,167 +466,54 @@ func (pa *path) runInner() error {
}
}
func ( pa * path ) shouldClose ( ) bool {
return pa . conf . Regexp != nil &&
pa . source == nil &&
len ( pa . readers ) == 0 &&
len ( pa . describeRequestsOnHold ) == 0 &&
len ( pa . readerAddRequestsOnHold ) == 0
}
func ( pa * path ) externalCmdEnv ( ) externalcmd . Environment {
_ , port , _ := net . SplitHostPort ( pa . rtspAddress )
env := externalcmd . Environment {
"MTX_PATH" : pa . name ,
"RTSP_PATH" : pa . name , // deprecated
"RTSP_PORT" : port ,
}
if len ( pa . matches ) > 1 {
for i , ma := range pa . matches [ 1 : ] {
env [ "G" + strconv . FormatInt ( int64 ( i + 1 ) , 10 ) ] = ma
}
}
return env
}
func ( pa * path ) onDemandStaticSourceStart ( ) {
pa . source . ( * sourceStatic ) . start ( )
pa . onDemandStaticSourceReadyTimer . Stop ( )
pa . onDemandStaticSourceReadyTimer = time . NewTimer ( time . Duration ( pa . conf . SourceOnDemandStartTimeout ) )
pa . onDemandStaticSourceState = pathOnDemandStateWaitingReady
}
func ( pa * path ) onDemandStaticSourceScheduleClose ( ) {
pa . onDemandStaticSourceCloseTimer . Stop ( )
pa . onDemandStaticSourceCloseTimer = time . NewTimer ( time . Duration ( pa . conf . SourceOnDemandCloseAfter ) )
pa . onDemandStaticSourceState = pathOnDemandStateClosing
}
func ( pa * path ) onDemandStaticSourceStop ( ) {
if pa . onDemandStaticSourceState == pathOnDemandStateClosing {
pa . onDemandStaticSourceCloseTimer . Stop ( )
pa . onDemandStaticSourceCloseTimer = newEmptyTimer ( )
}
pa . onDemandStaticSourceState = pathOnDemandStateInitial
pa . source . ( * sourceStatic ) . stop ( )
}
func ( pa * path ) onDemandStartPublisher ( ) {
pa . Log ( logger . Info , "runOnDemand command started" )
pa . onDemandCmd = externalcmd . NewCmd (
pa . externalCmdPool ,
pa . conf . RunOnDemand ,
pa . conf . RunOnDemandRestart ,
pa . externalCmdEnv ( ) ,
func ( err error ) {
pa . Log ( logger . Info , "runOnDemand command exited: %v" , err )
} )
pa . onDemandPublisherReadyTimer . Stop ( )
pa . onDemandPublisherReadyTimer = time . NewTimer ( time . Duration ( pa . conf . RunOnDemandStartTimeout ) )
pa . onDemandPublisherState = pathOnDemandStateWaitingReady
}
func ( pa * path ) onDemandPublisherScheduleClose ( ) {
pa . onDemandPublisherCloseTimer . Stop ( )
pa . onDemandPublisherCloseTimer = time . NewTimer ( time . Duration ( pa . conf . RunOnDemandCloseAfter ) )
pa . onDemandPublisherState = pathOnDemandStateClosing
}
func ( pa * path ) onDemandStopPublisher ( ) {
if pa . source != nil {
pa . source . ( publisher ) . close ( )
pa . doPublisherRemove ( )
func ( pa * path ) doOnDemandStaticSourceReadyTimer ( ) {
for _ , req := range pa . describeRequestsOnHold {
req . res <- pathDescribeRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . describeRequestsOnHold = nil
if pa . onDemandPublisherState == pathOnDemandStateClosing {
pa . onDemandPublisherCloseTimer . Stop ( )
pa . onDemandPublisherCloseTimer = newEmptyTimer ( )
for _ , req := range pa . readerAddRequestsOnHold {
req . res <- pathAddReaderRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . readerAddRequestsOnHold = nil
pa . onDemandPublisherState = pathOnDemandStateInitial
if pa . onDemandCmd != nil {
pa . onDemandCmd . Close ( )
pa . onDemandCmd = nil
pa . Log ( logger . Info , "runOnDemand command stopped" )
}
pa . onDemandStaticSourceStop ( )
}
func ( pa * path ) setReady ( desc * description . Session , allocateEncoder bool ) error {
stream , err := stream . New (
pa . udpMaxPayloadSize ,
desc ,
allocateEncoder ,
pa . bytesReceived ,
newLimitedLogger ( pa . source ) ,
)
if err != nil {
return err
}
pa . stream = stream
pa . readyTime = time . Now ( )
if pa . conf . RunOnReady != "" {
pa . Log ( logger . Info , "runOnReady command started" )
pa . onReadyCmd = externalcmd . NewCmd (
pa . externalCmdPool ,
pa . conf . RunOnReady ,
pa . conf . RunOnReadyRestart ,
pa . externalCmdEnv ( ) ,
func ( err error ) {
pa . Log ( logger . Info , "runOnReady command exited: %v" , err )
} )
}
pa . parent . pathReady ( pa )
return nil
func ( pa * path ) doOnDemandStaticSourceCloseTimer ( ) {
pa . setNotReady ( )
pa . onDemandStaticSourceStop ( )
}
func ( pa * path ) setNotReady ( ) {
pa . parent . pathNotReady ( pa )
for r := range pa . readers {
pa . doRemoveReader ( r )
r . close ( )
func ( pa * path ) doOnDemandPublisherReadyTimer ( ) {
for _ , req := range pa . describeRequestsOnHold {
req . res <- pathDescribeRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . describeRequestsOnHold = nil
if pa . onReadyCmd != nil {
pa . onReadyCmd . Close ( )
pa . onReadyCmd = nil
pa . Log ( logger . Info , "runOnReady command stopped" )
for _ , req := range pa . readerAddRequestsOnHold {
req . res <- pathAddReaderRes { err : fmt . Errorf ( "source of path '%s' has timed out" , pa . name ) }
}
pa . readerAddRequestsOnHold = nil
if pa . stream != nil {
pa . stream . Close ( )
pa . stream = nil
}
pa . onDemandStopPublisher ( )
}
func ( pa * path ) doRemoveReader ( r reader ) {
delete ( pa . readers , r )
func ( pa * path ) doOnDemandPublisherCloseTimer ( ) {
pa . onDemandStopPublisher ( )
}
func ( pa * path ) doPublisherRemove ( ) {
if pa . stream != nil {
pa . setNotReady ( )
func ( pa * path ) doReloadConf ( newConf * conf . PathConf ) {
if pa . conf . HasStaticSource ( ) {
go pa . source . ( * sourceStatic ) . reloadConf ( newConf )
}
pa . source = nil
pa . confMutex . Lock ( )
pa . conf = newConf
pa . confMutex . Unlock ( )
}
func ( pa * path ) handle SourceStaticSetReady( req pathSourceStaticSetReadyReq ) {
func ( pa * path ) doSourceStaticSetReady ( req pathSourceStaticSetReadyReq ) {
err := pa . setReady ( req . desc , req . generateRTPPackets )
if err != nil {
req . res <- pathSourceStaticSetReadyRes { err : err }
@ -674,7 +534,7 @@ func (pa *path) handleSourceStaticSetReady(req pathSourceStaticSetReadyReq) {
@@ -674,7 +534,7 @@ func (pa *path) handleSourceStaticSetReady(req pathSourceStaticSetReadyReq) {
pa . describeRequestsOnHold = nil
for _ , req := range pa . readerAddRequestsOnHold {
pa . h andleA ddReaderPost( req )
pa . addReaderPost ( req )
}
pa . readerAddRequestsOnHold = nil
}
@ -682,7 +542,7 @@ func (pa *path) handleSourceStaticSetReady(req pathSourceStaticSetReadyReq) {
@@ -682,7 +542,7 @@ func (pa *path) handleSourceStaticSetReady(req pathSourceStaticSetReadyReq) {
req . res <- pathSourceStaticSetReadyRes { stream : pa . stream }
}
func ( pa * path ) handle SourceStaticSetNotReady( req pathSourceStaticSetNotReadyReq ) {
func ( pa * path ) do SourceStaticSetNotReady( req pathSourceStaticSetNotReadyReq ) {
pa . setNotReady ( )
// send response before calling onDemandStaticSourceStop()
@ -694,7 +554,7 @@ func (pa *path) handleSourceStaticSetNotReady(req pathSourceStaticSetNotReadyReq
@@ -694,7 +554,7 @@ func (pa *path) handleSourceStaticSetNotReady(req pathSourceStaticSetNotReadyReq
}
}
func ( pa * path ) handle Describe( req pathDescribeReq ) {
func ( pa * path ) do Describe( req pathDescribeReq ) {
if _ , ok := pa . source . ( * sourceRedirect ) ; ok {
req . res <- pathDescribeRes {
redirect : pa . conf . SourceRedirect ,
@ -745,14 +605,14 @@ func (pa *path) handleDescribe(req pathDescribeReq) {
@@ -745,14 +605,14 @@ func (pa *path) handleDescribe(req pathDescribeReq) {
req . res <- pathDescribeRes { err : errPathNoOnePublishing { pathName : pa . name } }
}
func ( pa * path ) handle RemovePublisher( req pathRemovePublisherReq ) {
func ( pa * path ) do RemovePublisher( req pathRemovePublisherReq ) {
if pa . source == req . author {
pa . doPublisherRemove ( )
pa . executeRemovePublisher ( )
}
close ( req . res )
}
func ( pa * path ) handle AddPublisher( req pathAddPublisherReq ) {
func ( pa * path ) do AddPublisher( req pathAddPublisherReq ) {
if pa . conf . Source != "publisher" {
req . res <- pathAddPublisherRes {
err : fmt . Errorf ( "can't publish to path '%s' since 'source' is not 'publisher'" , pa . name ) ,
@ -768,7 +628,7 @@ func (pa *path) handleAddPublisher(req pathAddPublisherReq) {
@@ -768,7 +628,7 @@ func (pa *path) handleAddPublisher(req pathAddPublisherReq) {
pa . Log ( logger . Info , "closing existing publisher" )
pa . source . ( publisher ) . close ( )
pa . doPublisherRemove ( )
pa . executeRemovePublisher ( )
}
pa . source = req . author
@ -776,7 +636,7 @@ func (pa *path) handleAddPublisher(req pathAddPublisherReq) {
@@ -776,7 +636,7 @@ func (pa *path) handleAddPublisher(req pathAddPublisherReq) {
req . res <- pathAddPublisherRes { path : pa }
}
func ( pa * path ) handle StartPublisher( req pathStartPublisherReq ) {
func ( pa * path ) do StartPublisher( req pathStartPublisherReq ) {
if pa . source != req . author {
req . res <- pathStartPublisherRes { err : fmt . Errorf ( "publisher is not assigned to this path anymore" ) }
return
@ -806,7 +666,7 @@ func (pa *path) handleStartPublisher(req pathStartPublisherReq) {
@@ -806,7 +666,7 @@ func (pa *path) handleStartPublisher(req pathStartPublisherReq) {
pa . describeRequestsOnHold = nil
for _ , req := range pa . readerAddRequestsOnHold {
pa . h andleA ddReaderPost( req )
pa . addReaderPost ( req )
}
pa . readerAddRequestsOnHold = nil
}
@ -814,35 +674,16 @@ func (pa *path) handleStartPublisher(req pathStartPublisherReq) {
@@ -814,35 +674,16 @@ func (pa *path) handleStartPublisher(req pathStartPublisherReq) {
req . res <- pathStartPublisherRes { stream : pa . stream }
}
func ( pa * path ) handle StopPublisher( req pathStopPublisherReq ) {
func ( pa * path ) do StopPublisher( req pathStopPublisherReq ) {
if req . author == pa . source && pa . stream != nil {
pa . setNotReady ( )
}
close ( req . res )
}
func ( pa * path ) handleRemoveReader ( req pathRemoveReaderReq ) {
if _ , ok := pa . readers [ req . author ] ; ok {
pa . doRemoveReader ( req . author )
}
close ( req . res )
if len ( pa . readers ) == 0 {
if pa . conf . HasOnDemandStaticSource ( ) {
if pa . onDemandStaticSourceState == pathOnDemandStateReady {
pa . onDemandStaticSourceScheduleClose ( )
}
} else if pa . conf . HasOnDemandPublisher ( ) {
if pa . onDemandPublisherState == pathOnDemandStateReady {
pa . onDemandPublisherScheduleClose ( )
}
}
}
}
func ( pa * path ) handleAddReader ( req pathAddReaderReq ) {
func ( pa * path ) doAddReader ( req pathAddReaderReq ) {
if pa . stream != nil {
pa . h andleA ddReaderPost( req )
pa . addReaderPost ( req )
return
}
@ -865,45 +706,26 @@ func (pa *path) handleAddReader(req pathAddReaderReq) {
@@ -865,45 +706,26 @@ func (pa *path) handleAddReader(req pathAddReaderReq) {
req . res <- pathAddReaderRes { err : errPathNoOnePublishing { pathName : pa . name } }
}
func ( pa * path ) handleAddReaderPost ( req pathAdd ReaderReq) {
func ( pa * path ) doRemoveReader ( req pathRemove ReaderReq) {
if _ , ok := pa . readers [ req . author ] ; ok {
req . res <- pathAddReaderRes {
path : pa ,
stream : pa . stream ,
}
return
pa . executeRemoveReader ( req . author )
}
close ( req . res )
if pa . conf . MaxReaders != 0 && len ( pa . readers ) >= pa . conf . MaxReaders {
req . res <- pathAddReaderRes {
err : fmt . Errorf ( "maximum reader count reached" ) ,
}
return
}
pa . readers [ req . author ] = struct { } { }
if pa . conf . HasOnDemandStaticSource ( ) {
if pa . onDemandStaticSourceState == pathOnDemandStateClosing {
pa . onDemandStaticSourceState = pathOnDemandStateReady
pa . onDemandStaticSourceCloseTimer . Stop ( )
pa . onDemandStaticSourceCloseTimer = newEmptyTimer ( )
}
} else if pa . conf . HasOnDemandPublisher ( ) {
if pa . onDemandPublisherState == pathOnDemandStateClosing {
pa . onDemandPublisherState = pathOnDemandStateReady
pa . onDemandPublisherCloseTimer . Stop ( )
pa . onDemandPublisherCloseTimer = newEmptyTimer ( )
if len ( pa . readers ) == 0 {
if pa . conf . HasOnDemandStaticSource ( ) {
if pa . onDemandStaticSourceState == pathOnDemandStateReady {
pa . onDemandStaticSourceScheduleClose ( )
}
} else if pa . conf . HasOnDemandPublisher ( ) {
if pa . onDemandPublisherState == pathOnDemandStateReady {
pa . onDemandPublisherScheduleClose ( )
}
}
}
req . res <- pathAddReaderRes {
path : pa ,
stream : pa . stream ,
}
}
func ( pa * path ) handle APIPathsGet( req pathAPIPathsGetReq ) {
func ( pa * path ) doAPIPathsGet ( req pathAPIPathsGetReq ) {
req . res <- pathAPIPathsGetRes {
data : & apiPath {
Name : pa . name ,
@ -942,6 +764,204 @@ func (pa *path) handleAPIPathsGet(req pathAPIPathsGetReq) {
@@ -942,6 +764,204 @@ func (pa *path) handleAPIPathsGet(req pathAPIPathsGetReq) {
}
}
func ( pa * path ) shouldClose ( ) bool {
return pa . conf . Regexp != nil &&
pa . source == nil &&
len ( pa . readers ) == 0 &&
len ( pa . describeRequestsOnHold ) == 0 &&
len ( pa . readerAddRequestsOnHold ) == 0
}
func ( pa * path ) externalCmdEnv ( ) externalcmd . Environment {
_ , port , _ := net . SplitHostPort ( pa . rtspAddress )
env := externalcmd . Environment {
"MTX_PATH" : pa . name ,
"RTSP_PATH" : pa . name , // deprecated
"RTSP_PORT" : port ,
}
if len ( pa . matches ) > 1 {
for i , ma := range pa . matches [ 1 : ] {
env [ "G" + strconv . FormatInt ( int64 ( i + 1 ) , 10 ) ] = ma
}
}
return env
}
func ( pa * path ) onDemandStaticSourceStart ( ) {
pa . source . ( * sourceStatic ) . start ( )
pa . onDemandStaticSourceReadyTimer . Stop ( )
pa . onDemandStaticSourceReadyTimer = time . NewTimer ( time . Duration ( pa . conf . SourceOnDemandStartTimeout ) )
pa . onDemandStaticSourceState = pathOnDemandStateWaitingReady
}
func ( pa * path ) onDemandStaticSourceScheduleClose ( ) {
pa . onDemandStaticSourceCloseTimer . Stop ( )
pa . onDemandStaticSourceCloseTimer = time . NewTimer ( time . Duration ( pa . conf . SourceOnDemandCloseAfter ) )
pa . onDemandStaticSourceState = pathOnDemandStateClosing
}
func ( pa * path ) onDemandStaticSourceStop ( ) {
if pa . onDemandStaticSourceState == pathOnDemandStateClosing {
pa . onDemandStaticSourceCloseTimer . Stop ( )
pa . onDemandStaticSourceCloseTimer = newEmptyTimer ( )
}
pa . onDemandStaticSourceState = pathOnDemandStateInitial
pa . source . ( * sourceStatic ) . stop ( )
}
func ( pa * path ) onDemandStartPublisher ( ) {
pa . Log ( logger . Info , "runOnDemand command started" )
pa . onDemandCmd = externalcmd . NewCmd (
pa . externalCmdPool ,
pa . conf . RunOnDemand ,
pa . conf . RunOnDemandRestart ,
pa . externalCmdEnv ( ) ,
func ( err error ) {
pa . Log ( logger . Info , "runOnDemand command exited: %v" , err )
} )
pa . onDemandPublisherReadyTimer . Stop ( )
pa . onDemandPublisherReadyTimer = time . NewTimer ( time . Duration ( pa . conf . RunOnDemandStartTimeout ) )
pa . onDemandPublisherState = pathOnDemandStateWaitingReady
}
func ( pa * path ) onDemandPublisherScheduleClose ( ) {
pa . onDemandPublisherCloseTimer . Stop ( )
pa . onDemandPublisherCloseTimer = time . NewTimer ( time . Duration ( pa . conf . RunOnDemandCloseAfter ) )
pa . onDemandPublisherState = pathOnDemandStateClosing
}
func ( pa * path ) onDemandStopPublisher ( ) {
if pa . source != nil {
pa . source . ( publisher ) . close ( )
pa . executeRemovePublisher ( )
}
if pa . onDemandPublisherState == pathOnDemandStateClosing {
pa . onDemandPublisherCloseTimer . Stop ( )
pa . onDemandPublisherCloseTimer = newEmptyTimer ( )
}
pa . onDemandPublisherState = pathOnDemandStateInitial
if pa . onDemandCmd != nil {
pa . onDemandCmd . Close ( )
pa . onDemandCmd = nil
pa . Log ( logger . Info , "runOnDemand command stopped" )
}
}
func ( pa * path ) setReady ( desc * description . Session , allocateEncoder bool ) error {
var err error
pa . stream , err = stream . New (
pa . udpMaxPayloadSize ,
desc ,
allocateEncoder ,
pa . bytesReceived ,
logger . NewLimitedLogger ( pa . source ) ,
)
if err != nil {
return err
}
pa . readyTime = time . Now ( )
if pa . conf . RunOnReady != "" {
pa . Log ( logger . Info , "runOnReady command started" )
pa . onReadyCmd = externalcmd . NewCmd (
pa . externalCmdPool ,
pa . conf . RunOnReady ,
pa . conf . RunOnReadyRestart ,
pa . externalCmdEnv ( ) ,
func ( err error ) {
pa . Log ( logger . Info , "runOnReady command exited: %v" , err )
} )
}
pa . parent . pathReady ( pa )
return nil
}
func ( pa * path ) setNotReady ( ) {
pa . parent . pathNotReady ( pa )
for r := range pa . readers {
pa . executeRemoveReader ( r )
r . close ( )
}
if pa . onReadyCmd != nil {
pa . onReadyCmd . Close ( )
pa . onReadyCmd = nil
pa . Log ( logger . Info , "runOnReady command stopped" )
}
if pa . stream != nil {
pa . stream . Close ( )
pa . stream = nil
}
}
func ( pa * path ) executeRemoveReader ( r reader ) {
delete ( pa . readers , r )
}
func ( pa * path ) executeRemovePublisher ( ) {
if pa . stream != nil {
pa . setNotReady ( )
}
pa . source = nil
}
func ( pa * path ) addReaderPost ( req pathAddReaderReq ) {
if _ , ok := pa . readers [ req . author ] ; ok {
req . res <- pathAddReaderRes {
path : pa ,
stream : pa . stream ,
}
return
}
if pa . conf . MaxReaders != 0 && len ( pa . readers ) >= pa . conf . MaxReaders {
req . res <- pathAddReaderRes {
err : fmt . Errorf ( "maximum reader count reached" ) ,
}
return
}
pa . readers [ req . author ] = struct { } { }
if pa . conf . HasOnDemandStaticSource ( ) {
if pa . onDemandStaticSourceState == pathOnDemandStateClosing {
pa . onDemandStaticSourceState = pathOnDemandStateReady
pa . onDemandStaticSourceCloseTimer . Stop ( )
pa . onDemandStaticSourceCloseTimer = newEmptyTimer ( )
}
} else if pa . conf . HasOnDemandPublisher ( ) {
if pa . onDemandPublisherState == pathOnDemandStateClosing {
pa . onDemandPublisherState = pathOnDemandStateReady
pa . onDemandPublisherCloseTimer . Stop ( )
pa . onDemandPublisherCloseTimer = newEmptyTimer ( )
}
}
req . res <- pathAddReaderRes {
path : pa ,
stream : pa . stream ,
}
}
// reloadConf is called by pathManager.
func ( pa * path ) reloadConf ( newConf * conf . PathConf ) {
select {