From 6d97934e2489061057847b69326a971782e5098e Mon Sep 17 00:00:00 2001 From: Joe Turki Date: Fri, 14 Feb 2025 05:28:16 -0600 Subject: [PATCH] Upgrade golangci-lint, more linters Introduces new linters, upgrade golangci-lint to version (v1.63.4) --- .golangci.yml | 48 +++++--- application_defined.go | 5 +- application_defined_test.go | 5 +- compound_packet.go | 10 +- extended_report.go | 64 +++++++---- extended_report_test.go | 16 +-- full_intra_request.go | 23 ++-- goodbye.go | 13 ++- header.go | 15 ++- packet.go | 20 ++-- packet_buffer.go | 26 +++-- packet_buffer_test.go | 8 +- packet_stringifier.go | 10 +- packet_stringifier_test.go | 4 +- packet_test.go | 2 +- picture_loss_indication.go | 10 +- rapid_resynchronization_request.go | 10 +- raw_packet.go | 5 +- receiver_estimated_maximum_bitrate.go | 8 +- receiver_report.go | 30 ++--- receiver_report_test.go | 1 + reception_report.go | 4 +- rfc8888.go | 47 +++++--- sender_report.go | 25 ++-- sender_report_test.go | 1 + slice_loss_indication.go | 27 ++--- source_description.go | 44 ++++--- transport_layer_cc.go | 57 ++++++--- transport_layer_cc_test.go | 160 +++++++++++++++++++++++--- transport_layer_nack.go | 32 +++--- transport_layer_nack_test.go | 10 +- util.go | 12 +- util_test.go | 5 +- 33 files changed, 517 insertions(+), 240 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a3235be..0b74106 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,4 @@ + # SPDX-FileCopyrightText: 2023 The Pion community # SPDX-License-Identifier: MIT @@ -25,17 +26,32 @@ linters-settings: - ^os.Exit$ - ^panic$ - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: enable: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity - decorder # check declaration order and count of types, constants, variables and functions - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. @@ -46,18 +62,17 @@ linters: - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period - godox # Tool for detection of FIXME, TODO and other comment keywords - - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems - gosimple # Linter for Go source code that specializes in simplifying a code @@ -65,9 +80,15 @@ linters: - grouper # An analyzer to analyze expression groups. - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes @@ -75,28 +96,22 @@ linters: - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: - depguard # Go linter that checks if package imports are in a list of acceptable packages - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - nakedret # Finds naked returns in functions greater than a specified function length - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - mnd # An analyzer to detect magic numbers - nolintlint # Reports ill-formed or insufficient nolint directives - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated @@ -104,8 +119,7 @@ linters: - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - wrapcheck # Checks that errors returned from external packages are wrapped - wsl # Whitespace Linter - Forces you to use empty lines! diff --git a/application_defined.go b/application_defined.go index 77a1193..ca5f844 100644 --- a/application_defined.go +++ b/application_defined.go @@ -38,7 +38,7 @@ func (a ApplicationDefined) Marshal() ([]byte, error) { packetSize := a.MarshalSize() header := Header{ Type: TypeApplicationDefined, - Length: uint16((packetSize / 4) - 1), + Length: uint16((packetSize / 4) - 1), //nolint:gosec // G115 Padding: paddingSize != 0, Count: a.SubType, } @@ -110,7 +110,7 @@ func (a *ApplicationDefined) Unmarshal(rawPacket []byte) error { return nil } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (a *ApplicationDefined) MarshalSize() int { dataLength := len(a.Data) // Calculate the padding size to be added to make the packet length a multiple of 4 bytes. @@ -118,5 +118,6 @@ func (a *ApplicationDefined) MarshalSize() int { if paddingSize == 4 { paddingSize = 0 } + return 12 + dataLength + paddingSize } diff --git a/application_defined_test.go b/application_defined_test.go index 6db4c4f..1611cd0 100644 --- a/application_defined_test.go +++ b/application_defined_test.go @@ -144,7 +144,10 @@ func TestTApplicationPacketUnmarshal(t *testing.T) { t.Fatalf("SSRC %q result: got packet SSRC %x instead of %x", test.Name, apk.SSRC, 0x4baae1ab) } if apk.SSRC != apk.DestinationSSRC()[0] { - t.Fatalf("SSRC %q result: DestinationSSRC() %x doesn't match SSRC field %x", test.Name, apk.DestinationSSRC()[0], apk.SSRC) + t.Fatalf( + "SSRC %q result: DestinationSSRC() %x doesn't match SSRC field %x", + test.Name, apk.DestinationSSRC()[0], apk.SSRC, + ) } } } diff --git a/compound_packet.go b/compound_packet.go index a621c61..1752b64 100644 --- a/compound_packet.go +++ b/compound_packet.go @@ -23,6 +23,8 @@ import ( type CompoundPacket []Packet // Validate returns an error if this is not an RFC-compliant CompoundPacket. +// +//nolint:cyclop func (c CompoundPacket) Validate() error { if len(c) == 0 { return errEmptyCompound @@ -72,7 +74,7 @@ func (c CompoundPacket) Validate() error { return errMissingCNAME } -// CNAME returns the CNAME that *must* be present in every CompoundPacket +// CNAME returns the CNAME that *must* be present in every CompoundPacket. func (c CompoundPacket) CNAME() (string, error) { var err error @@ -97,6 +99,7 @@ func (c CompoundPacket) CNAME() (string, error) { } } } + return "", errMissingCNAME } @@ -107,15 +110,17 @@ func (c CompoundPacket) Marshal() ([]byte, error) { } p := []Packet(c) + return Marshal(p) } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (c CompoundPacket) MarshalSize() int { l := 0 for _, p := range c { l += p.MarshalSize() } + return l } @@ -157,5 +162,6 @@ func (c CompoundPacket) String() string { } } out = strings.TrimSuffix(strings.ReplaceAll(out, "\n", "\n\t"), "\t") + return out } diff --git a/extended_report.go b/extended_report.go index 0f9ee2c..7b025c9 100644 --- a/extended_report.go +++ b/extended_report.go @@ -23,13 +23,14 @@ import ( // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // : report blocks : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type ExtendedReport struct { SenderSSRC uint32 `fmt:"0x%X"` Reports []ReportBlock } // ReportBlock represents a single report within an ExtendedReport -// packet +// packet. type ReportBlock interface { DestinationSSRC() []uint32 setupBlockHeader() @@ -53,7 +54,7 @@ type XRHeader struct { BlockLength uint16 } -// BlockTypeType specifies the type of report in a report block +// BlockTypeType specifies the type of report in a report block. type BlockTypeType uint8 // Extended Report block types from RFC 3611. @@ -67,7 +68,7 @@ const ( VoIPMetricsReportBlockType = 7 // RFC 3611, section 4.7 ) -// String converts the Extended report block types into readable strings +// String converts the Extended report block types into readable strings. func (t BlockTypeType) String() string { switch t { case LossRLEReportBlockType: @@ -85,6 +86,7 @@ func (t BlockTypeType) String() string { case VoIPMetricsReportBlockType: return "VoIPMetricsReportBlockType" } + return fmt.Sprintf("invalid value %d", t) } @@ -108,6 +110,7 @@ func (t BlockTypeType) String() string { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | chunk n-1 | chunk n | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type rleReportBlock struct { XRHeader T uint8 `encoding:"omit"` @@ -146,7 +149,7 @@ type rleReportBlock struct { type Chunk uint16 // LossRLEReportBlock is used to report information about packet -// losses, as described in RFC 3611, section 4.1 +// losses, as described in RFC 3611, section 4.1. type LossRLEReportBlock rleReportBlock // DestinationSSRC returns an array of SSRC values that this report block refers to. @@ -157,7 +160,7 @@ func (b *LossRLEReportBlock) DestinationSSRC() []uint32 { func (b *LossRLEReportBlock) setupBlockHeader() { b.XRHeader.BlockType = LossRLEReportBlockType b.XRHeader.TypeSpecific = TypeSpecificField(b.T & 0x0F) - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *LossRLEReportBlock) unpackBlockHeader() { @@ -165,7 +168,7 @@ func (b *LossRLEReportBlock) unpackBlockHeader() { } // DuplicateRLEReportBlock is used to report information about packet -// duplication, as described in RFC 3611, section 4.1 +// duplication, as described in RFC 3611, section 4.1. type DuplicateRLEReportBlock rleReportBlock // DestinationSSRC returns an array of SSRC values that this report block refers to. @@ -176,7 +179,7 @@ func (b *DuplicateRLEReportBlock) DestinationSSRC() []uint32 { func (b *DuplicateRLEReportBlock) setupBlockHeader() { b.XRHeader.BlockType = DuplicateRLEReportBlockType b.XRHeader.TypeSpecific = TypeSpecificField(b.T & 0x0F) - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *DuplicateRLEReportBlock) unpackBlockHeader() { @@ -186,7 +189,7 @@ func (b *DuplicateRLEReportBlock) unpackBlockHeader() { // ChunkType enumerates the three kinds of chunks described in RFC 3611 section 4.1. type ChunkType uint8 -// These are the valid values that ChunkType can assume +// These are the valid values that ChunkType can assume. const ( RunLengthChunkType = 0 BitVectorChunkType = 1 @@ -197,21 +200,24 @@ func (c Chunk) String() string { switch c.Type() { case RunLengthChunkType: runType, _ := c.RunType() + return fmt.Sprintf("[RunLength type=%d, length=%d]", runType, c.Value()) case BitVectorChunkType: return fmt.Sprintf("[BitVector 0b%015b]", c.Value()) case TerminatingNullChunkType: return "[TerminatingNull]" } + return fmt.Sprintf("[0x%X]", uint16(c)) } -// Type returns the ChunkType that this Chunk represents +// Type returns the ChunkType that this Chunk represents. func (c Chunk) Type() ChunkType { if c == 0 { return TerminatingNullChunkType } - return ChunkType(c >> 15) + + return ChunkType(c >> 15) //nolint:gosec // G115 } // RunType returns the RunType that this Chunk represents. It is @@ -220,10 +226,11 @@ func (c Chunk) RunType() (uint, error) { if c.Type() != RunLengthChunkType { return 0, errWrongChunkType } + return uint((c >> 14) & 0x01), nil } -// Value returns the value represented in this Chunk +// Value returns the value represented in this Chunk. func (c Chunk) Value() uint { switch c.Type() { case RunLengthChunkType: @@ -233,6 +240,7 @@ func (c Chunk) Value() uint { case TerminatingNullChunkType: return 0 } + return uint(c) } @@ -257,6 +265,7 @@ func (c Chunk) Value() uint { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | Receipt time of packet (end_seq - 1) mod 65536 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type PacketReceiptTimesReportBlock struct { XRHeader T uint8 `encoding:"omit"` @@ -274,7 +283,7 @@ func (b *PacketReceiptTimesReportBlock) DestinationSSRC() []uint32 { func (b *PacketReceiptTimesReportBlock) setupBlockHeader() { b.XRHeader.BlockType = PacketReceiptTimesReportBlockType b.XRHeader.TypeSpecific = TypeSpecificField(b.T & 0x0F) - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *PacketReceiptTimesReportBlock) unpackBlockHeader() { @@ -294,6 +303,7 @@ func (b *PacketReceiptTimesReportBlock) unpackBlockHeader() { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | NTP timestamp, least significant word | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type ReceiverReferenceTimeReportBlock struct { XRHeader NTPTimestamp uint64 @@ -307,7 +317,7 @@ func (b *ReceiverReferenceTimeReportBlock) DestinationSSRC() []uint32 { func (b *ReceiverReferenceTimeReportBlock) setupBlockHeader() { b.XRHeader.BlockType = ReceiverReferenceTimeReportBlockType b.XRHeader.TypeSpecific = 0 - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *ReceiverReferenceTimeReportBlock) unpackBlockHeader() { @@ -332,6 +342,7 @@ func (b *ReceiverReferenceTimeReportBlock) unpackBlockHeader() { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block // : ... : 2 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// . type DLRRReportBlock struct { XRHeader Reports []DLRRReport @@ -350,13 +361,14 @@ func (b *DLRRReportBlock) DestinationSSRC() []uint32 { for i, r := range b.Reports { ssrc[i] = r.SSRC } + return ssrc } func (b *DLRRReportBlock) setupBlockHeader() { b.XRHeader.BlockType = DLRRReportBlockType b.XRHeader.TypeSpecific = 0 - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *DLRRReportBlock) unpackBlockHeader() { @@ -389,6 +401,7 @@ func (b *DLRRReportBlock) unpackBlockHeader() { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | min_ttl_or_hl | max_ttl_or_hl |mean_ttl_or_hl | dev_ttl_or_hl | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type StatisticsSummaryReportBlock struct { XRHeader LossReports bool `encoding:"omit"` @@ -411,10 +424,10 @@ type StatisticsSummaryReportBlock struct { } // TTLorHopLimitType encodes values for the ToH field in -// a StatisticsSummaryReportBlock +// a StatisticsSummaryReportBlock. type TTLorHopLimitType uint8 -// Values for TTLorHopLimitType +// Values for TTLorHopLimitType. const ( ToHMissing = 0 ToHIPv4 = 1 @@ -430,6 +443,7 @@ func (t TTLorHopLimitType) String() string { case ToHIPv6: return "[ToH = IPv6]" } + return "[ToH Flag is Invalid]" } @@ -451,7 +465,7 @@ func (b *StatisticsSummaryReportBlock) setupBlockHeader() { b.XRHeader.TypeSpecific |= 0x20 } b.XRHeader.TypeSpecific |= TypeSpecificField((b.TTLorHopLimit & 0x03) << 3) - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *StatisticsSummaryReportBlock) unpackBlockHeader() { @@ -486,6 +500,7 @@ func (b *StatisticsSummaryReportBlock) unpackBlockHeader() { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | JB maximum | JB abs max | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type VoIPMetricsReportBlock struct { XRHeader SSRC uint32 `fmt:"0x%X"` @@ -520,7 +535,7 @@ func (b *VoIPMetricsReportBlock) DestinationSSRC() []uint32 { func (b *VoIPMetricsReportBlock) setupBlockHeader() { b.XRHeader.BlockType = VoIPMetricsReportBlockType b.XRHeader.TypeSpecific = 0 - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *VoIPMetricsReportBlock) unpackBlockHeader() { @@ -539,18 +554,18 @@ func (b *UnknownReportBlock) DestinationSSRC() []uint32 { } func (b *UnknownReportBlock) setupBlockHeader() { - b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) + b.XRHeader.BlockLength = uint16(wireSize(b)/4 - 1) //nolint:gosec // G115 } func (b *UnknownReportBlock) unpackBlockHeader() { } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (x ExtendedReport) MarshalSize() int { return wireSize(x) } -// Marshal encodes the ExtendedReport in binary +// Marshal encodes the ExtendedReport in binary. func (x ExtendedReport) Marshal() ([]byte, error) { for _, p := range x.Reports { p.setupBlockHeader() @@ -561,7 +576,7 @@ func (x ExtendedReport) Marshal() ([]byte, error) { // RTCP Header header := Header{ Type: TypeExtendedReport, - Length: uint16(length / 4), + Length: uint16(length / 4), //nolint:gosec // G115 } headerBuffer, err := header.Marshal() if err != nil { @@ -584,7 +599,9 @@ func (x ExtendedReport) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the ExtendedReport from binary +// Unmarshal decodes the ExtendedReport from binary. +// +//nolint:cyclop func (x *ExtendedReport) Unmarshal(b []byte) error { var header Header if err := header.Unmarshal(b); err != nil { @@ -651,6 +668,7 @@ func (x *ExtendedReport) DestinationSSRC() []uint32 { for _, p := range x.Reports { ssrc = append(ssrc, p.DestinationSSRC()...) } + return ssrc } diff --git a/extended_report_test.go b/extended_report_test.go index 1004a21..c709817 100644 --- a/extended_report_test.go +++ b/extended_report_test.go @@ -9,10 +9,10 @@ import ( "testing" ) -// Assert that ExtendedReport is a Packet +// Assert that ExtendedReport is a Packet. var _ Packet = (*ExtendedReport)(nil) -// Assert that all the extended report blocks implement the interface +// Assert that all the extended report blocks implement the interface. var ( _ ReportBlock = (*LossRLEReportBlock)(nil) _ ReportBlock = (*DuplicateRLEReportBlock)(nil) @@ -254,13 +254,13 @@ func TestDecode(t *testing.T) { p.setupBlockHeader() } - p := new(ExtendedReport) - err := p.Unmarshal(encoded) + report := new(ExtendedReport) + err := report.Unmarshal(encoded) if err != nil { t.Fatalf("Error unmarshaling packet: %v", err) } - if !reflect.DeepEqual(p, expected) { + if !reflect.DeepEqual(report, expected) { t.Errorf("(deep equal) Decoded packet does not match expected packet") } @@ -269,13 +269,13 @@ func TestDecode(t *testing.T) { t.Fatal("Failed to cast") } - if p.String() != pktStringer.String() { + if report.String() != pktStringer.String() { t.Errorf("(string compare) Decoded packet does not match expected packet") } var includeSenderSSRC bool - for _, ssrc := range p.DestinationSSRC() { - if ssrc == p.SenderSSRC { + for _, ssrc := range report.DestinationSSRC() { + if ssrc == report.SenderSSRC { includeSenderSSRC = true } } diff --git a/full_intra_request.go b/full_intra_request.go index 7c67c50..0d93c5c 100644 --- a/full_intra_request.go +++ b/full_intra_request.go @@ -30,7 +30,7 @@ const ( var _ Packet = (*FullIntraRequest)(nil) -// Marshal encodes the FullIntraRequest +// Marshal encodes the FullIntraRequest. func (p FullIntraRequest) Marshal() ([]byte, error) { rawPacket := make([]byte, firOffset+(len(p.FIR)*8)) binary.BigEndian.PutUint32(rawPacket, p.SenderSSRC) @@ -48,38 +48,39 @@ func (p FullIntraRequest) Marshal() ([]byte, error) { return append(hData, rawPacket...), nil } -// Unmarshal decodes the TransportLayerNack +// Unmarshal decodes the TransportLayerNack. func (p *FullIntraRequest) Unmarshal(rawPacket []byte) error { if len(rawPacket) < (headerLength + ssrcLength) { return errPacketTooShort } - var h Header - if err := h.Unmarshal(rawPacket); err != nil { + var header Header + if err := header.Unmarshal(rawPacket); err != nil { return err } - if len(rawPacket) < (headerLength + int(4*h.Length)) { + if len(rawPacket) < (headerLength + int(4*header.Length)) { return errPacketTooShort } - if h.Type != TypePayloadSpecificFeedback || h.Count != FormatFIR { + if header.Type != TypePayloadSpecificFeedback || header.Count != FormatFIR { return errWrongType } // The FCI field MUST contain one or more FIR entries - if 4*h.Length-firOffset <= 0 || (4*h.Length)%8 != 0 { + if 4*header.Length-firOffset <= 0 || (4*header.Length)%8 != 0 { return errBadLength } p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) - for i := headerLength + firOffset; i < (headerLength + int(h.Length*4)); i += 8 { + for i := headerLength + firOffset; i < (headerLength + int(header.Length*4)); i += 8 { p.FIR = append(p.FIR, FIREntry{ binary.BigEndian.Uint32(rawPacket[i:]), rawPacket[i+4], }) } + return nil } @@ -88,11 +89,11 @@ func (p *FullIntraRequest) Header() Header { return Header{ Count: FormatFIR, Type: TypePayloadSpecificFeedback, - Length: uint16((p.MarshalSize() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), //nolint:gosec // G115 } } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (p *FullIntraRequest) MarshalSize() int { return headerLength + firOffset + len(p.FIR)*8 } @@ -103,6 +104,7 @@ func (p *FullIntraRequest) String() string { for _, e := range p.FIR { out += fmt.Sprintf(" (%x %v)", e.SSRC, e.SequenceNumber) } + return out } @@ -112,5 +114,6 @@ func (p *FullIntraRequest) DestinationSSRC() []uint32 { for _, entry := range p.FIR { ssrcs = append(ssrcs, entry.SSRC) } + return ssrcs } diff --git a/goodbye.go b/goodbye.go index f87731c..c647743 100644 --- a/goodbye.go +++ b/goodbye.go @@ -16,7 +16,7 @@ type Goodbye struct { Reason string } -// Marshal encodes the Goodbye packet in binary +// Marshal encodes the Goodbye packet in binary. func (g Goodbye) Marshal() ([]byte, error) { /* * 0 1 2 3 @@ -51,7 +51,7 @@ func (g Goodbye) Marshal() ([]byte, error) { } reasonOffset := len(g.Sources) * ssrcLength - packetBody[reasonOffset] = uint8(len(reason)) + packetBody[reasonOffset] = uint8(len(reason)) //nolint:gosec // G115 copy(packetBody[reasonOffset+1:], reason) } @@ -64,7 +64,7 @@ func (g Goodbye) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the Goodbye packet from binary +// Unmarshal decodes the Goodbye packet from binary. func (g *Goodbye) Unmarshal(rawPacket []byte) error { /* * 0 1 2 3 @@ -124,13 +124,13 @@ func (g *Goodbye) Unmarshal(rawPacket []byte) error { func (g *Goodbye) Header() Header { return Header{ Padding: false, - Count: uint8(len(g.Sources)), + Count: uint8(len(g.Sources)), //nolint:gosec //G115 Type: TypeGoodbye, - Length: uint16((g.MarshalSize() / 4) - 1), + Length: uint16((g.MarshalSize() / 4) - 1), //nolint:gosec //G115 } } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (g *Goodbye) MarshalSize() int { srcsLength := len(g.Sources) * ssrcLength // reason is optional @@ -149,6 +149,7 @@ func (g *Goodbye) MarshalSize() int { func (g *Goodbye) DestinationSSRC() []uint32 { out := make([]uint32, len(g.Sources)) copy(out, g.Sources) + return out } diff --git a/header.go b/header.go index 534c82f..f392e14 100644 --- a/header.go +++ b/header.go @@ -7,10 +7,12 @@ import ( "encoding/binary" ) -// PacketType specifies the type of an RTCP packet +// PacketType specifies the type of an RTCP packet. type PacketType uint8 -// RTCP packet types registered with IANA. See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4 +// RTCP packet types registered with IANA. See: +// +// https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4 const ( TypeSenderReport PacketType = 200 // RFC 3550, 6.4.1 TypeReceiverReport PacketType = 201 // RFC 3550, 6.4.2 @@ -23,7 +25,8 @@ const ( ) -// Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here +// Transport and Payload specific feedback messages overload the count field to act as a message type. +// those are listed here. const ( FormatSLI uint8 = 2 FormatPLI uint8 = 1 @@ -62,7 +65,7 @@ func (p PacketType) String() string { const rtpVersion = 2 -// A Header is the common header shared by all RTCP packets +// A Header is the common header shared by all RTCP packets. type Header struct { // If the padding bit is set, this individual RTCP packet contains // some additional padding octets at the end which are not part of @@ -88,7 +91,7 @@ const ( countMax = (1 << 5) - 1 ) -// Marshal encodes the Header in binary +// Marshal encodes the Header in binary. func (h Header) Marshal() ([]byte, error) { /* * 0 1 2 3 @@ -117,7 +120,7 @@ func (h Header) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the Header from binary +// Unmarshal decodes the Header from binary. func (h *Header) Unmarshal(rawPacket []byte) error { if len(rawPacket) < headerLength { return errPacketTooShort diff --git a/packet.go b/packet.go index fc3c9a3..637d9cd 100644 --- a/packet.go +++ b/packet.go @@ -3,7 +3,8 @@ package rtcp -// Packet represents an RTCP packet, a protocol used for out-of-band statistics and control information for an RTP session +// Packet represents an RTCP packet, a protocol used for out-of-band statistics +// and control information for an RTP session. type Packet interface { // DestinationSSRC returns an array of SSRC values that this packet refers to. DestinationSSRC() []uint32 @@ -41,7 +42,7 @@ func Unmarshal(rawData []byte) ([]Packet, error) { } } -// Marshal takes an array of Packets and serializes them to a single buffer +// Marshal takes an array of Packets and serializes them to a single buffer. func Marshal(packets []Packet) ([]byte, error) { out := make([]byte, 0) for _, p := range packets { @@ -51,26 +52,29 @@ func Marshal(packets []Packet) ([]byte, error) { } out = append(out, data...) } + return out, nil } // unmarshal is a factory which pulls the first RTCP packet from a bytestream, // and returns it's parsed representation, and the amount of data that was processed. +// +//nolint:cyclop func unmarshal(rawData []byte) (packet Packet, bytesprocessed int, err error) { - var h Header + var header Header - err = h.Unmarshal(rawData) + err = header.Unmarshal(rawData) if err != nil { return nil, 0, err } - bytesprocessed = int(h.Length+1) * 4 + bytesprocessed = int(header.Length+1) * 4 if bytesprocessed > len(rawData) { return nil, 0, errPacketTooShort } inPacket := rawData[:bytesprocessed] - switch h.Type { + switch header.Type { case TypeSenderReport: packet = new(SenderReport) @@ -84,7 +88,7 @@ func unmarshal(rawData []byte) (packet Packet, bytesprocessed int, err error) { packet = new(Goodbye) case TypeTransportSpecificFeedback: - switch h.Count { + switch header.Count { case FormatTLN: packet = new(TransportLayerNack) case FormatRRR: @@ -98,7 +102,7 @@ func unmarshal(rawData []byte) (packet Packet, bytesprocessed int, err error) { } case TypePayloadSpecificFeedback: - switch h.Count { + switch header.Count { case FormatPLI: packet = new(PictureLossIndication) case FormatSLI: diff --git a/packet_buffer.go b/packet_buffer.go index f6c7eaa..31c55b0 100644 --- a/packet_buffer.go +++ b/packet_buffer.go @@ -46,7 +46,9 @@ const omit = "omit" // PacketBuffer is initialized with. This function will // modify the PacketBuffer.bytes slice to exclude those // bytes that have been written into. -func (b *packetBuffer) write(v interface{}) error { //nolint:gocognit +// +//nolint:gocognit,cyclop +func (b *packetBuffer) write(v interface{}) error { value := reflect.ValueOf(v) // Indirect is safe to call on non-pointers, and @@ -67,7 +69,7 @@ func (b *packetBuffer) write(v interface{}) error { //nolint:gocognit return errWrongMarshalSize } if value.CanInterface() { - binary.BigEndian.PutUint16(b.bytes, uint16(value.Uint())) + binary.BigEndian.PutUint16(b.bytes, uint16(value.Uint())) //nolint:gosec // G115 } b.bytes = b.bytes[2:] case reflect.Uint32: @@ -75,7 +77,7 @@ func (b *packetBuffer) write(v interface{}) error { //nolint:gocognit return errWrongMarshalSize } if value.CanInterface() { - binary.BigEndian.PutUint32(b.bytes, uint32(value.Uint())) + binary.BigEndian.PutUint32(b.bytes, uint32(value.Uint())) //nolint:gosec // G115 } b.bytes = b.bytes[4:] case reflect.Uint64: @@ -117,6 +119,7 @@ func (b *packetBuffer) write(v interface{}) error { //nolint:gocognit default: return errBadStructMemberType } + return nil } @@ -124,7 +127,9 @@ func (b *packetBuffer) write(v interface{}) error { //nolint:gocognit // the structure passed as a parameter. This function will // modify the PacketBuffer.bytes slice to exclude those // bytes that have already been read. -func (b *packetBuffer) read(v interface{}) error { //nolint:gocognit +// +//nolint:gocognit,cyclop +func (b *packetBuffer) read(v interface{}) error { ptr := reflect.ValueOf(v) if ptr.Kind() != reflect.Ptr { return errBadReadParameter @@ -187,7 +192,10 @@ func (b *packetBuffer) read(v interface{}) error { //nolint:gocognit } if value.Field(i).CanInterface() { field := value.Field(i) - newFieldPtr := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())) //nolint:gosec // This is the only way to get a typed pointer to a structure's field + newFieldPtr := reflect.NewAt( + //nolint:gosec // This is the only way to get a typed pointer to a structure's field + field.Type(), unsafe.Pointer(field.UnsafeAddr()), + ) if err := b.read(newFieldPtr.Interface()); err != nil { return err } @@ -203,24 +211,27 @@ func (b *packetBuffer) read(v interface{}) error { //nolint:gocognit default: return errBadStructMemberType } + return nil } // Consumes `size` bytes and returns them as an -// independent PacketBuffer +// independent PacketBuffer. func (b *packetBuffer) split(size int) packetBuffer { if size > len(b.bytes) { size = len(b.bytes) } newBuffer := packetBuffer{bytes: b.bytes[:size]} + b.bytes = b.bytes[size:] + return newBuffer } // Returns the size that a structure will encode into. // This fuction doesn't check that Write() will succeed, // and may return unexpectedly large results for those -// structures that Write() will fail on +// structures that Write() will fail on. func wireSize(v interface{}) int { value := reflect.ValueOf(v) // Indirect is safe to call on non-pointers, and @@ -254,5 +265,6 @@ func wireSize(v interface{}) int { default: size = int(value.Type().Size()) } + return size } diff --git a/packet_buffer_test.go b/packet_buffer_test.go index 21a2c9e..324d71c 100644 --- a/packet_buffer_test.go +++ b/packet_buffer_test.go @@ -16,7 +16,7 @@ func TestWrite(t *testing.T) { SubB []uint8 } - s := struct { + structure := struct { A uint8 Z uint32 `encoding:"omit"` B uint16 @@ -48,14 +48,14 @@ func TestWrite(t *testing.T) { 0x00, 0x00, 0x00, 0x01, 1, 2, 3, 4, 0x00, 0x00, 0x00, 0x02, 5, 6, 7, 8, } - size := wireSize(s) + size := wireSize(structure) if size != len(expected) { t.Fatalf("wireSize() returned unexpected value. Expected %v, got %v", len(expected), size) } raw := make([]byte, len(expected)) buffer := packetBuffer{bytes: raw} - err := buffer.write(s) + err := buffer.write(structure) if err != nil { t.Fatalf("Serialization failed. Err = %v", err) } @@ -66,7 +66,7 @@ func TestWrite(t *testing.T) { // Check for overflow raw = make([]byte, len(expected)-1) buffer = packetBuffer{bytes: raw} - err = buffer.write(s) + err = buffer.write(structure) if !errors.Is(err, errWrongMarshalSize) { t.Fatalf("Serialization failed. Err = %v", err) } diff --git a/packet_stringifier.go b/packet_stringifier.go index dd7c01f..aadbc00 100644 --- a/packet_stringifier.go +++ b/packet_stringifier.go @@ -32,10 +32,12 @@ baseline implementation that works well in the majority of cases. */ func stringify(p Packet) string { value := reflect.Indirect(reflect.ValueOf(p)) + return formatField(value.Type().String(), "", p, "") } -func formatField(name string, format string, f interface{}, indent string) string { //nolint:gocognit +//nolint:gocognit,cyclop +func formatField(name string, format string, f interface{}, indent string) string { out := indent value := reflect.ValueOf(f) @@ -59,6 +61,7 @@ func formatField(name string, format string, f interface{}, indent string) strin // uses it) if stringMethod := value.MethodByName("String"); !isPacket && stringMethod.IsValid() { out += fmt.Sprintf("%s: %s\n", name, stringMethod.Call([]reflect.Value{})) + return out } @@ -77,7 +80,8 @@ func formatField(name string, format string, f interface{}, indent string) strin case reflect.Slice: childKind := value.Type().Elem().Kind() _, hasStringMethod := value.Type().Elem().MethodByName("String") - if hasStringMethod || childKind == reflect.Struct || childKind == reflect.Ptr || childKind == reflect.Interface || childKind == reflect.Slice { + if hasStringMethod || childKind == reflect.Struct || childKind == reflect.Ptr || + childKind == reflect.Interface || childKind == reflect.Slice { out += fmt.Sprintf("%s:\n", name) for i := 0; i < value.Len(); i++ { childName := fmt.Sprint(i) @@ -91,6 +95,7 @@ func formatField(name string, format string, f interface{}, indent string) strin out += formatField(childName, format, value.Index(i).Interface(), indent+"\t") } } + return out } @@ -102,5 +107,6 @@ func formatField(name string, format string, f interface{}, indent string) strin out += fmt.Sprintf("%s: "+format+"\n", name, value.Interface()) } } + return out } diff --git a/packet_stringifier_test.go b/packet_stringifier_test.go index 6628af0..527cd87 100644 --- a/packet_stringifier_test.go +++ b/packet_stringifier_test.go @@ -7,6 +7,7 @@ import ( "testing" ) +//nolint:maintidx func TestPrint(t *testing.T) { type Tests struct { packet Packet @@ -380,7 +381,8 @@ func TestPrint(t *testing.T) { "\t\t\tJitter: 273\n" + "\t\t\tLastSenderReport: 166945842\n" + "\t\t\tDelay: 150137\n" + - "\tProfileExtensions: [129 202 0 6 43 126 192 197 1 16 76 99 73 102 122 88 111 110 68 111 114 100 83 101 87 54 0 0]\n", + "\tProfileExtensions:" + + "[129 202 0 6 43 126 192 197 1 16 76 99 73 102 122 88 111 110 68 111 114 100 83 101 87 54 0 0]\n", }, { &SliceLossIndication{ diff --git a/packet_test.go b/packet_test.go index 6eb0a83..f188a74 100644 --- a/packet_test.go +++ b/packet_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" ) -// An RTCP packet from a packet dump +// An RTCP packet from a packet dump. func realPacket() []byte { return []byte{ // Receiver Report (offset=0) diff --git a/picture_loss_indication.go b/picture_loss_indication.go index 56a7de2..17379cd 100644 --- a/picture_loss_indication.go +++ b/picture_loss_indication.go @@ -8,7 +8,8 @@ import ( "fmt" ) -// The PictureLossIndication packet informs the encoder about the loss of an undefined amount of coded video data belonging to one or more pictures +// The PictureLossIndication packet informs the encoder about the loss of an undefined amount of +// coded video data belonging to one or more pictures. type PictureLossIndication struct { // SSRC of sender SenderSSRC uint32 @@ -21,7 +22,7 @@ const ( pliLength = 2 ) -// Marshal encodes the PictureLossIndication in binary +// Marshal encodes the PictureLossIndication in binary. func (p PictureLossIndication) Marshal() ([]byte, error) { /* * PLI does not require parameters. Therefore, the length field MUST be @@ -49,7 +50,7 @@ func (p PictureLossIndication) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the PictureLossIndication from binary +// Unmarshal decodes the PictureLossIndication from binary. func (p *PictureLossIndication) Unmarshal(rawPacket []byte) error { if len(rawPacket) < (headerLength + (ssrcLength * 2)) { return errPacketTooShort @@ -66,6 +67,7 @@ func (p *PictureLossIndication) Unmarshal(rawPacket []byte) error { p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) + return nil } @@ -78,7 +80,7 @@ func (p *PictureLossIndication) Header() Header { } } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (p *PictureLossIndication) MarshalSize() int { return headerLength + ssrcLength*2 } diff --git a/rapid_resynchronization_request.go b/rapid_resynchronization_request.go index dc67d49..d422033 100644 --- a/rapid_resynchronization_request.go +++ b/rapid_resynchronization_request.go @@ -8,7 +8,8 @@ import ( "fmt" ) -// The RapidResynchronizationRequest packet informs the encoder about the loss of an undefined amount of coded video data belonging to one or more pictures +// The RapidResynchronizationRequest packet informs the encoder about the loss of +// an undefined amount of coded video data belonging to one or more pictures. type RapidResynchronizationRequest struct { // SSRC of sender SenderSSRC uint32 @@ -27,7 +28,7 @@ const ( rrrMediaOffset = 4 ) -// Marshal encodes the RapidResynchronizationRequest in binary +// Marshal encodes the RapidResynchronizationRequest in binary. func (p RapidResynchronizationRequest) Marshal() ([]byte, error) { /* * RRR does not require parameters. Therefore, the length field MUST be @@ -50,7 +51,7 @@ func (p RapidResynchronizationRequest) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the RapidResynchronizationRequest from binary +// Unmarshal decodes the RapidResynchronizationRequest from binary. func (p *RapidResynchronizationRequest) Unmarshal(rawPacket []byte) error { if len(rawPacket) < (headerLength + (ssrcLength * 2)) { return errPacketTooShort @@ -67,10 +68,11 @@ func (p *RapidResynchronizationRequest) Unmarshal(rawPacket []byte) error { p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) + return nil } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (p *RapidResynchronizationRequest) MarshalSize() int { return headerLength + rrrHeaderLength } diff --git a/raw_packet.go b/raw_packet.go index eafb034..71ac152 100644 --- a/raw_packet.go +++ b/raw_packet.go @@ -22,6 +22,7 @@ func (r *RawPacket) Unmarshal(b []byte) error { *r = b var h Header + return h.Unmarshal(b) } @@ -31,6 +32,7 @@ func (r RawPacket) Header() Header { if err := h.Unmarshal(r); err != nil { return Header{} } + return h } @@ -41,10 +43,11 @@ func (r *RawPacket) DestinationSSRC() []uint32 { func (r RawPacket) String() string { out := fmt.Sprintf("RawPacket: %v", ([]byte)(r)) + return out } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (r RawPacket) MarshalSize() int { return len(r) } diff --git a/receiver_estimated_maximum_bitrate.go b/receiver_estimated_maximum_bitrate.go index 7be57e6..cb6cdae 100644 --- a/receiver_estimated_maximum_bitrate.go +++ b/receiver_estimated_maximum_bitrate.go @@ -42,7 +42,7 @@ func (p ReceiverEstimatedMaximumBitrate) Marshal() (buf []byte, err error) { return buf, nil } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (p ReceiverEstimatedMaximumBitrate) MarshalSize() int { return 20 + 4*len(p.SSRCs) } @@ -78,7 +78,7 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error buf[1] = 206 // Length of this packet in 32-bit words minus one. - length := uint16((p.MarshalSize() / 4) - 1) + length := uint16((p.MarshalSize() / 4) - 1) //nolint:gosec // G115 binary.BigEndian.PutUint16(buf[2:4], length) binary.BigEndian.PutUint32(buf[4:8], p.SenderSSRC) @@ -133,6 +133,8 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error } // Unmarshal reads a REMB packet from the given byte slice. +// +//nolint:cyclop func (p *ReceiverEstimatedMaximumBitrate) Unmarshal(buf []byte) (err error) { const mantissamax = 0x7FFFFF /* @@ -255,7 +257,7 @@ func (p *ReceiverEstimatedMaximumBitrate) Header() Header { return Header{ Count: FormatREMB, Type: TypePayloadSpecificFeedback, - Length: uint16((p.MarshalSize() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), //nolint:gosec // G115 } } diff --git a/receiver_report.go b/receiver_report.go index e917702..84c682d 100644 --- a/receiver_report.go +++ b/receiver_report.go @@ -8,7 +8,7 @@ import ( "fmt" ) -// A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream +// A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream. type ReceiverReport struct { // The synchronization source identifier for the originator of this RR packet. SSRC uint32 @@ -28,7 +28,7 @@ const ( rrReportOffset = rrSSRCOffset + ssrcLength ) -// Marshal encodes the ReceiverReport in binary +// Marshal encodes the ReceiverReport in binary. func (r ReceiverReport) Marshal() ([]byte, error) { /* * 0 1 2 3 @@ -82,10 +82,10 @@ func (r ReceiverReport) Marshal() ([]byte, error) { // if the length of the profile extensions isn't devisible // by 4, we need to pad the end. for (len(pe) & 0x3) != 0 { - pe = append(pe, 0) + pe = append(pe, 0) //nolint:makezero } - rawPacket = append(rawPacket, pe...) + rawPacket = append(rawPacket, pe...) //nolint:makezero hData, err := r.Header().Marshal() if err != nil { @@ -96,7 +96,7 @@ func (r ReceiverReport) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the ReceiverReport from binary +// Unmarshal decodes the ReceiverReport from binary. func (r *ReceiverReport) Unmarshal(rawPacket []byte) error { /* * 0 1 2 3 @@ -130,18 +130,18 @@ func (r *ReceiverReport) Unmarshal(rawPacket []byte) error { return errPacketTooShort } - var h Header - if err := h.Unmarshal(rawPacket); err != nil { + var header Header + if err := header.Unmarshal(rawPacket); err != nil { return err } - if h.Type != TypeReceiverReport { + if header.Type != TypeReceiverReport { return errWrongType } r.SSRC = binary.BigEndian.Uint32(rawPacket[rrSSRCOffset:]) - for i := rrReportOffset; i < len(rawPacket) && len(r.Reports) < int(h.Count); i += receptionReportLength { + for i := rrReportOffset; i < len(rawPacket) && len(r.Reports) < int(header.Count); i += receptionReportLength { var rr ReceptionReport if err := rr.Unmarshal(rawPacket[i:]); err != nil { return err @@ -150,28 +150,30 @@ func (r *ReceiverReport) Unmarshal(rawPacket []byte) error { } r.ProfileExtensions = rawPacket[rrReportOffset+(len(r.Reports)*receptionReportLength):] - if uint8(len(r.Reports)) != h.Count { + //nolint:gosec // G115 + if uint8(len(r.Reports)) != header.Count { return errInvalidHeader } return nil } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (r *ReceiverReport) MarshalSize() int { repsLength := 0 for _, rep := range r.Reports { repsLength += rep.len() } + return headerLength + ssrcLength + repsLength } // Header returns the Header associated with this packet. func (r *ReceiverReport) Header() Header { return Header{ - Count: uint8(len(r.Reports)), + Count: uint8(len(r.Reports)), //nolint:gosec // G115 Type: TypeReceiverReport, - Length: uint16((r.MarshalSize()/4)-1) + uint16(getPadding(len(r.ProfileExtensions))), + Length: uint16((r.MarshalSize()/4)-1) + uint16(getPadding(len(r.ProfileExtensions))), //nolint:gosec // G115 } } @@ -181,6 +183,7 @@ func (r *ReceiverReport) DestinationSSRC() []uint32 { for i, v := range r.Reports { out[i] = v.SSRC } + return out } @@ -191,5 +194,6 @@ func (r ReceiverReport) String() string { out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) } out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions) + return out } diff --git a/receiver_report_test.go b/receiver_report_test.go index d6b0b9b..dddbc27 100644 --- a/receiver_report_test.go +++ b/receiver_report_test.go @@ -184,6 +184,7 @@ func tooManyReports() []ReceptionReport { Delay: 7, }) } + return tooManyReports } diff --git a/reception_report.go b/reception_report.go index c0b0605..f2b4548 100644 --- a/reception_report.go +++ b/reception_report.go @@ -47,7 +47,7 @@ const ( delayOffset = 20 ) -// Marshal encodes the ReceptionReport in binary +// Marshal encodes the ReceptionReport in binary. func (r ReceptionReport) Marshal() ([]byte, error) { /* * 0 1 2 3 @@ -90,7 +90,7 @@ func (r ReceptionReport) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the ReceptionReport from binary +// Unmarshal decodes the ReceptionReport from binary. func (r *ReceptionReport) Unmarshal(rawPacket []byte) error { if len(rawPacket) < receptionReportLength { return errPacketTooShort diff --git a/rfc8888.go b/rfc8888.go index 544c6e3..50b6e6d 100644 --- a/rfc8888.go +++ b/rfc8888.go @@ -45,23 +45,23 @@ var ( errMetricBlockLength = errors.New("feedback report metric blocks must be exactly 2 bytes") ) -// ECN represents the two ECN bits +// ECN represents the two ECN bits. type ECN uint8 const ( //nolint:misspell - // ECNNonECT signals Non ECN-Capable Transport, Non-ECT + // ECNNonECT signals Non ECN-Capable Transport, Non-ECT. ECNNonECT ECN = iota // 00 //nolint:misspell - // ECNECT1 signals ECN Capable Transport, ECT(0) + // ECNECT1 signals ECN Capable Transport, ECT(0). ECNECT1 // 01 //nolint:misspell - // ECNECT0 signals ECN Capable Transport, ECT(1) + // ECNECT0 signals ECN Capable Transport, ECT(1). ECNECT0 // 10 - // ECNCE signals ECN Congestion Encountered, CE + // ECNCE signals ECN Congestion Encountered, CE. ECNCE // 11 ) @@ -89,20 +89,22 @@ func (b CCFeedbackReport) DestinationSSRC() []uint32 { for i, block := range b.ReportBlocks { ssrcs[i] = block.MediaSSRC } + return ssrcs } -// Len returns the length of the report in bytes +// Len returns the length of the report in bytes. func (b *CCFeedbackReport) Len() int { return b.MarshalSize() } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (b *CCFeedbackReport) MarshalSize() int { n := 0 for _, block := range b.ReportBlocks { n += block.len() } + return reportBlockOffset + n + reportTimestampLength } @@ -112,11 +114,11 @@ func (b *CCFeedbackReport) Header() Header { Padding: false, Count: FormatCCFB, Type: TypeTransportSpecificFeedback, - Length: uint16(b.MarshalSize()/4 - 1), + Length: uint16(b.MarshalSize()/4 - 1), //nolint:gosec // G115 } } -// Marshal encodes the Congestion Control Feedback Report in binary +// Marshal encodes the Congestion Control Feedback Report in binary. func (b CCFeedbackReport) Marshal() ([]byte, error) { header := b.Header() headerBuf, err := header.Marshal() @@ -138,6 +140,7 @@ func (b CCFeedbackReport) Marshal() ([]byte, error) { } binary.BigEndian.PutUint32(buf[offset:], b.ReportTimestamp) + return buf, nil } @@ -150,10 +153,11 @@ func (b CCFeedbackReport) String() string { out += fmt.Sprintf("%v ", report) } out += "\n" + return out } -// Unmarshal decodes the Congestion Control Feedback Report from binary +// Unmarshal decodes the Congestion Control Feedback Report from binary. func (b *CCFeedbackReport) Unmarshal(rawPacket []byte) error { if len(rawPacket) < headerLength+ssrcLength+reportTimestampLength { return errPacketTooShort @@ -195,7 +199,7 @@ const ( maxMetricBlocks = 16384 ) -// CCFeedbackReportBlock is a Feedback Report Block +// CCFeedbackReportBlock is a Feedback Report Block. type CCFeedbackReportBlock struct { // SSRC of the RTP stream on which this block is reporting MediaSSRC uint32 @@ -203,12 +207,13 @@ type CCFeedbackReportBlock struct { MetricBlocks []CCFeedbackMetricBlock } -// len returns the length of the report block in bytes +// len returns the length of the report block in bytes. func (b *CCFeedbackReportBlock) len() int { n := len(b.MetricBlocks) if n%2 != 0 { n++ } + return reportsOffset + 2*n } @@ -217,13 +222,15 @@ func (b CCFeedbackReportBlock) String() string { out += fmt.Sprintf("\tReport Begin Sequence Nr %d\n", b.BeginSequence) out += fmt.Sprintf("\tReport length %d\n\t", len(b.MetricBlocks)) for i, block := range b.MetricBlocks { + //nolint:gosec // G115 out += fmt.Sprintf("{nr: %d, rx: %v, ts: %v} ", b.BeginSequence+uint16(i), block.Received, block.ArrivalTimeOffset) } out += "\n" + return out } -// marshal encodes the Congestion Control Feedback Report Block in binary +// marshal encodes the Congestion Control Feedback Report Block in binary. func (b CCFeedbackReportBlock) marshal() ([]byte, error) { if len(b.MetricBlocks) > maxMetricBlocks { return nil, errTooManyReports @@ -233,7 +240,7 @@ func (b CCFeedbackReportBlock) marshal() ([]byte, error) { binary.BigEndian.PutUint32(buf[ssrcOffset:], b.MediaSSRC) binary.BigEndian.PutUint16(buf[beginSequenceOffset:], b.BeginSequence) - length := uint16(len(b.MetricBlocks)) + length := uint16(len(b.MetricBlocks)) //nolint:gosec // G115 if length > 0 { length-- } @@ -251,7 +258,7 @@ func (b CCFeedbackReportBlock) marshal() ([]byte, error) { return buf, nil } -// Unmarshal decodes the Congestion Control Feedback Report Block from binary +// Unmarshal decodes the Congestion Control Feedback Report Block from binary. func (b *CCFeedbackReportBlock) unmarshal(rawPacket []byte) error { if len(rawPacket) < reportsOffset { return errReportBlockLength @@ -283,6 +290,7 @@ func (b *CCFeedbackReportBlock) unmarshal(rawPacket []byte) error { } b.MetricBlocks[i] = mb } + return nil } @@ -290,7 +298,7 @@ const ( metricBlockLength = 2 ) -// CCFeedbackMetricBlock is a Feedback Metric Block +// CCFeedbackMetricBlock is a Feedback Metric Block. type CCFeedbackMetricBlock struct { Received bool ECN ECN @@ -299,7 +307,7 @@ type CCFeedbackMetricBlock struct { ArrivalTimeOffset uint16 } -// Marshal encodes the Congestion Control Feedback Metric Block in binary +// Marshal encodes the Congestion Control Feedback Metric Block in binary. func (b CCFeedbackMetricBlock) marshal() ([]byte, error) { buf := make([]byte, 2) r := uint16(0) @@ -320,10 +328,11 @@ func (b CCFeedbackMetricBlock) marshal() ([]byte, error) { } binary.BigEndian.PutUint16(buf, dst) + return buf, nil } -// Unmarshal decodes the Congestion Control Feedback Metric Block from binary +// Unmarshal decodes the Congestion Control Feedback Metric Block from binary. func (b *CCFeedbackMetricBlock) unmarshal(rawPacket []byte) error { if len(rawPacket) != metricBlockLength { return errMetricBlockLength @@ -332,9 +341,11 @@ func (b *CCFeedbackMetricBlock) unmarshal(rawPacket []byte) error { if !b.Received { b.ECN = ECNNonECT b.ArrivalTimeOffset = 0 + return nil } b.ECN = ECN(rawPacket[0] >> 5 & 0x03) b.ArrivalTimeOffset = binary.BigEndian.Uint16(rawPacket) & 0x1FFF + return nil } diff --git a/sender_report.go b/sender_report.go index aaee0ee..0ad8699 100644 --- a/sender_report.go +++ b/sender_report.go @@ -8,7 +8,7 @@ import ( "fmt" ) -// A SenderReport (SR) packet provides reception quality feedback for an RTP stream +// A SenderReport (SR) packet provides reception quality feedback for an RTP stream. type SenderReport struct { // The synchronization source identifier for the originator of this SR packet. SSRC uint32 @@ -56,7 +56,7 @@ const ( srReportOffset = srOctetCountOffset + srOctetCountLength ) -// Marshal encodes the SenderReport in binary +// Marshal encodes the SenderReport in binary. func (r SenderReport) Marshal() ([]byte, error) { /* * 0 1 2 3 @@ -130,7 +130,7 @@ func (r SenderReport) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the SenderReport from binary +// Unmarshal decodes the SenderReport from binary. func (r *SenderReport) Unmarshal(rawPacket []byte) error { /* * 0 1 2 3 @@ -174,12 +174,12 @@ func (r *SenderReport) Unmarshal(rawPacket []byte) error { return errPacketTooShort } - var h Header - if err := h.Unmarshal(rawPacket); err != nil { + var header Header + if err := header.Unmarshal(rawPacket); err != nil { return err } - if h.Type != TypeSenderReport { + if header.Type != TypeSenderReport { return errWrongType } @@ -192,7 +192,7 @@ func (r *SenderReport) Unmarshal(rawPacket []byte) error { r.OctetCount = binary.BigEndian.Uint32(packetBody[srOctetCountOffset:]) offset := srReportOffset - for i := 0; i < int(h.Count); i++ { + for i := 0; i < int(header.Count); i++ { rrEnd := offset + receptionReportLength if rrEnd > len(packetBody) { return errPacketTooShort @@ -211,7 +211,7 @@ func (r *SenderReport) Unmarshal(rawPacket []byte) error { r.ProfileExtensions = packetBody[offset:] } - if uint8(len(r.Reports)) != h.Count { + if uint8(len(r.Reports)) != header.Count { //nolint:gosec // G115 return errInvalidHeader } @@ -225,24 +225,26 @@ func (r *SenderReport) DestinationSSRC() []uint32 { out[i] = v.SSRC } out[len(r.Reports)] = r.SSRC + return out } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (r *SenderReport) MarshalSize() int { repsLength := 0 for _, rep := range r.Reports { repsLength += rep.len() } + return headerLength + srHeaderLength + repsLength + len(r.ProfileExtensions) } // Header returns the Header associated with this packet. func (r *SenderReport) Header() Header { return Header{ - Count: uint8(len(r.Reports)), + Count: uint8(len(r.Reports)), //nolint:gosec // G115 Type: TypeSenderReport, - Length: uint16((r.MarshalSize() / 4) - 1), + Length: uint16((r.MarshalSize() / 4) - 1), //nolint:gosec // G115 } } @@ -258,5 +260,6 @@ func (r SenderReport) String() string { out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber) } out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions) + return out } diff --git a/sender_report_test.go b/sender_report_test.go index 603f80b..3f62d7c 100644 --- a/sender_report_test.go +++ b/sender_report_test.go @@ -193,6 +193,7 @@ func TestSenderReportUnmarshal(t *testing.T) { for _, v := range dstSsrc { if v == sr.SSRC { ssrcFound = true + break } } diff --git a/slice_loss_indication.go b/slice_loss_indication.go index 014fcb7..43e2d80 100644 --- a/slice_loss_indication.go +++ b/slice_loss_indication.go @@ -22,7 +22,7 @@ type SLIEntry struct { Picture uint8 } -// The SliceLossIndication packet informs the encoder about the loss of a picture slice +// The SliceLossIndication packet informs the encoder about the loss of a picture slice. type SliceLossIndication struct { // SSRC of sender SenderSSRC uint32 @@ -38,7 +38,7 @@ const ( sliOffset = 8 ) -// Marshal encodes the SliceLossIndication in binary +// Marshal encodes the SliceLossIndication in binary. func (p SliceLossIndication) Marshal() ([]byte, error) { if len(p.SLI)+sliLength > math.MaxUint8 { return nil, errTooManyReports @@ -61,39 +61,40 @@ func (p SliceLossIndication) Marshal() ([]byte, error) { return append(hData, rawPacket...), nil } -// Unmarshal decodes the SliceLossIndication from binary +// Unmarshal decodes the SliceLossIndication from binary. func (p *SliceLossIndication) Unmarshal(rawPacket []byte) error { if len(rawPacket) < (headerLength + ssrcLength) { return errPacketTooShort } - var h Header - if err := h.Unmarshal(rawPacket); err != nil { + var header Header + if err := header.Unmarshal(rawPacket); err != nil { return err } - if len(rawPacket) < (headerLength + int(4*h.Length)) { + if len(rawPacket) < (headerLength + int(4*header.Length)) { return errPacketTooShort } - if h.Type != TypeTransportSpecificFeedback || h.Count != FormatSLI { + if header.Type != TypeTransportSpecificFeedback || header.Count != FormatSLI { return errWrongType } p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) - for i := headerLength + sliOffset; i < (headerLength + int(h.Length*4)); i += 4 { + for i := headerLength + sliOffset; i < (headerLength + int(header.Length*4)); i += 4 { sli := binary.BigEndian.Uint32(rawPacket[i:]) p.SLI = append(p.SLI, SLIEntry{ - First: uint16((sli >> 19) & 0x1FFF), - Number: uint16((sli >> 6) & 0x1FFF), - Picture: uint8(sli & 0x3F), + First: uint16((sli >> 19) & 0x1FFF), //nolint:gosec // G115 + Number: uint16((sli >> 6) & 0x1FFF), //nolint:gosec // G115 + Picture: uint8(sli & 0x3F), //nolint:gosec // G115 }) } + return nil } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (p *SliceLossIndication) MarshalSize() int { return headerLength + sliOffset + (len(p.SLI) * 4) } @@ -103,7 +104,7 @@ func (p *SliceLossIndication) Header() Header { return Header{ Count: FormatSLI, Type: TypeTransportSpecificFeedback, - Length: uint16((p.MarshalSize() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), //nolint:gosec // G115 } } diff --git a/source_description.go b/source_description.go index fc29d8e..6d6f2a0 100644 --- a/source_description.go +++ b/source_description.go @@ -11,7 +11,9 @@ import ( // SDESType is the item type used in the RTCP SDES control packet. type SDESType uint8 -// RTP SDES item types registered with IANA. See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-5 +// RTP SDES item types registered with IANA. +// See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-5 +// . const ( SDESEnd SDESType = iota // end of SDES list RFC 3550, 6.5 SDESCNAME // canonical name RFC 3550, 6.5.1 @@ -24,6 +26,7 @@ const ( SDESPrivate // private extensions RFC 3550, 6.5.8 (not implemented) ) +//nolint:cyclop func (s SDESType) String() string { switch s { case SDESEnd: @@ -77,7 +80,7 @@ func NewCNAMESourceDescription(ssrc uint32, cname string) *SourceDescription { } } -// Marshal encodes the SourceDescription in binary +// Marshal encodes the SourceDescription in binary. func (s SourceDescription) Marshal() ([]byte, error) { /* * 0 1 2 3 @@ -123,7 +126,7 @@ func (s SourceDescription) Marshal() ([]byte, error) { return rawPacket, nil } -// Unmarshal decodes the SourceDescription from binary +// Unmarshal decodes the SourceDescription from binary. func (s *SourceDescription) Unmarshal(rawPacket []byte) error { /* * 0 1 2 3 @@ -143,12 +146,12 @@ func (s *SourceDescription) Unmarshal(rawPacket []byte) error { * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ */ - var h Header - if err := h.Unmarshal(rawPacket); err != nil { + var header Header + if err := header.Unmarshal(rawPacket); err != nil { return err } - if h.Type != TypeSourceDescription { + if header.Type != TypeSourceDescription { return errWrongType } @@ -162,39 +165,40 @@ func (s *SourceDescription) Unmarshal(rawPacket []byte) error { i += chunk.len() } - if len(s.Chunks) != int(h.Count) { + if len(s.Chunks) != int(header.Count) { return errInvalidHeader } return nil } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (s *SourceDescription) MarshalSize() int { chunksLength := 0 for _, c := range s.Chunks { chunksLength += c.len() } + return headerLength + chunksLength } // Header returns the Header associated with this packet. func (s *SourceDescription) Header() Header { return Header{ - Count: uint8(len(s.Chunks)), + Count: uint8(len(s.Chunks)), //nolint:gosec // G115 Type: TypeSourceDescription, - Length: uint16((s.MarshalSize() / 4) - 1), + Length: uint16((s.MarshalSize() / 4) - 1), //nolint:gosec // G115 } } -// A SourceDescriptionChunk contains items describing a single RTP source +// A SourceDescriptionChunk contains items describing a single RTP source. type SourceDescriptionChunk struct { // The source (ssrc) or contributing source (csrc) identifier this packet describes Source uint32 Items []SourceDescriptionItem } -// Marshal encodes the SourceDescriptionChunk in binary +// Marshal encodes the SourceDescriptionChunk in binary. func (s SourceDescriptionChunk) Marshal() ([]byte, error) { /* * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ @@ -213,19 +217,19 @@ func (s SourceDescriptionChunk) Marshal() ([]byte, error) { if err != nil { return nil, err } - rawPacket = append(rawPacket, data...) + rawPacket = append(rawPacket, data...) //nolint:makezero } // The list of items in each chunk MUST be terminated by one or more null octets - rawPacket = append(rawPacket, uint8(SDESEnd)) + rawPacket = append(rawPacket, uint8(SDESEnd)) //nolint:makezero // additional null octets MUST be included if needed to pad until the next 32-bit boundary - rawPacket = append(rawPacket, make([]byte, getPadding(len(rawPacket)))...) + rawPacket = append(rawPacket, make([]byte, getPadding(len(rawPacket)))...) //nolint:makezero return rawPacket, nil } -// Unmarshal decodes the SourceDescriptionChunk from binary +// Unmarshal decodes the SourceDescriptionChunk from binary. func (s *SourceDescriptionChunk) Unmarshal(rawPacket []byte) error { /* * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ @@ -293,7 +297,7 @@ func (s SourceDescriptionItem) Len() int { return sdesTypeLen + sdesOctetCountLen + len([]byte(s.Text)) } -// Marshal encodes the SourceDescriptionItem in binary +// Marshal encodes the SourceDescriptionItem in binary. func (s SourceDescriptionItem) Marshal() ([]byte, error) { /* * 0 1 2 3 @@ -318,12 +322,12 @@ func (s SourceDescriptionItem) Marshal() ([]byte, error) { } rawPacket[sdesOctetCountOffset] = uint8(octetCount) - rawPacket = append(rawPacket, txtBytes...) + rawPacket = append(rawPacket, txtBytes...) //nolint:makezero return rawPacket, nil } -// Unmarshal decodes the SourceDescriptionItem from binary +// Unmarshal decodes the SourceDescriptionItem from binary. func (s *SourceDescriptionItem) Unmarshal(rawPacket []byte) error { /* * 0 1 2 3 @@ -356,6 +360,7 @@ func (s *SourceDescription) DestinationSSRC() []uint32 { for i, v := range s.Chunks { out[i] = v.Source } + return out } @@ -364,5 +369,6 @@ func (s *SourceDescription) String() string { for _, c := range s.Chunks { out += fmt.Sprintf("\t%x: %s\n", c.Source, c.Items) } + return out } diff --git a/transport_layer_cc.go b/transport_layer_cc.go index 84ead7d..de464cb 100644 --- a/transport_layer_cc.go +++ b/transport_layer_cc.go @@ -39,28 +39,28 @@ import ( // | recv delta | recv delta | zero padding | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// for packet status chunk +// for packet status chunk. const ( - // type of packet status chunk + // type of packet status chunk. TypeTCCRunLengthChunk = 0 TypeTCCStatusVectorChunk = 1 - // len of packet status chunk + // len of packet status chunk. packetStatusChunkLength = 2 ) -// type of packet status symbol and recv delta +// type of packet status symbol and recv delta. const ( // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.1 TypeTCCPacketNotReceived = uint16(iota) TypeTCCPacketReceivedSmallDelta TypeTCCPacketReceivedLargeDelta // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-7 - // see Example 2: "packet received, w/o recv delta" + // see Example 2: "packet received, w/o recv delta". TypeTCCPacketReceivedWithoutDelta ) -// for status vector chunk +// for status vector chunk. const ( // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.4 TypeTCCSymbolSizeOneBit = 0 @@ -69,6 +69,7 @@ const ( // Notice: RFC is wrong: "packet received" (0) and "packet not received" (1) // if S == TypeTCCSymbolSizeOneBit, symbol list will be: TypeTCCPacketNotReceived TypeTCCPacketReceivedSmallDelta // if S == TypeTCCSymbolSizeTwoBit, symbol list will be same as above: + //. ) func numOfBitsOfSymbolSize() map[uint16]uint16 { @@ -84,7 +85,7 @@ var ( ) // PacketStatusChunk has two kinds: -// RunLengthChunk and StatusVectorChunk +// RunLengthChunk and StatusVectorChunk. type PacketStatusChunk interface { Marshal() ([]byte, error) Unmarshal(rawPacket []byte) error @@ -96,6 +97,7 @@ type PacketStatusChunk interface { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // |T| S | Run Length | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type RunLengthChunk struct { PacketStatusChunk @@ -133,6 +135,7 @@ func (r RunLengthChunk) Marshal() ([]byte, error) { } binary.BigEndian.PutUint16(chunk, dst) + return chunk, nil } @@ -152,6 +155,7 @@ func (r *RunLengthChunk) Unmarshal(rawPacket []byte) error { // get RunLength // r.RunLength = uint16(rawPacket[0]&0x1F)*256 + uint16(rawPacket[1]) r.RunLength = getNBitsFromByte(rawPacket[0], 3, 5)<<8 + uint16(rawPacket[1]) + return nil } @@ -161,6 +165,7 @@ func (r *RunLengthChunk) Unmarshal(rawPacket []byte) error { // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // |T|S| symbol list | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type StatusVectorChunk struct { PacketStatusChunk // T = TypeTCCRunLengthChunk @@ -195,7 +200,7 @@ func (r StatusVectorChunk) Marshal() ([]byte, error) { numOfBits := numOfBitsOfSymbolSize()[r.SymbolSize] // append 14 bit SymbolList for i, s := range r.SymbolList { - index := numOfBits*uint16(i) + 2 + index := numOfBits*uint16(i) + 2 //nolint:gosec // G115 dst, err = setNBitsOfUint16(dst, numOfBits, index, s) if err != nil { return nil, err @@ -224,6 +229,7 @@ func (r *StatusVectorChunk) Unmarshal(rawPacket []byte) error { for i := uint16(0); i < 8; i++ { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i, 1)) } + return nil } if r.SymbolSize == TypeTCCSymbolSizeTwoBit { @@ -233,10 +239,12 @@ func (r *StatusVectorChunk) Unmarshal(rawPacket []byte) error { for i := uint16(0); i < 4; i++ { r.SymbolList = append(r.SymbolList, getNBitsFromByte(rawPacket[1], i*2, 2)) } + return nil } r.SymbolSize = getNBitsFromByte(rawPacket[0], 2, 6)<<8 + uint16(rawPacket[1]) + return nil } @@ -263,6 +271,7 @@ func (r RecvDelta) Marshal() ([]byte, error) { if r.Type == TypeTCCPacketReceivedSmallDelta && delta >= 0 && delta <= math.MaxUint8 { deltaChunk := make([]byte, 1) deltaChunk[0] = byte(delta) + return deltaChunk, nil } @@ -270,6 +279,7 @@ func (r RecvDelta) Marshal() ([]byte, error) { if r.Type == TypeTCCPacketReceivedLargeDelta && delta >= math.MinInt16 && delta <= math.MaxInt16 { deltaChunk := make([]byte, 2) binary.BigEndian.PutUint16(deltaChunk, uint16(delta)) + return deltaChunk, nil } @@ -289,16 +299,18 @@ func (r *RecvDelta) Unmarshal(rawPacket []byte) error { if chunkLen == 1 { r.Type = TypeTCCPacketReceivedSmallDelta r.Delta = TypeTCCDeltaScaleFactor * int64(rawPacket[0]) + return nil } r.Type = TypeTCCPacketReceivedLargeDelta - r.Delta = TypeTCCDeltaScaleFactor * int64(int16(binary.BigEndian.Uint16(rawPacket))) + r.Delta = TypeTCCDeltaScaleFactor * int64(int16(binary.BigEndian.Uint16(rawPacket))) //nolint:gosec // G115 + return nil } const ( - // the offset after header + // the offset after header. baseSequenceNumberOffset = 8 packetStatusCountOffset = 10 referenceTimeOffset = 12 @@ -350,7 +362,8 @@ type TransportLayerCC struct { // } func (t *TransportLayerCC) packetLen() uint16 { - n := uint16(headerLength + packetChunkOffset + len(t.PacketChunks)*2) + //nolint:gocognit,cyclop + n := uint16(headerLength + packetChunkOffset + len(t.PacketChunks)*2) //nolint:gosec // G115 for _, d := range t.RecvDeltas { if d.Type == TypeTCCPacketReceivedSmallDelta { n++ @@ -358,15 +371,16 @@ func (t *TransportLayerCC) packetLen() uint16 { n += 2 } } + return n } -// Len return total bytes with padding +// Len return total bytes with padding. func (t *TransportLayerCC) Len() uint16 { - return uint16(t.MarshalSize()) + return uint16(t.MarshalSize()) //nolint:gosec // G115 } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (t *TransportLayerCC) MarshalSize() int { n := t.packetLen() // has padding @@ -394,10 +408,11 @@ func (t TransportLayerCC) String() string { out += fmt.Sprintf("%+v ", delta) } out += "\n" + return out } -// Marshal encodes the TransportLayerCC in binary +// Marshal encodes the TransportLayerCC in binary. func (t TransportLayerCC) Marshal() ([]byte, error) { header, err := t.Header.Marshal() if err != nil { @@ -435,14 +450,16 @@ func (t TransportLayerCC) Marshal() ([]byte, error) { } if t.Header.Padding { - payload[len(payload)-1] = uint8(t.MarshalSize() - int(t.packetLen())) + payload[len(payload)-1] = uint8(t.MarshalSize() - int(t.packetLen())) //nolint:gosec // G115 } return append(header, payload...), nil } // Unmarshal .. -func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { //nolint:gocognit +// +//nolint:gocognit,cyclop +func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { if len(rawPacket) < (headerLength + ssrcLength) { return errPacketTooShort } @@ -515,12 +532,13 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { //nolint:gocognit } if packetStatus.SymbolSize == TypeTCCSymbolSizeTwoBit { for j := 0; j < len(packetStatus.SymbolList); j++ { - if packetStatus.SymbolList[j] == TypeTCCPacketReceivedSmallDelta || packetStatus.SymbolList[j] == TypeTCCPacketReceivedLargeDelta { + if packetStatus.SymbolList[j] == TypeTCCPacketReceivedSmallDelta || + packetStatus.SymbolList[j] == TypeTCCPacketReceivedLargeDelta { t.RecvDeltas = append(t.RecvDeltas, &RecvDelta{Type: packetStatus.SymbolList[j]}) } } } - processedPacketNum += uint16(len(packetStatus.SymbolList)) + processedPacketNum += uint16(len(packetStatus.SymbolList)) //nolint:gosec // G115 } packetStatusPos += packetStatusChunkLength t.PacketChunks = append(t.PacketChunks, iPacketStatus) @@ -562,5 +580,6 @@ func localMin(x, y uint16) uint16 { if x < y { return x } + return y } diff --git a/transport_layer_cc_test.go b/transport_layer_cc_test.go index 9e3c7b1..0f10ad5 100644 --- a/transport_layer_cc_test.go +++ b/transport_layer_cc_test.go @@ -104,7 +104,22 @@ func TestTransportLayerCC_StatusVectorChunkUnmarshal(t *testing.T) { Want: StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeOneBit, - SymbolList: []uint16{TypeTCCPacketNotReceived, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, WantError: nil, }, @@ -115,7 +130,15 @@ func TestTransportLayerCC_StatusVectorChunkUnmarshal(t *testing.T) { Want: StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeTwoBit, - SymbolList: []uint16{TypeTCCPacketNotReceived, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, WantError: nil, }, @@ -126,7 +149,8 @@ func TestTransportLayerCC_StatusVectorChunkUnmarshal(t *testing.T) { t.Fatalf("Unmarshal err: %v", err) } - if got, want := chunk, test.Want; got.Type != want.Type || got.SymbolSize != want.SymbolSize || !reflect.DeepEqual(got.SymbolList, want.SymbolList) { + if got, want := chunk, test.Want; got.Type != want.Type || + got.SymbolSize != want.SymbolSize || !reflect.DeepEqual(got.SymbolList, want.SymbolList) { t.Fatalf("Unmarshal %q : got = %v, want %v", test.Name, got, want) } } @@ -145,7 +169,22 @@ func TestTransportLayerCC_StatusVectorChunkMarshal(t *testing.T) { Data: StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeOneBit, - SymbolList: []uint16{TypeTCCPacketNotReceived, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, Want: []byte{0x9F, 0x1C}, WantError: nil, @@ -156,7 +195,15 @@ func TestTransportLayerCC_StatusVectorChunkMarshal(t *testing.T) { Data: StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeTwoBit, - SymbolList: []uint16{TypeTCCPacketNotReceived, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, Want: []byte{0xCD, 0x50}, WantError: nil, @@ -287,6 +334,9 @@ func TestTransportLayerCC_RecvDeltaMarshal(t *testing.T) { // 0b00000000,0b10011001,0b00000000,0b00000001, // 0b00111101,0b11101000,0b00000010,0b00010111, // 0b00100000,0b00000001,0b10010100,0b00000001, +// . +// +//nolint:maintidx func TestTransportLayerCC_Unmarshal(t *testing.T) { for _, test := range []struct { Name string @@ -363,12 +413,28 @@ func TestTransportLayerCC_Unmarshal(t *testing.T) { &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeTwoBit, - SymbolList: []uint16{TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedLargeDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedLargeDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeTwoBit, - SymbolList: []uint16{TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedWithoutDelta}, + SymbolList: []uint16{ + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedWithoutDelta, + }, }, }, // 0b10010100 @@ -544,7 +610,22 @@ func TestTransportLayerCC_Unmarshal(t *testing.T) { &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: 0, - SymbolList: []uint16{TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, }, RecvDeltas: []*RecvDelta{ @@ -597,7 +678,15 @@ func TestTransportLayerCC_Unmarshal(t *testing.T) { &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeTwoBit, - SymbolList: []uint16{TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketReceivedLargeDelta}, + SymbolList: []uint16{ + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedLargeDelta, + }, }, &RunLengthChunk{ Type: TypeTCCRunLengthChunk, @@ -704,6 +793,7 @@ func TestTransportLayerCC_Unmarshal(t *testing.T) { } } +//nolint:maintidx func TestTransportLayerCC_Marshal(t *testing.T) { for _, test := range []struct { Name string @@ -771,12 +861,28 @@ func TestTransportLayerCC_Marshal(t *testing.T) { &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeTwoBit, - SymbolList: []uint16{TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedLargeDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedLargeDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeTwoBit, - SymbolList: []uint16{TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedWithoutDelta, TypeTCCPacketReceivedWithoutDelta}, + SymbolList: []uint16{ + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedWithoutDelta, + TypeTCCPacketReceivedWithoutDelta, + }, }, }, // 0b10010100 @@ -952,7 +1058,22 @@ func TestTransportLayerCC_Marshal(t *testing.T) { &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeOneBit, - SymbolList: []uint16{TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, }, RecvDeltas: []*RecvDelta{ @@ -1004,7 +1125,20 @@ func TestTransportLayerCC_Marshal(t *testing.T) { &StatusVectorChunk{ Type: TypeTCCStatusVectorChunk, SymbolSize: TypeTCCSymbolSizeOneBit, - SymbolList: []uint16{TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketReceivedSmallDelta, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived, TypeTCCPacketNotReceived}, + SymbolList: []uint16{ + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketReceivedSmallDelta, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + TypeTCCPacketNotReceived, + }, }, }, RecvDeltas: []*RecvDelta{ diff --git a/transport_layer_nack.go b/transport_layer_nack.go index 802b915..c0e3b8f 100644 --- a/transport_layer_nack.go +++ b/transport_layer_nack.go @@ -14,7 +14,7 @@ import ( type PacketBitmap uint16 // NackPair is a wire-representation of a collection of -// Lost RTP packets +// Lost RTP packets. type NackPair struct { // ID of lost packets PacketID uint16 @@ -37,7 +37,7 @@ type TransportLayerNack struct { } // NackPairsFromSequenceNumbers generates a slice of NackPair from a list of SequenceNumbers -// This handles generating the proper values for PacketID/LostPackets +// This handles generating the proper values for PacketID/LostPackets. func NackPairsFromSequenceNumbers(sequenceNumbers []uint16) (pairs []NackPair) { if len(sequenceNumbers) == 0 { return []NackPair{} @@ -50,12 +50,14 @@ func NackPairsFromSequenceNumbers(sequenceNumbers []uint16) (pairs []NackPair) { if m-nackPair.PacketID > 16 { pairs = append(pairs, *nackPair) nackPair = &NackPair{PacketID: m} + continue } nackPair.LostPackets |= 1 << (m - nackPair.PacketID - 1) } pairs = append(pairs, *nackPair) + return } @@ -79,13 +81,15 @@ func (n *NackPair) Range(f func(seqno uint16) bool) { } } -// PacketList returns a list of Nack'd packets that's referenced by a NackPair +// PacketList returns a list of Nack'd packets that's referenced by a NackPair. func (n *NackPair) PacketList() []uint16 { out := make([]uint16, 0, 17) n.Range(func(seqno uint16) bool { out = append(out, seqno) + return true }) + return out } @@ -94,7 +98,7 @@ const ( nackOffset = 8 ) -// Marshal encodes the TransportLayerNack in binary +// Marshal encodes the TransportLayerNack in binary. func (p TransportLayerNack) Marshal() ([]byte, error) { if len(p.Nacks)+tlnLength > math.MaxUint8 { return nil, errTooManyReports @@ -116,42 +120,43 @@ func (p TransportLayerNack) Marshal() ([]byte, error) { return append(hData, rawPacket...), nil } -// Unmarshal decodes the TransportLayerNack from binary +// Unmarshal decodes the TransportLayerNack from binary. func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error { if len(rawPacket) < (headerLength + ssrcLength) { return errPacketTooShort } - var h Header - if err := h.Unmarshal(rawPacket); err != nil { + var header Header + if err := header.Unmarshal(rawPacket); err != nil { return err } - if len(rawPacket) < (headerLength + int(4*h.Length)) { + if len(rawPacket) < (headerLength + int(4*header.Length)) { return errPacketTooShort } - if h.Type != TypeTransportSpecificFeedback || h.Count != FormatTLN { + if header.Type != TypeTransportSpecificFeedback || header.Count != FormatTLN { return errWrongType } // The FCI field MUST contain at least one and MAY contain more than one Generic NACK - if 4*h.Length <= nackOffset { + if 4*header.Length <= nackOffset { return errBadLength } p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) - for i := headerLength + nackOffset; i < (headerLength + int(h.Length*4)); i += 4 { + for i := headerLength + nackOffset; i < (headerLength + int(header.Length*4)); i += 4 { p.Nacks = append(p.Nacks, NackPair{ binary.BigEndian.Uint16(rawPacket[i:]), PacketBitmap(binary.BigEndian.Uint16(rawPacket[i+2:])), }) } + return nil } -// MarshalSize returns the size of the packet once marshaled +// MarshalSize returns the size of the packet once marshaled. func (p *TransportLayerNack) MarshalSize() int { return headerLength + nackOffset + (len(p.Nacks) * 4) } @@ -161,7 +166,7 @@ func (p *TransportLayerNack) Header() Header { return Header{ Count: FormatTLN, Type: TypeTransportSpecificFeedback, - Length: uint16((p.MarshalSize() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), //nolint:gosec // G115 } } @@ -172,6 +177,7 @@ func (p TransportLayerNack) String() string { for _, i := range p.Nacks { out += fmt.Sprintf("\t%d\t%b\n", i.PacketID, i.LostPackets) } + return out } diff --git a/transport_layer_nack_test.go b/transport_layer_nack_test.go index 9b5179f..6d3b656 100644 --- a/transport_layer_nack_test.go +++ b/transport_layer_nack_test.go @@ -136,6 +136,8 @@ func TestTransportLayerNackRoundTrip(t *testing.T) { } func testNackPair(t *testing.T, s []uint16, n NackPair) { + t.Helper() + l := n.PacketList() if !reflect.DeepEqual(l, s) { t.Errorf("%v: expected %v, got %v", n, s, l) @@ -151,11 +153,12 @@ func TestNackPair(t *testing.T) { } func TestNackPairRange(t *testing.T) { - n := NackPair{42, 2} + pair := NackPair{42, 2} out := make([]uint16, 0) - n.Range(func(s uint16) bool { + pair.Range(func(s uint16) bool { out = append(out, s) + return true }) if !reflect.DeepEqual(out, []uint16{42, 44}) { @@ -163,8 +166,9 @@ func TestNackPairRange(t *testing.T) { } out = make([]uint16, 0) - n.Range(func(s uint16) bool { + pair.Range(func(s uint16) bool { out = append(out, s) + return false }) if !reflect.DeepEqual(out, []uint16{42}) { diff --git a/util.go b/util.go index c68cebe..705b290 100644 --- a/util.go +++ b/util.go @@ -3,15 +3,16 @@ package rtcp -// getPadding Returns the padding required to make the length a multiple of 4 +// getPadding Returns the padding required to make the length a multiple of 4. func getPadding(packetLen int) int { if packetLen%4 == 0 { return 0 } + return 4 - (packetLen % 4) } -// setNBitsOfUint16 will truncate the value to size, left-shift to startIndex position and set +// setNBitsOfUint16 will truncate the value to size, left-shift to startIndex position and set. func setNBitsOfUint16(src, size, startIndex, val uint16) (uint16, error) { if startIndex+size > 16 { return 0, errInvalidSizeOrStartIndex @@ -23,19 +24,20 @@ func setNBitsOfUint16(src, size, startIndex, val uint16) (uint16, error) { return src | (val << (16 - size - startIndex)), nil } -// appendBit32 will left-shift and append n bits of val +// appendBit32 will left-shift and append n bits of val. func appendNBitsToUint32(src, n, val uint32) uint32 { return (src << n) | (val & (0xFFFFFFFF >> (32 - n))) } -// getNBit get n bits from 1 byte, begin with a position +// getNBit get n bits from 1 byte, begin with a position. func getNBitsFromByte(b byte, begin, n uint16) uint16 { endShift := 8 - (begin + n) mask := (0xFF >> begin) & uint8(0xFF<> endShift } -// get24BitFromBytes get 24bits from `[3]byte` slice +// get24BitFromBytes get 24bits from `[3]byte` slice. func get24BitsFromBytes(b []byte) uint32 { return uint32(b[0])<<16 + uint32(b[1])<<8 + uint32(b[2]) } diff --git a/util_test.go b/util_test.go index 2ff0ca8..c82b9fa 100644 --- a/util_test.go +++ b/util_test.go @@ -26,7 +26,9 @@ func TestGetPadding(t *testing.T) { {input: 500, result: 0}, } for _, testCase := range cases { - assert.Equalf(getPadding(testCase.input), testCase.result, "Test case returned wrong value for input %d", testCase.input) + assert.Equalf( + getPadding(testCase.input), testCase.result, "Test case returned wrong value for input %d", testCase.input, + ) } } @@ -66,6 +68,7 @@ func TestSetNBitsOfUint16(t *testing.T) { if err.Error() != test.err { t.Fatalf("setNBitsOfUint16 %q : got = %v, want %v", test.name, err, test.err) } + return } if got != test.result {