mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-20 02:00:05 -08:00
move clientrtsp inside serverrtsp
This commit is contained in:
parent
37d752ba61
commit
ff8aadf722
9 changed files with 302 additions and 254 deletions
|
|
@ -136,6 +136,7 @@ type Client interface {
|
||||||
IsClient()
|
IsClient()
|
||||||
IsSource()
|
IsSource()
|
||||||
Close()
|
Close()
|
||||||
|
CloseRequest()
|
||||||
Authenticate([]headers.AuthMethod,
|
Authenticate([]headers.AuthMethod,
|
||||||
string, []interface{},
|
string, []interface{},
|
||||||
string, string, interface{}) error
|
string, string, interface{}) error
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,11 @@ func (c *Client) Close() {
|
||||||
close(c.terminate)
|
close(c.terminate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseRequest closes a Client.
|
||||||
|
func (c *Client) CloseRequest() {
|
||||||
|
c.parent.OnClientClose(c)
|
||||||
|
}
|
||||||
|
|
||||||
// IsClient implements client.Client.
|
// IsClient implements client.Client.
|
||||||
func (c *Client) IsClient() {}
|
func (c *Client) IsClient() {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,19 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aler9/gortsplib"
|
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
|
||||||
"github.com/aler9/rtsp-simple-server/internal/client"
|
"github.com/aler9/rtsp-simple-server/internal/client"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/clienthls"
|
"github.com/aler9/rtsp-simple-server/internal/clienthls"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/clientrtmp"
|
"github.com/aler9/rtsp-simple-server/internal/clientrtmp"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/clientrtsp"
|
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/serverhls"
|
"github.com/aler9/rtsp-simple-server/internal/serverhls"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/serverrtmp"
|
"github.com/aler9/rtsp-simple-server/internal/serverrtmp"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/serverrtsp"
|
|
||||||
"github.com/aler9/rtsp-simple-server/internal/stats"
|
"github.com/aler9/rtsp-simple-server/internal/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PathManager is implemented by pathman.PathManager.
|
// PathManager is implemented by pathman.PathManager.
|
||||||
type PathManager interface {
|
type PathManager interface {
|
||||||
ClientClose() chan client.Client
|
|
||||||
OnClientDescribe(client.DescribeReq)
|
OnClientDescribe(client.DescribeReq)
|
||||||
OnClientAnnounce(client.AnnounceReq)
|
OnClientAnnounce(client.AnnounceReq)
|
||||||
OnClientSetupPlay(client.SetupPlayReq)
|
OnClientSetupPlay(client.SetupPlayReq)
|
||||||
|
|
@ -45,8 +41,6 @@ type ClientManager struct {
|
||||||
protocols map[base.StreamProtocol]struct{}
|
protocols map[base.StreamProtocol]struct{}
|
||||||
stats *stats.Stats
|
stats *stats.Stats
|
||||||
pathMan PathManager
|
pathMan PathManager
|
||||||
serverPlain *serverrtsp.Server
|
|
||||||
serverTLS *serverrtsp.Server
|
|
||||||
serverRTMP *serverrtmp.Server
|
serverRTMP *serverrtmp.Server
|
||||||
serverHLS *serverhls.Server
|
serverHLS *serverhls.Server
|
||||||
parent Parent
|
parent Parent
|
||||||
|
|
@ -76,8 +70,6 @@ func New(
|
||||||
protocols map[base.StreamProtocol]struct{},
|
protocols map[base.StreamProtocol]struct{},
|
||||||
stats *stats.Stats,
|
stats *stats.Stats,
|
||||||
pathMan PathManager,
|
pathMan PathManager,
|
||||||
serverPlain *serverrtsp.Server,
|
|
||||||
serverTLS *serverrtsp.Server,
|
|
||||||
serverRTMP *serverrtmp.Server,
|
serverRTMP *serverrtmp.Server,
|
||||||
serverHLS *serverhls.Server,
|
serverHLS *serverhls.Server,
|
||||||
parent Parent) *ClientManager {
|
parent Parent) *ClientManager {
|
||||||
|
|
@ -94,8 +86,6 @@ func New(
|
||||||
protocols: protocols,
|
protocols: protocols,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
pathMan: pathMan,
|
pathMan: pathMan,
|
||||||
serverPlain: serverPlain,
|
|
||||||
serverTLS: serverTLS,
|
|
||||||
serverRTMP: serverRTMP,
|
serverRTMP: serverRTMP,
|
||||||
serverHLS: serverHLS,
|
serverHLS: serverHLS,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
|
|
@ -125,20 +115,6 @@ func (cm *ClientManager) Log(level logger.Level, format string, args ...interfac
|
||||||
func (cm *ClientManager) run() {
|
func (cm *ClientManager) run() {
|
||||||
defer close(cm.done)
|
defer close(cm.done)
|
||||||
|
|
||||||
tcpAccept := func() chan *gortsplib.ServerConn {
|
|
||||||
if cm.serverPlain != nil {
|
|
||||||
return cm.serverPlain.Accept()
|
|
||||||
}
|
|
||||||
return make(chan *gortsplib.ServerConn)
|
|
||||||
}()
|
|
||||||
|
|
||||||
tlsAccept := func() chan *gortsplib.ServerConn {
|
|
||||||
if cm.serverTLS != nil {
|
|
||||||
return cm.serverTLS.Accept()
|
|
||||||
}
|
|
||||||
return make(chan *gortsplib.ServerConn)
|
|
||||||
}()
|
|
||||||
|
|
||||||
rtmpAccept := func() chan net.Conn {
|
rtmpAccept := func() chan net.Conn {
|
||||||
if cm.serverRTMP != nil {
|
if cm.serverRTMP != nil {
|
||||||
return cm.serverRTMP.Accept()
|
return cm.serverRTMP.Accept()
|
||||||
|
|
@ -156,36 +132,6 @@ func (cm *ClientManager) run() {
|
||||||
outer:
|
outer:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case conn := <-tcpAccept:
|
|
||||||
c := clientrtsp.New(
|
|
||||||
false,
|
|
||||||
cm.rtspAddress,
|
|
||||||
cm.readTimeout,
|
|
||||||
cm.runOnConnect,
|
|
||||||
cm.runOnConnectRestart,
|
|
||||||
cm.protocols,
|
|
||||||
&cm.wg,
|
|
||||||
cm.stats,
|
|
||||||
conn,
|
|
||||||
cm.pathMan,
|
|
||||||
cm)
|
|
||||||
cm.clients[c] = struct{}{}
|
|
||||||
|
|
||||||
case conn := <-tlsAccept:
|
|
||||||
c := clientrtsp.New(
|
|
||||||
true,
|
|
||||||
cm.rtspAddress,
|
|
||||||
cm.readTimeout,
|
|
||||||
cm.runOnConnect,
|
|
||||||
cm.runOnConnectRestart,
|
|
||||||
cm.protocols,
|
|
||||||
&cm.wg,
|
|
||||||
cm.stats,
|
|
||||||
conn,
|
|
||||||
cm.pathMan,
|
|
||||||
cm)
|
|
||||||
cm.clients[c] = struct{}{}
|
|
||||||
|
|
||||||
case nconn := <-rtmpAccept:
|
case nconn := <-rtmpAccept:
|
||||||
c := clientrtmp.New(
|
c := clientrtmp.New(
|
||||||
cm.rtspAddress,
|
cm.rtspAddress,
|
||||||
|
|
@ -218,12 +164,6 @@ outer:
|
||||||
}
|
}
|
||||||
c.OnRequest(req)
|
c.OnRequest(req)
|
||||||
|
|
||||||
case c := <-cm.pathMan.ClientClose():
|
|
||||||
if _, ok := cm.clients[c]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cm.onClientClose(c)
|
|
||||||
|
|
||||||
case c := <-cm.clientClose:
|
case c := <-cm.clientClose:
|
||||||
if _, ok := cm.clients[c]; !ok {
|
if _, ok := cm.clients[c]; !ok {
|
||||||
continue
|
continue
|
||||||
|
|
@ -236,15 +176,7 @@ outer:
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for range cm.clientClose {
|
||||||
select {
|
|
||||||
case _, ok := <-cm.clientClose:
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-cm.pathMan.ClientClose():
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,11 @@ func (c *Client) Close() {
|
||||||
close(c.terminate)
|
close(c.terminate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseRequest closes a Client.
|
||||||
|
func (c *Client) CloseRequest() {
|
||||||
|
c.parent.OnClientClose(c)
|
||||||
|
}
|
||||||
|
|
||||||
// IsClient implements client.Client.
|
// IsClient implements client.Client.
|
||||||
func (c *Client) IsClient() {}
|
func (c *Client) IsClient() {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ type PathMan interface {
|
||||||
// Parent is implemented by clientman.ClientMan.
|
// Parent is implemented by clientman.ClientMan.
|
||||||
type Parent interface {
|
type Parent interface {
|
||||||
Log(logger.Level, string, ...interface{})
|
Log(logger.Level, string, ...interface{})
|
||||||
OnClientClose(client.Client)
|
OnClientClose(*Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is a RTSP client.
|
// Client is a RTSP client.
|
||||||
|
|
@ -118,12 +118,7 @@ func New(
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic.AddInt64(c.stats.CountClients, 1)
|
atomic.AddInt64(c.stats.CountClients, 1)
|
||||||
c.log(logger.Info, "connected (%s)", func() string {
|
c.log(logger.Info, "connected")
|
||||||
if isTLS {
|
|
||||||
return "RTSP/TLS"
|
|
||||||
}
|
|
||||||
return "RTSP/TCP"
|
|
||||||
}())
|
|
||||||
|
|
||||||
c.wg.Add(1)
|
c.wg.Add(1)
|
||||||
go c.run()
|
go c.run()
|
||||||
|
|
@ -134,9 +129,15 @@ func New(
|
||||||
// Close closes a Client.
|
// Close closes a Client.
|
||||||
func (c *Client) Close() {
|
func (c *Client) Close() {
|
||||||
atomic.AddInt64(c.stats.CountClients, -1)
|
atomic.AddInt64(c.stats.CountClients, -1)
|
||||||
|
c.log(logger.Info, "disconnected")
|
||||||
close(c.terminate)
|
close(c.terminate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseRequest closes a Client.
|
||||||
|
func (c *Client) CloseRequest() {
|
||||||
|
c.parent.OnClientClose(c)
|
||||||
|
}
|
||||||
|
|
||||||
// IsClient implements client.Client.
|
// IsClient implements client.Client.
|
||||||
func (c *Client) IsClient() {}
|
func (c *Client) IsClient() {}
|
||||||
|
|
||||||
|
|
@ -155,7 +156,6 @@ var errTerminated = errors.New("terminated")
|
||||||
|
|
||||||
func (c *Client) run() {
|
func (c *Client) run() {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
defer c.log(logger.Info, "disconnected")
|
|
||||||
|
|
||||||
if c.runOnConnect != "" {
|
if c.runOnConnect != "" {
|
||||||
_, port, _ := net.SplitHostPort(c.rtspAddress)
|
_, port, _ := net.SplitHostPort(c.rtspAddress)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ func newEmptyTimer() *time.Timer {
|
||||||
type Parent interface {
|
type Parent interface {
|
||||||
Log(logger.Level, string, ...interface{})
|
Log(logger.Level, string, ...interface{})
|
||||||
OnPathClose(*Path)
|
OnPathClose(*Path)
|
||||||
OnPathClientClose(client.Client)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type sourceRedirect struct{}
|
type sourceRedirect struct{}
|
||||||
|
|
@ -310,7 +309,7 @@ outer:
|
||||||
case clientStateRecord:
|
case clientStateRecord:
|
||||||
atomic.AddInt64(pa.stats.CountPublishers, -1)
|
atomic.AddInt64(pa.stats.CountPublishers, -1)
|
||||||
}
|
}
|
||||||
pa.parent.OnPathClientClose(c)
|
c.CloseRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pa.clientsWg.Wait()
|
pa.clientsWg.Wait()
|
||||||
|
|
@ -471,7 +470,7 @@ func (pa *Path) removeClient(c client.Client) {
|
||||||
for oc, state := range pa.clients {
|
for oc, state := range pa.clients {
|
||||||
if state != clientStatePreRemove {
|
if state != clientStatePreRemove {
|
||||||
pa.removeClient(oc)
|
pa.removeClient(oc)
|
||||||
pa.parent.OnPathClientClose(oc)
|
oc.CloseRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -511,7 +510,7 @@ func (pa *Path) onSourceSetNotReady() {
|
||||||
for c, state := range pa.clients {
|
for c, state := range pa.clients {
|
||||||
if c != pa.source && state != clientStatePreRemove {
|
if c != pa.source && state != clientStatePreRemove {
|
||||||
pa.removeClient(c)
|
pa.removeClient(c)
|
||||||
pa.parent.OnPathClientClose(c)
|
c.CloseRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -670,7 +669,7 @@ func (pa *Path) onClientAnnounce(req client.AnnounceReq) {
|
||||||
pa.Log(logger.Info, "disconnecting existing publisher")
|
pa.Log(logger.Info, "disconnecting existing publisher")
|
||||||
curPublisher := pa.source.(client.Client)
|
curPublisher := pa.source.(client.Client)
|
||||||
pa.removeClient(curPublisher)
|
pa.removeClient(curPublisher)
|
||||||
pa.parent.OnPathClientClose(curPublisher)
|
curPublisher.CloseRequest()
|
||||||
|
|
||||||
// prevent path closure
|
// prevent path closure
|
||||||
if pa.closeTimerStarted {
|
if pa.closeTimerStarted {
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,7 @@ type PathManager struct {
|
||||||
terminate chan struct{}
|
terminate chan struct{}
|
||||||
|
|
||||||
// out
|
// out
|
||||||
clientClose chan client.Client
|
done chan struct{}
|
||||||
done chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a PathManager.
|
// New allocates a PathManager.
|
||||||
|
|
@ -76,7 +75,6 @@ func New(
|
||||||
clientSetupPlay: make(chan client.SetupPlayReq),
|
clientSetupPlay: make(chan client.SetupPlayReq),
|
||||||
clientAnnounce: make(chan client.AnnounceReq),
|
clientAnnounce: make(chan client.AnnounceReq),
|
||||||
terminate: make(chan struct{}),
|
terminate: make(chan struct{}),
|
||||||
clientClose: make(chan client.Client),
|
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,10 +86,6 @@ func New(
|
||||||
|
|
||||||
// Close closes a PathManager.
|
// Close closes a PathManager.
|
||||||
func (pm *PathManager) Close() {
|
func (pm *PathManager) Close() {
|
||||||
go func() {
|
|
||||||
for range pm.clientClose {
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
close(pm.terminate)
|
close(pm.terminate)
|
||||||
<-pm.done
|
<-pm.done
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +265,6 @@ outer:
|
||||||
pm.wg.Wait()
|
pm.wg.Wait()
|
||||||
|
|
||||||
close(pm.confReload)
|
close(pm.confReload)
|
||||||
close(pm.clientClose)
|
|
||||||
close(pm.pathClose)
|
close(pm.pathClose)
|
||||||
close(pm.clientDescribe)
|
close(pm.clientDescribe)
|
||||||
close(pm.clientSetupPlay)
|
close(pm.clientSetupPlay)
|
||||||
|
|
@ -332,11 +325,6 @@ func (pm *PathManager) OnPathClose(pa *path.Path) {
|
||||||
pm.pathClose <- pa
|
pm.pathClose <- pa
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnPathClientClose is called by path.Path.
|
|
||||||
func (pm *PathManager) OnPathClientClose(c client.Client) {
|
|
||||||
pm.clientClose <- c
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnClientDescribe is called by clientman.ClientMan.
|
// OnClientDescribe is called by clientman.ClientMan.
|
||||||
func (pm *PathManager) OnClientDescribe(req client.DescribeReq) {
|
func (pm *PathManager) OnClientDescribe(req client.DescribeReq) {
|
||||||
pm.clientDescribe <- req
|
pm.clientDescribe <- req
|
||||||
|
|
@ -351,8 +339,3 @@ func (pm *PathManager) OnClientAnnounce(req client.AnnounceReq) {
|
||||||
func (pm *PathManager) OnClientSetupPlay(req client.SetupPlayReq) {
|
func (pm *PathManager) OnClientSetupPlay(req client.SetupPlayReq) {
|
||||||
pm.clientSetupPlay <- req
|
pm.clientSetupPlay <- req
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientClose is called by clientman.ClientMan.
|
|
||||||
func (pm *PathManager) ClientClose() chan client.Client {
|
|
||||||
return pm.clientClose
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,16 @@ package serverrtsp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"sync/atomic"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aler9/gortsplib"
|
"github.com/aler9/gortsplib"
|
||||||
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/clientrtsp"
|
||||||
"github.com/aler9/rtsp-simple-server/internal/logger"
|
"github.com/aler9/rtsp-simple-server/internal/logger"
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/pathman"
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parent is implemented by program.
|
// Parent is implemented by program.
|
||||||
|
|
@ -17,15 +21,26 @@ type Parent interface {
|
||||||
|
|
||||||
// Server is a RTSP listener.
|
// Server is a RTSP listener.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
useTLS bool
|
readTimeout time.Duration
|
||||||
parent Parent
|
isTLS bool
|
||||||
|
rtspAddress string
|
||||||
|
protocols map[base.StreamProtocol]struct{}
|
||||||
|
runOnConnect string
|
||||||
|
runOnConnectRestart bool
|
||||||
|
stats *stats.Stats
|
||||||
|
pathMan *pathman.PathManager
|
||||||
|
parent Parent
|
||||||
|
|
||||||
srv *gortsplib.Server
|
srv *gortsplib.Server
|
||||||
closed uint32
|
wg sync.WaitGroup
|
||||||
|
clients map[*clientrtsp.Client]struct{}
|
||||||
|
|
||||||
|
// in
|
||||||
|
clientClose chan *clientrtsp.Client
|
||||||
|
terminate chan struct{}
|
||||||
|
|
||||||
// out
|
// out
|
||||||
accept chan *gortsplib.ServerConn
|
done chan struct{}
|
||||||
done chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a Server.
|
// New allocates a Server.
|
||||||
|
|
@ -38,9 +53,15 @@ func New(
|
||||||
useUDP bool,
|
useUDP bool,
|
||||||
rtpAddress string,
|
rtpAddress string,
|
||||||
rtcpAddress string,
|
rtcpAddress string,
|
||||||
useTLS bool,
|
isTLS bool,
|
||||||
serverCert string,
|
serverCert string,
|
||||||
serverKey string,
|
serverKey string,
|
||||||
|
rtspAddress string,
|
||||||
|
protocols map[base.StreamProtocol]struct{},
|
||||||
|
runOnConnect string,
|
||||||
|
runOnConnectRestart bool,
|
||||||
|
stats *stats.Stats,
|
||||||
|
pathMan *pathman.PathManager,
|
||||||
parent Parent) (*Server, error) {
|
parent Parent) (*Server, error) {
|
||||||
|
|
||||||
conf := gortsplib.ServerConf{
|
conf := gortsplib.ServerConf{
|
||||||
|
|
@ -55,7 +76,7 @@ func New(
|
||||||
conf.UDPRTCPAddress = rtcpAddress
|
conf.UDPRTCPAddress = rtcpAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
if useTLS {
|
if isTLS {
|
||||||
cert, err := tls.LoadX509KeyPair(serverCert, serverKey)
|
cert, err := tls.LoadX509KeyPair(serverCert, serverKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -70,70 +91,146 @@ func New(
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
useTLS: useTLS,
|
readTimeout: readTimeout,
|
||||||
parent: parent,
|
isTLS: isTLS,
|
||||||
srv: srv,
|
rtspAddress: rtspAddress,
|
||||||
accept: make(chan *gortsplib.ServerConn),
|
protocols: protocols,
|
||||||
done: make(chan struct{}),
|
stats: stats,
|
||||||
|
pathMan: pathMan,
|
||||||
|
parent: parent,
|
||||||
|
srv: srv,
|
||||||
|
clients: make(map[*clientrtsp.Client]struct{}),
|
||||||
|
clientClose: make(chan *clientrtsp.Client),
|
||||||
|
terminate: make(chan struct{}),
|
||||||
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.UDPRTPAddress != "" {
|
if conf.UDPRTPAddress != "" {
|
||||||
parent.Log(logger.Info, "[RTSP/UDP/RTP listener] opened on %s", conf.UDPRTPAddress)
|
s.Log(logger.Info, "UDP/RTP listener opened on %s", conf.UDPRTPAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.UDPRTCPAddress != "" {
|
if conf.UDPRTCPAddress != "" {
|
||||||
parent.Log(logger.Info, "[RTSP/UDP/RTCP listener] opened on %s", conf.UDPRTCPAddress)
|
s.Log(logger.Info, "UDP/RTCP listener opened on %s", conf.UDPRTCPAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log(logger.Info, "opened on %s", address)
|
s.Log(logger.Info, "TCP listener opened on %s", address)
|
||||||
|
|
||||||
go s.run()
|
go s.run()
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) log(level logger.Level, format string, args ...interface{}) {
|
// Log is the main logging function.
|
||||||
|
func (s *Server) Log(level logger.Level, format string, args ...interface{}) {
|
||||||
label := func() string {
|
label := func() string {
|
||||||
if s.useTLS {
|
if s.isTLS {
|
||||||
return "RTSP/TLS"
|
return "RTSPS"
|
||||||
}
|
}
|
||||||
return "RTSP/TCP"
|
return "RTSP"
|
||||||
}()
|
}()
|
||||||
s.parent.Log(level, "[%s listener] "+format, append([]interface{}{label}, args...)...)
|
s.parent.Log(level, "[%s] "+format, append([]interface{}{label}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes a Server.
|
// Close closes a Server.
|
||||||
func (s *Server) Close() {
|
func (s *Server) Close() {
|
||||||
go func() {
|
close(s.terminate)
|
||||||
for co := range s.accept {
|
|
||||||
co.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
atomic.StoreUint32(&s.closed, 1)
|
|
||||||
s.srv.Close()
|
|
||||||
<-s.done
|
<-s.done
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) run() {
|
func (s *Server) run() {
|
||||||
defer close(s.done)
|
defer close(s.done)
|
||||||
|
|
||||||
for {
|
s.wg.Add(1)
|
||||||
conn, err := s.srv.Accept()
|
clientNew := make(chan *gortsplib.ServerConn)
|
||||||
if err != nil {
|
acceptErr := make(chan error)
|
||||||
if atomic.LoadUint32(&s.closed) == 1 {
|
go func() {
|
||||||
break
|
defer s.wg.Done()
|
||||||
}
|
acceptErr <- func() error {
|
||||||
s.log(logger.Warn, "ERR: %s", err)
|
for {
|
||||||
continue
|
conn, err := s.srv.Accept()
|
||||||
}
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
s.accept <- conn
|
clientNew <- conn
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
|
||||||
|
outer:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-acceptErr:
|
||||||
|
s.Log(logger.Warn, "ERR: %s", err)
|
||||||
|
break outer
|
||||||
|
|
||||||
|
case conn := <-clientNew:
|
||||||
|
c := clientrtsp.New(
|
||||||
|
s.isTLS,
|
||||||
|
s.rtspAddress,
|
||||||
|
s.readTimeout,
|
||||||
|
s.runOnConnect,
|
||||||
|
s.runOnConnectRestart,
|
||||||
|
s.protocols,
|
||||||
|
&s.wg,
|
||||||
|
s.stats,
|
||||||
|
conn,
|
||||||
|
s.pathMan,
|
||||||
|
s)
|
||||||
|
s.clients[c] = struct{}{}
|
||||||
|
|
||||||
|
case c := <-s.clientClose:
|
||||||
|
if _, ok := s.clients[c]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.doClientClose(c)
|
||||||
|
|
||||||
|
case <-s.terminate:
|
||||||
|
break outer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(s.accept)
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case _, ok := <-acceptErr:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case conn, ok := <-clientNew:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
|
||||||
|
case _, ok := <-s.clientClose:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
s.srv.Close()
|
||||||
|
|
||||||
|
for c := range s.clients {
|
||||||
|
s.doClientClose(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.wg.Wait()
|
||||||
|
|
||||||
|
close(acceptErr)
|
||||||
|
close(clientNew)
|
||||||
|
close(s.clientClose)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept returns a channel to accept incoming connections.
|
func (s *Server) doClientClose(c *clientrtsp.Client) {
|
||||||
func (s *Server) Accept() chan *gortsplib.ServerConn {
|
delete(s.clients, c)
|
||||||
return s.accept
|
c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnClientClose is called by a client.
|
||||||
|
func (s *Server) OnClientClose(c *clientrtsp.Client) {
|
||||||
|
s.clientClose <- c
|
||||||
}
|
}
|
||||||
|
|
|
||||||
248
main.go
248
main.go
|
|
@ -191,53 +191,6 @@ func (p *program) createResources(initial bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.conf.RTSPDisable &&
|
|
||||||
(p.conf.EncryptionParsed == conf.EncryptionNo ||
|
|
||||||
p.conf.EncryptionParsed == conf.EncryptionOptional) {
|
|
||||||
if p.serverRTSPPlain == nil {
|
|
||||||
_, useUDP := p.conf.ProtocolsParsed[gortsplib.StreamProtocolUDP]
|
|
||||||
p.serverRTSPPlain, err = serverrtsp.New(
|
|
||||||
p.conf.RTSPAddress,
|
|
||||||
p.conf.ReadTimeout,
|
|
||||||
p.conf.WriteTimeout,
|
|
||||||
p.conf.ReadBufferCount,
|
|
||||||
p.conf.ReadBufferSize,
|
|
||||||
useUDP,
|
|
||||||
p.conf.RTPAddress,
|
|
||||||
p.conf.RTCPAddress,
|
|
||||||
false,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !p.conf.RTSPDisable &&
|
|
||||||
(p.conf.EncryptionParsed == conf.EncryptionStrict ||
|
|
||||||
p.conf.EncryptionParsed == conf.EncryptionOptional) {
|
|
||||||
if p.serverRTSPTLS == nil {
|
|
||||||
p.serverRTSPTLS, err = serverrtsp.New(
|
|
||||||
p.conf.RTSPSAddress,
|
|
||||||
p.conf.ReadTimeout,
|
|
||||||
p.conf.WriteTimeout,
|
|
||||||
p.conf.ReadBufferCount,
|
|
||||||
p.conf.ReadBufferSize,
|
|
||||||
false,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
true,
|
|
||||||
p.conf.ServerCert,
|
|
||||||
p.conf.ServerKey,
|
|
||||||
p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
||||||
|
|
@ -286,17 +239,79 @@ func (p *program) createResources(initial bool) error {
|
||||||
p.conf.ProtocolsParsed,
|
p.conf.ProtocolsParsed,
|
||||||
p.stats,
|
p.stats,
|
||||||
p.pathMan,
|
p.pathMan,
|
||||||
p.serverRTSPPlain,
|
|
||||||
p.serverRTSPTLS,
|
|
||||||
p.serverRTMP,
|
p.serverRTMP,
|
||||||
p.serverHLS,
|
p.serverHLS,
|
||||||
p)
|
p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !p.conf.RTSPDisable &&
|
||||||
|
(p.conf.EncryptionParsed == conf.EncryptionNo ||
|
||||||
|
p.conf.EncryptionParsed == conf.EncryptionOptional) {
|
||||||
|
if p.serverRTSPPlain == nil {
|
||||||
|
_, useUDP := p.conf.ProtocolsParsed[gortsplib.StreamProtocolUDP]
|
||||||
|
p.serverRTSPPlain, err = serverrtsp.New(
|
||||||
|
p.conf.RTSPAddress,
|
||||||
|
p.conf.ReadTimeout,
|
||||||
|
p.conf.WriteTimeout,
|
||||||
|
p.conf.ReadBufferCount,
|
||||||
|
p.conf.ReadBufferSize,
|
||||||
|
useUDP,
|
||||||
|
p.conf.RTPAddress,
|
||||||
|
p.conf.RTCPAddress,
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
p.conf.RTSPAddress,
|
||||||
|
p.conf.ProtocolsParsed,
|
||||||
|
p.conf.RunOnConnect,
|
||||||
|
p.conf.RunOnConnectRestart,
|
||||||
|
p.stats,
|
||||||
|
p.pathMan,
|
||||||
|
p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.conf.RTSPDisable &&
|
||||||
|
(p.conf.EncryptionParsed == conf.EncryptionStrict ||
|
||||||
|
p.conf.EncryptionParsed == conf.EncryptionOptional) {
|
||||||
|
if p.serverRTSPTLS == nil {
|
||||||
|
p.serverRTSPTLS, err = serverrtsp.New(
|
||||||
|
p.conf.RTSPSAddress,
|
||||||
|
p.conf.ReadTimeout,
|
||||||
|
p.conf.WriteTimeout,
|
||||||
|
p.conf.ReadBufferCount,
|
||||||
|
p.conf.ReadBufferSize,
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
p.conf.ServerCert,
|
||||||
|
p.conf.ServerKey,
|
||||||
|
p.conf.RTSPAddress,
|
||||||
|
p.conf.ProtocolsParsed,
|
||||||
|
p.conf.RunOnConnect,
|
||||||
|
p.conf.RunOnConnectRestart,
|
||||||
|
p.stats,
|
||||||
|
p.pathMan,
|
||||||
|
p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *program) closeResources(newConf *conf.Conf) {
|
func (p *program) closeResources(newConf *conf.Conf) {
|
||||||
|
closeStats := false
|
||||||
|
if newConf == nil {
|
||||||
|
closeStats = true
|
||||||
|
}
|
||||||
|
|
||||||
closeLogger := false
|
closeLogger := false
|
||||||
if newConf == nil ||
|
if newConf == nil ||
|
||||||
!reflect.DeepEqual(newConf.LogDestinationsParsed, p.conf.LogDestinationsParsed) ||
|
!reflect.DeepEqual(newConf.LogDestinationsParsed, p.conf.LogDestinationsParsed) ||
|
||||||
|
|
@ -307,17 +322,68 @@ 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.MetricsAddress != p.conf.MetricsAddress {
|
newConf.MetricsAddress != p.conf.MetricsAddress ||
|
||||||
|
closeStats {
|
||||||
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.PPROFAddress != p.conf.PPROFAddress {
|
newConf.PPROFAddress != p.conf.PPROFAddress ||
|
||||||
|
closeStats {
|
||||||
closePPROF = true
|
closePPROF = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeServerRTMP := false
|
||||||
|
if newConf == nil ||
|
||||||
|
newConf.RTMPDisable != p.conf.RTMPDisable ||
|
||||||
|
newConf.RTMPAddress != p.conf.RTMPAddress ||
|
||||||
|
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
||||||
|
closeStats {
|
||||||
|
closeServerRTMP = true
|
||||||
|
}
|
||||||
|
|
||||||
|
closeServerHLS := false
|
||||||
|
if newConf == nil ||
|
||||||
|
newConf.HLSDisable != p.conf.HLSDisable ||
|
||||||
|
newConf.HLSAddress != p.conf.HLSAddress ||
|
||||||
|
closeStats {
|
||||||
|
closeServerHLS = true
|
||||||
|
}
|
||||||
|
|
||||||
|
closePathMan := false
|
||||||
|
if newConf == nil ||
|
||||||
|
newConf.RTSPAddress != p.conf.RTSPAddress ||
|
||||||
|
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
||||||
|
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
||||||
|
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
||||||
|
newConf.ReadBufferSize != p.conf.ReadBufferSize ||
|
||||||
|
!reflect.DeepEqual(newConf.AuthMethodsParsed, p.conf.AuthMethodsParsed) ||
|
||||||
|
closeStats {
|
||||||
|
closePathMan = true
|
||||||
|
} else if !reflect.DeepEqual(newConf.Paths, p.conf.Paths) {
|
||||||
|
p.pathMan.OnProgramConfReload(newConf.Paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
closeClientMan := false
|
||||||
|
if newConf == nil ||
|
||||||
|
closeServerRTMP ||
|
||||||
|
closeServerHLS ||
|
||||||
|
closePathMan ||
|
||||||
|
newConf.HLSSegmentCount != p.conf.HLSSegmentCount ||
|
||||||
|
newConf.HLSSegmentDuration != p.conf.HLSSegmentDuration ||
|
||||||
|
newConf.RTSPAddress != p.conf.RTSPAddress ||
|
||||||
|
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
||||||
|
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
||||||
|
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
||||||
|
newConf.RunOnConnect != p.conf.RunOnConnect ||
|
||||||
|
newConf.RunOnConnectRestart != p.conf.RunOnConnectRestart ||
|
||||||
|
!reflect.DeepEqual(newConf.ProtocolsParsed, p.conf.ProtocolsParsed) ||
|
||||||
|
closeStats {
|
||||||
|
closeClientMan = true
|
||||||
|
}
|
||||||
|
|
||||||
closeServerPlain := false
|
closeServerPlain := false
|
||||||
if newConf == nil ||
|
if newConf == nil ||
|
||||||
newConf.RTSPDisable != p.conf.RTSPDisable ||
|
newConf.RTSPDisable != p.conf.RTSPDisable ||
|
||||||
|
|
@ -328,7 +394,13 @@ func (p *program) closeResources(newConf *conf.Conf) {
|
||||||
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.RTPAddress != p.conf.RTPAddress ||
|
newConf.RTPAddress != p.conf.RTPAddress ||
|
||||||
newConf.RTCPAddress != p.conf.RTCPAddress {
|
newConf.RTCPAddress != p.conf.RTCPAddress ||
|
||||||
|
newConf.RTSPAddress != p.conf.RTSPAddress ||
|
||||||
|
!reflect.DeepEqual(newConf.ProtocolsParsed, p.conf.ProtocolsParsed) ||
|
||||||
|
newConf.RunOnConnect != p.conf.RunOnConnect ||
|
||||||
|
newConf.RunOnConnectRestart != p.conf.RunOnConnectRestart ||
|
||||||
|
closeStats ||
|
||||||
|
closePathMan {
|
||||||
closeServerPlain = true
|
closeServerPlain = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,60 +413,24 @@ func (p *program) closeResources(newConf *conf.Conf) {
|
||||||
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
||||||
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
||||||
newConf.ServerCert != p.conf.ServerCert ||
|
newConf.ServerCert != p.conf.ServerCert ||
|
||||||
newConf.ServerKey != p.conf.ServerKey {
|
newConf.ServerKey != p.conf.ServerKey ||
|
||||||
|
newConf.RTSPAddress != p.conf.RTSPAddress ||
|
||||||
|
!reflect.DeepEqual(newConf.ProtocolsParsed, p.conf.ProtocolsParsed) ||
|
||||||
|
newConf.RunOnConnect != p.conf.RunOnConnect ||
|
||||||
|
newConf.RunOnConnectRestart != p.conf.RunOnConnectRestart ||
|
||||||
|
closeStats ||
|
||||||
|
closePathMan {
|
||||||
closeServerTLS = true
|
closeServerTLS = true
|
||||||
}
|
}
|
||||||
|
|
||||||
closeServerRTMP := false
|
if closeServerTLS && p.serverRTSPTLS != nil {
|
||||||
if newConf == nil ||
|
p.serverRTSPTLS.Close()
|
||||||
newConf.RTMPDisable != p.conf.RTMPDisable ||
|
p.serverRTSPTLS = nil
|
||||||
newConf.RTMPAddress != p.conf.RTMPAddress ||
|
|
||||||
newConf.ReadTimeout != p.conf.ReadTimeout {
|
|
||||||
closeServerRTMP = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closeServerHLS := false
|
if closeServerPlain && p.serverRTSPPlain != nil {
|
||||||
if newConf == nil ||
|
p.serverRTSPPlain.Close()
|
||||||
newConf.HLSDisable != p.conf.HLSDisable ||
|
p.serverRTSPPlain = nil
|
||||||
newConf.HLSAddress != p.conf.HLSAddress {
|
|
||||||
closeServerHLS = true
|
|
||||||
}
|
|
||||||
|
|
||||||
closePathMan := false
|
|
||||||
if newConf == nil ||
|
|
||||||
newConf.RTSPAddress != p.conf.RTSPAddress ||
|
|
||||||
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
|
||||||
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
|
||||||
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
|
||||||
newConf.ReadBufferSize != p.conf.ReadBufferSize ||
|
|
||||||
!reflect.DeepEqual(newConf.AuthMethodsParsed, p.conf.AuthMethodsParsed) {
|
|
||||||
closePathMan = true
|
|
||||||
} else if !reflect.DeepEqual(newConf.Paths, p.conf.Paths) {
|
|
||||||
p.pathMan.OnProgramConfReload(newConf.Paths)
|
|
||||||
}
|
|
||||||
|
|
||||||
closeClientMan := false
|
|
||||||
if newConf == nil ||
|
|
||||||
closeServerPlain ||
|
|
||||||
closeServerTLS ||
|
|
||||||
closeServerRTMP ||
|
|
||||||
closeServerHLS ||
|
|
||||||
closePathMan ||
|
|
||||||
newConf.HLSSegmentCount != p.conf.HLSSegmentCount ||
|
|
||||||
newConf.HLSSegmentDuration != p.conf.HLSSegmentDuration ||
|
|
||||||
newConf.RTSPAddress != p.conf.RTSPAddress ||
|
|
||||||
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
|
||||||
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
|
||||||
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
|
||||||
newConf.RunOnConnect != p.conf.RunOnConnect ||
|
|
||||||
newConf.RunOnConnectRestart != p.conf.RunOnConnectRestart ||
|
|
||||||
!reflect.DeepEqual(newConf.ProtocolsParsed, p.conf.ProtocolsParsed) {
|
|
||||||
closeClientMan = true
|
|
||||||
}
|
|
||||||
|
|
||||||
closeStats := false
|
|
||||||
if newConf == nil {
|
|
||||||
closeStats = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if closeClientMan && p.clientMan != nil {
|
if closeClientMan && p.clientMan != nil {
|
||||||
|
|
@ -417,16 +453,6 @@ func (p *program) closeResources(newConf *conf.Conf) {
|
||||||
p.serverRTMP = nil
|
p.serverRTMP = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if closeServerTLS && p.serverRTSPTLS != nil {
|
|
||||||
p.serverRTSPTLS.Close()
|
|
||||||
p.serverRTSPTLS = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if closeServerPlain && p.serverRTSPPlain != nil {
|
|
||||||
p.serverRTSPPlain.Close()
|
|
||||||
p.serverRTSPPlain = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if closePPROF && p.pprof != nil {
|
if closePPROF && p.pprof != nil {
|
||||||
p.pprof.Close()
|
p.pprof.Close()
|
||||||
p.pprof = nil
|
p.pprof = nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue