diff --git a/README.md b/README.md index e3fac54e..288d3002 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,8 @@ Go ≥ 1.14 is required. Features: * Client - * General - * Query servers about published streams - * Encrypt connection with TLS (RTSPS) + * Query servers about available streams + * Encrypt connection with TLS (RTSPS) * Reading * Read streams from servers with UDP or TCP * Select protocol automatically @@ -24,6 +23,7 @@ Features: * Generate RTCP receiver reports automatically * Publishing * Publish streams to servers with UDP or TCP + * Select protocol automatically * Pause publishing without disconnecting from the server * Generate RTCP sender reports automatically * Server @@ -32,7 +32,7 @@ Features: * Write streams to clients with UDP or TCP * Encrypt streams with TLS (RTSPS) * Generate RTCP sender and receiver reports automatically -* General +* Utilities * Encode and decode RTSP primitives, RTP/H264, RTP/AAC, SDP ## Table of contents diff --git a/serverconn_test.go b/serverconn_test.go index 2becff95..d577d2dd 100644 --- a/serverconn_test.go +++ b/serverconn_test.go @@ -416,7 +416,7 @@ func TestServerCSeq(t *testing.T) { require.Equal(t, base.HeaderValue{"5"}, res.Header["CSeq"]) } -func TestServerCSeqNo(t *testing.T) { +func TestServerCSeqMissing(t *testing.T) { s, err := Serve("127.0.0.1:8554") require.NoError(t, err) defer s.Close() diff --git a/serverconnpublish_test.go b/serverconnpublish_test.go index b4cda5a0..b860c249 100644 --- a/serverconnpublish_test.go +++ b/serverconnpublish_test.go @@ -283,7 +283,7 @@ func TestServerPublishSetupDifferentPaths(t *testing.T) { require.Equal(t, "invalid track path (test2stream/trackID=0)", err.Error()) } -func TestServerPublishSetupDouble(t *testing.T) { +func TestServerPublishSetupTrackTwice(t *testing.T) { serverErr := make(chan error) s, err := Serve("127.0.0.1:8554") @@ -516,7 +516,7 @@ func TestServerPublishRecordPartialTracks(t *testing.T) { require.Equal(t, "not all announced tracks have been setup", err.Error()) } -func TestServerPublishReceivePackets(t *testing.T) { +func TestServerPublishFrames(t *testing.T) { for _, proto := range []string{ "udp", "tcp", @@ -708,3 +708,136 @@ func TestServerPublishReceivePackets(t *testing.T) { }) } } + +func TestServerPublishFramesWrongProtocol(t *testing.T) { + conf := ServerConf{ + UDPRTPAddress: "127.0.0.1:8000", + UDPRTCPAddress: "127.0.0.1:8001", + } + + s, err := conf.Serve("127.0.0.1:8554") + require.NoError(t, err) + defer s.Close() + + serverDone := make(chan struct{}) + defer func() { <-serverDone }() + go func() { + defer close(serverDone) + + conn, err := s.Accept() + require.NoError(t, err) + defer conn.Close() + + onAnnounce := func(ctx *ServerConnAnnounceCtx) (*base.Response, error) { + return &base.Response{ + StatusCode: base.StatusOK, + }, nil + } + + onSetup := func(ctx *ServerConnSetupCtx) (*base.Response, error) { + return &base.Response{ + StatusCode: base.StatusOK, + }, nil + } + + onRecord := func(ctx *ServerConnRecordCtx) (*base.Response, error) { + return &base.Response{ + StatusCode: base.StatusOK, + }, nil + } + + onFrame := func(trackID int, typ StreamType, buf []byte) { + t.Error("should not happen") + } + + <-conn.Read(ServerConnReadHandlers{ + OnAnnounce: onAnnounce, + OnSetup: onSetup, + OnRecord: onRecord, + OnFrame: onFrame, + }) + }() + + conn, err := net.Dial("tcp", "localhost:8554") + require.NoError(t, err) + defer conn.Close() + bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) + + track, err := NewTrackH264(96, []byte("123456"), []byte("123456")) + require.NoError(t, err) + + tracks := Tracks{track} + for i, t := range tracks { + t.Media.Attributes = append(t.Media.Attributes, psdp.Attribute{ + Key: "control", + Value: "trackID=" + strconv.FormatInt(int64(i), 10), + }) + } + + err = base.Request{ + Method: base.Announce, + URL: base.MustParseURL("rtsp://localhost:8554/teststream"), + Header: base.Header{ + "CSeq": base.HeaderValue{"1"}, + "Content-Type": base.HeaderValue{"application/sdp"}, + }, + Body: tracks.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) + + inTH := &headers.Transport{ + Delivery: func() *base.StreamDelivery { + v := base.StreamDeliveryUnicast + return &v + }(), + Mode: func() *headers.TransportMode { + v := headers.TransportModeRecord + return &v + }(), + Protocol: StreamProtocolUDP, + ClientPorts: &[2]int{35466, 35467}, + } + + err = base.Request{ + Method: base.Setup, + URL: base.MustParseURL("rtsp://localhost:8554/teststream/trackID=0"), + Header: base.Header{ + "CSeq": base.HeaderValue{"2"}, + "Transport": inTH.Write(), + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = res.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.StatusOK, res.StatusCode) + + var th headers.Transport + err = th.Read(res.Header["Transport"]) + require.NoError(t, err) + + err = base.Request{ + Method: base.Record, + URL: base.MustParseURL("rtsp://localhost:8554/teststream"), + Header: base.Header{ + "CSeq": base.HeaderValue{"3"}, + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = res.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.StatusOK, res.StatusCode) + + err = base.InterleavedFrame{ + TrackID: 0, + StreamType: StreamTypeRTP, + Payload: []byte("\x01\x02\x03\x04"), + }.Write(bconn.Writer) + require.NoError(t, err) +} diff --git a/serverconnread_test.go b/serverconnread_test.go index 3c826d17..65bd5c37 100644 --- a/serverconnread_test.go +++ b/serverconnread_test.go @@ -210,7 +210,7 @@ func TestServerReadSetupDifferentPaths(t *testing.T) { require.Equal(t, "can't setup tracks with different paths", err.Error()) } -func TestServerReadSetupDouble(t *testing.T) { +func TestServerReadSetupTrackTwice(t *testing.T) { serverErr := make(chan error) s, err := Serve("127.0.0.1:8554") @@ -291,7 +291,7 @@ func TestServerReadSetupDouble(t *testing.T) { require.Equal(t, "track 0 has already been setup", err.Error()) } -func TestServerReadReceivePackets(t *testing.T) { +func TestServerReadFrames(t *testing.T) { for _, proto := range []string{ "udp", "tcp",