|
|
|
@ -10,6 +10,11 @@ package logic
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/q191201771/naza/pkg/bininfo"
|
|
|
|
|
"github.com/q191201771/naza/pkg/defertaskthread"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
"strings"
|
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
@ -24,9 +29,15 @@ import (
|
|
|
|
|
"github.com/q191201771/lal/pkg/httpflv"
|
|
|
|
|
"github.com/q191201771/lal/pkg/rtmp"
|
|
|
|
|
"github.com/q191201771/naza/pkg/nazalog"
|
|
|
|
|
_ "net/http/pprof"
|
|
|
|
|
//"github.com/felixge/fgprof"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ServerManager struct {
|
|
|
|
|
option Option
|
|
|
|
|
serverStartTime string
|
|
|
|
|
config *Config
|
|
|
|
|
|
|
|
|
|
httpServerManager *base.HttpServerManager
|
|
|
|
|
httpServerHandler *HttpServerHandler
|
|
|
|
|
hlsServerHandler *hls.ServerHandler
|
|
|
|
@ -40,34 +51,81 @@ type ServerManager struct {
|
|
|
|
|
groupManager IGroupManager
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewServerManager() *ServerManager {
|
|
|
|
|
m := &ServerManager{
|
|
|
|
|
exitChan: make(chan struct{}),
|
|
|
|
|
groupManager: NewSimpleGroupManager(),
|
|
|
|
|
func NewServerManager(confFile string, modOption ...ModOption) *ServerManager {
|
|
|
|
|
sm := &ServerManager{
|
|
|
|
|
serverStartTime: time.Now().Format("2006-01-02 15:04:05.999"),
|
|
|
|
|
exitChan: make(chan struct{}),
|
|
|
|
|
}
|
|
|
|
|
sm.groupManager = NewSimpleGroupManager(sm)
|
|
|
|
|
|
|
|
|
|
sm.config = LoadConfAndInitLog(confFile)
|
|
|
|
|
|
|
|
|
|
// TODO(chef): refactor 启动信息可以考虑放入package base中,所有的app都打印
|
|
|
|
|
dir, _ := os.Getwd()
|
|
|
|
|
nazalog.Infof("wd: %s", dir)
|
|
|
|
|
nazalog.Infof("args: %s", strings.Join(os.Args, " "))
|
|
|
|
|
nazalog.Infof("bininfo: %s", bininfo.StringifySingleLine())
|
|
|
|
|
nazalog.Infof("version: %s", base.LalFullInfo)
|
|
|
|
|
nazalog.Infof("github: %s", base.LalGithubSite)
|
|
|
|
|
nazalog.Infof("doc: %s", base.LalDocSite)
|
|
|
|
|
nazalog.Infof("serverStartTime: %s", sm.serverStartTime)
|
|
|
|
|
|
|
|
|
|
if sm.config.HlsConfig.Enable && sm.config.HlsConfig.UseMemoryAsDiskFlag {
|
|
|
|
|
nazalog.Infof("hls use memory as disk.")
|
|
|
|
|
hls.SetUseMemoryAsDiskFlag(true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if sm.config.RecordConfig.EnableFlv {
|
|
|
|
|
if err := os.MkdirAll(sm.config.RecordConfig.FlvOutPath, 0777); err != nil {
|
|
|
|
|
nazalog.Errorf("record flv mkdir error. path=%s, err=%+v", sm.config.RecordConfig.FlvOutPath, err)
|
|
|
|
|
}
|
|
|
|
|
if err := os.MkdirAll(sm.config.RecordConfig.MpegtsOutPath, 0777); err != nil {
|
|
|
|
|
nazalog.Errorf("record mpegts mkdir error. path=%s, err=%+v", sm.config.RecordConfig.MpegtsOutPath, err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sm.option = defaultOption
|
|
|
|
|
for _, fn := range modOption {
|
|
|
|
|
fn(&sm.option)
|
|
|
|
|
}
|
|
|
|
|
if sm.option.notifyHandler == nil {
|
|
|
|
|
sm.option.notifyHandler = NewHttpNotify(sm.config.HttpNotifyConfig)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if config.HttpflvConfig.Enable || config.HttpflvConfig.EnableHttps ||
|
|
|
|
|
config.HttptsConfig.Enable || config.HttptsConfig.EnableHttps ||
|
|
|
|
|
config.HlsConfig.Enable || config.HlsConfig.EnableHttps {
|
|
|
|
|
m.httpServerManager = base.NewHttpServerManager()
|
|
|
|
|
m.httpServerHandler = NewHttpServerHandler(m)
|
|
|
|
|
m.hlsServerHandler = hls.NewServerHandler(config.HlsConfig.OutPath)
|
|
|
|
|
if sm.config.HttpflvConfig.Enable || sm.config.HttpflvConfig.EnableHttps ||
|
|
|
|
|
sm.config.HttptsConfig.Enable || sm.config.HttptsConfig.EnableHttps ||
|
|
|
|
|
sm.config.HlsConfig.Enable || sm.config.HlsConfig.EnableHttps {
|
|
|
|
|
sm.httpServerManager = base.NewHttpServerManager()
|
|
|
|
|
sm.httpServerHandler = NewHttpServerHandler(sm)
|
|
|
|
|
sm.hlsServerHandler = hls.NewServerHandler(sm.config.HlsConfig.OutPath)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if config.RtmpConfig.Enable {
|
|
|
|
|
m.rtmpServer = rtmp.NewServer(m, config.RtmpConfig.Addr)
|
|
|
|
|
if sm.config.RtmpConfig.Enable {
|
|
|
|
|
// TODO(chef): refactor 参数顺序统一。Observer都放最后好一些。比如rtmp和rtsp的NewServer
|
|
|
|
|
sm.rtmpServer = rtmp.NewServer(sm, sm.config.RtmpConfig.Addr)
|
|
|
|
|
}
|
|
|
|
|
if config.RtspConfig.Enable {
|
|
|
|
|
m.rtspServer = rtsp.NewServer(config.RtspConfig.Addr, m)
|
|
|
|
|
if sm.config.RtspConfig.Enable {
|
|
|
|
|
sm.rtspServer = rtsp.NewServer(sm.config.RtspConfig.Addr, sm)
|
|
|
|
|
}
|
|
|
|
|
if config.HttpApiConfig.Enable {
|
|
|
|
|
m.httpApiServer = NewHttpApiServer(config.HttpApiConfig.Addr, m)
|
|
|
|
|
if sm.config.HttpApiConfig.Enable {
|
|
|
|
|
sm.httpApiServer = NewHttpApiServer(sm.config.HttpApiConfig.Addr, sm)
|
|
|
|
|
}
|
|
|
|
|
return m
|
|
|
|
|
|
|
|
|
|
return sm
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- implement ILalServer interface --------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) RunLoop() error {
|
|
|
|
|
notifyHandler.OnServerStart()
|
|
|
|
|
sm.option.notifyHandler.OnServerStart(sm.StatLalInfo())
|
|
|
|
|
|
|
|
|
|
if sm.config.PprofConfig.Enable {
|
|
|
|
|
go runWebPprof(sm.config.PprofConfig.Addr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
go base.RunSignalHandler(func() {
|
|
|
|
|
sm.Dispose()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
var addMux = func(config CommonHttpServerConfig, handler base.Handler, name string) error {
|
|
|
|
|
if config.Enable {
|
|
|
|
@ -97,13 +155,13 @@ func (sm *ServerManager) RunLoop() error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := addMux(config.HttpflvConfig.CommonHttpServerConfig, sm.httpServerHandler.ServeSubSession, "httpflv"); err != nil {
|
|
|
|
|
if err := addMux(sm.config.HttpflvConfig.CommonHttpServerConfig, sm.httpServerHandler.ServeSubSession, "httpflv"); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if err := addMux(config.HttptsConfig.CommonHttpServerConfig, sm.httpServerHandler.ServeSubSession, "httpts"); err != nil {
|
|
|
|
|
if err := addMux(sm.config.HttptsConfig.CommonHttpServerConfig, sm.httpServerHandler.ServeSubSession, "httpts"); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if err := addMux(config.HlsConfig.CommonHttpServerConfig, sm.hlsServerHandler.ServeHTTP, "hls"); err != nil {
|
|
|
|
|
if err := addMux(sm.config.HlsConfig.CommonHttpServerConfig, sm.hlsServerHandler.ServeHTTP, "hls"); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -142,17 +200,17 @@ func (sm *ServerManager) RunLoop() error {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
go func() {
|
|
|
|
|
if err := sm.httpApiServer.Runloop(); err != nil {
|
|
|
|
|
if err := sm.httpApiServer.RunLoop(); err != nil {
|
|
|
|
|
nazalog.Error(err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uis := uint32(config.HttpNotifyConfig.UpdateIntervalSec)
|
|
|
|
|
uis := uint32(sm.config.HttpNotifyConfig.UpdateIntervalSec)
|
|
|
|
|
var updateInfo base.UpdateInfo
|
|
|
|
|
updateInfo.ServerId = config.ServerId
|
|
|
|
|
updateInfo.Groups = sm.statAllGroup()
|
|
|
|
|
notifyHandler.OnUpdate(updateInfo)
|
|
|
|
|
updateInfo.ServerId = sm.config.ServerId
|
|
|
|
|
updateInfo.Groups = sm.StatAllGroup()
|
|
|
|
|
sm.option.notifyHandler.OnUpdate(updateInfo)
|
|
|
|
|
|
|
|
|
|
t := time.NewTicker(1 * time.Second)
|
|
|
|
|
defer t.Stop()
|
|
|
|
@ -194,9 +252,9 @@ func (sm *ServerManager) RunLoop() error {
|
|
|
|
|
|
|
|
|
|
// 定时通过http notify发送group相关的信息
|
|
|
|
|
if uis != 0 && (count%uis) == 0 {
|
|
|
|
|
updateInfo.ServerId = config.ServerId
|
|
|
|
|
updateInfo.Groups = sm.statAllGroup()
|
|
|
|
|
notifyHandler.OnUpdate(updateInfo)
|
|
|
|
|
updateInfo.ServerId = sm.config.ServerId
|
|
|
|
|
updateInfo.Groups = sm.StatAllGroup()
|
|
|
|
|
sm.option.notifyHandler.OnUpdate(updateInfo)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -226,22 +284,85 @@ func (sm *ServerManager) Dispose() {
|
|
|
|
|
sm.exitChan <- struct{}{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) GetGroup(appName string, streamName string) *Group {
|
|
|
|
|
func (sm *ServerManager) StatLalInfo() base.LalInfo {
|
|
|
|
|
var lalInfo base.LalInfo
|
|
|
|
|
lalInfo.BinInfo = bininfo.StringifySingleLine()
|
|
|
|
|
lalInfo.LalVersion = base.LalVersion
|
|
|
|
|
lalInfo.ApiVersion = base.HttpApiVersion
|
|
|
|
|
lalInfo.NotifyVersion = base.HttpNotifyVersion
|
|
|
|
|
lalInfo.StartTime = sm.serverStartTime
|
|
|
|
|
lalInfo.ServerId = sm.config.ServerId
|
|
|
|
|
return lalInfo
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) StatAllGroup() (sgs []base.StatGroup) {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
return sm.getGroup(appName, streamName)
|
|
|
|
|
sm.groupManager.Iterate(func(group *Group) bool {
|
|
|
|
|
sgs = append(sgs, group.GetStat())
|
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// rtmp.ServerObserver interface
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
func (sm *ServerManager) StatGroup(streamName string) *base.StatGroup {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
g := sm.getGroup("", streamName)
|
|
|
|
|
if g == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
// copy
|
|
|
|
|
var ret base.StatGroup
|
|
|
|
|
ret = g.GetStat()
|
|
|
|
|
return &ret
|
|
|
|
|
}
|
|
|
|
|
func (sm *ServerManager) CtrlStartPull(info base.ApiCtrlStartPullReq) {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
g := sm.getGroup(info.AppName, info.StreamName)
|
|
|
|
|
if g == nil {
|
|
|
|
|
nazalog.Warnf("group not exist, ignore start pull. streamName=%s", info.StreamName)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
var url string
|
|
|
|
|
if info.UrlParam != "" {
|
|
|
|
|
url = fmt.Sprintf("rtmp://%s/%s/%s?%s", info.Addr, info.AppName, info.StreamName, info.UrlParam)
|
|
|
|
|
} else {
|
|
|
|
|
url = fmt.Sprintf("rtmp://%s/%s/%s", info.Addr, info.AppName, info.StreamName)
|
|
|
|
|
}
|
|
|
|
|
g.StartPull(url)
|
|
|
|
|
}
|
|
|
|
|
func (sm *ServerManager) CtrlKickOutSession(info base.ApiCtrlKickOutSession) base.HttpResponseBasic {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
g := sm.getGroup("", info.StreamName)
|
|
|
|
|
if g == nil {
|
|
|
|
|
return base.HttpResponseBasic{
|
|
|
|
|
ErrorCode: base.ErrorCodeGroupNotFound,
|
|
|
|
|
Desp: base.DespGroupNotFound,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !g.KickOutSession(info.SessionId) {
|
|
|
|
|
return base.HttpResponseBasic{
|
|
|
|
|
ErrorCode: base.ErrorCodeSessionNotFound,
|
|
|
|
|
Desp: base.DespSessionNotFound,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return base.HttpResponseBasic{
|
|
|
|
|
ErrorCode: base.ErrorCodeSucc,
|
|
|
|
|
Desp: base.DespSucc,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- implement rtmp.ServerObserver interface -----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnRtmpConnect(session *rtmp.ServerSession, opa rtmp.ObjectPairArray) {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
var info base.RtmpConnectInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.SessionId = session.UniqueKey()
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
if app, err := opa.FindString("app"); err == nil {
|
|
|
|
@ -253,7 +374,7 @@ func (sm *ServerManager) OnRtmpConnect(session *rtmp.ServerSession, opa rtmp.Obj
|
|
|
|
|
if tcUrl, err := opa.FindString("tcUrl"); err == nil {
|
|
|
|
|
info.TcUrl = tcUrl
|
|
|
|
|
}
|
|
|
|
|
notifyHandler.OnRtmpConnect(info)
|
|
|
|
|
sm.option.notifyHandler.OnRtmpConnect(info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnNewRtmpPubSession(session *rtmp.ServerSession) bool {
|
|
|
|
@ -265,7 +386,7 @@ func (sm *ServerManager) OnNewRtmpPubSession(session *rtmp.ServerSession) bool {
|
|
|
|
|
// TODO chef: res值为false时,可以考虑不回调
|
|
|
|
|
// TODO chef: 每次赋值都逐个拼,代码冗余,考虑直接用ISession抽离一下代码
|
|
|
|
|
var info base.PubStartInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtmp
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -275,7 +396,7 @@ func (sm *ServerManager) OnNewRtmpPubSession(session *rtmp.ServerSession) bool {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnPubStart(info)
|
|
|
|
|
sm.option.notifyHandler.OnPubStart(info)
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -290,7 +411,7 @@ func (sm *ServerManager) OnDelRtmpPubSession(session *rtmp.ServerSession) {
|
|
|
|
|
group.DelRtmpPubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.PubStopInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtmp
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -300,7 +421,7 @@ func (sm *ServerManager) OnDelRtmpPubSession(session *rtmp.ServerSession) {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnPubStop(info)
|
|
|
|
|
sm.option.notifyHandler.OnPubStop(info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnNewRtmpSubSession(session *rtmp.ServerSession) bool {
|
|
|
|
@ -310,7 +431,7 @@ func (sm *ServerManager) OnNewRtmpSubSession(session *rtmp.ServerSession) bool {
|
|
|
|
|
group.AddRtmpSubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStartInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtmp
|
|
|
|
|
info.Protocol = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -320,7 +441,7 @@ func (sm *ServerManager) OnNewRtmpSubSession(session *rtmp.ServerSession) bool {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStart(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStart(info)
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
@ -336,7 +457,7 @@ func (sm *ServerManager) OnDelRtmpSubSession(session *rtmp.ServerSession) {
|
|
|
|
|
group.DelRtmpSubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStopInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtmp
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
|
info.StreamName = session.StreamName()
|
|
|
|
@ -345,12 +466,10 @@ func (sm *ServerManager) OnDelRtmpSubSession(session *rtmp.ServerSession) {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStop(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStop(info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// httpflv.ServerObserver interface
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// ----- implement HttpServerHandlerObserver interface -----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnNewHttpflvSubSession(session *httpflv.SubSession) bool {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
@ -359,7 +478,7 @@ func (sm *ServerManager) OnNewHttpflvSubSession(session *httpflv.SubSession) boo
|
|
|
|
|
group.AddHttpflvSubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStartInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolHttpflv
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -369,7 +488,7 @@ func (sm *ServerManager) OnNewHttpflvSubSession(session *httpflv.SubSession) boo
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStart(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStart(info)
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -384,7 +503,7 @@ func (sm *ServerManager) OnDelHttpflvSubSession(session *httpflv.SubSession) {
|
|
|
|
|
group.DelHttpflvSubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStopInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolHttpflv
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -394,13 +513,9 @@ func (sm *ServerManager) OnDelHttpflvSubSession(session *httpflv.SubSession) {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStop(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStop(info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// httpts.ServerObserver interface
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnNewHttptsSubSession(session *httpts.SubSession) bool {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
@ -408,7 +523,7 @@ func (sm *ServerManager) OnNewHttptsSubSession(session *httpts.SubSession) bool
|
|
|
|
|
group.AddHttptsSubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStartInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolHttpts
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -418,7 +533,7 @@ func (sm *ServerManager) OnNewHttptsSubSession(session *httpts.SubSession) bool
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStart(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStart(info)
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -433,7 +548,7 @@ func (sm *ServerManager) OnDelHttptsSubSession(session *httpts.SubSession) {
|
|
|
|
|
group.DelHttptsSubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStopInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolHttpts
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -443,12 +558,10 @@ func (sm *ServerManager) OnDelHttptsSubSession(session *httpts.SubSession) {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStop(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStop(info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// rtsp.ServerObserver interface
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// ----- implement rtsp.ServerObserver interface -----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnNewRtspSessionConnect(session *rtsp.ServerCommandSession) {
|
|
|
|
|
// TODO chef: impl me
|
|
|
|
@ -465,7 +578,7 @@ func (sm *ServerManager) OnNewRtspPubSession(session *rtsp.PubSession) bool {
|
|
|
|
|
res := group.AddRtspPubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.PubStartInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtsp
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -475,7 +588,7 @@ func (sm *ServerManager) OnNewRtspPubSession(session *rtsp.PubSession) bool {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnPubStart(info)
|
|
|
|
|
sm.option.notifyHandler.OnPubStart(info)
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
@ -492,7 +605,7 @@ func (sm *ServerManager) OnDelRtspPubSession(session *rtsp.PubSession) {
|
|
|
|
|
group.DelRtspPubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.PubStopInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtsp
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -502,7 +615,7 @@ func (sm *ServerManager) OnDelRtspPubSession(session *rtsp.PubSession) {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnPubStop(info)
|
|
|
|
|
sm.option.notifyHandler.OnPubStop(info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnNewRtspSubSessionDescribe(session *rtsp.SubSession) (ok bool, sdp []byte) {
|
|
|
|
@ -520,7 +633,7 @@ func (sm *ServerManager) OnNewRtspSubSessionPlay(session *rtsp.SubSession) bool
|
|
|
|
|
res := group.HandleNewRtspSubSessionPlay(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStartInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtsp
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -530,7 +643,7 @@ func (sm *ServerManager) OnNewRtspSubSessionPlay(session *rtsp.SubSession) bool
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStart(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStart(info)
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
@ -547,7 +660,7 @@ func (sm *ServerManager) OnDelRtspSubSession(session *rtsp.SubSession) {
|
|
|
|
|
group.DelRtspSubSession(session)
|
|
|
|
|
|
|
|
|
|
var info base.SubStopInfo
|
|
|
|
|
info.ServerId = config.ServerId
|
|
|
|
|
info.ServerId = sm.config.ServerId
|
|
|
|
|
info.Protocol = base.ProtocolRtsp
|
|
|
|
|
info.Url = session.Url()
|
|
|
|
|
info.AppName = session.AppName()
|
|
|
|
@ -557,81 +670,60 @@ func (sm *ServerManager) OnDelRtspSubSession(session *rtsp.SubSession) {
|
|
|
|
|
info.RemoteAddr = session.GetStat().RemoteAddr
|
|
|
|
|
info.HasInSession = group.HasInSession()
|
|
|
|
|
info.HasOutSession = group.HasOutSession()
|
|
|
|
|
notifyHandler.OnSubStop(info)
|
|
|
|
|
sm.option.notifyHandler.OnSubStop(info)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// HttpApiServerObserver interface
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
// ----- implement IGroupCreator interface -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnStatAllGroup() (sgs []base.StatGroup) {
|
|
|
|
|
return sm.statAllGroup()
|
|
|
|
|
func (sm *ServerManager) CreateGroup(appName string, streamName string) *Group {
|
|
|
|
|
return NewGroup(appName, streamName, sm.config, sm)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnStatGroup(streamName string) *base.StatGroup {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
g := sm.getGroup("", streamName)
|
|
|
|
|
if g == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
// copy
|
|
|
|
|
var ret base.StatGroup
|
|
|
|
|
ret = g.GetStat()
|
|
|
|
|
return &ret
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnCtrlStartPull(info base.ApiCtrlStartPullReq) {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
g := sm.getGroup(info.AppName, info.StreamName)
|
|
|
|
|
if g == nil {
|
|
|
|
|
nazalog.Warnf("group not exist, ignore start pull. streamName=%s", info.StreamName)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
var url string
|
|
|
|
|
if info.UrlParam != "" {
|
|
|
|
|
url = fmt.Sprintf("rtmp://%s/%s/%s?%s", info.Addr, info.AppName, info.StreamName, info.UrlParam)
|
|
|
|
|
} else {
|
|
|
|
|
url = fmt.Sprintf("rtmp://%s/%s/%s", info.Addr, info.AppName, info.StreamName)
|
|
|
|
|
}
|
|
|
|
|
g.StartPull(url)
|
|
|
|
|
}
|
|
|
|
|
// ----- implement GroupObserver interface -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) CleanupHlsIfNeeded(appName string, streamName string, path string) {
|
|
|
|
|
if sm.config.HlsConfig.Enable &&
|
|
|
|
|
(sm.config.HlsConfig.CleanupMode == hls.CleanupModeInTheEnd || sm.config.HlsConfig.CleanupMode == hls.CleanupModeAsap) {
|
|
|
|
|
defertaskthread.Go(
|
|
|
|
|
sm.config.HlsConfig.FragmentDurationMs*sm.config.HlsConfig.FragmentNum*2,
|
|
|
|
|
func(param ...interface{}) {
|
|
|
|
|
appName := param[0].(string)
|
|
|
|
|
streamName := param[1].(string)
|
|
|
|
|
outPath := param[2].(string)
|
|
|
|
|
|
|
|
|
|
if g := sm.GetGroup(appName, streamName); g != nil {
|
|
|
|
|
if g.IsHlsMuxerAlive() {
|
|
|
|
|
nazalog.Warnf("cancel cleanup hls file path since hls muxer still alive. streamName=%s", streamName)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) OnCtrlKickOutSession(info base.ApiCtrlKickOutSession) base.HttpResponseBasic {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
g := sm.getGroup("", info.StreamName)
|
|
|
|
|
if g == nil {
|
|
|
|
|
return base.HttpResponseBasic{
|
|
|
|
|
ErrorCode: base.ErrorCodeGroupNotFound,
|
|
|
|
|
Desp: base.DespGroupNotFound,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !g.KickOutSession(info.SessionId) {
|
|
|
|
|
return base.HttpResponseBasic{
|
|
|
|
|
ErrorCode: base.ErrorCodeSessionNotFound,
|
|
|
|
|
Desp: base.DespSessionNotFound,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return base.HttpResponseBasic{
|
|
|
|
|
ErrorCode: base.ErrorCodeSucc,
|
|
|
|
|
Desp: base.DespSucc,
|
|
|
|
|
nazalog.Infof("cleanup hls file path. streamName=%s, path=%s", streamName, outPath)
|
|
|
|
|
if err := hls.RemoveAll(outPath); err != nil {
|
|
|
|
|
nazalog.Warnf("cleanup hls file path error. path=%s, err=%+v", outPath, err)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
appName,
|
|
|
|
|
streamName,
|
|
|
|
|
path,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) statAllGroup() (sgs []base.StatGroup) {
|
|
|
|
|
func (sm *ServerManager) Config() *Config {
|
|
|
|
|
return sm.config
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sm *ServerManager) GetGroup(appName string, streamName string) *Group {
|
|
|
|
|
sm.mutex.Lock()
|
|
|
|
|
defer sm.mutex.Unlock()
|
|
|
|
|
sm.groupManager.Iterate(func(group *Group) bool {
|
|
|
|
|
sgs = append(sgs, group.GetStat())
|
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
return sm.getGroup(appName, streamName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- private method ------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
// 注意,函数内部不加锁,由调用方保证加锁进入
|
|
|
|
|
func (sm *ServerManager) getOrCreateGroup(appName string, streamName string) *Group {
|
|
|
|
|
g, createFlag := sm.groupManager.GetOrCreateGroup(appName, streamName)
|
|
|
|
@ -644,3 +736,17 @@ func (sm *ServerManager) getOrCreateGroup(appName string, streamName string) *Gr
|
|
|
|
|
func (sm *ServerManager) getGroup(appName string, streamName string) *Group {
|
|
|
|
|
return sm.groupManager.GetGroup(appName, streamName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
func runWebPprof(addr string) {
|
|
|
|
|
nazalog.Infof("start web pprof listen. addr=%s", addr)
|
|
|
|
|
|
|
|
|
|
//nazalog.Warn("start fgprof.")
|
|
|
|
|
//http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
|
|
|
|
|
|
|
|
|
|
if err := http.ListenAndServe(addr, nil); err != nil {
|
|
|
|
|
nazalog.Error(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|