move externalcmd, syslog, loghandler into dedicated folders
This commit is contained in:
parent
5ca5005040
commit
52019ac75e
20
client.go
20
client.go
|
@ -15,6 +15,8 @@ import (
|
|||
"github.com/aler9/gortsplib/base"
|
||||
"github.com/aler9/gortsplib/headers"
|
||||
"github.com/aler9/gortsplib/rtcpreceiver"
|
||||
|
||||
"github.com/aler9/rtsp-simple-server/externalcmd"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -191,10 +193,10 @@ var errRunPlay = errors.New("play")
|
|||
var errRunRecord = errors.New("record")
|
||||
|
||||
func (c *client) run() {
|
||||
var onConnectCmd *externalCmd
|
||||
var onConnectCmd *externalcmd.ExternalCmd
|
||||
if c.p.conf.RunOnConnect != "" {
|
||||
var err error
|
||||
onConnectCmd, err = startExternalCommand(c.p.conf.RunOnConnect, "")
|
||||
onConnectCmd, err = externalcmd.New(c.p.conf.RunOnConnect, "")
|
||||
if err != nil {
|
||||
c.log("ERR: %s", err)
|
||||
}
|
||||
|
@ -207,7 +209,7 @@ func (c *client) run() {
|
|||
}
|
||||
|
||||
if onConnectCmd != nil {
|
||||
onConnectCmd.close()
|
||||
onConnectCmd.Close()
|
||||
}
|
||||
|
||||
close(c.describe)
|
||||
|
@ -889,10 +891,10 @@ func (c *client) runPlay() bool {
|
|||
return "tracks"
|
||||
}(), c.streamProtocol)
|
||||
|
||||
var onReadCmd *externalCmd
|
||||
var onReadCmd *externalcmd.ExternalCmd
|
||||
if c.path.conf.RunOnRead != "" {
|
||||
var err error
|
||||
onReadCmd, err = startExternalCommand(c.path.conf.RunOnRead, c.path.name)
|
||||
onReadCmd, err = externalcmd.New(c.path.conf.RunOnRead, c.path.name)
|
||||
if err != nil {
|
||||
c.log("ERR: %s", err)
|
||||
}
|
||||
|
@ -905,7 +907,7 @@ func (c *client) runPlay() bool {
|
|||
}
|
||||
|
||||
if onReadCmd != nil {
|
||||
onReadCmd.close()
|
||||
onReadCmd.Close()
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -1033,10 +1035,10 @@ func (c *client) runRecord() bool {
|
|||
return "tracks"
|
||||
}(), c.streamProtocol)
|
||||
|
||||
var onPublishCmd *externalCmd
|
||||
var onPublishCmd *externalcmd.ExternalCmd
|
||||
if c.path.conf.RunOnPublish != "" {
|
||||
var err error
|
||||
onPublishCmd, err = startExternalCommand(c.path.conf.RunOnPublish, c.path.name)
|
||||
onPublishCmd, err = externalcmd.New(c.path.conf.RunOnPublish, c.path.name)
|
||||
if err != nil {
|
||||
c.log("ERR: %s", err)
|
||||
}
|
||||
|
@ -1049,7 +1051,7 @@ func (c *client) runRecord() bool {
|
|||
}
|
||||
|
||||
if onPublishCmd != nil {
|
||||
onPublishCmd.close()
|
||||
onPublishCmd.Close()
|
||||
}
|
||||
|
||||
return false
|
||||
|
|
11
conf.go
11
conf.go
|
@ -14,6 +14,7 @@ import (
|
|||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/aler9/rtsp-simple-server/confenv"
|
||||
"github.com/aler9/rtsp-simple-server/loghandler"
|
||||
)
|
||||
|
||||
type pathConf struct {
|
||||
|
@ -51,7 +52,7 @@ type conf struct {
|
|||
Metrics bool `yaml:"metrics"`
|
||||
Pprof bool `yaml:"pprof"`
|
||||
LogDestinations []string `yaml:"logDestinations"`
|
||||
logDestinationsParsed map[logDestination]struct{} ``
|
||||
logDestinationsParsed map[loghandler.Destination]struct{} ``
|
||||
LogFile string `yaml:"logFile"`
|
||||
Paths map[string]*pathConf `yaml:"paths"`
|
||||
}
|
||||
|
@ -161,17 +162,17 @@ func loadConf(fpath string, stdin io.Reader) (*conf, error) {
|
|||
if len(conf.LogDestinations) == 0 {
|
||||
conf.LogDestinations = []string{"stdout"}
|
||||
}
|
||||
conf.logDestinationsParsed = make(map[logDestination]struct{})
|
||||
conf.logDestinationsParsed = make(map[loghandler.Destination]struct{})
|
||||
for _, dest := range conf.LogDestinations {
|
||||
switch dest {
|
||||
case "stdout":
|
||||
conf.logDestinationsParsed[logDestinationStdout] = struct{}{}
|
||||
conf.logDestinationsParsed[loghandler.DestinationStdout] = struct{}{}
|
||||
|
||||
case "file":
|
||||
conf.logDestinationsParsed[logDestinationFile] = struct{}{}
|
||||
conf.logDestinationsParsed[loghandler.DestinationFile] = struct{}{}
|
||||
|
||||
case "syslog":
|
||||
conf.logDestinationsParsed[logDestinationSyslog] = struct{}{}
|
||||
conf.logDestinationsParsed[loghandler.DestinationSyslog] = struct{}{}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported log destination: %s", dest)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package externalcmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
@ -7,11 +7,11 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type externalCmd struct {
|
||||
type ExternalCmd struct {
|
||||
cmd *exec.Cmd
|
||||
}
|
||||
|
||||
func startExternalCommand(cmdstr string, pathName string) (*externalCmd, error) {
|
||||
func New(cmdstr string, pathName string) (*ExternalCmd, error) {
|
||||
var cmd *exec.Cmd
|
||||
if runtime.GOOS == "windows" {
|
||||
// on Windows the shell is not used and command is started directly
|
||||
|
@ -38,12 +38,12 @@ func startExternalCommand(cmdstr string, pathName string) (*externalCmd, error)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &externalCmd{
|
||||
return &ExternalCmd{
|
||||
cmd: cmd,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *externalCmd) close() {
|
||||
func (e *ExternalCmd) Close() {
|
||||
// on Windows it's not possible to send os.Interrupt to a process
|
||||
// Kill() is the only supported way
|
||||
if runtime.GOOS == "windows" {
|
74
log.go
74
log.go
|
@ -1,74 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
type logDestination int
|
||||
|
||||
const (
|
||||
logDestinationStdout logDestination = iota
|
||||
logDestinationFile
|
||||
logDestinationSyslog
|
||||
)
|
||||
|
||||
type logHandler struct {
|
||||
logDestinations map[logDestination]struct{}
|
||||
logFile *os.File
|
||||
logSyslog *logSyslog
|
||||
}
|
||||
|
||||
func newLogHandler(logDestinations map[logDestination]struct{}, logFilePath string) (*logHandler, error) {
|
||||
lh := &logHandler{
|
||||
logDestinations: logDestinations,
|
||||
}
|
||||
|
||||
if _, ok := logDestinations[logDestinationFile]; ok {
|
||||
var err error
|
||||
lh.logFile, err = os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
lh.close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := logDestinations[logDestinationSyslog]; ok {
|
||||
var err error
|
||||
lh.logSyslog, err = newLogSyslog()
|
||||
if err != nil {
|
||||
lh.close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
log.SetOutput(lh)
|
||||
|
||||
return lh, nil
|
||||
}
|
||||
|
||||
func (lh *logHandler) close() {
|
||||
if lh.logFile != nil {
|
||||
lh.logFile.Close()
|
||||
}
|
||||
|
||||
if lh.logSyslog != nil {
|
||||
lh.logSyslog.close()
|
||||
}
|
||||
}
|
||||
|
||||
func (lh *logHandler) Write(p []byte) (int, error) {
|
||||
if _, ok := lh.logDestinations[logDestinationStdout]; ok {
|
||||
print(string(p))
|
||||
}
|
||||
|
||||
if _, ok := lh.logDestinations[logDestinationFile]; ok {
|
||||
lh.logFile.Write(p)
|
||||
}
|
||||
|
||||
if _, ok := lh.logDestinations[logDestinationSyslog]; ok {
|
||||
lh.logSyslog.write(p)
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package loghandler
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/aler9/rtsp-simple-server/syslog"
|
||||
)
|
||||
|
||||
type Destination int
|
||||
|
||||
const (
|
||||
DestinationStdout Destination = iota
|
||||
DestinationFile
|
||||
DestinationSyslog
|
||||
)
|
||||
|
||||
type LogHandler struct {
|
||||
destinations map[Destination]struct{}
|
||||
file *os.File
|
||||
syslog io.WriteCloser
|
||||
}
|
||||
|
||||
func New(destinations map[Destination]struct{}, filePath string) (*LogHandler, error) {
|
||||
lh := &LogHandler{
|
||||
destinations: destinations,
|
||||
}
|
||||
|
||||
if _, ok := destinations[DestinationFile]; ok {
|
||||
var err error
|
||||
lh.file, err = os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
lh.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := destinations[DestinationSyslog]; ok {
|
||||
var err error
|
||||
lh.syslog, err = syslog.New("rtsp-simple-server")
|
||||
if err != nil {
|
||||
lh.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
log.SetOutput(lh)
|
||||
|
||||
return lh, nil
|
||||
}
|
||||
|
||||
func (lh *LogHandler) Close() {
|
||||
if lh.file != nil {
|
||||
lh.file.Close()
|
||||
}
|
||||
|
||||
if lh.syslog != nil {
|
||||
lh.syslog.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (lh *LogHandler) Write(p []byte) (int, error) {
|
||||
if _, ok := lh.destinations[DestinationStdout]; ok {
|
||||
print(string(p))
|
||||
}
|
||||
|
||||
if _, ok := lh.destinations[DestinationFile]; ok {
|
||||
lh.file.Write(p)
|
||||
}
|
||||
|
||||
if _, ok := lh.destinations[DestinationSyslog]; ok {
|
||||
lh.syslog.Write(p)
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log/syslog"
|
||||
)
|
||||
|
||||
type logSyslog struct {
|
||||
inner *syslog.Writer
|
||||
}
|
||||
|
||||
func newLogSyslog() (*logSyslog, error) {
|
||||
inner, err := syslog.New(syslog.LOG_INFO|syslog.LOG_DAEMON, "rtsp-simple-server")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &logSyslog{
|
||||
inner: inner,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ls *logSyslog) close() {
|
||||
ls.inner.Close()
|
||||
}
|
||||
|
||||
func (ls *logSyslog) write(p []byte) (int, error) {
|
||||
return ls.inner.Write(p)
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type logSyslog struct {
|
||||
}
|
||||
|
||||
func newLogSyslog() (*logSyslog, error) {
|
||||
return nil, fmt.Errorf("not implemented on windows")
|
||||
}
|
||||
|
||||
func (ls *logSyslog) close() {
|
||||
}
|
||||
|
||||
func (ls *logSyslog) write(p []byte) (int, error) {
|
||||
return 0, nil
|
||||
}
|
8
main.go
8
main.go
|
@ -11,6 +11,8 @@ import (
|
|||
|
||||
"github.com/aler9/gortsplib"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
|
||||
"github.com/aler9/rtsp-simple-server/loghandler"
|
||||
)
|
||||
|
||||
var Version = "v0.0.0"
|
||||
|
@ -21,7 +23,7 @@ const (
|
|||
|
||||
type program struct {
|
||||
conf *conf
|
||||
logHandler *logHandler
|
||||
logHandler *loghandler.LogHandler
|
||||
metrics *metrics
|
||||
pprof *pprof
|
||||
paths map[string]*path
|
||||
|
@ -75,7 +77,7 @@ func newProgram(args []string, stdin io.Reader) (*program, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
logHandler, err := newLogHandler(conf.logDestinationsParsed, conf.LogFile)
|
||||
logHandler, err := loghandler.New(conf.logDestinationsParsed, conf.LogFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -376,7 +378,7 @@ outer:
|
|||
p.pprof.close()
|
||||
}
|
||||
|
||||
p.logHandler.close()
|
||||
p.logHandler.Close()
|
||||
|
||||
close(p.clientNew)
|
||||
close(p.clientClose)
|
||||
|
|
16
path.go
16
path.go
|
@ -5,6 +5,8 @@ import (
|
|||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/aler9/rtsp-simple-server/externalcmd"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -28,8 +30,8 @@ type path struct {
|
|||
sourceSdp []byte
|
||||
lastDescribeReq time.Time
|
||||
lastDescribeActivation time.Time
|
||||
onInitCmd *externalCmd
|
||||
onDemandCmd *externalCmd
|
||||
onInitCmd *externalcmd.ExternalCmd
|
||||
onDemandCmd *externalcmd.ExternalCmd
|
||||
}
|
||||
|
||||
func newPath(p *program, name string, conf *pathConf) *path {
|
||||
|
@ -67,7 +69,7 @@ func (pa *path) onInit() {
|
|||
pa.log("starting on init command")
|
||||
|
||||
var err error
|
||||
pa.onInitCmd, err = startExternalCommand(pa.conf.RunOnInit, pa.name)
|
||||
pa.onInitCmd, err = externalcmd.New(pa.conf.RunOnInit, pa.name)
|
||||
if err != nil {
|
||||
pa.log("ERR: %s", err)
|
||||
}
|
||||
|
@ -86,12 +88,12 @@ func (pa *path) onClose(wait bool) {
|
|||
|
||||
if pa.onInitCmd != nil {
|
||||
pa.log("stopping on init command (closing)")
|
||||
pa.onInitCmd.close()
|
||||
pa.onInitCmd.Close()
|
||||
}
|
||||
|
||||
if pa.onDemandCmd != nil {
|
||||
pa.log("stopping on demand command (closing)")
|
||||
pa.onDemandCmd.close()
|
||||
pa.onDemandCmd.Close()
|
||||
}
|
||||
|
||||
for c := range pa.p.clients {
|
||||
|
@ -182,7 +184,7 @@ func (pa *path) onCheck() {
|
|||
!pa.hasClientReaders() &&
|
||||
time.Since(pa.lastDescribeReq) >= onDemandCmdStopAfterDescribePeriod {
|
||||
pa.log("stopping on demand command (not requested anymore)")
|
||||
pa.onDemandCmd.close()
|
||||
pa.onDemandCmd.Close()
|
||||
pa.onDemandCmd = nil
|
||||
}
|
||||
|
||||
|
@ -247,7 +249,7 @@ func (pa *path) onDescribe(client *client) {
|
|||
pa.lastDescribeActivation = time.Now()
|
||||
|
||||
var err error
|
||||
pa.onDemandCmd, err = startExternalCommand(pa.conf.RunOnDemand, pa.name)
|
||||
pa.onDemandCmd, err = externalcmd.New(pa.conf.RunOnDemand, pa.name)
|
||||
if err != nil {
|
||||
pa.log("ERR: %s", err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// +build !windows
|
||||
|
||||
package syslog
|
||||
|
||||
import (
|
||||
"io"
|
||||
native "log/syslog"
|
||||
)
|
||||
|
||||
type syslog struct {
|
||||
inner *native.Writer
|
||||
}
|
||||
|
||||
func New(prefix string) (io.WriteCloser, error) {
|
||||
inner, err := native.New(native.LOG_INFO|native.LOG_DAEMON, prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &syslog{
|
||||
inner: inner,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ls *syslog) Close() error {
|
||||
return ls.inner.Close()
|
||||
}
|
||||
|
||||
func (ls *syslog) Write(p []byte) (int, error) {
|
||||
return ls.inner.Write(p)
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// +build windows
|
||||
|
||||
package syslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type syslog struct {
|
||||
}
|
||||
|
||||
func New(prefix string) (io.WriteCloser, error) {
|
||||
return nil, fmt.Errorf("not implemented on windows")
|
||||
}
|
||||
|
||||
func (ls *syslog) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ls *syslog) Write(p []byte) (int, error) {
|
||||
return 0, nil
|
||||
}
|
Loading…
Reference in New Issue