Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ linters:
- 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
- modernize # Replace and suggests simplifications to code
- 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.
Expand Down
1 change: 1 addition & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var (
errBadFirstPacket = errors.New("rtcp: first packet in compound must be SR or RR")
errMissingCNAME = errors.New("rtcp: compound missing SourceDescription with CNAME")
errPacketBeforeCNAME = errors.New("rtcp: feedback packet seen before CNAME")
errTooManySSRCs = errors.New("rtcp: too many SSRCs")
errTooManyReports = errors.New("rtcp: too many reports")
errTooManyChunks = errors.New("rtcp: too many chunks")
errTooManySources = errors.New("rtcp: too many sources")
Expand Down
2 changes: 1 addition & 1 deletion extended_report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func TestEncode(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, len(expected), len(rawPacket), "Encoded message length does not match expected length")

for i := 0; i < len(rawPacket); i++ {
for i := range rawPacket {
assert.Equalf(t, expected[i], rawPacket[i], "Byte %d of encoded packet does not match", i)
}
}
Expand Down
8 changes: 5 additions & 3 deletions full_intra_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package rtcp
import (
"encoding/binary"
"fmt"
"strings"
)

// A FIREntry is a (SSRC, seqno) pair, as carried by FullIntraRequest.
Expand Down Expand Up @@ -99,13 +100,14 @@ func (p *FullIntraRequest) MarshalSize() int {
}

func (p *FullIntraRequest) String() string {
out := fmt.Sprintf("FullIntraRequest %x %x",
var out strings.Builder
fmt.Fprintf(&out, "FullIntraRequest %x %x",
p.SenderSSRC, p.MediaSSRC)
for _, e := range p.FIR {
out += fmt.Sprintf(" (%x %v)", e.SSRC, e.SequenceNumber)
fmt.Fprintf(&out, " (%x %v)", e.SSRC, e.SequenceNumber)
}

return out
return out.String()
}

// DestinationSSRC returns an array of SSRC values that this packet refers to.
Expand Down
10 changes: 6 additions & 4 deletions goodbye.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package rtcp
import (
"encoding/binary"
"fmt"
"strings"
)

// The Goodbye packet indicates that one or more sources are no longer active.
Expand Down Expand Up @@ -154,11 +155,12 @@ func (g *Goodbye) DestinationSSRC() []uint32 {
}

func (g Goodbye) String() string {
out := "Goodbye\n"
var out strings.Builder
out.WriteString("Goodbye\n")
for i, s := range g.Sources {
out += fmt.Sprintf("\tSource %d: %x\n", i, s)
fmt.Fprintf(&out, "\tSource %d: %x\n", i, s)
}
out += fmt.Sprintf("\tReason: %s\n", g.Reason)
fmt.Fprintf(&out, "\tReason: %s\n", g.Reason)

return out
return out.String()
}
11 changes: 6 additions & 5 deletions goodbye_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package rtcp

import (
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -125,13 +126,13 @@ func TestGoodbyeUnmarshal(t *testing.T) {
func TestGoodbyeRoundTrip(t *testing.T) {
// a slice with enough sources to overflow an 5-bit int
var tooManySources []uint32
var tooLongText string
var tooLongText strings.Builder

for i := 0; i < (1 << 5); i++ {
for range 1 << 5 {
tooManySources = append(tooManySources, 0x00)
}
for i := 0; i < (1 << 8); i++ {
tooLongText += "x"
for range 1 << 8 {
tooLongText.WriteString("x")
}

for _, test := range []struct {
Expand Down Expand Up @@ -187,7 +188,7 @@ func TestGoodbyeRoundTrip(t *testing.T) {
Name: "reason too long",
Bye: Goodbye{
Sources: []uint32{},
Reason: tooLongText,
Reason: tooLongText.String(),
},
WantError: errReasonTooLong,
},
Expand Down
12 changes: 6 additions & 6 deletions packet_buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (b *packetBuffer) write(v any) error {
return errWrongMarshalSize
}
if value.CanInterface() {
b.bytes[0] = byte(value.Uint())
b.bytes[0] = byte(value.Uint()) //nolint:gosec // value.Kind() == reflect.Uint8 guarantees range
}
b.bytes = b.bytes[1:]
case reflect.Uint16:
Expand Down Expand Up @@ -109,7 +109,7 @@ func (b *packetBuffer) write(v any) error {
return err
}
} else {
advance := int(value.Field(i).Type().Size())
advance := int(value.Field(i).Type().Size()) //nolint:gosec // RTCP struct field sizes are small and controlled
if len(b.bytes) < advance {
return errWrongMarshalSize
}
Expand Down Expand Up @@ -200,7 +200,7 @@ func (b *packetBuffer) read(v any) error {
return err
}
} else {
advance := int(value.Field(i).Type().Size())
advance := int(value.Field(i).Type().Size()) //nolint:gosec //Size comes from type system and is bounded
if len(b.bytes) < advance {
return errWrongMarshalSize
}
Expand Down Expand Up @@ -245,7 +245,7 @@ func wireSize(v any) int {
if value.Index(i).CanInterface() {
size += wireSize(value.Index(i).Interface())
} else {
size += int(value.Index(i).Type().Size())
size += int(value.Index(i).Type().Size()) //nolint:gosec // RTCP element sizes are small and bounded
}
}

Expand All @@ -258,12 +258,12 @@ func wireSize(v any) int {
if value.Field(i).CanInterface() {
size += wireSize(value.Field(i).Interface())
} else {
size += int(value.Field(i).Type().Size())
size += int(value.Field(i).Type().Size()) // nolint:gosec // Size comes from type system and is bounded
}
}

default:
size = int(value.Type().Size())
size = int(value.Type().Size()) // nolint:gosec // Size comes from type system and is bounde
}

return size
Expand Down
2 changes: 1 addition & 1 deletion packet_stringifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func formatField(name string, format string, f any, indent string) string {
return fmt.Sprintf("%s%s: <nil>\n", out, name)
}

isPacket := reflect.TypeOf(f).Implements(reflect.TypeOf((*Packet)(nil)).Elem())
isPacket := reflect.TypeOf(f).Implements(reflect.TypeFor[Packet]())

// Resolve pointers to their underlying values
if value.Type().Kind() == reflect.Ptr && !value.IsNil() {
Expand Down
12 changes: 8 additions & 4 deletions receiver_estimated_maximum_bitrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error
buf[15] = 'B'

// Write the length of the ssrcs to follow at the end
buf[16] = byte(len(p.SSRCs))
if len(p.SSRCs) > math.MaxUint8 {
return 0, errTooManySSRCs
}

buf[16] = byte(len(p.SSRCs)) //nolint:gosec // length validated above

exp := 0
bitrate := p.Bitrate
Expand All @@ -118,9 +122,9 @@ func (p ReceiverEstimatedMaximumBitrate) MarshalTo(buf []byte) (n int, err error
// We can't quite use the binary package because
// a) it's a uint24 and b) the exponent is only 6-bits
// Just trust me; this is big-endian encoding.
buf[17] = byte(exp<<2) | byte(mantissa>>16)
buf[18] = byte(mantissa >> 8)
buf[19] = byte(mantissa)
buf[17] = byte(exp<<2) | byte(mantissa>>16) //nolint: gosec // mantissa is limited to 18 bits
buf[18] = byte(mantissa >> 8) //nolint: gosec // mantissa is limited to 18 bits
buf[19] = byte(mantissa) // nolint: gosec // mantissa is limited to 18 bits

// Write the SSRCs at the very end.
n = 20
Expand Down
12 changes: 7 additions & 5 deletions receiver_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package rtcp
import (
"encoding/binary"
"fmt"
"strings"
)

// A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream.
Expand Down Expand Up @@ -188,12 +189,13 @@ func (r *ReceiverReport) DestinationSSRC() []uint32 {
}

func (r ReceiverReport) String() string {
out := fmt.Sprintf("ReceiverReport from %x\n", r.SSRC)
out += "\tSSRC \tLost\tLastSequence\n"
var out strings.Builder
fmt.Fprintf(&out, "ReceiverReport from %x\n", r.SSRC)
out.WriteString("\tSSRC \tLost\tLastSequence\n")
for _, i := range r.Reports {
out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber)
fmt.Fprintf(&out, "\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)
fmt.Fprintf(&out, "\tProfile Extension Data: %v\n", r.ProfileExtensions)

return out
return out.String()
}
2 changes: 1 addition & 1 deletion receiver_report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func TestReceiverReportUnmarshal(t *testing.T) {
func tooManyReports() []ReceptionReport {
// a slice with enough ReceptionReports to overflow an 5-bit int
var tooManyReports []ReceptionReport
for i := 0; i < (1 << 5); i++ {
for range 1 << 5 {
tooManyReports = append(tooManyReports, ReceptionReport{
SSRC: 2,
FractionLost: 2,
Expand Down
35 changes: 18 additions & 17 deletions rfc8888.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"math"
"strings"
)

// https://www.rfc-editor.org/rfc/rfc8888.html#name-rtcp-congestion-control-fee
Expand Down Expand Up @@ -164,16 +165,17 @@ func (b CCFeedbackReport) Marshal() ([]byte, error) {
}

func (b CCFeedbackReport) String() string {
out := fmt.Sprintf("CCFB:\n\tHeader %v\n", b.Header())
out += fmt.Sprintf("CCFB:\n\tSender SSRC %d\n", b.SenderSSRC)
out += fmt.Sprintf("\tReport Timestamp %d\n", b.ReportTimestamp)
out += "\tFeedback Reports \n"
var out strings.Builder
fmt.Fprintf(&out, "CCFB:\n\tHeader %v\n", b.Header())
fmt.Fprintf(&out, "CCFB:\n\tSender SSRC %d\n", b.SenderSSRC)
fmt.Fprintf(&out, "\tReport Timestamp %d\n", b.ReportTimestamp)
out.WriteString("\tFeedback Reports \n")
for _, report := range b.ReportBlocks {
out += fmt.Sprintf("%v ", report)
fmt.Fprintf(&out, "%v ", report)
}
out += "\n"
out.WriteString("\n")

return out
return out.String()
}

// Unmarshal decodes the Congestion Control Feedback Report from binary.
Expand Down Expand Up @@ -237,22 +239,21 @@ func (b *CCFeedbackReportBlock) len() int {
}

func (b CCFeedbackReportBlock) String() string {
out := fmt.Sprintf("\tReport Block Media SSRC %d\n", b.MediaSSRC)
out += fmt.Sprintf("\tReport Begin Sequence Nr %d\n", b.BeginSequence)
out += fmt.Sprintf("\tReport length %d\n\t", len(b.MetricBlocks))
var out strings.Builder
fmt.Fprintf(&out, "\tReport Block Media SSRC %d\n", b.MediaSSRC)
fmt.Fprintf(&out, "\tReport Begin Sequence Nr %d\n", b.BeginSequence)
fmt.Fprintf(&out, "\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, ecn: %v} ",
fmt.Fprintf(&out, "{nr: %d, rx: %v, ts: %v, ecn: %v} ",
b.BeginSequence+uint16(i),
block.Received,
block.ArrivalTimeOffset,
block.ECN,
)
block.ECN)
}
out += "\n"
out.WriteString("\n")

return out
return out.String()
}

// marshal encodes the Congestion Control Feedback Report Block in binary.
Expand Down Expand Up @@ -301,7 +302,7 @@ func (b *CCFeedbackReportBlock) unmarshal(rawPacket []byte) error {
}

b.MetricBlocks = make([]CCFeedbackMetricBlock, numReports)
for i := int(0); i < numReports; i++ {
for i := range numReports {
var mb CCFeedbackMetricBlock
offset := reportsOffset + 2*i
if err := mb.unmarshal(rawPacket[offset : offset+2]); err != nil {
Expand Down
5 changes: 0 additions & 5 deletions rfc8888_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ func TestCCFeedbackMetricBlockUnmarshalMarshal(t *testing.T) {
},
},
} {
test := test
t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) {
var block CCFeedbackMetricBlock
err := block.unmarshal(test.Data)
Expand Down Expand Up @@ -112,7 +111,6 @@ func TestCCFeedbackMetricBlockUnmarshalMarshal(t *testing.T) {
},
},
} {
test := test
t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) {
var block CCFeedbackMetricBlock
err := block.unmarshal(test.Data)
Expand All @@ -122,7 +120,6 @@ func TestCCFeedbackMetricBlockUnmarshalMarshal(t *testing.T) {
}

for _, l := range []int{0, 1, 3} {
l := l
t.Run(fmt.Sprintf("shortMetricBlock-%v", l), func(t *testing.T) {
var block CCFeedbackMetricBlock
data := make([]byte, l)
Expand Down Expand Up @@ -248,7 +245,6 @@ func TestCCFeedbackReportBlockUnmarshalMarshal(t *testing.T) {
},
},
} {
test := test
t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) {
var block CCFeedbackReportBlock
err := block.unmarshal(test.Data)
Expand Down Expand Up @@ -409,7 +405,6 @@ func TestCCFeedbackReportUnmarshalMarshal(t *testing.T) {
},
},
} {
test := test
t.Run(fmt.Sprintf("Unmarshal-%v", test.Name), func(t *testing.T) {
pkts, err := Unmarshal(test.Data)
assert.NoError(t, err)
Expand Down
20 changes: 11 additions & 9 deletions sender_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package rtcp
import (
"encoding/binary"
"fmt"
"strings"
)

// A SenderReport (SR) packet provides reception quality feedback for an RTP stream.
Expand Down Expand Up @@ -249,17 +250,18 @@ func (r *SenderReport) Header() Header {
}

func (r SenderReport) String() string {
out := fmt.Sprintf("SenderReport from %x\n", r.SSRC)
out += fmt.Sprintf("\tNTPTime:\t%d\n", r.NTPTime)
out += fmt.Sprintf("\tRTPTIme:\t%d\n", r.RTPTime)
out += fmt.Sprintf("\tPacketCount:\t%d\n", r.PacketCount)
out += fmt.Sprintf("\tOctetCount:\t%d\n", r.OctetCount)
var out strings.Builder
fmt.Fprintf(&out, "SenderReport from %x\n", r.SSRC)
fmt.Fprintf(&out, "\tNTPTime:\t%d\n", r.NTPTime)
fmt.Fprintf(&out, "\tRTPTIme:\t%d\n", r.RTPTime)
fmt.Fprintf(&out, "\tPacketCount:\t%d\n", r.PacketCount)
fmt.Fprintf(&out, "\tOctetCount:\t%d\n", r.OctetCount)

out += "\tSSRC \tLost\tLastSequence\n"
out.WriteString("\tSSRC \tLost\tLastSequence\n")
for _, i := range r.Reports {
out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber)
fmt.Fprintf(&out, "\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)
fmt.Fprintf(&out, "\tProfile Extension Data: %v\n", r.ProfileExtensions)

return out
return out.String()
}
Loading
Loading