diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c69cf287..eec09f70 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ jobs: - uses: golangci/golangci-lint-action@v2 with: - version: v1.38 + version: v1.40 go-mod-tidy: runs-on: ubuntu-20.04 diff --git a/.golangci.yml b/.golangci.yml index 5c7573c1..722bcea8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,6 +2,7 @@ linters: enable: - bodyclose + - dupl - exportloopref - gochecknoinits - gocritic @@ -12,6 +13,7 @@ linters: - lll - prealloc - unconvert + - whitespace disable: - errcheck diff --git a/Makefile b/Makefile index 7265e335..f4e085ba 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BASE_IMAGE = amd64/golang:1.17-alpine3.13 -LINT_IMAGE = golangci/golangci-lint:v1.38.0 +LINT_IMAGE = golangci/golangci-lint:v1.40 .PHONY: $(shell ls) @@ -36,7 +36,7 @@ export DOCKERFILE_FORMAT format: echo "$$DOCKERFILE_FORMAT" | docker build -q . -f - -t temp docker run --rm -it -v $(PWD):/s -w /s temp \ - sh -c "find . -type f -name '*.go' | xargs gofumpt -l -w" + sh -c "gofumpt -l -w ." define DOCKERFILE_TEST FROM $(BASE_IMAGE) diff --git a/client_publish_test.go b/client_publish_test.go index 89e052e5..1558bd34 100644 --- a/client_publish_test.go +++ b/client_publish_test.go @@ -83,7 +83,6 @@ func TestClientPublishSerial(t *testing.T) { th.Protocol = headers.TransportProtocolUDP th.ServerPorts = &[2]int{34556, 34557} th.ClientPorts = inTH.ClientPorts - } else { th.Protocol = headers.TransportProtocolTCP th.InterleavedIDs = inTH.InterleavedIDs @@ -125,7 +124,6 @@ func TestClientPublishSerial(t *testing.T) { n, _, err := l1.ReadFrom(buf) require.NoError(t, err) require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, buf[:n]) - } else { var f base.InterleavedFrame f.Payload = make([]byte, 2048) @@ -269,7 +267,6 @@ func TestClientPublishParallel(t *testing.T) { th.Protocol = headers.TransportProtocolUDP th.ServerPorts = &[2]int{34556, 34557} th.ClientPorts = inTH.ClientPorts - } else { th.Protocol = headers.TransportProtocolTCP th.InterleavedIDs = inTH.InterleavedIDs @@ -409,7 +406,6 @@ func TestClientPublishPauseSerial(t *testing.T) { th.Protocol = headers.TransportProtocolUDP th.ServerPorts = &[2]int{34556, 34557} th.ClientPorts = inTH.ClientPorts - } else { th.Protocol = headers.TransportProtocolTCP th.InterleavedIDs = inTH.InterleavedIDs @@ -565,7 +561,6 @@ func TestClientPublishPauseParallel(t *testing.T) { th.Protocol = headers.TransportProtocolUDP th.ServerPorts = &[2]int{34556, 34557} th.ClientPorts = inTH.ClientPorts - } else { th.Protocol = headers.TransportProtocolTCP th.InterleavedIDs = inTH.InterleavedIDs diff --git a/client_read_test.go b/client_read_test.go index 90844ee0..58ff8d90 100644 --- a/client_read_test.go +++ b/client_read_test.go @@ -184,7 +184,6 @@ func TestClientRead(t *testing.T) { require.NoError(t, err) l = tls.NewListener(l, &tls.Config{Certificates: []tls.Certificate{cert}}) - } else { scheme = "rtsp" } @@ -1527,7 +1526,6 @@ func TestClientReadPause(t *testing.T) { th.Protocol = headers.TransportProtocolUDP th.ServerPorts = &[2]int{34556, 34557} th.ClientPorts = inTH.ClientPorts - } else { th.Protocol = headers.TransportProtocolTCP th.InterleavedIDs = inTH.InterleavedIDs @@ -1894,7 +1892,6 @@ func TestClientReadErrorTimeout(t *testing.T) { th.Protocol = headers.TransportProtocolUDP th.ServerPorts = &[2]int{34556, 34557} th.ClientPorts = inTH.ClientPorts - } else { th.Protocol = headers.TransportProtocolTCP th.InterleavedIDs = inTH.InterleavedIDs diff --git a/clientconn.go b/clientconn.go index fc1b5d56..f2739a0e 100644 --- a/clientconn.go +++ b/clientconn.go @@ -571,7 +571,6 @@ func (cc *ClientConn) runBackgroundPlayUDP() error { checkStreamInitial = false checkStreamTicker.Stop() checkStreamTicker = time.NewTicker(clientConnCheckStreamPeriod) - } else { inTimeout := func() bool { now := time.Now() @@ -1024,7 +1023,6 @@ func (cc *ClientConn) doDescribe(u *base.URL) (Tracks, *base.URL, *base.Response res.StatusCode >= base.StatusMovedPermanently && res.StatusCode <= base.StatusUseProxy && len(res.Header["Location"]) == 1 { - cc.reset(false) u, err := base.ParseURL(res.Header["Location"][0]) @@ -1303,7 +1301,6 @@ func (cc *ClientConn) doSetup( if res.StatusCode == base.StatusUnsupportedTransport && cc.protocol == nil && cc.c.Transport == nil { - v := TransportTCP cc.protocol = &v diff --git a/pkg/headers/range.go b/pkg/headers/range.go index fca2e636..5f741d58 100644 --- a/pkg/headers/range.go +++ b/pkg/headers/range.go @@ -65,7 +65,6 @@ func (t *RangeSMPTETime) read(s string) error { return err } t.Subframe = uint(tmp) - } else { tmp, err := strconv.ParseUint(parts[0], 10, 64) if err != nil { diff --git a/server_publish_test.go b/server_publish_test.go index 43b98a23..719178a3 100644 --- a/server_publish_test.go +++ b/server_publish_test.go @@ -18,6 +18,44 @@ import ( "github.com/aler9/gortsplib/pkg/headers" ) +func invalidURLAnnounceReq(t *testing.T, control string) base.Request { + return base.Request{ + Method: base.Announce, + URL: mustParseURL("rtsp://localhost:8554/teststream"), + Header: base.Header{ + "CSeq": base.HeaderValue{"1"}, + "Content-Type": base.HeaderValue{"application/sdp"}, + }, + Body: func() []byte { + track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}}) + require.NoError(t, err) + track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{ + Key: "control", + Value: control, + }) + + sout := &psdp.SessionDescription{ + SessionName: psdp.SessionName("Stream"), + Origin: psdp.Origin{ + Username: "-", + NetworkType: "IN", + AddressType: "IP4", + UnicastAddress: "127.0.0.1", + }, + TimeDescriptions: []psdp.TimeDescription{ + {Timing: psdp.Timing{0, 0}}, //nolint:govet + }, + MediaDescriptions: []*psdp.MediaDescription{ + track.Media, + }, + } + + byts, _ := sout.Marshal() + return byts + }(), + } +} + func TestServerPublishErrorAnnounce(t *testing.T) { for _, ca := range []struct { name string @@ -92,119 +130,17 @@ func TestServerPublishErrorAnnounce(t *testing.T) { }, { "invalid URL 1", - base.Request{ - Method: base.Announce, - URL: mustParseURL("rtsp://localhost:8554/teststream"), - Header: base.Header{ - "CSeq": base.HeaderValue{"1"}, - "Content-Type": base.HeaderValue{"application/sdp"}, - }, - Body: func() []byte { - track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}}) - require.NoError(t, err) - track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{ - Key: "control", - Value: "rtsp:// aaaaa", - }) - - sout := &psdp.SessionDescription{ - SessionName: psdp.SessionName("Stream"), - Origin: psdp.Origin{ - Username: "-", - NetworkType: "IN", - AddressType: "IP4", - UnicastAddress: "127.0.0.1", - }, - TimeDescriptions: []psdp.TimeDescription{ - {Timing: psdp.Timing{0, 0}}, //nolint:govet - }, - MediaDescriptions: []*psdp.MediaDescription{ - track.Media, - }, - } - - byts, _ := sout.Marshal() - return byts - }(), - }, + invalidURLAnnounceReq(t, "rtsp:// aaaaa"), "unable to generate track URL", }, { "invalid URL 2", - base.Request{ - Method: base.Announce, - URL: mustParseURL("rtsp://localhost:8554/teststream"), - Header: base.Header{ - "CSeq": base.HeaderValue{"1"}, - "Content-Type": base.HeaderValue{"application/sdp"}, - }, - Body: func() []byte { - track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}}) - require.NoError(t, err) - track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{ - Key: "control", - Value: "rtsp://host", - }) - - sout := &psdp.SessionDescription{ - SessionName: psdp.SessionName("Stream"), - Origin: psdp.Origin{ - Username: "-", - NetworkType: "IN", - AddressType: "IP4", - UnicastAddress: "127.0.0.1", - }, - TimeDescriptions: []psdp.TimeDescription{ - {Timing: psdp.Timing{0, 0}}, //nolint:govet - }, - MediaDescriptions: []*psdp.MediaDescription{ - track.Media, - }, - } - - byts, _ := sout.Marshal() - return byts - }(), - }, + invalidURLAnnounceReq(t, "rtsp://host"), "invalid track URL (rtsp://localhost:8554)", }, { "invalid URL 3", - base.Request{ - Method: base.Announce, - URL: mustParseURL("rtsp://localhost:8554/teststream"), - Header: base.Header{ - "CSeq": base.HeaderValue{"1"}, - "Content-Type": base.HeaderValue{"application/sdp"}, - }, - Body: func() []byte { - track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}}) - require.NoError(t, err) - track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{ - Key: "control", - Value: "rtsp://host/otherpath", - }) - - sout := &psdp.SessionDescription{ - SessionName: psdp.SessionName("Stream"), - Origin: psdp.Origin{ - Username: "-", - NetworkType: "IN", - AddressType: "IP4", - UnicastAddress: "127.0.0.1", - }, - TimeDescriptions: []psdp.TimeDescription{ - {Timing: psdp.Timing{0, 0}}, //nolint:govet - }, - MediaDescriptions: []*psdp.MediaDescription{ - track.Media, - }, - } - - byts, _ := sout.Marshal() - return byts - }(), - }, + invalidURLAnnounceReq(t, "rtsp://host/otherpath"), "invalid track path: must begin with 'teststream', but is 'otherpath'", }, } { @@ -847,7 +783,6 @@ func TestServerPublish(t *testing.T) { IP: net.ParseIP("127.0.0.1"), Port: th.ServerPorts[1], }) - } else { err = base.InterleavedFrame{ Channel: 0, @@ -873,7 +808,6 @@ func TestServerPublish(t *testing.T) { n, _, err := l2.ReadFrom(buf) require.NoError(t, err) require.Equal(t, []byte{0x09, 0x0A, 0x0B, 0x0C}, buf[:n]) - } else { var f base.InterleavedFrame f.Payload = make([]byte, 2048) diff --git a/server_read_test.go b/server_read_test.go index 9aa9de24..3eed256f 100644 --- a/server_read_test.go +++ b/server_read_test.go @@ -142,148 +142,111 @@ func TestServerReadSetupPath(t *testing.T) { } } -func TestServerReadErrorSetupDifferentPaths(t *testing.T) { - connClosed := make(chan struct{}) +func TestServerReadSetupErrors(t *testing.T) { + for _, ca := range []string{"different paths", "double setup"} { + t.Run(ca, func(t *testing.T) { + connClosed := make(chan struct{}) - track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}}) - require.NoError(t, err) + track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}}) + require.NoError(t, err) - stream := NewServerStream(Tracks{track}) + stream := NewServerStream(Tracks{track}) - s := &Server{ - Handler: &testServerHandler{ - onConnClose: func(ctx *ServerHandlerOnConnCloseCtx) { - require.Equal(t, "can't setup tracks with different paths", ctx.Error.Error()) - close(connClosed) - }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) { - return &base.Response{ - StatusCode: base.StatusOK, - }, stream, nil - }, - }, + s := &Server{ + Handler: &testServerHandler{ + onConnClose: func(ctx *ServerHandlerOnConnCloseCtx) { + if ca == "different paths" { + require.Equal(t, "can't setup tracks with different paths", ctx.Error.Error()) + } else { + require.Equal(t, "track 0 has already been setup", ctx.Error.Error()) + } + close(connClosed) + }, + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) { + return &base.Response{ + StatusCode: base.StatusOK, + }, stream, nil + }, + }, + } + + err = s.Start("localhost:8554") + require.NoError(t, err) + defer s.Close() + + conn, err := net.Dial("tcp", "localhost:8554") + require.NoError(t, err) + defer conn.Close() + bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) + + th := &headers.Transport{ + Protocol: headers.TransportProtocolTCP, + Delivery: func() *headers.TransportDelivery { + v := headers.TransportDeliveryUnicast + return &v + }(), + Mode: func() *headers.TransportMode { + v := headers.TransportModePlay + return &v + }(), + InterleavedIDs: &[2]int{0, 1}, + } + + if ca == "different paths" { + res, err := writeReqReadRes(bconn, base.Request{ + Method: base.Setup, + URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"), + Header: base.Header{ + "CSeq": base.HeaderValue{"1"}, + "Transport": th.Write(), + }, + }) + require.NoError(t, err) + require.Equal(t, base.StatusOK, res.StatusCode) + + th.InterleavedIDs = &[2]int{2, 3} + + res, err = writeReqReadRes(bconn, base.Request{ + Method: base.Setup, + URL: mustParseURL("rtsp://localhost:8554/test12stream/trackID=1"), + Header: base.Header{ + "CSeq": base.HeaderValue{"2"}, + "Transport": th.Write(), + "Session": res.Header["Session"], + }, + }) + require.NoError(t, err) + require.Equal(t, base.StatusBadRequest, res.StatusCode) + } else { + res, err := writeReqReadRes(bconn, base.Request{ + Method: base.Setup, + URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"), + Header: base.Header{ + "CSeq": base.HeaderValue{"1"}, + "Transport": th.Write(), + }, + }) + require.NoError(t, err) + require.Equal(t, base.StatusOK, res.StatusCode) + + th.InterleavedIDs = &[2]int{2, 3} + + res, err = writeReqReadRes(bconn, base.Request{ + Method: base.Setup, + URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"), + Header: base.Header{ + "CSeq": base.HeaderValue{"2"}, + "Transport": th.Write(), + "Session": res.Header["Session"], + }, + }) + require.NoError(t, err) + require.Equal(t, base.StatusBadRequest, res.StatusCode) + } + + <-connClosed + }) } - - err = s.Start("localhost:8554") - require.NoError(t, err) - defer s.Close() - - conn, err := net.Dial("tcp", "localhost:8554") - require.NoError(t, err) - defer conn.Close() - bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - - th := &headers.Transport{ - Protocol: headers.TransportProtocolTCP, - Delivery: func() *headers.TransportDelivery { - v := headers.TransportDeliveryUnicast - return &v - }(), - Mode: func() *headers.TransportMode { - v := headers.TransportModePlay - return &v - }(), - InterleavedIDs: &[2]int{0, 1}, - } - - res, err := writeReqReadRes(bconn, base.Request{ - Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"), - Header: base.Header{ - "CSeq": base.HeaderValue{"1"}, - "Transport": th.Write(), - }, - }) - require.NoError(t, err) - require.Equal(t, base.StatusOK, res.StatusCode) - - th.InterleavedIDs = &[2]int{2, 3} - - res, err = writeReqReadRes(bconn, base.Request{ - Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/test12stream/trackID=1"), - Header: base.Header{ - "CSeq": base.HeaderValue{"2"}, - "Transport": th.Write(), - "Session": res.Header["Session"], - }, - }) - require.NoError(t, err) - require.Equal(t, base.StatusBadRequest, res.StatusCode) - - <-connClosed -} - -func TestServerReadErrorSetupTrackTwice(t *testing.T) { - connClosed := make(chan struct{}) - - track, err := NewTrackH264(96, &TrackConfigH264{[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}}) - require.NoError(t, err) - - stream := NewServerStream(Tracks{track}) - - s := &Server{ - Handler: &testServerHandler{ - onConnClose: func(ctx *ServerHandlerOnConnCloseCtx) { - require.Equal(t, "track 0 has already been setup", ctx.Error.Error()) - close(connClosed) - }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) { - return &base.Response{ - StatusCode: base.StatusOK, - }, stream, nil - }, - }, - } - - err = s.Start("localhost:8554") - require.NoError(t, err) - defer s.Close() - - conn, err := net.Dial("tcp", "localhost:8554") - require.NoError(t, err) - defer conn.Close() - bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - - th := &headers.Transport{ - Protocol: headers.TransportProtocolTCP, - Delivery: func() *headers.TransportDelivery { - v := headers.TransportDeliveryUnicast - return &v - }(), - Mode: func() *headers.TransportMode { - v := headers.TransportModePlay - return &v - }(), - InterleavedIDs: &[2]int{0, 1}, - } - - res, err := writeReqReadRes(bconn, base.Request{ - Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"), - Header: base.Header{ - "CSeq": base.HeaderValue{"1"}, - "Transport": th.Write(), - }, - }) - require.NoError(t, err) - require.Equal(t, base.StatusOK, res.StatusCode) - - th.InterleavedIDs = &[2]int{2, 3} - - res, err = writeReqReadRes(bconn, base.Request{ - Method: base.Setup, - URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"), - Header: base.Header{ - "CSeq": base.HeaderValue{"2"}, - "Transport": th.Write(), - "Session": res.Header["Session"], - }, - }) - require.NoError(t, err) - require.Equal(t, base.StatusBadRequest, res.StatusCode) - - <-connClosed } func TestServerRead(t *testing.T) { diff --git a/server_test.go b/server_test.go index aa8e15eb..27fdc561 100644 --- a/server_test.go +++ b/server_test.go @@ -409,7 +409,6 @@ func TestServerHighLevelPublishRead(t *testing.T) { cert, err := tls.X509KeyPair(serverCert, serverKey) require.NoError(t, err) s.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cert}} - } else { proto = "rtsp" s.UDPRTPAddress = "127.0.0.1:8000" diff --git a/serverconn.go b/serverconn.go index 6d34e972..cc32230f 100644 --- a/serverconn.go +++ b/serverconn.go @@ -191,7 +191,6 @@ func (sc *ServerConn) run() { return liberrors.ErrServerTerminated{} } } - } else { err := req.Read(sc.br) if err != nil { @@ -522,7 +521,6 @@ func (sc *ServerConn) handleRequestOuter(req *base.Request) error { // start background write sc.tcpFrameBackgroundWriteDone = make(chan struct{}) go sc.tcpFrameBackgroundWrite() - } else { if sc.tcpFrameIsRecording { sc.tcpFrameTimeout = false diff --git a/serversession.go b/serversession.go index 2d8638ae..c523f5aa 100644 --- a/serversession.go +++ b/serversession.go @@ -294,7 +294,6 @@ func (ss *ServerSession) run() { if (ss.state != ServerSessionStatePublish && ss.state != ServerSessionStateRead) || *ss.setuppedTransport == TransportTCP { - // close if there are no associated connections if len(ss.conns) == 0 { return liberrors.ErrServerSessionNoAssociatedConns{}