Browse Source

Add option to run a script when client connects or disconnects (Linux only for now)

pull/2/head
Jonathan Sims 6 years ago
parent
commit
37d938da17
  1. 3
      README.md
  2. 20
      client.go
  3. 27
      main.go

3
README.md

@ -14,6 +14,7 @@ Features:
* Each stream can have multiple video and audio tracks * Each stream can have multiple video and audio tracks
* Supports the RTP/RTCP streaming protocol * Supports the RTP/RTCP streaming protocol
* Optional authentication mechanism for publishers * Optional authentication mechanism for publishers
* Optionally run a script on client connect or disconnect (currently Linux only)
* Compatible with Linux and Windows, does not require any dependency or interpreter, it's a single executable * Compatible with Linux and Windows, does not require any dependency or interpreter, it's a single executable
## Installation ## Installation
@ -73,6 +74,8 @@ Flags:
--rtp-port=8000 port of the RTP UDP listener --rtp-port=8000 port of the RTP UDP listener
--rtcp-port=8001 port of the RTCP UDP listener --rtcp-port=8001 port of the RTCP UDP listener
--publish-key="" optional authentication key required to publish --publish-key="" optional authentication key required to publish
--pre-script="" optional script to run on client connect
--post-script="" optional script to run on client disconnect
``` ```
## Links ## Links

20
client.go

@ -6,6 +6,7 @@ import (
"log" "log"
"net" "net"
"net/url" "net/url"
"os/exec"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -162,7 +163,18 @@ func (c *client) log(format string, args ...interface{}) {
} }
func (c *client) run() { func (c *client) run() {
defer func() {
if c.p.postScript != "" {
postScript := exec.Command(c.p.postScript)
err := postScript.Run()
if err != nil {
c.log("ERR: %s", err)
}
}
}()
defer c.log("disconnected") defer c.log("disconnected")
defer func() { defer func() {
c.p.mutex.Lock() c.p.mutex.Lock()
defer c.p.mutex.Unlock() defer c.p.mutex.Unlock()
@ -174,6 +186,14 @@ func (c *client) run() {
c.log("connected") c.log("connected")
if c.p.preScript != "" {
preScript := exec.Command(c.p.preScript)
err := preScript.Run()
if err != nil {
c.log("ERR: %s", err)
}
}
for { for {
req, err := c.conn.ReadRequest() req, err := c.conn.ReadRequest()
if err != nil { if err != nil {

27
main.go

@ -6,6 +6,7 @@ import (
"net" "net"
"os" "os"
"regexp" "regexp"
"runtime"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -53,6 +54,8 @@ type program struct {
rtpPort int rtpPort int
rtcpPort int rtcpPort int
publishKey string publishKey string
preScript string
postScript string
mutex sync.RWMutex mutex sync.RWMutex
rtspl *serverTcpListener rtspl *serverTcpListener
rtpl *serverUdpListener rtpl *serverUdpListener
@ -61,7 +64,7 @@ type program struct {
publishers map[string]*client publishers map[string]*client
} }
func newProgram(protocolsStr string, rtspPort int, rtpPort int, rtcpPort int, publishKey string) (*program, error) { func newProgram(protocolsStr string, rtspPort int, rtpPort int, rtcpPort int, publishKey string, preScript string, postScript string) (*program, error) {
if rtspPort == 0 { if rtspPort == 0 {
return nil, fmt.Errorf("rtsp port not provided") return nil, fmt.Errorf("rtsp port not provided")
@ -106,6 +109,22 @@ func newProgram(protocolsStr string, rtspPort int, rtpPort int, rtcpPort int, pu
} }
} }
if preScript != "" {
if runtime.GOOS != "linux" {
return nil, fmt.Errorf("connect script currenty supported only on Linux")
} else if !regexp.MustCompile(`(?m)^(.+)\/([^/]+)$`).MatchString(preScript) {
return nil, fmt.Errorf("connect script must be a valid path")
}
}
if postScript != "" {
if runtime.GOOS != "linux" {
return nil, fmt.Errorf("disconnect script currently supported only on Linux")
} else if !regexp.MustCompile(`(?m)^(.+)\/([^/]+)$`).MatchString(postScript) {
return nil, fmt.Errorf("disconnect script must be a valid path")
}
}
log.Printf("rtsp-simple-server %s", Version) log.Printf("rtsp-simple-server %s", Version)
p := &program{ p := &program{
@ -114,6 +133,8 @@ func newProgram(protocolsStr string, rtspPort int, rtpPort int, rtcpPort int, pu
rtpPort: rtpPort, rtpPort: rtpPort,
rtcpPort: rtcpPort, rtcpPort: rtcpPort,
publishKey: publishKey, publishKey: publishKey,
preScript: preScript,
postScript: postScript,
clients: make(map[*client]struct{}), clients: make(map[*client]struct{}),
publishers: make(map[string]*client), publishers: make(map[string]*client),
} }
@ -189,6 +210,8 @@ func main() {
rtpPort := kingpin.Flag("rtp-port", "port of the RTP UDP listener").Default("8000").Int() rtpPort := kingpin.Flag("rtp-port", "port of the RTP UDP listener").Default("8000").Int()
rtcpPort := kingpin.Flag("rtcp-port", "port of the RTCP UDP listener").Default("8001").Int() rtcpPort := kingpin.Flag("rtcp-port", "port of the RTCP UDP listener").Default("8001").Int()
publishKey := kingpin.Flag("publish-key", "optional authentication key required to publish").Default("").String() publishKey := kingpin.Flag("publish-key", "optional authentication key required to publish").Default("").String()
preScript := kingpin.Flag("pre-script", "optional script to run on client connect").Default("").String()
postScript := kingpin.Flag("post-script", "optional script to run on client disconnect").Default("").String()
kingpin.Parse() kingpin.Parse()
@ -197,7 +220,7 @@ func main() {
os.Exit(0) os.Exit(0)
} }
p, err := newProgram(*protocols, *rtspPort, *rtpPort, *rtcpPort, *publishKey) p, err := newProgram(*protocols, *rtspPort, *rtpPort, *rtcpPort, *publishKey, *preScript, *postScript)
if err != nil { if err != nil {
log.Fatal("ERR: ", err) log.Fatal("ERR: ", err)
} }

Loading…
Cancel
Save