You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/logic/server_manager.go

157 lines
3.6 KiB
Go

// Copyright 2019, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package logic
import (
"sync"
"time"
"github.com/q191201771/lal/pkg/httpflv"
"github.com/q191201771/lal/pkg/rtmp"
log "github.com/q191201771/naza/pkg/nazalog"
)
type ServerManager struct {
config *Config
httpFlvServer *httpflv.Server
rtmpServer *rtmp.Server
groupMap map[string]*Group // TODO chef: with appName
mutex sync.Mutex
exitChan chan struct{}
}
var _ rtmp.ServerObserver = &ServerManager{}
func NewServerManager(config *Config) *ServerManager {
m := &ServerManager{
config: config,
groupMap: make(map[string]*Group),
exitChan: make(chan struct{}),
}
if len(config.HTTPFlv.SubListenAddr) != 0 {
m.httpFlvServer = httpflv.NewServer(m, config.HTTPFlv.SubListenAddr, config.SubIdleTimeout)
}
if len(config.RTMP.Addr) != 0 {
m.rtmpServer = rtmp.NewServer(m, config.RTMP.Addr)
}
return m
}
func (sm *ServerManager) RunLoop() {
if sm.httpFlvServer != nil {
go func() {
if err := sm.httpFlvServer.RunLoop(); err != nil {
log.Error(err)
}
}()
}
if sm.rtmpServer != nil {
go func() {
if err := sm.rtmpServer.RunLoop(); err != nil {
log.Error(err)
}
}()
}
t := time.NewTicker(1 * time.Second)
defer t.Stop()
var count uint32
for {
select {
case <-sm.exitChan:
return
case <-t.C:
sm.check()
count++
if (count % 10) == 0 {
sm.mutex.Lock()
log.Infof("group size:%d", len(sm.groupMap))
sm.mutex.Unlock()
}
}
}
}
func (sm *ServerManager) Dispose() {
log.Debug("dispose server manager.")
if sm.httpFlvServer != nil {
sm.httpFlvServer.Dispose()
}
if sm.rtmpServer != nil {
sm.rtmpServer.Dispose()
}
sm.mutex.Lock()
for _, group := range sm.groupMap {
group.Dispose(lalErr)
}
sm.groupMap = nil
sm.mutex.Unlock()
sm.exitChan <- struct{}{}
}
// ServerObserver of rtmp.Server
func (sm *ServerManager) NewRTMPPubSessionCB(session *rtmp.ServerSession) bool {
group := sm.getOrCreateGroup(session.AppName, session.StreamName)
return group.AddRTMPPubSession(session)
}
// ServerObserver of rtmp.Server
func (sm *ServerManager) NewRTMPSubSessionCB(session *rtmp.ServerSession) bool {
group := sm.getOrCreateGroup(session.AppName, session.StreamName)
group.AddRTMPSubSession(session)
return true
}
// ServerObserver of rtmp.Server
func (sm *ServerManager) DelRTMPPubSessionCB(session *rtmp.ServerSession) {
group := sm.getOrCreateGroup(session.AppName, session.StreamName)
group.DelRTMPPubSession(session)
}
// ServerObserver of rtmp.Server
func (sm *ServerManager) DelRTMPSubSessionCB(session *rtmp.ServerSession) {
group := sm.getOrCreateGroup(session.AppName, session.StreamName)
group.DelRTMPSubSession(session)
}
// ServerObserver of httpflv.Server
func (sm *ServerManager) NewHTTPFlvSubSessionCB(session *httpflv.SubSession) bool {
group := sm.getOrCreateGroup(session.AppName, session.StreamName)
group.AddHTTPFlvSubSession(session)
return true
}
func (sm *ServerManager) check() {
sm.mutex.Lock()
defer sm.mutex.Unlock()
for k, group := range sm.groupMap {
if group.IsTotalEmpty() {
log.Infof("erase empty group manager. [%s]", group.UniqueKey)
group.Dispose(lalErr)
delete(sm.groupMap, k)
}
}
}
func (sm *ServerManager) getOrCreateGroup(appName string, streamName string) *Group {
sm.mutex.Lock()
defer sm.mutex.Unlock()
group, exist := sm.groupMap[streamName]
if !exist {
group = NewGroup(appName, streamName)
sm.groupMap[streamName] = group
}
go group.RunLoop()
return group
}