@ -158,16 +158,16 @@ func (c *Client) run() {
@@ -158,16 +158,16 @@ func (c *Client) run() {
}
onDescribe := func ( req * base . Request ) ( * base . Response , error ) {
base Path, ok := req . URL . Base Path( )
req Path, ok := req . URL . RTSP Path( )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "unable to find base path (%s)" , req . URL )
} , fmt . Errorf ( "invalid path (%s)" , req . URL )
}
c . describeData = make ( chan describeData )
path , err := c . parent . OnClientDescribe ( c , base Path, req )
path , err := c . parent . OnClientDescribe ( c , req Path, req )
if err != nil {
switch terr := err . ( type ) {
case errAuthNotCritical :
@ -199,7 +199,7 @@ func (c *Client) run() {
@@ -199,7 +199,7 @@ func (c *Client) run() {
c . path = nil
if res . err != nil {
c . log ( logger . Info , "no one is publishing to path '%s'" , base Path)
c . log ( logger . Info , "no one is publishing to path '%s'" , req Path)
return & base . Response {
StatusCode : base . StatusNotFound ,
} , nil
@ -242,14 +242,14 @@ func (c *Client) run() {
@@ -242,14 +242,14 @@ func (c *Client) run() {
}
onAnnounce := func ( req * base . Request , tracks gortsplib . Tracks ) ( * base . Response , error ) {
base Path, ok := req . URL . Base Path( )
req Path, ok := req . URL . RTSP Path( )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "unable to find base path (%s)" , req . URL )
} , fmt . Errorf ( "invalid path (%s)" , req . URL )
}
path , err := c . parent . OnClientAnnounce ( c , base Path, tracks , req )
path , err := c . parent . OnClientAnnounce ( c , req Path, tracks , req )
if err != nil {
switch terr := err . ( type ) {
case errAuthNotCritical :
@ -281,19 +281,28 @@ func (c *Client) run() {
@@ -281,19 +281,28 @@ func (c *Client) run() {
}
onSetup := func ( req * base . Request , th * headers . Transport , trackID int ) ( * base . Response , error ) {
basePath , _ , ok := req . URL . BasePathControlAttr ( )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "unable to find control attribute (%s)" , req . URL )
}
switch c . conn . State ( ) {
case gortsplib . ServerConnStateInitial , gortsplib . ServerConnStatePrePlay : // play
if c . path != nil && basePath != c . path . Name ( ) {
pathAndQuery , ok := req . URL . RTSPPathAndQuery ( )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "path has changed, was '%s', now is '%s'" , c . path . Name ( ) , basePath )
} , fmt . Errorf ( "invalid path (%s)" , req . URL )
}
_ , pathAndQuery , ok = base . PathSplitControlAttribute ( pathAndQuery )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "invalid path (%s)" , req . URL )
}
reqPath , _ := base . PathSplitQuery ( pathAndQuery )
if c . path != nil && reqPath != c . path . Name ( ) {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "path has changed, was '%s', now is '%s'" , c . path . Name ( ) , reqPath )
}
// play with UDP
@ -304,7 +313,7 @@ func (c *Client) run() {
@@ -304,7 +313,7 @@ func (c *Client) run() {
} , nil
}
path , err := c . parent . OnClientSetupPlay ( c , base Path, trackID , req )
path , err := c . parent . OnClientSetupPlay ( c , req Path, trackID , req )
if err != nil {
switch terr := err . ( type ) {
case errAuthNotCritical :
@ -346,7 +355,7 @@ func (c *Client) run() {
@@ -346,7 +355,7 @@ func (c *Client) run() {
} , nil
}
path , err := c . parent . OnClientSetupPlay ( c , base Path, trackID , req )
path , err := c . parent . OnClientSetupPlay ( c , req Path, trackID , req )
if err != nil {
switch terr := err . ( type ) {
case errAuthNotCritical :
@ -380,11 +389,18 @@ func (c *Client) run() {
@@ -380,11 +389,18 @@ func (c *Client) run() {
} , nil
default : // record
// after ANNOUNCE, c.path is already set
if basePath != c . path . Name ( ) {
reqPathAndQuery , ok := req . URL . RTSPPathAndQuery ( )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "path has changed, was '%s', now is '%s'" , c . path . Name ( ) , basePath )
} , fmt . Errorf ( "invalid path (%s)" , req . URL )
}
if ! strings . HasPrefix ( reqPathAndQuery , c . path . Name ( ) ) {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "invalid path: must begin with '%s', but is '%s'" ,
c . path . Name ( ) , reqPathAndQuery )
}
// record with UDP
@ -395,18 +411,6 @@ func (c *Client) run() {
@@ -395,18 +411,6 @@ func (c *Client) run() {
} , nil
}
if th . ClientPorts == nil {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "transport header does not have valid client ports (%s)" , req . Header [ "Transport" ] )
}
if c . conn . TracksLen ( ) >= c . path . SourceTrackCount ( ) {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "all the tracks have already been setup" )
}
return & base . Response {
StatusCode : base . StatusOK ,
Header : base . Header {
@ -423,12 +427,6 @@ func (c *Client) run() {
@@ -423,12 +427,6 @@ func (c *Client) run() {
} , nil
}
if c . conn . TracksLen ( ) >= c . path . SourceTrackCount ( ) {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "all the tracks have already been setup" )
}
return & base . Response {
StatusCode : base . StatusOK ,
Header : base . Header {
@ -440,20 +438,20 @@ func (c *Client) run() {
@@ -440,20 +438,20 @@ func (c *Client) run() {
onPlay := func ( req * base . Request ) ( * base . Response , error ) {
if c . conn . State ( ) == gortsplib . ServerConnStatePrePlay {
base Path, ok := req . URL . Base Path( )
req Path, ok := req . URL . RTSP Path( )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "unable to find base path (%s)" , req . URL )
} , fmt . Errorf ( "invalid path (%s)" , req . URL )
}
// path can end with a slash, remove it
base Path = strings . TrimSuffix ( base Path, "/" )
req Path = strings . TrimSuffix ( req Path, "/" )
if base Path != c . path . Name ( ) {
if req Path != c . path . Name ( ) {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "path has changed, was '%s', now is '%s'" , c . path . Name ( ) , base Path)
} , fmt . Errorf ( "path has changed, was '%s', now is '%s'" , c . path . Name ( ) , req Path)
}
c . startPlay ( )
@ -468,20 +466,20 @@ func (c *Client) run() {
@@ -468,20 +466,20 @@ func (c *Client) run() {
}
onRecord := func ( req * base . Request ) ( * base . Response , error ) {
base Path, ok := req . URL . Base Path( )
req Path, ok := req . URL . RTSP Path( )
if ! ok {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "unable to find base path (%s)" , req . URL )
} , fmt . Errorf ( "invalid path (%s)" , req . URL )
}
// path can end with a slash, remove it
base Path = strings . TrimSuffix ( base Path, "/" )
req Path = strings . TrimSuffix ( req Path, "/" )
if base Path != c . path . Name ( ) {
if req Path != c . path . Name ( ) {
return & base . Response {
StatusCode : base . StatusBadRequest ,
} , fmt . Errorf ( "path has changed, was '%s', now is '%s'" , c . path . Name ( ) , base Path)
} , fmt . Errorf ( "path has changed, was '%s', now is '%s'" , c . path . Name ( ) , req Path)
}
c . startRecord ( )
@ -592,7 +590,8 @@ func (errAuthCritical) Error() string {
@@ -592,7 +590,8 @@ func (errAuthCritical) Error() string {
}
// Authenticate performs an authentication.
func ( c * Client ) Authenticate ( authMethods [ ] headers . AuthMethod , ips [ ] interface { } , user string , pass string , req * base . Request ) error {
func ( c * Client ) Authenticate ( authMethods [ ] headers . AuthMethod , ips [ ] interface { } ,
user string , pass string , req * base . Request , altURL * base . URL ) error {
// validate ip
if ips != nil {
ip := c . ip ( )
@ -615,7 +614,8 @@ func (c *Client) Authenticate(authMethods []headers.AuthMethod, ips []interface{
@@ -615,7 +614,8 @@ func (c *Client) Authenticate(authMethods []headers.AuthMethod, ips []interface{
c . authValidator = auth . NewValidator ( user , pass , authMethods )
}
err := c . authValidator . ValidateHeader ( req . Header [ "Authorization" ] , req . Method , req . URL )
err := c . authValidator . ValidateHeader ( req . Header [ "Authorization" ] ,
req . Method , req . URL , altURL )
if err != nil {
c . authFailures ++
@ -658,12 +658,15 @@ func (c *Client) Authenticate(authMethods []headers.AuthMethod, ips []interface{
@@ -658,12 +658,15 @@ func (c *Client) Authenticate(authMethods []headers.AuthMethod, ips []interface{
func ( c * Client ) startPlay ( ) {
c . path . OnClientPlay ( c )
c . log ( logger . Info , "is reading from path '%s', %d %s with %s" , c . path . Name ( ) , c . conn . TracksLen ( ) , func ( ) string {
if c . conn . TracksLen ( ) == 1 {
return "track"
}
return "tracks"
} ( ) , * c . conn . TracksProtocol ( ) )
c . log ( logger . Info , "is reading from path '%s', %d %s with %s" , c . path . Name ( ) ,
c . conn . SetuppedTracksLen ( ) ,
func ( ) string {
if c . conn . SetuppedTracksLen ( ) == 1 {
return "track"
}
return "tracks"
} ( ) ,
* c . conn . SetuppedTracksProtocol ( ) )
if c . path . Conf ( ) . RunOnRead != "" {
c . onReadCmd = externalcmd . New ( c . path . Conf ( ) . RunOnRead , c . path . Conf ( ) . RunOnReadRestart , externalcmd . Environment {
@ -682,12 +685,15 @@ func (c *Client) stopPlay() {
@@ -682,12 +685,15 @@ func (c *Client) stopPlay() {
func ( c * Client ) startRecord ( ) {
c . path . OnClientRecord ( c )
c . log ( logger . Info , "is publishing to path '%s', %d %s with %s" , c . path . Name ( ) , c . conn . TracksLen ( ) , func ( ) string {
if c . conn . TracksLen ( ) == 1 {
return "track"
}
return "tracks"
} ( ) , * c . conn . TracksProtocol ( ) )
c . log ( logger . Info , "is publishing to path '%s', %d %s with %s" , c . path . Name ( ) ,
c . conn . SetuppedTracksLen ( ) ,
func ( ) string {
if c . conn . SetuppedTracksLen ( ) == 1 {
return "track"
}
return "tracks"
} ( ) ,
* c . conn . SetuppedTracksProtocol ( ) )
if c . path . Conf ( ) . RunOnPublish != "" {
c . onPublishCmd = externalcmd . New ( c . path . Conf ( ) . RunOnPublish , c . path . Conf ( ) . RunOnPublishRestart , externalcmd . Environment {
@ -705,7 +711,7 @@ func (c *Client) stopRecord() {
@@ -705,7 +711,7 @@ func (c *Client) stopRecord() {
// OnReaderFrame implements path.Reader.
func ( c * Client ) OnReaderFrame ( trackID int , streamType base . StreamType , buf [ ] byte ) {
if ! c . conn . HasTrack ( trackID ) {
if ! c . conn . HasSetupped Track ( trackID ) {
return
}