From c3e99ee583e228119237cbe88f0afbf9087edcbc Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Sat, 28 Dec 2019 23:46:32 +0100 Subject: [PATCH] fix OPTIONS method; reorder methods --- README.md | 5 ++- rtsp_client.go | 102 +++++++++++++++++++++++++------------------------ 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index b25e163e..277f22c5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,10 @@ _rtsp-simple-server_ is a simple, ready-to-use and zero-dependency RTSP server, This software was developed with the aim of simulating a live camera feed for debugging purposes, and therefore to use files instead of real streams. Another reason for the development was the deprecation of _FFserver_, the component of the FFmpeg project that allowed to create a RTSP server with _FFmpeg_ (but this server can be used with any software that supports RTSP). -It actually supports *one* publisher, while readers can be more than one. +Features: +* Supports reading and publishing streams +* Supports one publisher at once, while readers can be more than one. +* Supports reading via UDP and TCP
diff --git a/rtsp_client.go b/rtsp_client.go index c3410615..8bd1e061 100644 --- a/rtsp_client.go +++ b/rtsp_client.go @@ -104,9 +104,11 @@ func (c *rtspClient) run(wg sync.WaitGroup) { "CSeq": cseq, "Public": strings.Join([]string{ "DESCRIBE", + "ANNOUNCE", "SETUP", "PLAY", "PAUSE", + "RECORD", "TEARDOWN", }, ", "), }, @@ -152,6 +154,56 @@ func (c *rtspClient) run(wg sync.WaitGroup) { return } + case "ANNOUNCE": + if c.state != "STARTING" { + c.log("ERR: client is in state '%s'", c.state) + return + } + + ct, ok := req.Headers["Content-Type"] + if !ok { + c.log("ERR: Content-Type header missing") + return + } + + if ct != "application/sdp" { + c.log("ERR: unsupported Content-Type '%s'", ct) + return + } + + err := func() error { + c.p.mutex.Lock() + defer c.p.mutex.Unlock() + + if c.p.streamAuthor != nil { + return fmt.Errorf("another client is already streaming") + } + + c.p.streamAuthor = c + c.p.streamSdp = req.Content + return nil + }() + if err != nil { + c.log("ERR: %s", err) + return + } + + err = c.rconn.WriteResponse(&rtsp.Response{ + StatusCode: 200, + Status: "OK", + Headers: map[string]string{ + "CSeq": cseq, + }, + }) + if err != nil { + c.log("ERR: %s", err) + return + } + + c.p.mutex.Lock() + c.state = "ANNOUNCE" + c.p.mutex.Unlock() + case "SETUP": transport, ok := req.Headers["Transport"] if !ok { @@ -354,56 +406,6 @@ func (c *rtspClient) run(wg sync.WaitGroup) { c.state = "RECORD" c.p.mutex.Unlock() - case "ANNOUNCE": - if c.state != "STARTING" { - c.log("ERR: client is in state '%s'", c.state) - return - } - - ct, ok := req.Headers["Content-Type"] - if !ok { - c.log("ERR: Content-Type header missing") - return - } - - if ct != "application/sdp" { - c.log("ERR: unsupported Content-Type '%s'", ct) - return - } - - err := func() error { - c.p.mutex.Lock() - defer c.p.mutex.Unlock() - - if c.p.streamAuthor != nil { - return fmt.Errorf("another client is already streaming") - } - - c.p.streamAuthor = c - c.p.streamSdp = req.Content - return nil - }() - if err != nil { - c.log("ERR: %s", err) - return - } - - err = c.rconn.WriteResponse(&rtsp.Response{ - StatusCode: 200, - Status: "OK", - Headers: map[string]string{ - "CSeq": cseq, - }, - }) - if err != nil { - c.log("ERR: %s", err) - return - } - - c.p.mutex.Lock() - c.state = "ANNOUNCE" - c.p.mutex.Unlock() - case "TEARDOWN": return