ServerConn: support SETUP calls without trackID (https://github.com/aler9/rtsp-simple-server/issues/155)

This commit is contained in:
aler9
2021-01-18 13:13:34 +01:00
parent 9602c653a7
commit 4c12bbe5a0
5 changed files with 79 additions and 8 deletions

View File

@@ -20,8 +20,8 @@ import (
var mutex sync.Mutex var mutex sync.Mutex
var publisher *gortsplib.ServerConn var publisher *gortsplib.ServerConn
var sdp []byte
var readers = make(map[*gortsplib.ServerConn]struct{}) var readers = make(map[*gortsplib.ServerConn]struct{})
var sdp []byte
// this is called for each incoming connection // this is called for each incoming connection
func handleConn(conn *gortsplib.ServerConn) { func handleConn(conn *gortsplib.ServerConn) {
@@ -117,7 +117,7 @@ func handleConn(conn *gortsplib.ServerConn) {
}, nil }, nil
} }
// called after receiving a Frame. // called after receiving a frame.
onFrame := func(trackID int, typ gortsplib.StreamType, buf []byte) { onFrame := func(trackID int, typ gortsplib.StreamType, buf []byte) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()

View File

@@ -19,8 +19,8 @@ import (
var mutex sync.Mutex var mutex sync.Mutex
var publisher *gortsplib.ServerConn var publisher *gortsplib.ServerConn
var sdp []byte
var readers = make(map[*gortsplib.ServerConn]struct{}) var readers = make(map[*gortsplib.ServerConn]struct{})
var sdp []byte
// this is called for each incoming connection // this is called for each incoming connection
func handleConn(conn *gortsplib.ServerConn) { func handleConn(conn *gortsplib.ServerConn) {
@@ -116,7 +116,7 @@ func handleConn(conn *gortsplib.ServerConn) {
}, nil }, nil
} }
// called after receiving a Frame. // called after receiving a frame.
onFrame := func(trackID int, typ gortsplib.StreamType, buf []byte) { onFrame := func(trackID int, typ gortsplib.StreamType, buf []byte) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()

View File

@@ -19,8 +19,8 @@ import (
var mutex sync.Mutex var mutex sync.Mutex
var publisher *gortsplib.ServerConn var publisher *gortsplib.ServerConn
var sdp []byte
var readers = make(map[*gortsplib.ServerConn]struct{}) var readers = make(map[*gortsplib.ServerConn]struct{})
var sdp []byte
// this is called for each incoming connection // this is called for each incoming connection
func handleConn(conn *gortsplib.ServerConn) { func handleConn(conn *gortsplib.ServerConn) {
@@ -116,7 +116,7 @@ func handleConn(conn *gortsplib.ServerConn) {
}, nil }, nil
} }
// called after receiving a Frame. // called after receiving a frame.
onFrame := func(trackID int, typ gortsplib.StreamType, buf []byte) { onFrame := func(trackID int, typ gortsplib.StreamType, buf []byte) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()

View File

@@ -413,6 +413,75 @@ func TestServerTeardownResponse(t *testing.T) {
require.Equal(t, io.EOF, err) require.Equal(t, io.EOF, err)
} }
func TestServerSetupWithoutTrackID(t *testing.T) {
ts, err := newTestServ(nil)
require.NoError(t, err)
defer ts.close()
cnt1, err := newContainer("ffmpeg", "publish", []string{
"-re",
"-stream_loop", "-1",
"-i", "emptyvideo.ts",
"-c", "copy",
"-f", "rtsp",
"-rtsp_transport", "tcp",
"rtsp://localhost:8554/teststream",
})
require.NoError(t, err)
defer cnt1.close()
time.Sleep(1 * time.Second)
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
err = base.Request{
Method: base.Setup,
URL: base.MustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
"CSeq": base.HeaderValue{"1"},
"Transport": headers.Transport{
Protocol: StreamProtocolTCP,
Delivery: func() *base.StreamDelivery {
v := base.StreamDeliveryUnicast
return &v
}(),
Mode: func() *headers.TransportMode {
v := headers.TransportModePlay
return &v
}(),
InterleavedIds: &[2]int{0, 1},
}.Write(),
},
}.Write(bconn.Writer)
require.NoError(t, err)
var res base.Response
err = res.Read(bconn.Reader)
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
err = base.Request{
Method: base.Play,
URL: base.MustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
"CSeq": base.HeaderValue{"2"},
},
}.Write(bconn.Writer)
require.NoError(t, err)
err = res.Read(bconn.Reader)
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
var fr base.InterleavedFrame
fr.Payload = make([]byte, 2048)
err = fr.Read(bconn.Reader)
require.NoError(t, err)
}
func TestServerResponseBeforeFrames(t *testing.T) { func TestServerResponseBeforeFrames(t *testing.T) {
ts, err := newTestServ(nil) ts, err := newTestServ(nil)
require.NoError(t, err) require.NoError(t, err)

View File

@@ -70,8 +70,10 @@ type ServerConnTrack struct {
func extractTrackID(pathAndQuery string, mode *headers.TransportMode, trackLen int) (int, error) { func extractTrackID(pathAndQuery string, mode *headers.TransportMode, trackLen int) (int, error) {
if mode == nil || *mode == headers.TransportModePlay { if mode == nil || *mode == headers.TransportModePlay {
i := strings.Index(pathAndQuery, "/trackID=") i := strings.Index(pathAndQuery, "/trackID=")
// URL doesn't contain trackID - we assume it's track 0
if i < 0 { if i < 0 {
return 0, fmt.Errorf("unable to find control attribute (%s)", pathAndQuery) return 0, nil
} }
tmp, err := strconv.ParseInt(pathAndQuery[i+len("/trackID="):], 10, 64) tmp, err := strconv.ParseInt(pathAndQuery[i+len("/trackID="):], 10, 64)
@@ -128,7 +130,7 @@ type ServerConnReadHandlers struct {
// if nil, it is generated automatically. // if nil, it is generated automatically.
OnTeardown func(req *base.Request) (*base.Response, error) OnTeardown func(req *base.Request) (*base.Response, error)
// called after receiving a Frame. // called after receiving a frame.
OnFrame func(trackID int, streamType StreamType, payload []byte) OnFrame func(trackID int, streamType StreamType, payload []byte)
} }