forked from External/mediamtx
move clientrtmp inside serverrtmp
This commit is contained in:
parent
ff8aadf722
commit
22ba5f3f18
4 changed files with 172 additions and 85 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
package clientman
|
package clientman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -9,10 +8,8 @@ import (
|
||||||
|
|
||||||
"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/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/stats"
|
"github.com/aler9/rtsp-simple-server/internal/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -41,7 +38,6 @@ type ClientManager struct {
|
||||||
protocols map[base.StreamProtocol]struct{}
|
protocols map[base.StreamProtocol]struct{}
|
||||||
stats *stats.Stats
|
stats *stats.Stats
|
||||||
pathMan PathManager
|
pathMan PathManager
|
||||||
serverRTMP *serverrtmp.Server
|
|
||||||
serverHLS *serverhls.Server
|
serverHLS *serverhls.Server
|
||||||
parent Parent
|
parent Parent
|
||||||
|
|
||||||
|
|
@ -70,7 +66,6 @@ func New(
|
||||||
protocols map[base.StreamProtocol]struct{},
|
protocols map[base.StreamProtocol]struct{},
|
||||||
stats *stats.Stats,
|
stats *stats.Stats,
|
||||||
pathMan PathManager,
|
pathMan PathManager,
|
||||||
serverRTMP *serverrtmp.Server,
|
|
||||||
serverHLS *serverhls.Server,
|
serverHLS *serverhls.Server,
|
||||||
parent Parent) *ClientManager {
|
parent Parent) *ClientManager {
|
||||||
|
|
||||||
|
|
@ -86,7 +81,6 @@ func New(
|
||||||
protocols: protocols,
|
protocols: protocols,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
pathMan: pathMan,
|
pathMan: pathMan,
|
||||||
serverRTMP: serverRTMP,
|
|
||||||
serverHLS: serverHLS,
|
serverHLS: serverHLS,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
clients: make(map[client.Client]struct{}),
|
clients: make(map[client.Client]struct{}),
|
||||||
|
|
@ -115,13 +109,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)
|
||||||
|
|
||||||
rtmpAccept := func() chan net.Conn {
|
|
||||||
if cm.serverRTMP != nil {
|
|
||||||
return cm.serverRTMP.Accept()
|
|
||||||
}
|
|
||||||
return make(chan net.Conn)
|
|
||||||
}()
|
|
||||||
|
|
||||||
hlsRequest := func() chan serverhls.Request {
|
hlsRequest := func() chan serverhls.Request {
|
||||||
if cm.serverHLS != nil {
|
if cm.serverHLS != nil {
|
||||||
return cm.serverHLS.Request()
|
return cm.serverHLS.Request()
|
||||||
|
|
@ -132,21 +119,6 @@ func (cm *ClientManager) run() {
|
||||||
outer:
|
outer:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case nconn := <-rtmpAccept:
|
|
||||||
c := clientrtmp.New(
|
|
||||||
cm.rtspAddress,
|
|
||||||
cm.readTimeout,
|
|
||||||
cm.writeTimeout,
|
|
||||||
cm.readBufferCount,
|
|
||||||
cm.runOnConnect,
|
|
||||||
cm.runOnConnectRestart,
|
|
||||||
&cm.wg,
|
|
||||||
cm.stats,
|
|
||||||
nconn,
|
|
||||||
cm.pathMan,
|
|
||||||
cm)
|
|
||||||
cm.clients[c] = struct{}{}
|
|
||||||
|
|
||||||
case req := <-hlsRequest:
|
case req := <-hlsRequest:
|
||||||
c, ok := cm.clientsByHLSPath[req.Path]
|
c, ok := cm.clientsByHLSPath[req.Path]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,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 RTMP client.
|
// Client is a RTMP client.
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@ package serverrtmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"sync/atomic"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/clientrtmp"
|
||||||
"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.
|
||||||
|
|
@ -14,19 +18,39 @@ type Parent interface {
|
||||||
|
|
||||||
// Server is a RTMP listener.
|
// Server is a RTMP listener.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
parent Parent
|
readTimeout time.Duration
|
||||||
|
writeTimeout time.Duration
|
||||||
|
readBufferCount int
|
||||||
|
rtspAddress string
|
||||||
|
runOnConnect string
|
||||||
|
runOnConnectRestart bool
|
||||||
|
stats *stats.Stats
|
||||||
|
pathMan *pathman.PathManager
|
||||||
|
parent Parent
|
||||||
|
|
||||||
l net.Listener
|
l net.Listener
|
||||||
closed uint32
|
wg sync.WaitGroup
|
||||||
|
clients map[*clientrtmp.Client]struct{}
|
||||||
|
|
||||||
|
// in
|
||||||
|
clientClose chan *clientrtmp.Client
|
||||||
|
terminate chan struct{}
|
||||||
|
|
||||||
// out
|
// out
|
||||||
accept chan net.Conn
|
done chan struct{}
|
||||||
done chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a Server.
|
// New allocates a Server.
|
||||||
func New(
|
func New(
|
||||||
address string,
|
address string,
|
||||||
|
readTimeout time.Duration,
|
||||||
|
writeTimeout time.Duration,
|
||||||
|
readBufferCount int,
|
||||||
|
rtspAddress string,
|
||||||
|
runOnConnect string,
|
||||||
|
runOnConnectRestart bool,
|
||||||
|
stats *stats.Stats,
|
||||||
|
pathMan *pathman.PathManager,
|
||||||
parent Parent) (*Server, error) {
|
parent Parent) (*Server, error) {
|
||||||
|
|
||||||
l, err := net.Listen("tcp", address)
|
l, err := net.Listen("tcp", address)
|
||||||
|
|
@ -35,55 +59,134 @@ func New(
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
parent: parent,
|
readTimeout: readTimeout,
|
||||||
l: l,
|
writeTimeout: writeTimeout,
|
||||||
accept: make(chan net.Conn),
|
readBufferCount: readBufferCount,
|
||||||
done: make(chan struct{}),
|
rtspAddress: rtspAddress,
|
||||||
|
runOnConnect: runOnConnect,
|
||||||
|
runOnConnectRestart: runOnConnectRestart,
|
||||||
|
stats: stats,
|
||||||
|
pathMan: pathMan,
|
||||||
|
parent: parent,
|
||||||
|
l: l,
|
||||||
|
clients: make(map[*clientrtmp.Client]struct{}),
|
||||||
|
clientClose: make(chan *clientrtmp.Client),
|
||||||
|
terminate: make(chan struct{}),
|
||||||
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log(logger.Info, "opened on %s", address)
|
s.Log(logger.Info, "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.
|
||||||
s.parent.Log(level, "[RTMP listener] "+format, append([]interface{}{}, args...)...)
|
func (s *Server) Log(level logger.Level, format string, args ...interface{}) {
|
||||||
|
s.parent.Log(level, "[RTMP] "+format, append([]interface{}{}, 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.l.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)
|
||||||
nconn, err := s.l.Accept()
|
clientNew := make(chan net.Conn)
|
||||||
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.l.Accept()
|
||||||
}
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
s.accept <- nconn
|
clientNew <- conn
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
|
||||||
|
outer:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case err := <-acceptErr:
|
||||||
|
s.Log(logger.Warn, "ERR: %s", err)
|
||||||
|
break outer
|
||||||
|
|
||||||
|
case nconn := <-clientNew:
|
||||||
|
c := clientrtmp.New(
|
||||||
|
s.rtspAddress,
|
||||||
|
s.readTimeout,
|
||||||
|
s.writeTimeout,
|
||||||
|
s.readBufferCount,
|
||||||
|
s.runOnConnect,
|
||||||
|
s.runOnConnectRestart,
|
||||||
|
&s.wg,
|
||||||
|
s.stats,
|
||||||
|
nconn,
|
||||||
|
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.l.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 *clientrtmp.Client) {
|
||||||
func (s *Server) Accept() chan net.Conn {
|
delete(s.clients, c)
|
||||||
return s.accept
|
c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnClientClose is called by a client.
|
||||||
|
func (s *Server) OnClientClose(c *clientrtmp.Client) {
|
||||||
|
s.clientClose <- c
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
main.go
56
main.go
|
|
@ -191,17 +191,6 @@ func (p *program) createResources(initial bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.conf.RTMPDisable {
|
|
||||||
if p.serverRTMP == nil {
|
|
||||||
p.serverRTMP, err = serverrtmp.New(
|
|
||||||
p.conf.RTMPAddress,
|
|
||||||
p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
||||||
|
|
@ -239,7 +228,6 @@ func (p *program) createResources(initial bool) error {
|
||||||
p.conf.ProtocolsParsed,
|
p.conf.ProtocolsParsed,
|
||||||
p.stats,
|
p.stats,
|
||||||
p.pathMan,
|
p.pathMan,
|
||||||
p.serverRTMP,
|
|
||||||
p.serverHLS,
|
p.serverHLS,
|
||||||
p)
|
p)
|
||||||
}
|
}
|
||||||
|
|
@ -303,6 +291,25 @@ func (p *program) createResources(initial bool) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !p.conf.RTMPDisable {
|
||||||
|
if p.serverRTMP == nil {
|
||||||
|
p.serverRTMP, err = serverrtmp.New(
|
||||||
|
p.conf.RTMPAddress,
|
||||||
|
p.conf.ReadTimeout,
|
||||||
|
p.conf.WriteTimeout,
|
||||||
|
p.conf.ReadBufferCount,
|
||||||
|
p.conf.RTSPAddress,
|
||||||
|
p.conf.RunOnConnect,
|
||||||
|
p.conf.RunOnConnectRestart,
|
||||||
|
p.stats,
|
||||||
|
p.pathMan,
|
||||||
|
p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,15 +342,6 @@ func (p *program) closeResources(newConf *conf.Conf) {
|
||||||
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
|
closeServerHLS := false
|
||||||
if newConf == nil ||
|
if newConf == nil ||
|
||||||
newConf.HLSDisable != p.conf.HLSDisable ||
|
newConf.HLSDisable != p.conf.HLSDisable ||
|
||||||
|
|
@ -368,7 +366,6 @@ func (p *program) closeResources(newConf *conf.Conf) {
|
||||||
|
|
||||||
closeClientMan := false
|
closeClientMan := false
|
||||||
if newConf == nil ||
|
if newConf == nil ||
|
||||||
closeServerRTMP ||
|
|
||||||
closeServerHLS ||
|
closeServerHLS ||
|
||||||
closePathMan ||
|
closePathMan ||
|
||||||
newConf.HLSSegmentCount != p.conf.HLSSegmentCount ||
|
newConf.HLSSegmentCount != p.conf.HLSSegmentCount ||
|
||||||
|
|
@ -423,6 +420,21 @@ func (p *program) closeResources(newConf *conf.Conf) {
|
||||||
closeServerTLS = true
|
closeServerTLS = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeServerRTMP := false
|
||||||
|
if newConf == nil ||
|
||||||
|
newConf.RTMPDisable != p.conf.RTMPDisable ||
|
||||||
|
newConf.RTMPAddress != p.conf.RTMPAddress ||
|
||||||
|
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
||||||
|
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
||||||
|
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
||||||
|
newConf.RTSPAddress != p.conf.RTSPAddress ||
|
||||||
|
newConf.RunOnConnect != p.conf.RunOnConnect ||
|
||||||
|
newConf.RunOnConnectRestart != p.conf.RunOnConnectRestart ||
|
||||||
|
closeStats ||
|
||||||
|
closePathMan {
|
||||||
|
closeServerRTMP = true
|
||||||
|
}
|
||||||
|
|
||||||
if closeServerTLS && p.serverRTSPTLS != nil {
|
if closeServerTLS && p.serverRTSPTLS != nil {
|
||||||
p.serverRTSPTLS.Close()
|
p.serverRTSPTLS.Close()
|
||||||
p.serverRTSPTLS = nil
|
p.serverRTSPTLS = nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue