allow to set a different listen IP for each listener (#343)

This commit is contained in:
aler9 2021-04-24 18:25:19 +02:00
parent 97a9cedb1e
commit a1a56ff203
21 changed files with 129 additions and 156 deletions

View File

@ -84,9 +84,9 @@ endef
export DOCKERFILE_RUN export DOCKERFILE_RUN
define CONFIG_RUN define CONFIG_RUN
#rtspPort: 8555 #rtspAddress: :8555
#rtpPort: 8002 #rtpAddress: :8002
#rtcpPort: 8003 #rtcpAddress: :8003
#metrics: yes #metrics: yes
#pprof: yes #pprof: yes

View File

@ -127,10 +127,10 @@ There are two ways to change the configuration:
docker run --rm -it --network=host -v $PWD/rtsp-simple-server.yml:/rtsp-simple-server.yml aler9/rtsp-simple-server docker run --rm -it --network=host -v $PWD/rtsp-simple-server.yml:/rtsp-simple-server.yml aler9/rtsp-simple-server
``` ```
* By overriding configuration parameters with environment variables, in the format `RTSP_PARAMNAME`, where `PARAMNAME` is the uppercase name of a parameter. For instance, the `rtspPort` parameter can be overridden in the following way: * By overriding configuration parameters with environment variables, in the format `RTSP_PARAMNAME`, where `PARAMNAME` is the uppercase name of a parameter. For instance, the `rtspAddress` parameter can be overridden in the following way:
``` ```
RTSP_RTSPPORT=8555 ./rtsp-simple-server RTSP_RTSPADDRESS="127.0.0.1:8554" ./rtsp-simple-server
``` ```
Parameters in maps can be overridden by using underscores, in the following way: Parameters in maps can be overridden by using underscores, in the following way:

View File

@ -7,9 +7,9 @@ PROXY_PROTOCOL=tcp
# source # source
CONF="" CONF=""
CONF="${CONF}rtspPort: 8555\n" CONF="${CONF}rtspAddress: :8555\n"
CONF="${CONF}rtpPort: 8002\n" CONF="${CONF}rtpAddress: :8002\n"
CONF="${CONF}rtcpPort: 8003\n" CONF="${CONF}rtcpAddress: :8003\n"
echo -e "$CONF" > /source.conf echo -e "$CONF" > /source.conf
RTSP_RTMPDISABLE=yes /rtsp-simple-server /source.conf & RTSP_RTMPDISABLE=yes /rtsp-simple-server /source.conf &

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.15
require ( require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
github.com/aler9/gortsplib v0.0.0-20210424151845-5480da6c83d7 github.com/aler9/gortsplib v0.0.0-20210424164934-262f28340026
github.com/asticode/go-astits v0.0.0-00010101000000-000000000000 github.com/asticode/go-astits v0.0.0-00010101000000-000000000000
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify v1.4.9

4
go.sum
View File

@ -4,8 +4,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2c
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/aler9/go-astits v0.0.0-20210423195926-582b09ed7c04 h1:CXgQLsU4uxWAmsXNOjGLbj0A+0IlRcpZpMgI13fmVwo= github.com/aler9/go-astits v0.0.0-20210423195926-582b09ed7c04 h1:CXgQLsU4uxWAmsXNOjGLbj0A+0IlRcpZpMgI13fmVwo=
github.com/aler9/go-astits v0.0.0-20210423195926-582b09ed7c04/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ= github.com/aler9/go-astits v0.0.0-20210423195926-582b09ed7c04/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ=
github.com/aler9/gortsplib v0.0.0-20210424151845-5480da6c83d7 h1:Fynhg1I1cm7yTj1IzBjmWyqcRVe9iYbQDqa72u8f2HM= github.com/aler9/gortsplib v0.0.0-20210424164934-262f28340026 h1:KQ8G/yC8r1aPSMvto+L0UQEgHWgU6d6H1pCk5JVm8w4=
github.com/aler9/gortsplib v0.0.0-20210424151845-5480da6c83d7/go.mod h1:zVCg+TQX445hh1pC5QgAuuBvvXZMWLY1XYz626dGFqY= github.com/aler9/gortsplib v0.0.0-20210424164934-262f28340026/go.mod h1:zVCg+TQX445hh1pC5QgAuuBvvXZMWLY1XYz626dGFqY=
github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927 h1:95mXJ5fUCYpBRdSOnLAQAdJHHKxxxJrVCiaqDi965YQ= github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927 h1:95mXJ5fUCYpBRdSOnLAQAdJHHKxxxJrVCiaqDi965YQ=
github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927/go.mod h1:vzuE21rowz+lT1NGsWbreIvYulgBpCGnQyeTyFblUHc= github.com/aler9/rtmp v0.0.0-20210403095203-3be4a5535927/go.mod h1:vzuE21rowz+lT1NGsWbreIvYulgBpCGnQyeTyFblUHc=
github.com/asticode/go-astikit v0.20.0 h1:+7N+J4E4lWx2QOkRdOf6DafWJMv6O4RRfgClwQokrH8= github.com/asticode/go-astikit v0.20.0 h1:+7N+J4E4lWx2QOkRdOf6DafWJMv6O4RRfgClwQokrH8=

View File

@ -36,7 +36,7 @@ type Parent interface {
type ClientManager struct { type ClientManager struct {
hlsSegmentCount int hlsSegmentCount int
hlsSegmentDuration time.Duration hlsSegmentDuration time.Duration
rtspPort int rtspAddress string
readTimeout time.Duration readTimeout time.Duration
writeTimeout time.Duration writeTimeout time.Duration
readBufferCount int readBufferCount int
@ -67,7 +67,7 @@ type ClientManager struct {
func New( func New(
hlsSegmentCount int, hlsSegmentCount int,
hlsSegmentDuration time.Duration, hlsSegmentDuration time.Duration,
rtspPort int, rtspAddress string,
readTimeout time.Duration, readTimeout time.Duration,
writeTimeout time.Duration, writeTimeout time.Duration,
readBufferCount int, readBufferCount int,
@ -85,7 +85,7 @@ func New(
cm := &ClientManager{ cm := &ClientManager{
hlsSegmentCount: hlsSegmentCount, hlsSegmentCount: hlsSegmentCount,
hlsSegmentDuration: hlsSegmentDuration, hlsSegmentDuration: hlsSegmentDuration,
rtspPort: rtspPort, rtspAddress: rtspAddress,
readTimeout: readTimeout, readTimeout: readTimeout,
writeTimeout: writeTimeout, writeTimeout: writeTimeout,
readBufferCount: readBufferCount, readBufferCount: readBufferCount,
@ -159,7 +159,7 @@ outer:
case conn := <-tcpAccept: case conn := <-tcpAccept:
c := clientrtsp.New( c := clientrtsp.New(
false, false,
cm.rtspPort, cm.rtspAddress,
cm.readTimeout, cm.readTimeout,
cm.runOnConnect, cm.runOnConnect,
cm.runOnConnectRestart, cm.runOnConnectRestart,
@ -174,7 +174,7 @@ outer:
case conn := <-tlsAccept: case conn := <-tlsAccept:
c := clientrtsp.New( c := clientrtsp.New(
true, true,
cm.rtspPort, cm.rtspAddress,
cm.readTimeout, cm.readTimeout,
cm.runOnConnect, cm.runOnConnect,
cm.runOnConnectRestart, cm.runOnConnectRestart,
@ -188,7 +188,7 @@ outer:
case nconn := <-rtmpAccept: case nconn := <-rtmpAccept:
c := clientrtmp.New( c := clientrtmp.New(
cm.rtspPort, cm.rtspAddress,
cm.readTimeout, cm.readTimeout,
cm.writeTimeout, cm.writeTimeout,
cm.readBufferCount, cm.readBufferCount,

View File

@ -5,7 +5,6 @@ import (
"io" "io"
"net" "net"
"net/url" "net/url"
"strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -81,7 +80,7 @@ type Parent interface {
// Client is a RTMP client. // Client is a RTMP client.
type Client struct { type Client struct {
rtspPort int rtspAddress string
readTimeout time.Duration readTimeout time.Duration
writeTimeout time.Duration writeTimeout time.Duration
readBufferCount int readBufferCount int
@ -102,7 +101,7 @@ type Client struct {
// New allocates a Client. // New allocates a Client.
func New( func New(
rtspPort int, rtspAddress string,
readTimeout time.Duration, readTimeout time.Duration,
writeTimeout time.Duration, writeTimeout time.Duration,
readBufferCount int, readBufferCount int,
@ -115,7 +114,7 @@ func New(
parent Parent) *Client { parent Parent) *Client {
c := &Client{ c := &Client{
rtspPort: rtspPort, rtspAddress: rtspAddress,
readTimeout: readTimeout, readTimeout: readTimeout,
writeTimeout: writeTimeout, writeTimeout: writeTimeout,
readBufferCount: readBufferCount, readBufferCount: readBufferCount,
@ -163,9 +162,10 @@ func (c *Client) run() {
defer c.log(logger.Info, "disconnected") defer c.log(logger.Info, "disconnected")
if c.runOnConnect != "" { if c.runOnConnect != "" {
_, port, _ := net.SplitHostPort(c.rtspAddress)
onConnectCmd := externalcmd.New(c.runOnConnect, c.runOnConnectRestart, externalcmd.Environment{ onConnectCmd := externalcmd.New(c.runOnConnect, c.runOnConnectRestart, externalcmd.Environment{
Path: "", Path: "",
Port: strconv.FormatInt(int64(c.rtspPort), 10), Port: port,
}) })
defer onConnectCmd.Close() defer onConnectCmd.Close()
} }
@ -480,10 +480,11 @@ func (c *Client) runPublish() {
var onPublishCmd *externalcmd.Cmd var onPublishCmd *externalcmd.Cmd
if path.Conf().RunOnPublish != "" { if path.Conf().RunOnPublish != "" {
_, port, _ := net.SplitHostPort(c.rtspAddress)
onPublishCmd = externalcmd.New(path.Conf().RunOnPublish, onPublishCmd = externalcmd.New(path.Conf().RunOnPublish,
path.Conf().RunOnPublishRestart, externalcmd.Environment{ path.Conf().RunOnPublishRestart, externalcmd.Environment{
Path: path.Name(), Path: path.Name(),
Port: strconv.FormatInt(int64(c.rtspPort), 10), Port: port,
}) })
} }

View File

@ -60,7 +60,7 @@ type Parent interface {
// Client is a RTSP client. // Client is a RTSP client.
type Client struct { type Client struct {
rtspPort int rtspAddress string
readTimeout time.Duration readTimeout time.Duration
runOnConnect string runOnConnect string
runOnConnectRestart bool runOnConnectRestart bool
@ -92,7 +92,7 @@ type Client struct {
// New allocates a Client. // New allocates a Client.
func New( func New(
isTLS bool, isTLS bool,
rtspPort int, rtspAddress string,
readTimeout time.Duration, readTimeout time.Duration,
runOnConnect string, runOnConnect string,
runOnConnectRestart bool, runOnConnectRestart bool,
@ -104,7 +104,7 @@ func New(
parent Parent) *Client { parent Parent) *Client {
c := &Client{ c := &Client{
rtspPort: rtspPort, rtspAddress: rtspAddress,
readTimeout: readTimeout, readTimeout: readTimeout,
runOnConnect: runOnConnect, runOnConnect: runOnConnect,
runOnConnectRestart: runOnConnectRestart, runOnConnectRestart: runOnConnectRestart,
@ -158,9 +158,10 @@ func (c *Client) run() {
defer c.log(logger.Info, "disconnected") defer c.log(logger.Info, "disconnected")
if c.runOnConnect != "" { if c.runOnConnect != "" {
_, port, _ := net.SplitHostPort(c.rtspAddress)
onConnectCmd := externalcmd.New(c.runOnConnect, c.runOnConnectRestart, externalcmd.Environment{ onConnectCmd := externalcmd.New(c.runOnConnect, c.runOnConnectRestart, externalcmd.Environment{
Path: "", Path: "",
Port: strconv.FormatInt(int64(c.rtspPort), 10), Port: port,
}) })
defer onConnectCmd.Close() defer onConnectCmd.Close()
} }
@ -588,9 +589,10 @@ func (c *Client) playStart() client.PlayRes {
*c.conn.StreamProtocol()) *c.conn.StreamProtocol())
if c.path.Conf().RunOnRead != "" { if c.path.Conf().RunOnRead != "" {
_, port, _ := net.SplitHostPort(c.rtspAddress)
c.onReadCmd = externalcmd.New(c.path.Conf().RunOnRead, c.path.Conf().RunOnReadRestart, externalcmd.Environment{ c.onReadCmd = externalcmd.New(c.path.Conf().RunOnRead, c.path.Conf().RunOnReadRestart, externalcmd.Environment{
Path: c.path.Name(), Path: c.path.Name(),
Port: strconv.FormatInt(int64(c.rtspPort), 10), Port: port,
}) })
} }
@ -628,9 +630,10 @@ func (c *Client) recordStart() error {
*c.conn.StreamProtocol()) *c.conn.StreamProtocol())
if c.path.Conf().RunOnPublish != "" { if c.path.Conf().RunOnPublish != "" {
_, port, _ := net.SplitHostPort(c.rtspAddress)
c.onPublishCmd = externalcmd.New(c.path.Conf().RunOnPublish, c.path.Conf().RunOnPublishRestart, externalcmd.Environment{ c.onPublishCmd = externalcmd.New(c.path.Conf().RunOnPublish, c.path.Conf().RunOnPublishRestart, externalcmd.Environment{
Path: c.path.Name(), Path: c.path.Name(),
Port: strconv.FormatInt(int64(c.rtspPort), 10), Port: port,
}) })
} }

View File

@ -53,14 +53,13 @@ type Conf struct {
LogDestinations []string `yaml:"logDestinations"` LogDestinations []string `yaml:"logDestinations"`
LogDestinationsParsed map[logger.Destination]struct{} `yaml:"-" json:"-"` LogDestinationsParsed map[logger.Destination]struct{} `yaml:"-" json:"-"`
LogFile string `yaml:"logFile"` LogFile string `yaml:"logFile"`
ListenIP string `yaml:"listenIP"`
ReadTimeout time.Duration `yaml:"readTimeout"` ReadTimeout time.Duration `yaml:"readTimeout"`
WriteTimeout time.Duration `yaml:"writeTimeout"` WriteTimeout time.Duration `yaml:"writeTimeout"`
ReadBufferCount int `yaml:"readBufferCount"` ReadBufferCount int `yaml:"readBufferCount"`
Metrics bool `yaml:"metrics"` Metrics bool `yaml:"metrics"`
MetricsPort int `yaml:"metricsPort"` MetricsAddress string `yaml:"metricsAddress"`
PPROF bool `yaml:"pprof"` PPROF bool `yaml:"pprof"`
PPROFPort int `yaml:"pprofPort"` PPROFAddress string `yaml:"pprofAddress"`
RunOnConnect string `yaml:"runOnConnect"` RunOnConnect string `yaml:"runOnConnect"`
RunOnConnectRestart bool `yaml:"runOnConnectRestart"` RunOnConnectRestart bool `yaml:"runOnConnectRestart"`
@ -70,10 +69,10 @@ type Conf struct {
ProtocolsParsed map[gortsplib.StreamProtocol]struct{} `yaml:"-" json:"-"` ProtocolsParsed map[gortsplib.StreamProtocol]struct{} `yaml:"-" json:"-"`
Encryption string `yaml:"encryption"` Encryption string `yaml:"encryption"`
EncryptionParsed Encryption `yaml:"-" json:"-"` EncryptionParsed Encryption `yaml:"-" json:"-"`
RTSPPort int `yaml:"rtspPort"` RTSPAddress string `yaml:"rtspAddress"`
RTSPSPort int `yaml:"rtspsPort"` RTSPSAddress string `yaml:"rtspsAddress"`
RTPPort int `yaml:"rtpPort"` RTPAddress string `yaml:"rtpAddress"`
RTCPPort int `yaml:"rtcpPort"` RTCPAddress string `yaml:"rtcpAddress"`
ServerKey string `yaml:"serverKey"` ServerKey string `yaml:"serverKey"`
ServerCert string `yaml:"serverCert"` ServerCert string `yaml:"serverCert"`
AuthMethods []string `yaml:"authMethods"` AuthMethods []string `yaml:"authMethods"`
@ -81,12 +80,12 @@ type Conf struct {
ReadBufferSize int `yaml:"readBufferSize"` ReadBufferSize int `yaml:"readBufferSize"`
// rtmp // rtmp
RTMPDisable bool `yaml:"rtmpDisable"` RTMPDisable bool `yaml:"rtmpDisable"`
RTMPPort int `yaml:"rtmpPort"` RTMPAddress string `yaml:"rtmpAddress"`
// hls // hls
HLSDisable bool `yaml:"hlsDisable"` HLSDisable bool `yaml:"hlsDisable"`
HLSPort int `yaml:"hlsPort"` HLSAddress string `yaml:"hlsAddress"`
HLSSegmentCount int `yaml:"hlsSegmentCount"` HLSSegmentCount int `yaml:"hlsSegmentCount"`
HLSSegmentDuration time.Duration `yaml:"hlsSegmentDuration"` HLSSegmentDuration time.Duration `yaml:"hlsSegmentDuration"`
@ -145,12 +144,12 @@ func (conf *Conf) fillAndCheck() error {
conf.ReadBufferCount = 512 conf.ReadBufferCount = 512
} }
if conf.MetricsPort == 0 { if conf.MetricsAddress == "" {
conf.MetricsPort = 9998 conf.MetricsAddress = ":9998"
} }
if conf.PPROFPort == 0 { if conf.PPROFAddress == "" {
conf.MetricsPort = 9999 conf.MetricsAddress = ":9999"
} }
if len(conf.Protocols) == 0 { if len(conf.Protocols) == 0 {
@ -194,23 +193,17 @@ func (conf *Conf) fillAndCheck() error {
return fmt.Errorf("unsupported encryption value: '%s'", conf.Encryption) return fmt.Errorf("unsupported encryption value: '%s'", conf.Encryption)
} }
if conf.RTSPPort == 0 { if conf.RTSPAddress == "" {
conf.RTSPPort = 8554 conf.RTSPAddress = ":8554"
} }
if conf.RTSPSPort == 0 { if conf.RTSPSAddress == "" {
conf.RTSPSPort = 8555 conf.RTSPSAddress = ":8555"
} }
if conf.RTPPort == 0 { if conf.RTPAddress == "" {
conf.RTPPort = 8000 conf.RTPAddress = ":8000"
} }
if (conf.RTPPort % 2) != 0 { if conf.RTCPAddress == "" {
return fmt.Errorf("rtp port must be even") conf.RTCPAddress = ":8001"
}
if conf.RTCPPort == 0 {
conf.RTCPPort = 8001
}
if conf.RTCPPort != (conf.RTPPort + 1) {
return fmt.Errorf("rtcp and rtp ports must be consecutive")
} }
if conf.ServerKey == "" { if conf.ServerKey == "" {
@ -236,12 +229,12 @@ func (conf *Conf) fillAndCheck() error {
} }
} }
if conf.RTMPPort == 0 { if conf.RTMPAddress == "" {
conf.RTMPPort = 1935 conf.RTMPAddress = ":1935"
} }
if conf.HLSPort == 0 { if conf.HLSAddress == "" {
conf.HLSPort = 8888 conf.HLSAddress = ":8888"
} }
if conf.HLSSegmentCount == 0 { if conf.HLSSegmentCount == 0 {
conf.HLSSegmentCount = 5 conf.HLSSegmentCount = 5

View File

@ -36,8 +36,8 @@ func TestEnvironment(t *testing.T) {
defer os.Unsetenv("RTSP_RUNONCONNECT") defer os.Unsetenv("RTSP_RUNONCONNECT")
// int // int
os.Setenv("RTSP_RTSPPORT", "8555") os.Setenv("RTSP_READBUFFERCOUNT", "3000")
defer os.Unsetenv("RTSP_RTSPPORT") defer os.Unsetenv("RTSP_READBUFFERCOUNT")
// bool // bool
os.Setenv("RTSP_METRICS", "yes") os.Setenv("RTSP_METRICS", "yes")
@ -79,7 +79,7 @@ func TestEnvironment(t *testing.T) {
require.Equal(t, "test=cmd", conf.RunOnConnect) require.Equal(t, "test=cmd", conf.RunOnConnect)
require.Equal(t, 8555, conf.RTSPPort) require.Equal(t, 3000, conf.ReadBufferCount)
require.Equal(t, true, conf.Metrics) require.Equal(t, true, conf.Metrics)

View File

@ -34,13 +34,11 @@ type Metrics struct {
// New allocates a metrics. // New allocates a metrics.
func New( func New(
listenIP string, address string,
port int,
stats *stats.Stats, stats *stats.Stats,
parent Parent, parent Parent,
) (*Metrics, error) { ) (*Metrics, error) {
address := listenIP + ":" + strconv.FormatInt(int64(port), 10)
listener, err := net.Listen("tcp", address) listener, err := net.Listen("tcp", address)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2,7 +2,7 @@ package path
import ( import (
"fmt" "fmt"
"strconv" "net"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -59,7 +59,7 @@ const (
// Path is a path. // Path is a path.
type Path struct { type Path struct {
rtspPort int rtspAddress string
readTimeout time.Duration readTimeout time.Duration
writeTimeout time.Duration writeTimeout time.Duration
readBufferCount int readBufferCount int
@ -105,7 +105,7 @@ type Path struct {
// New allocates a Path. // New allocates a Path.
func New( func New(
rtspPort int, rtspAddress string,
readTimeout time.Duration, readTimeout time.Duration,
writeTimeout time.Duration, writeTimeout time.Duration,
readBufferCount int, readBufferCount int,
@ -118,7 +118,7 @@ func New(
parent Parent) *Path { parent Parent) *Path {
pa := &Path{ pa := &Path{
rtspPort: rtspPort, rtspAddress: rtspAddress,
readTimeout: readTimeout, readTimeout: readTimeout,
writeTimeout: writeTimeout, writeTimeout: writeTimeout,
readBufferCount: readBufferCount, readBufferCount: readBufferCount,
@ -175,9 +175,10 @@ func (pa *Path) run() {
var onInitCmd *externalcmd.Cmd var onInitCmd *externalcmd.Cmd
if pa.conf.RunOnInit != "" { if pa.conf.RunOnInit != "" {
pa.Log(logger.Info, "on init command started") pa.Log(logger.Info, "on init command started")
_, port, _ := net.SplitHostPort(pa.rtspAddress)
onInitCmd = externalcmd.New(pa.conf.RunOnInit, pa.conf.RunOnInitRestart, externalcmd.Environment{ onInitCmd = externalcmd.New(pa.conf.RunOnInit, pa.conf.RunOnInitRestart, externalcmd.Environment{
Path: pa.name, Path: pa.name,
Port: strconv.FormatInt(int64(pa.rtspPort), 10), Port: port,
}) })
} }
@ -536,9 +537,10 @@ func (pa *Path) fixedPublisherStart() {
// start on-demand command // start on-demand command
if pa.onDemandCmd == nil { if pa.onDemandCmd == nil {
pa.Log(logger.Info, "on demand command started") pa.Log(logger.Info, "on demand command started")
_, port, _ := net.SplitHostPort(pa.rtspAddress)
pa.onDemandCmd = externalcmd.New(pa.conf.RunOnDemand, pa.conf.RunOnDemandRestart, externalcmd.Environment{ pa.onDemandCmd = externalcmd.New(pa.conf.RunOnDemand, pa.conf.RunOnDemandRestart, externalcmd.Environment{
Path: pa.name, Path: pa.name,
Port: strconv.FormatInt(int64(pa.rtspPort), 10), Port: port,
}) })
if pa.sourceState != sourceStateWaitingDescribe { if pa.sourceState != sourceStateWaitingDescribe {

View File

@ -21,7 +21,7 @@ type Parent interface {
// PathManager is a path.Path manager. // PathManager is a path.Path manager.
type PathManager struct { type PathManager struct {
rtspPort int rtspAddress string
readTimeout time.Duration readTimeout time.Duration
writeTimeout time.Duration writeTimeout time.Duration
readBufferCount int readBufferCount int
@ -49,7 +49,7 @@ type PathManager struct {
// New allocates a PathManager. // New allocates a PathManager.
func New( func New(
rtspPort int, rtspAddress string,
readTimeout time.Duration, readTimeout time.Duration,
writeTimeout time.Duration, writeTimeout time.Duration,
readBufferCount int, readBufferCount int,
@ -60,7 +60,7 @@ func New(
parent Parent) *PathManager { parent Parent) *PathManager {
pm := &PathManager{ pm := &PathManager{
rtspPort: rtspPort, rtspAddress: rtspAddress,
readTimeout: readTimeout, readTimeout: readTimeout,
writeTimeout: writeTimeout, writeTimeout: writeTimeout,
readBufferCount: readBufferCount, readBufferCount: readBufferCount,
@ -280,7 +280,7 @@ outer:
func (pm *PathManager) createPath(confName string, conf *conf.PathConf, name string) { func (pm *PathManager) createPath(confName string, conf *conf.PathConf, name string) {
pm.paths[name] = path.New( pm.paths[name] = path.New(
pm.rtspPort, pm.rtspAddress,
pm.readTimeout, pm.readTimeout,
pm.writeTimeout, pm.writeTimeout,
pm.readBufferCount, pm.readBufferCount,

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"net" "net"
"net/http" "net/http"
"strconv"
// start pprof // start pprof
_ "net/http/pprof" _ "net/http/pprof"
@ -25,11 +24,10 @@ type PPROF struct {
// New allocates a PPROF. // New allocates a PPROF.
func New( func New(
listenIP string, address string,
port int,
parent Parent, parent Parent,
) (*PPROF, error) { ) (*PPROF, error) {
address := listenIP + ":" + strconv.FormatInt(int64(port), 10)
listener, err := net.Listen("tcp", address) listener, err := net.Listen("tcp", address)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -5,7 +5,6 @@ import (
"io" "io"
"net" "net"
"net/http" "net/http"
"strconv"
"strings" "strings"
"github.com/aler9/rtsp-simple-server/internal/logger" "github.com/aler9/rtsp-simple-server/internal/logger"
@ -38,11 +37,10 @@ type Server struct {
// New allocates a Server. // New allocates a Server.
func New( func New(
listenIP string, address string,
port int,
parent Parent, parent Parent,
) (*Server, error) { ) (*Server, error) {
address := listenIP + ":" + strconv.FormatInt(int64(port), 10)
ln, err := net.Listen("tcp", address) ln, err := net.Listen("tcp", address)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2,7 +2,6 @@ package serverrtmp
import ( import (
"net" "net"
"strconv"
"sync/atomic" "sync/atomic"
"github.com/aler9/rtsp-simple-server/internal/logger" "github.com/aler9/rtsp-simple-server/internal/logger"
@ -27,11 +26,9 @@ type Server struct {
// New allocates a Server. // New allocates a Server.
func New( func New(
listenIP string, address string,
port int,
parent Parent) (*Server, error) { parent Parent) (*Server, error) {
address := listenIP + ":" + strconv.FormatInt(int64(port), 10)
l, err := net.Listen("tcp", address) l, err := net.Listen("tcp", address)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2,7 +2,6 @@ package serverrtsp
import ( import (
"crypto/tls" "crypto/tls"
"strconv"
"sync/atomic" "sync/atomic"
"time" "time"
@ -31,15 +30,14 @@ type Server struct {
// New allocates a Server. // New allocates a Server.
func New( func New(
listenIP string, address string,
port int,
readTimeout time.Duration, readTimeout time.Duration,
writeTimeout time.Duration, writeTimeout time.Duration,
readBufferCount int, readBufferCount int,
readBufferSize int, readBufferSize int,
useUDP bool, useUDP bool,
rtpPort int, rtpAddress string,
rtcpPort int, rtcpAddress string,
useTLS bool, useTLS bool,
serverCert string, serverCert string,
serverKey string, serverKey string,
@ -53,8 +51,8 @@ func New(
} }
if useUDP { if useUDP {
conf.UDPRTPAddress = listenIP + ":" + strconv.FormatInt(int64(rtpPort), 10) conf.UDPRTPAddress = rtpAddress
conf.UDPRTCPAddress = listenIP + ":" + strconv.FormatInt(int64(rtcpPort), 10) conf.UDPRTCPAddress = rtcpAddress
} }
if useTLS { if useTLS {
@ -66,7 +64,6 @@ func New(
conf.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cert}} conf.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cert}}
} }
address := listenIP + ":" + strconv.FormatInt(int64(port), 10)
srv, err := conf.Serve(address) srv, err := conf.Serve(address)
if err != nil { if err != nil {
return nil, err return nil, err

56
main.go
View File

@ -171,8 +171,7 @@ func (p *program) createResources(initial bool) error {
if p.conf.Metrics { if p.conf.Metrics {
if p.metrics == nil { if p.metrics == nil {
p.metrics, err = metrics.New( p.metrics, err = metrics.New(
p.conf.ListenIP, p.conf.MetricsAddress,
p.conf.MetricsPort,
p.stats, p.stats,
p) p)
if err != nil { if err != nil {
@ -184,8 +183,7 @@ func (p *program) createResources(initial bool) error {
if p.conf.PPROF { if p.conf.PPROF {
if p.pprof == nil { if p.pprof == nil {
p.pprof, err = pprof.New( p.pprof, err = pprof.New(
p.conf.ListenIP, p.conf.PPROFAddress,
p.conf.PPROFPort,
p) p)
if err != nil { if err != nil {
return err return err
@ -199,15 +197,14 @@ func (p *program) createResources(initial bool) error {
if p.serverRTSPPlain == nil { if p.serverRTSPPlain == nil {
_, useUDP := p.conf.ProtocolsParsed[gortsplib.StreamProtocolUDP] _, useUDP := p.conf.ProtocolsParsed[gortsplib.StreamProtocolUDP]
p.serverRTSPPlain, err = serverrtsp.New( p.serverRTSPPlain, err = serverrtsp.New(
p.conf.ListenIP, p.conf.RTSPAddress,
p.conf.RTSPPort,
p.conf.ReadTimeout, p.conf.ReadTimeout,
p.conf.WriteTimeout, p.conf.WriteTimeout,
p.conf.ReadBufferCount, p.conf.ReadBufferCount,
p.conf.ReadBufferSize, p.conf.ReadBufferSize,
useUDP, useUDP,
p.conf.RTPPort, p.conf.RTPAddress,
p.conf.RTCPPort, p.conf.RTCPAddress,
false, false,
"", "",
"", "",
@ -223,15 +220,14 @@ func (p *program) createResources(initial bool) error {
p.conf.EncryptionParsed == conf.EncryptionOptional) { p.conf.EncryptionParsed == conf.EncryptionOptional) {
if p.serverRTSPTLS == nil { if p.serverRTSPTLS == nil {
p.serverRTSPTLS, err = serverrtsp.New( p.serverRTSPTLS, err = serverrtsp.New(
p.conf.ListenIP, p.conf.RTSPSAddress,
p.conf.RTSPSPort,
p.conf.ReadTimeout, p.conf.ReadTimeout,
p.conf.WriteTimeout, p.conf.WriteTimeout,
p.conf.ReadBufferCount, p.conf.ReadBufferCount,
p.conf.ReadBufferSize, p.conf.ReadBufferSize,
false, false,
0, "",
0, "",
true, true,
p.conf.ServerCert, p.conf.ServerCert,
p.conf.ServerKey, p.conf.ServerKey,
@ -245,8 +241,7 @@ func (p *program) createResources(initial bool) error {
if !p.conf.RTMPDisable { if !p.conf.RTMPDisable {
if p.serverRTMP == nil { if p.serverRTMP == nil {
p.serverRTMP, err = serverrtmp.New( p.serverRTMP, err = serverrtmp.New(
p.conf.ListenIP, p.conf.RTMPAddress,
p.conf.RTMPPort,
p) p)
if err != nil { if err != nil {
return err return err
@ -257,8 +252,7 @@ func (p *program) createResources(initial bool) error {
if !p.conf.HLSDisable { if !p.conf.HLSDisable {
if p.serverHLS == nil { if p.serverHLS == nil {
p.serverHLS, err = serverhls.New( p.serverHLS, err = serverhls.New(
p.conf.ListenIP, p.conf.HLSAddress,
p.conf.HLSPort,
p) p)
if err != nil { if err != nil {
return err return err
@ -268,7 +262,7 @@ func (p *program) createResources(initial bool) error {
if p.pathMan == nil { if p.pathMan == nil {
p.pathMan = pathman.New( p.pathMan = pathman.New(
p.conf.RTSPPort, p.conf.RTSPAddress,
p.conf.ReadTimeout, p.conf.ReadTimeout,
p.conf.WriteTimeout, p.conf.WriteTimeout,
p.conf.ReadBufferCount, p.conf.ReadBufferCount,
@ -283,7 +277,7 @@ func (p *program) createResources(initial bool) error {
p.clientMan = clientman.New( p.clientMan = clientman.New(
p.conf.HLSSegmentCount, p.conf.HLSSegmentCount,
p.conf.HLSSegmentDuration, p.conf.HLSSegmentDuration,
p.conf.RTSPPort, p.conf.RTSPAddress,
p.conf.ReadTimeout, p.conf.ReadTimeout,
p.conf.WriteTimeout, p.conf.WriteTimeout,
p.conf.ReadBufferCount, p.conf.ReadBufferCount,
@ -313,16 +307,14 @@ func (p *program) closeResources(newConf *conf.Conf) {
closeMetrics := false closeMetrics := false
if newConf == nil || if newConf == nil ||
newConf.Metrics != p.conf.Metrics || newConf.Metrics != p.conf.Metrics ||
newConf.ListenIP != p.conf.ListenIP || newConf.MetricsAddress != p.conf.MetricsAddress {
newConf.MetricsPort != p.conf.MetricsPort {
closeMetrics = true closeMetrics = true
} }
closePPROF := false closePPROF := false
if newConf == nil || if newConf == nil ||
newConf.PPROF != p.conf.PPROF || newConf.PPROF != p.conf.PPROF ||
newConf.ListenIP != p.conf.ListenIP || newConf.PPROFAddress != p.conf.PPROFAddress {
newConf.PPROFPort != p.conf.PPROFPort {
closePPROF = true closePPROF = true
} }
@ -330,14 +322,13 @@ func (p *program) closeResources(newConf *conf.Conf) {
if newConf == nil || if newConf == nil ||
newConf.RTSPDisable != p.conf.RTSPDisable || newConf.RTSPDisable != p.conf.RTSPDisable ||
newConf.EncryptionParsed != p.conf.EncryptionParsed || newConf.EncryptionParsed != p.conf.EncryptionParsed ||
newConf.ListenIP != p.conf.ListenIP || newConf.RTSPAddress != p.conf.RTSPAddress ||
newConf.RTSPPort != p.conf.RTSPPort ||
newConf.ReadTimeout != p.conf.ReadTimeout || newConf.ReadTimeout != p.conf.ReadTimeout ||
newConf.WriteTimeout != p.conf.WriteTimeout || newConf.WriteTimeout != p.conf.WriteTimeout ||
newConf.ReadBufferCount != p.conf.ReadBufferCount || newConf.ReadBufferCount != p.conf.ReadBufferCount ||
!reflect.DeepEqual(newConf.ProtocolsParsed, p.conf.ProtocolsParsed) || !reflect.DeepEqual(newConf.ProtocolsParsed, p.conf.ProtocolsParsed) ||
newConf.RTPPort != p.conf.RTPPort || newConf.RTPAddress != p.conf.RTPAddress ||
newConf.RTCPPort != p.conf.RTCPPort { newConf.RTCPAddress != p.conf.RTCPAddress {
closeServerPlain = true closeServerPlain = true
} }
@ -345,8 +336,7 @@ func (p *program) closeResources(newConf *conf.Conf) {
if newConf == nil || if newConf == nil ||
newConf.RTSPDisable != p.conf.RTSPDisable || newConf.RTSPDisable != p.conf.RTSPDisable ||
newConf.EncryptionParsed != p.conf.EncryptionParsed || newConf.EncryptionParsed != p.conf.EncryptionParsed ||
newConf.ListenIP != p.conf.ListenIP || newConf.RTSPSAddress != p.conf.RTSPSAddress ||
newConf.RTSPSPort != p.conf.RTSPSPort ||
newConf.ReadTimeout != p.conf.ReadTimeout || newConf.ReadTimeout != p.conf.ReadTimeout ||
newConf.WriteTimeout != p.conf.WriteTimeout || newConf.WriteTimeout != p.conf.WriteTimeout ||
newConf.ReadBufferCount != p.conf.ReadBufferCount || newConf.ReadBufferCount != p.conf.ReadBufferCount ||
@ -358,8 +348,7 @@ func (p *program) closeResources(newConf *conf.Conf) {
closeServerRTMP := false closeServerRTMP := false
if newConf == nil || if newConf == nil ||
newConf.RTMPDisable != p.conf.RTMPDisable || newConf.RTMPDisable != p.conf.RTMPDisable ||
newConf.ListenIP != p.conf.ListenIP || newConf.RTMPAddress != p.conf.RTMPAddress ||
newConf.RTMPPort != p.conf.RTMPPort ||
newConf.ReadTimeout != p.conf.ReadTimeout { newConf.ReadTimeout != p.conf.ReadTimeout {
closeServerRTMP = true closeServerRTMP = true
} }
@ -367,14 +356,13 @@ func (p *program) closeResources(newConf *conf.Conf) {
closeServerHLS := false closeServerHLS := false
if newConf == nil || if newConf == nil ||
newConf.HLSDisable != p.conf.HLSDisable || newConf.HLSDisable != p.conf.HLSDisable ||
newConf.ListenIP != p.conf.ListenIP || newConf.HLSAddress != p.conf.HLSAddress {
newConf.HLSPort != p.conf.HLSPort {
closeServerHLS = true closeServerHLS = true
} }
closePathMan := false closePathMan := false
if newConf == nil || if newConf == nil ||
newConf.RTSPPort != p.conf.RTSPPort || newConf.RTSPAddress != p.conf.RTSPAddress ||
newConf.ReadTimeout != p.conf.ReadTimeout || newConf.ReadTimeout != p.conf.ReadTimeout ||
newConf.WriteTimeout != p.conf.WriteTimeout || newConf.WriteTimeout != p.conf.WriteTimeout ||
newConf.ReadBufferCount != p.conf.ReadBufferCount || newConf.ReadBufferCount != p.conf.ReadBufferCount ||
@ -394,7 +382,7 @@ func (p *program) closeResources(newConf *conf.Conf) {
closePathMan || closePathMan ||
newConf.HLSSegmentCount != p.conf.HLSSegmentCount || newConf.HLSSegmentCount != p.conf.HLSSegmentCount ||
newConf.HLSSegmentDuration != p.conf.HLSSegmentDuration || newConf.HLSSegmentDuration != p.conf.HLSSegmentDuration ||
newConf.RTSPPort != p.conf.RTSPPort || newConf.RTSPAddress != p.conf.RTSPAddress ||
newConf.ReadTimeout != p.conf.ReadTimeout || newConf.ReadTimeout != p.conf.ReadTimeout ||
newConf.WriteTimeout != p.conf.WriteTimeout || newConf.WriteTimeout != p.conf.WriteTimeout ||
newConf.ReadBufferCount != p.conf.ReadBufferCount || newConf.ReadBufferCount != p.conf.ReadBufferCount ||

View File

@ -596,7 +596,7 @@ func TestClientRTSPNonCompliantFrameSize(t *testing.T) {
"hlsDisable: yes\n" + "hlsDisable: yes\n" +
"protocols: [tcp]\n" + "protocols: [tcp]\n" +
"readBufferSize: 4500\n" + "readBufferSize: 4500\n" +
"rtspPort: 8555\n" + "rtspAddress: :8555\n" +
"paths:\n" + "paths:\n" +
" teststream:\n" + " teststream:\n" +
" source: rtsp://" + ownDockerIP + ":8554/teststream\n" + " source: rtsp://" + ownDockerIP + ":8554/teststream\n" +

View File

@ -26,9 +26,9 @@ func TestSourceRTSP(t *testing.T) {
case "udp", "tcp": case "udp", "tcp":
p1, ok := testProgram("rtmpDisable: yes\n" + p1, ok := testProgram("rtmpDisable: yes\n" +
"hlsDisable: yes\n" + "hlsDisable: yes\n" +
"rtspPort: 8555\n" + "rtspAddress: :8555\n" +
"rtpPort: 8100\n" + "rtpAddress: :8100\n" +
"rtcpPort: 8101\n" + "rtcpAddress: :8101\n" +
"paths:\n" + "paths:\n" +
" all:\n" + " all:\n" +
" readUser: testuser\n" + " readUser: testuser\n" +
@ -69,9 +69,9 @@ func TestSourceRTSP(t *testing.T) {
p, ok := testProgram("rtmpDisable: yes\n" + p, ok := testProgram("rtmpDisable: yes\n" +
"hlsDisable: yes\n" + "hlsDisable: yes\n" +
"rtspPort: 8555\n" + "rtspAddress: :8555\n" +
"rtpPort: 8100\n" + "rtpAddress: :8100\n" +
"rtcpPort: 8101\n" + "rtcpAddress: :8101\n" +
"readTimeout: 20s\n" + "readTimeout: 20s\n" +
"protocols: [tcp]\n" + "protocols: [tcp]\n" +
"encryption: yes\n" + "encryption: yes\n" +

View File

@ -9,8 +9,6 @@ logDestinations: [stdout]
# if "file" is in logDestinations, this is the file which will receive the logs. # if "file" is in logDestinations, this is the file which will receive the logs.
logFile: rtsp-simple-server.log logFile: rtsp-simple-server.log
# listen IP. If provided, all listeners will listen on this specific IP.
listenIP:
# timeout of read operations. # timeout of read operations.
readTimeout: 10s readTimeout: 10s
# timeout of write operations. # timeout of write operations.
@ -22,13 +20,13 @@ readBufferCount: 512
# enable Prometheus-compatible metrics. # enable Prometheus-compatible metrics.
metrics: no metrics: no
# port of the metrics listener. # address of the metrics listener.
metricsPort: 9998 metricsAddress: :9998
# enable pprof-compatible endpoint to monitor performances. # enable pprof-compatible endpoint to monitor performances.
pprof: no pprof: no
# port of the pprof listener. # address of the pprof listener.
pprofPort: 9999 pprofAddress: :9999
# command to run when a client connects to the server. # command to run when a client connects to the server.
# this is terminated with SIGINT when a client disconnects from the server. # this is terminated with SIGINT when a client disconnects from the server.
@ -51,14 +49,14 @@ protocols: [udp, tcp]
# encrypt handshake and TCP streams with TLS (RTSPS). # encrypt handshake and TCP streams with TLS (RTSPS).
# available values are "no", "strict", "optional". # available values are "no", "strict", "optional".
encryption: no encryption: no
# port of the TCP/RTSP listener. This is used only if encryption is "no" or "optional". # address of the TCP/RTSP listener. This is used only if encryption is "no" or "optional".
rtspPort: 8554 rtspAddress: :8554
# port of the TCP/TLS/RTSPS listener. This is used only if encryption is "strict" or "optional". # address of the TCP/TLS/RTSPS listener. This is used only if encryption is "strict" or "optional".
rtspsPort: 8555 rtspsAddress: :8555
# port of the UDP/RTP listener. This is used only if "udp" is in protocols. # address of the UDP/RTP listener. This is used only if "udp" is in protocols.
rtpPort: 8000 rtpAddress: :8000
# port of the UDP/RTCP listener. This is used only if "udp" is in protocols. # address of the UDP/RTCP listener. This is used only if "udp" is in protocols.
rtcpPort: 8001 rtcpAddress: :8001
# path to the server key. This is used only if encryption is "strict" or "optional". # path to the server key. This is used only if encryption is "strict" or "optional".
# this can be generated with: # this can be generated with:
# openssl genrsa -out server.key 2048 # openssl genrsa -out server.key 2048
@ -78,16 +76,16 @@ readBufferSize: 2048
# disable support for the RTMP protocol. # disable support for the RTMP protocol.
rtmpDisable: no rtmpDisable: no
# port of the RTMP listener. # address of the RTMP listener.
rtmpPort: 1935 rtmpAddress: :1935
############################################### ###############################################
# HLS options # HLS options
# disable support for the HLS protocol. # disable support for the HLS protocol.
hlsDisable: no hlsDisable: no
# port of the HLS listener. # address of the HLS listener.
hlsPort: 8888 hlsAddress: :8888
# number of HLS segments to generate. # number of HLS segments to generate.
# increasing segments allows more buffering, # increasing segments allows more buffering,
# decreasing segments decrease latency. # decreasing segments decrease latency.