Browse Source

support relative fallback paths (#201)

pull/235/head v0.14.1
aler9 6 years ago
parent
commit
22ab4d489e
  1. 4
      README.md
  2. 14
      internal/conf/path.go
  3. 15
      internal/path/path.go
  4. 16
      main_test.go
  5. 9
      rtsp-simple-server.yml

4
README.md

@ -414,12 +414,12 @@ paths: @@ -414,12 +414,12 @@ paths:
### Fallback stream
If no one is publishing to the server, readers can be redirected to a fallback URL that is serving a fallback stream:
If no one is publishing to the server, readers can be redirected to a fallback path or URL that is serving a fallback stream:
```yml
paths:
withfallback:
fallback: rtsp://otherurl/otherpath
fallback: /otherpath
```
### Start on boot with systemd

14
internal/conf/path.go

@ -198,8 +198,8 @@ func (pconf *PathConf) fillAndCheck(name string) error { @@ -198,8 +198,8 @@ func (pconf *PathConf) fillAndCheck(name string) error {
}
if pconf.SourceOnDemand {
if pconf.Source != "record" {
return fmt.Errorf("'sourceOnDemand' is useless when source is not 'record', since the stream is not provided by a publisher, but by a fixed source")
if pconf.Source == "record" {
return fmt.Errorf("'sourceOnDemand' is useless when source is 'record'")
}
}
@ -212,18 +212,26 @@ func (pconf *PathConf) fillAndCheck(name string) error { @@ -212,18 +212,26 @@ func (pconf *PathConf) fillAndCheck(name string) error {
}
if pconf.Fallback != "" {
if strings.HasPrefix(pconf.Fallback, "/") {
err := CheckPathName(pconf.Fallback[1:])
if err != nil {
return fmt.Errorf("'%s': %s", pconf.Fallback, err)
}
} else {
_, err := base.ParseURL(pconf.Fallback)
if err != nil {
return fmt.Errorf("'%s' is not a valid RTSP url", pconf.Fallback)
}
}
}
if (pconf.PublishUser != "" && pconf.PublishPass == "") || (pconf.PublishUser == "" && pconf.PublishPass != "") {
return fmt.Errorf("read username and password must be both filled")
}
if pconf.PublishUser != "" {
if pconf.Source != "record" {
return fmt.Errorf("'publishUser' is useless when source is not 'record', since the stream is not provided by a publisher, but by a fixed source")
return fmt.Errorf("'publishUser' is useless when source is not 'record'")
}
if !strings.HasPrefix(pconf.PublishUser, "sha256:") && !reUserPass.MatchString(pconf.PublishUser) {

15
internal/path/path.go

@ -9,6 +9,7 @@ import ( @@ -9,6 +9,7 @@ import (
"time"
"github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/base"
"github.com/aler9/rtsp-simple-server/internal/client"
"github.com/aler9/rtsp-simple-server/internal/clientrtsp"
@ -598,7 +599,19 @@ func (pa *Path) onClientDescribe(req client.DescribeReq) { @@ -598,7 +599,19 @@ func (pa *Path) onClientDescribe(req client.DescribeReq) {
case sourceStateNotReady:
if pa.conf.Fallback != "" {
req.Res <- client.DescribeRes{nil, pa.conf.Fallback, nil} //nolint:govet
fallbackURL := func() string {
if strings.HasPrefix(pa.conf.Fallback, "/") {
ur := base.URL{
Scheme: req.Req.URL.Scheme,
User: req.Req.URL.User,
Host: req.Req.URL.Host,
Path: pa.conf.Fallback,
}
return ur.String()
}
return pa.conf.Fallback
}()
req.Res <- client.DescribeRes{nil, fallbackURL, nil} //nolint:govet
return
}

16
main_test.go

@ -851,9 +851,21 @@ func TestRedirect(t *testing.T) { @@ -851,9 +851,21 @@ func TestRedirect(t *testing.T) {
}
func TestFallback(t *testing.T) {
for _, ca := range []string{
"absolute",
"relative",
} {
t.Run(ca, func(t *testing.T) {
val := func() string {
if ca == "absolute" {
return "rtsp://" + ownDockerIP + ":8554/path2"
}
return "/path2"
}()
p1, ok := testProgram("paths:\n" +
" path1:\n" +
" fallback: rtsp://" + ownDockerIP + ":8554/path2\n" +
" fallback: " + val + "\n" +
" path2:\n")
require.Equal(t, true, ok)
defer p1.close()
@ -882,6 +894,8 @@ func TestFallback(t *testing.T) { @@ -882,6 +894,8 @@ func TestFallback(t *testing.T) {
require.NoError(t, err)
defer cnt2.close()
require.Equal(t, 0, cnt2.wait())
})
}
}
func TestRTMP(t *testing.T) {

9
rtsp-simple-server.yml

@ -86,12 +86,12 @@ paths: @@ -86,12 +86,12 @@ paths:
# * redirect -> the stream is provided by another path or server
source: record
# if the source is an RTSP url, this is the protocol that will be used to
# if the source is an RTSP URL, this is the protocol that will be used to
# pull the stream. available options are "automatic", "udp", "tcp".
# the tcp protocol can help to overcome the error "no UDP packets received recently".
sourceProtocol: automatic
# if the source is an RTSP or RTMP url, it will be pulled only when at least
# if the source is an RTSP or RTMP URL, it will be pulled only when at least
# one reader is connected, saving bandwidth.
sourceOnDemand: no
# if sourceOnDemand is "yes", readers will be put on hold until the source is
@ -101,11 +101,12 @@ paths: @@ -101,11 +101,12 @@ paths:
# readers connected and this amount of time has passed.
sourceOnDemandCloseAfter: 10s
# if the source is "redirect", this is the RTSP url which clients will be
# if the source is "redirect", this is the RTSP URL which clients will be
# redirected to.
sourceRedirect:
# fallback url to redirect clients to when nobody is publishing to this path.
# fallback stream to redirect clients to when nobody is publishing to this path.
# this can be a relative path (i.e. /otherstream) or an absolute RTSP URL.
fallback:
# username required to publish.

Loading…
Cancel
Save