diff --git a/.golangci.yml b/.golangci.yml index a3235be..88cb4fb 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,17 +25,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 +61,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 +79,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 +95,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 +118,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/base_lexer.go b/base_lexer.go index edd532a..4cd9dc5 100644 --- a/base_lexer.go +++ b/base_lexer.go @@ -21,6 +21,7 @@ func (e syntaxError) Error() string { if e.i < 0 { e.i = 0 } + return fmt.Sprintf("sdp: syntax error at pos %d: %s", e.i, strconv.QuoteToASCII(e.s[e.i:e.i+1])) } @@ -38,6 +39,7 @@ func (l *baseLexer) unreadByte() error { return errDocumentStart } l.pos-- + return nil } @@ -47,6 +49,7 @@ func (l *baseLexer) readByte() (byte, error) { } ch := l.value[l.pos] l.pos++ + return ch, nil } @@ -64,7 +67,7 @@ func (l *baseLexer) nextLine() error { } } -func (l *baseLexer) readWhitespace() error { +func (l *baseLexer) readWhitespace() error { //notlint:cyclop for { ch, err := l.readByte() if errors.Is(err, io.EOF) { @@ -78,7 +81,7 @@ func (l *baseLexer) readWhitespace() error { } } -func (l *baseLexer) readUint64Field() (i uint64, err error) { +func (l *baseLexer) readUint64Field() (i uint64, err error) { //nolint:cyclop for { ch, err := l.readByte() if errors.Is(err, io.EOF) && i > 0 { @@ -91,6 +94,7 @@ func (l *baseLexer) readUint64Field() (i uint64, err error) { if err := l.unreadByte(); err != nil { return i, err } + break } @@ -98,6 +102,7 @@ func (l *baseLexer) readUint64Field() (i uint64, err error) { if err := l.readWhitespace(); err != nil { return i, err } + break } @@ -130,7 +135,7 @@ func (l *baseLexer) readUint64Field() (i uint64, err error) { return i, nil } -// Returns next field on this line or empty string if no more fields on line +// Returns next field on this line or empty string if no more fields on line. func (l *baseLexer) readField() (string, error) { start := l.pos var stop int @@ -147,6 +152,7 @@ func (l *baseLexer) readField() (string, error) { if err := l.unreadByte(); err != nil { return "", err } + break } @@ -154,13 +160,15 @@ func (l *baseLexer) readField() (string, error) { if err := l.readWhitespace(); err != nil { return "", err } + break } } + return l.value[start:stop], nil } -// Returns symbols until line end +// Returns symbols until line end. func (l *baseLexer) readLine() (string, error) { start := l.pos trim := 1 @@ -212,5 +220,6 @@ func anyOf(element string, data ...string) bool { return true } } + return false } diff --git a/base_lexer_test.go b/base_lexer_test.go index dcd975a..2a956b1 100644 --- a/base_lexer_test.go +++ b/base_lexer_test.go @@ -8,7 +8,7 @@ import ( "testing" ) -func TestLexer(t *testing.T) { +func TestLexer(t *testing.T) { //nolint:cyclop t.Run("single field", func(t *testing.T) { for k, value := range map[string]string{ "clean": "aaa", @@ -38,10 +38,10 @@ func TestLexer(t *testing.T) { }) t.Run("many fields", func(t *testing.T) { - l := &baseLexer{value: "aaa 123\nf1 f2\nlast"} + lex := &baseLexer{value: "aaa 123\nf1 f2\nlast"} t.Run("first line", func(t *testing.T) { - field, err := l.readField() + field, err := lex.readField() if err != nil { t.Fatal(err) } @@ -49,7 +49,7 @@ func TestLexer(t *testing.T) { t.Errorf("aaa not parsed, got: '%v'", field) } - value, err := l.readUint64Field() + value, err := lex.readUint64Field() if err != nil { t.Fatal(err) } @@ -57,13 +57,13 @@ func TestLexer(t *testing.T) { t.Errorf("aaa not parsed, got: '%v'", field) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { t.Fatal(err) } }) t.Run("second line", func(t *testing.T) { - field, err := l.readField() + field, err := lex.readField() if err != nil { t.Fatal(err) } @@ -71,7 +71,7 @@ func TestLexer(t *testing.T) { t.Errorf("value not parsed, got: '%v'", field) } - field, err = l.readField() + field, err = lex.readField() if err != nil { t.Fatal(err) } @@ -79,7 +79,7 @@ func TestLexer(t *testing.T) { t.Errorf("value not parsed, got: '%v'", field) } - field, err = l.readField() + field, err = lex.readField() if err != nil { t.Fatal(err) } @@ -87,13 +87,13 @@ func TestLexer(t *testing.T) { t.Errorf("value not parsed, got: '%v'", field) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { t.Fatal(err) } }) t.Run("last line", func(t *testing.T) { - field, err := l.readField() + field, err := lex.readField() if err != nil { t.Fatal(err) } diff --git a/common_description.go b/common_description.go index 9db7903..6d678ce 100644 --- a/common_description.go +++ b/common_description.go @@ -85,10 +85,10 @@ func (c *Address) marshalInto(b []byte) []byte { func (c Address) marshalSize() (size int) { size = len(c.Address) if c.TTL != nil { - size += 1 + lenUint(uint64(*c.TTL)) + size += 1 + lenUint(uint64(*c.TTL)) //nolint:gosec // G115 } if c.Range != nil { - size += 1 + lenUint(uint64(*c.Range)) + size += 1 + lenUint(uint64(*c.Range)) //nolint:gosec // G115 } return @@ -111,6 +111,7 @@ func (b Bandwidth) marshalInto(d []byte) []byte { d = append(d, "X-"...) } d = append(append(d, b.Type...), ':') + return strconv.AppendUint(d, b.Bandwidth, 10) } @@ -120,6 +121,7 @@ func (b Bandwidth) marshalSize() (size int) { } size += len(b.Type) + 1 + lenUint(b.Bandwidth) + return } @@ -145,14 +147,14 @@ type Attribute struct { Value string } -// NewPropertyAttribute constructs a new attribute +// NewPropertyAttribute constructs a new attribute. func NewPropertyAttribute(key string) Attribute { return Attribute{ Key: key, } } -// NewAttribute constructs a new attribute +// NewAttribute constructs a new attribute. func NewAttribute(key, value string) Attribute { return Attribute{ Key: key, diff --git a/direction.go b/direction.go index 936130c..8cc97bf 100644 --- a/direction.go +++ b/direction.go @@ -5,17 +5,17 @@ package sdp import "errors" -// Direction is a marker for transmission directon of an endpoint +// Direction is a marker for transmission directon of an endpoint. type Direction int const ( - // DirectionSendRecv is for bidirectional communication + // DirectionSendRecv is for bidirectional communication. DirectionSendRecv Direction = iota + 1 - // DirectionSendOnly is for outgoing communication + // DirectionSendOnly is for outgoing communication. DirectionSendOnly - // DirectionRecvOnly is for incoming communication + // DirectionRecvOnly is for incoming communication. DirectionRecvOnly - // DirectionInactive is for no communication + // DirectionInactive is for no communication. DirectionInactive ) diff --git a/extmap.go b/extmap.go index bbcd9d6..0114b56 100644 --- a/extmap.go +++ b/extmap.go @@ -10,7 +10,7 @@ import ( "strings" ) -// Default ext values +// Default ext values. const ( DefExtMapValueABSSendTime = 1 DefExtMapValueTransportCC = 2 @@ -25,7 +25,7 @@ const ( AudioLevelURI = "urn:ietf:params:rtp-hdrext:ssrc-audio-level" ) -// ExtMap represents the activation of a single RTP header extension +// ExtMap represents the activation of a single RTP header extension. type ExtMap struct { Value int Direction Direction @@ -33,12 +33,12 @@ type ExtMap struct { ExtAttr *string } -// Clone converts this object to an Attribute +// Clone converts this object to an Attribute. func (e *ExtMap) Clone() Attribute { return Attribute{Key: "extmap", Value: e.string()} } -// Unmarshal creates an Extmap from a string +// Unmarshal creates an Extmap from a string. func (e *ExtMap) Unmarshal(raw string) error { parts := strings.SplitN(raw, ":", 2) if len(parts) != 2 { @@ -80,10 +80,11 @@ func (e *ExtMap) Unmarshal(raw string) error { e.Value = int(value) e.Direction = direction e.URI = uri + return nil } -// Marshal creates a string from an ExtMap +// Marshal creates a string from an ExtMap. func (e *ExtMap) Marshal() string { return e.Name() + ":" + e.string() } @@ -106,7 +107,7 @@ func (e *ExtMap) string() string { return output } -// Name returns the constant name of this object +// Name returns the constant name of this object. func (e *ExtMap) Name() string { return "extmap" } diff --git a/jsep.go b/jsep.go index 600acf5..388a13e 100644 --- a/jsep.go +++ b/jsep.go @@ -10,7 +10,7 @@ import ( "time" ) -// Constants for SDP attributes used in JSEP +// Constants for SDP attributes used in JSEP. const ( AttrKeyCandidate = "candidate" AttrKeyEndOfCandidates = "end-of-candidates" @@ -33,7 +33,7 @@ const ( AttrKeyExtMapAllowMixed = "extmap-allow-mixed" ) -// Constants for semantic tokens used in JSEP +// Constants for semantic tokens used in JSEP. const ( SemanticTokenLipSynchronization = "LS" SemanticTokenFlowIdentification = "FID" @@ -41,7 +41,7 @@ const ( SemanticTokenWebRTCMediaStreams = "WMS" ) -// Constants for extmap key +// Constants for extmap key. const ( ExtMapValueTransportCC = 3 ) @@ -67,12 +67,12 @@ func NewJSEPSessionDescription(identity bool) (*SessionDescription, error) { if err != nil { return nil, err } - d := &SessionDescription{ + descr := &SessionDescription{ Version: 0, Origin: Origin{ Username: "-", SessionID: sid, - SessionVersion: uint64(time.Now().Unix()), + SessionVersion: uint64(time.Now().Unix()), //nolint:gosec // G115 NetworkType: "IN", AddressType: "IP4", UnicastAddress: "0.0.0.0", @@ -93,32 +93,35 @@ func NewJSEPSessionDescription(identity bool) (*SessionDescription, error) { } if identity { - d.WithPropertyAttribute(AttrKeyIdentity) + descr.WithPropertyAttribute(AttrKeyIdentity) } - return d, nil + return descr, nil } -// WithPropertyAttribute adds a property attribute 'a=key' to the session description +// WithPropertyAttribute adds a property attribute 'a=key' to the session description. func (s *SessionDescription) WithPropertyAttribute(key string) *SessionDescription { s.Attributes = append(s.Attributes, NewPropertyAttribute(key)) + return s } -// WithValueAttribute adds a value attribute 'a=key:value' to the session description +// WithValueAttribute adds a value attribute 'a=key:value' to the session description. func (s *SessionDescription) WithValueAttribute(key, value string) *SessionDescription { s.Attributes = append(s.Attributes, NewAttribute(key, value)) + return s } -// WithFingerprint adds a fingerprint to the session description +// WithFingerprint adds a fingerprint to the session description. func (s *SessionDescription) WithFingerprint(algorithm, value string) *SessionDescription { return s.WithValueAttribute("fingerprint", algorithm+" "+value) } -// WithMedia adds a media description to the session description +// WithMedia adds a media description to the session description. func (s *SessionDescription) WithMedia(md *MediaDescription) *SessionDescription { s.MediaDescriptions = append(s.MediaDescriptions, md) + return s } @@ -141,32 +144,40 @@ func NewJSEPMediaDescription(codecType string, _ []string) *MediaDescription { } } -// WithPropertyAttribute adds a property attribute 'a=key' to the media description +// WithPropertyAttribute adds a property attribute 'a=key' to the media description. func (d *MediaDescription) WithPropertyAttribute(key string) *MediaDescription { d.Attributes = append(d.Attributes, NewPropertyAttribute(key)) + return d } -// WithValueAttribute adds a value attribute 'a=key:value' to the media description +// WithValueAttribute adds a value attribute 'a=key:value' to the media description. func (d *MediaDescription) WithValueAttribute(key, value string) *MediaDescription { d.Attributes = append(d.Attributes, NewAttribute(key, value)) + return d } -// WithFingerprint adds a fingerprint to the media description +// WithFingerprint adds a fingerprint to the media description. func (d *MediaDescription) WithFingerprint(algorithm, value string) *MediaDescription { return d.WithValueAttribute("fingerprint", algorithm+" "+value) } -// WithICECredentials adds ICE credentials to the media description +// WithICECredentials adds ICE credentials to the media description. func (d *MediaDescription) WithICECredentials(username, password string) *MediaDescription { return d. WithValueAttribute("ice-ufrag", username). WithValueAttribute("ice-pwd", password) } -// WithCodec adds codec information to the media description -func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate uint32, channels uint16, fmtp string) *MediaDescription { +// WithCodec adds codec information to the media description. +func (d *MediaDescription) WithCodec( + payloadType uint8, + name string, + clockrate uint32, + channels uint16, + fmtp string, +) *MediaDescription { d.MediaName.Formats = append(d.MediaName.Formats, strconv.Itoa(int(payloadType))) rtpmap := fmt.Sprintf("%d %s/%d", payloadType, name, clockrate) if channels > 0 { @@ -176,10 +187,11 @@ func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate u if fmtp != "" { d.WithValueAttribute("fmtp", fmt.Sprintf("%d %s", payloadType, fmtp)) } + return d } -// WithMediaSource adds media source information to the media description +// WithMediaSource adds media source information to the media description. func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, label string) *MediaDescription { return d. WithValueAttribute("ssrc", fmt.Sprintf("%d cname:%s", ssrc, cname)). // Deprecated but not phased out? @@ -188,23 +200,24 @@ func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, labe WithValueAttribute("ssrc", fmt.Sprintf("%d label:%s", ssrc, label)) // Deprecated but not phased out? } -// WithCandidate adds an ICE candidate to the media description -// Deprecated: use WithICECandidate instead +// WithCandidate adds an ICE candidate to the media description. +// Deprecated: use WithICECandidate instead. func (d *MediaDescription) WithCandidate(value string) *MediaDescription { return d.WithValueAttribute("candidate", value) } -// WithExtMap adds an extmap to the media description +// WithExtMap adds an extmap to the media description. func (d *MediaDescription) WithExtMap(e ExtMap) *MediaDescription { return d.WithPropertyAttribute(e.Marshal()) } -// WithTransportCCExtMap adds an extmap to the media description +// WithTransportCCExtMap adds an extmap to the media description. func (d *MediaDescription) WithTransportCCExtMap() *MediaDescription { uri, _ := url.Parse(extMapURI()[ExtMapValueTransportCC]) e := ExtMap{ Value: ExtMapValueTransportCC, URI: uri, } + return d.WithExtMap(e) } diff --git a/marshal.go b/marshal.go index 43dd738..81b6aa1 100644 --- a/marshal.go +++ b/marshal.go @@ -37,97 +37,97 @@ package sdp // b=* (zero or more bandwidth information lines) // k=* (encryption key) // a=* (zero or more media attribute lines) -func (s *SessionDescription) Marshal() ([]byte, error) { - m := make(marshaller, 0, s.MarshalSize()) +func (s *SessionDescription) Marshal() ([]byte, error) { //nolint:cyclop + marsh := make(marshaller, 0, s.MarshalSize()) - m.addKeyValue("v=", s.Version.marshalInto) - m.addKeyValue("o=", s.Origin.marshalInto) - m.addKeyValue("s=", s.SessionName.marshalInto) + marsh.addKeyValue("v=", s.Version.marshalInto) + marsh.addKeyValue("o=", s.Origin.marshalInto) + marsh.addKeyValue("s=", s.SessionName.marshalInto) if s.SessionInformation != nil { - m.addKeyValue("i=", s.SessionInformation.marshalInto) + marsh.addKeyValue("i=", s.SessionInformation.marshalInto) } if s.URI != nil { - m = append(m, "u="...) - m = append(m, s.URI.String()...) - m = append(m, "\r\n"...) + marsh = append(marsh, "u="...) + marsh = append(marsh, s.URI.String()...) + marsh = append(marsh, "\r\n"...) } if s.EmailAddress != nil { - m.addKeyValue("e=", s.EmailAddress.marshalInto) + marsh.addKeyValue("e=", s.EmailAddress.marshalInto) } if s.PhoneNumber != nil { - m.addKeyValue("p=", s.PhoneNumber.marshalInto) + marsh.addKeyValue("p=", s.PhoneNumber.marshalInto) } if s.ConnectionInformation != nil { - m.addKeyValue("c=", s.ConnectionInformation.marshalInto) + marsh.addKeyValue("c=", s.ConnectionInformation.marshalInto) } for _, b := range s.Bandwidth { - m.addKeyValue("b=", b.marshalInto) + marsh.addKeyValue("b=", b.marshalInto) } for _, td := range s.TimeDescriptions { - m.addKeyValue("t=", td.Timing.marshalInto) + marsh.addKeyValue("t=", td.Timing.marshalInto) for _, r := range td.RepeatTimes { - m.addKeyValue("r=", r.marshalInto) + marsh.addKeyValue("r=", r.marshalInto) } } if len(s.TimeZones) > 0 { - m = append(m, "z="...) + marsh = append(marsh, "z="...) for i, z := range s.TimeZones { if i > 0 { - m = append(m, ' ') + marsh = append(marsh, ' ') } - m = z.marshalInto(m) + marsh = z.marshalInto(marsh) } - m = append(m, "\r\n"...) + marsh = append(marsh, "\r\n"...) } if s.EncryptionKey != nil { - m.addKeyValue("k=", s.EncryptionKey.marshalInto) + marsh.addKeyValue("k=", s.EncryptionKey.marshalInto) } for _, a := range s.Attributes { - m.addKeyValue("a=", a.marshalInto) + marsh.addKeyValue("a=", a.marshalInto) } for _, md := range s.MediaDescriptions { - m.addKeyValue("m=", md.MediaName.marshalInto) + marsh.addKeyValue("m=", md.MediaName.marshalInto) if md.MediaTitle != nil { - m.addKeyValue("i=", md.MediaTitle.marshalInto) + marsh.addKeyValue("i=", md.MediaTitle.marshalInto) } if md.ConnectionInformation != nil { - m.addKeyValue("c=", md.ConnectionInformation.marshalInto) + marsh.addKeyValue("c=", md.ConnectionInformation.marshalInto) } for _, b := range md.Bandwidth { - m.addKeyValue("b=", b.marshalInto) + marsh.addKeyValue("b=", b.marshalInto) } if md.EncryptionKey != nil { - m.addKeyValue("k=", md.EncryptionKey.marshalInto) + marsh.addKeyValue("k=", md.EncryptionKey.marshalInto) } for _, a := range md.Attributes { - m.addKeyValue("a=", a.marshalInto) + marsh.addKeyValue("a=", a.marshalInto) } } - return m, nil + return marsh, nil } -// `$type=` and CRLF size +// `$type=` and CRLF size. const lineBaseSize = 4 // MarshalSize returns the size of the SessionDescription once marshaled. -func (s *SessionDescription) MarshalSize() (marshalSize int) { +func (s *SessionDescription) MarshalSize() (marshalSize int) { //nolint:cyclop marshalSize += lineBaseSize + s.Version.marshalSize() marshalSize += lineBaseSize + s.Origin.marshalSize() marshalSize += lineBaseSize + s.SessionName.marshalSize() @@ -225,6 +225,7 @@ func lenUint(i uint64) (count int) { i /= 10 count++ } + return } @@ -232,6 +233,7 @@ func lenInt(i int64) (count int) { if i < 0 { return lenUint(uint64(-i)) + 1 } + return lenUint(uint64(i)) } diff --git a/marshal_test.go b/marshal_test.go index 60b06be..2c0691a 100644 --- a/marshal_test.go +++ b/marshal_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -// nolint: goconst +//nolint:goconst const ( CanonicalMarshalSDP = "v=0\r\n" + "o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5\r\n" + @@ -38,7 +38,7 @@ const ( "a=rtpmap:99 h263-1998/90000\r\n" ) -// nolint: goconst +//nolint:goconst func TestMarshalCanonical(t *testing.T) { sd := &SessionDescription{ Version: 0, @@ -57,6 +57,7 @@ func TestMarshalCanonical(t *testing.T) { if err != nil { return nil } + return uri }(), EmailAddress: &(&struct{ x EmailAddress }{"j.doe@example.com (Jane Doe)"}).x, diff --git a/media_description.go b/media_description.go index d5d76e4..e307115 100644 --- a/media_description.go +++ b/media_description.go @@ -37,13 +37,14 @@ type MediaDescription struct { Attributes []Attribute } -// Attribute returns the value of an attribute and if it exists +// Attribute returns the value of an attribute and if it exists. func (d *MediaDescription) Attribute(key string) (string, bool) { for _, a := range d.Attributes { if a.Key == key { return a.Value, true } } + return "", false } @@ -61,6 +62,7 @@ func (p *RangedPort) String() string { if p.Range != nil { output += "/" + strconv.Itoa(*p.Range) } + return output } @@ -70,6 +72,7 @@ func (p RangedPort) marshalInto(b []byte) []byte { b = append(b, '/') b = strconv.AppendInt(b, int64(*p.Range), 10) } + return b } @@ -109,6 +112,7 @@ func (m MediaName) marshalInto(b []byte) []byte { appendList(m.Protos, '/') b = append(b, ' ') appendList(m.Formats, ' ') + return b } diff --git a/session_description.go b/session_description.go index a9e25da..dee37a4 100644 --- a/session_description.go +++ b/session_description.go @@ -69,13 +69,14 @@ type SessionDescription struct { MediaDescriptions []*MediaDescription } -// Attribute returns the value of an attribute and if it exists +// Attribute returns the value of an attribute and if it exists. func (s *SessionDescription) Attribute(key string) (string, bool) { for _, a := range s.Attributes { if a.Key == key { return a.Value, true } } + return "", false } @@ -116,6 +117,7 @@ func (o Origin) marshalInto(b []byte) []byte { b = append(strconv.AppendUint(b, o.SessionVersion, 10), ' ') b = append(append(b, o.NetworkType...), ' ') b = append(append(b, o.AddressType...), ' ') + return append(b, o.UnicastAddress...) } @@ -193,6 +195,7 @@ func (z TimeZone) String() string { func (z TimeZone) marshalInto(b []byte) []byte { b = strconv.AppendUint(b, z.AdjustmentTime, 10) b = append(b, ' ') + return strconv.AppendInt(b, z.Offset, 10) } diff --git a/time_description.go b/time_description.go index 0a5baa4..1682ba3 100644 --- a/time_description.go +++ b/time_description.go @@ -33,6 +33,7 @@ func (t Timing) String() string { func (t Timing) marshalInto(b []byte) []byte { b = append(strconv.AppendUint(b, t.StartTime, 10), ' ') + return strconv.AppendUint(b, t.StopTime, 10) } diff --git a/unmarshal.go b/unmarshal.go index 9e90320..e884b0f 100644 --- a/unmarshal.go +++ b/unmarshal.go @@ -107,34 +107,35 @@ var ( // | s14 | 14 | | | | | | | | 12 | | | | | | | | | // | s15 | | 14 | | | 15 | | | | 12 | | | | | | | | | // | s16 | | 14 | | | | 15 | | | 12 | | | | | | | | | -// +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+ +// +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+ . func (s *SessionDescription) UnmarshalString(value string) error { var ok bool - l := new(lexer) - if l.cache, ok = unmarshalCachePool.Get().(*unmarshalCache); !ok { + lex := new(lexer) + if lex.cache, ok = unmarshalCachePool.Get().(*unmarshalCache); !ok { return errSDPCacheInvalid } - defer unmarshalCachePool.Put(l.cache) + defer unmarshalCachePool.Put(lex.cache) - l.cache.reset() - l.desc = s - l.value = value + lex.cache.reset() + lex.desc = s + lex.value = value for state := s1; state != nil; { var err error - state, err = state(l) + state, err = state(lex) if err != nil { return err } } - s.Attributes = l.cache.cloneSessionAttributes() - populateMediaAttributes(l.cache, l.desc) + s.Attributes = lex.cache.cloneSessionAttributes() + populateMediaAttributes(lex.cache, lex.desc) + return nil } // Unmarshal converts the value into a []byte and then calls UnmarshalString. -// Callers should use the more performant UnmarshalString +// Callers should use the more performant UnmarshalString. func (s *SessionDescription) Unmarshal(value []byte) error { return s.UnmarshalString(string(value)) } @@ -144,6 +145,7 @@ func s1(l *lexer) (stateFn, error) { if key == 'v' { return unmarshalProtocolVersion } + return nil }) } @@ -153,6 +155,7 @@ func s2(l *lexer) (stateFn, error) { if key == 'o' { return unmarshalOrigin } + return nil }) } @@ -162,6 +165,7 @@ func s3(l *lexer) (stateFn, error) { if key == 's' { return unmarshalSessionName } + return nil }) } @@ -184,6 +188,7 @@ func s4(l *lexer) (stateFn, error) { case 't': return unmarshalTiming } + return nil }) } @@ -196,6 +201,7 @@ func s5(l *lexer) (stateFn, error) { case 't': return unmarshalTiming } + return nil }) } @@ -212,6 +218,7 @@ func s6(l *lexer) (stateFn, error) { case 't': return unmarshalTiming } + return nil }) } @@ -232,6 +239,7 @@ func s7(l *lexer) (stateFn, error) { case 't': return unmarshalTiming } + return nil }) } @@ -246,6 +254,7 @@ func s8(l *lexer) (stateFn, error) { case 't': return unmarshalTiming } + return nil }) } @@ -266,6 +275,7 @@ func s9(l *lexer) (stateFn, error) { case 'm': return unmarshalMediaDescription } + return nil }) } @@ -284,6 +294,7 @@ func s10(l *lexer) (stateFn, error) { case 't': return unmarshalTiming } + return nil }) } @@ -296,6 +307,7 @@ func s11(l *lexer) (stateFn, error) { case 'm': return unmarshalMediaDescription } + return nil }) } @@ -316,6 +328,7 @@ func s12(l *lexer) (stateFn, error) { case 'm': return unmarshalMediaDescription } + return nil }) } @@ -330,6 +343,7 @@ func s13(l *lexer) (stateFn, error) { case 'm': return unmarshalMediaDescription } + return nil }) } @@ -354,6 +368,7 @@ func s14(l *lexer) (stateFn, error) { case 'm': return unmarshalMediaDescription } + return nil }) } @@ -375,6 +390,7 @@ func s15(l *lexer) (stateFn, error) { case 'm': return unmarshalMediaDescription } + return nil }) } @@ -396,6 +412,7 @@ func s16(l *lexer) (stateFn, error) { case 'm': return unmarshalMediaDescription } + return nil }) } @@ -419,52 +436,52 @@ func unmarshalProtocolVersion(l *lexer) (stateFn, error) { return s2, nil } -func unmarshalOrigin(l *lexer) (stateFn, error) { +func unmarshalOrigin(lex *lexer) (stateFn, error) { var err error - l.desc.Origin.Username, err = l.readField() + lex.desc.Origin.Username, err = lex.readField() if err != nil { return nil, err } - l.desc.Origin.SessionID, err = l.readUint64Field() + lex.desc.Origin.SessionID, err = lex.readUint64Field() if err != nil { return nil, err } - l.desc.Origin.SessionVersion, err = l.readUint64Field() + lex.desc.Origin.SessionVersion, err = lex.readUint64Field() if err != nil { return nil, err } - l.desc.Origin.NetworkType, err = l.readField() + lex.desc.Origin.NetworkType, err = lex.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.6 - if !anyOf(l.desc.Origin.NetworkType, "IN") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, l.desc.Origin.NetworkType) + if !anyOf(lex.desc.Origin.NetworkType, "IN") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, lex.desc.Origin.NetworkType) } - l.desc.Origin.AddressType, err = l.readField() + lex.desc.Origin.AddressType, err = lex.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.7 - if !anyOf(l.desc.Origin.AddressType, "IP4", "IP6") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, l.desc.Origin.AddressType) + if !anyOf(lex.desc.Origin.AddressType, "IP4", "IP6") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, lex.desc.Origin.AddressType) } - l.desc.Origin.UnicastAddress, err = l.readField() + lex.desc.Origin.UnicastAddress, err = lex.readField() if err != nil { return nil, err } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } @@ -478,6 +495,7 @@ func unmarshalSessionName(l *lexer) (stateFn, error) { } l.desc.SessionName = SessionName(value) + return s4, nil } @@ -489,6 +507,7 @@ func unmarshalSessionInformation(l *lexer) (stateFn, error) { sessionInformation := Information(value) l.desc.SessionInformation = &sessionInformation + return s7, nil } @@ -514,6 +533,7 @@ func unmarshalEmail(l *lexer) (stateFn, error) { emailAddress := EmailAddress(value) l.desc.EmailAddress = &emailAddress + return s6, nil } @@ -525,6 +545,7 @@ func unmarshalPhone(l *lexer) (stateFn, error) { phoneNumber := PhoneNumber(value) l.desc.PhoneNumber = &phoneNumber + return s8, nil } @@ -534,33 +555,34 @@ func unmarshalSessionConnectionInformation(l *lexer) (stateFn, error) { if err != nil { return nil, err } + return s5, nil } func (l *lexer) unmarshalConnectionInformation() (*ConnectionInformation, error) { var err error - var c ConnectionInformation + var connInfo ConnectionInformation - c.NetworkType, err = l.readField() + connInfo.NetworkType, err = l.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.6 - if !anyOf(c.NetworkType, "IN") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, c.NetworkType) + if !anyOf(connInfo.NetworkType, "IN") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, connInfo.NetworkType) } - c.AddressType, err = l.readField() + connInfo.AddressType, err = l.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.7 - if !anyOf(c.AddressType, "IP4", "IP6") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, c.AddressType) + if !anyOf(connInfo.AddressType, "IP4", "IP6") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, connInfo.AddressType) } address, err := l.readField() @@ -569,15 +591,15 @@ func (l *lexer) unmarshalConnectionInformation() (*ConnectionInformation, error) } if address != "" { - c.Address = new(Address) - c.Address.Address = address + connInfo.Address = new(Address) + connInfo.Address.Address = address } if err := l.nextLine(); err != nil { return nil, err } - return &c, nil + return &connInfo, nil } func unmarshalSessionBandwidth(l *lexer) (stateFn, error) { @@ -624,35 +646,36 @@ func unmarshalBandwidth(value string) (*Bandwidth, error) { }, nil } -func unmarshalTiming(l *lexer) (stateFn, error) { +func unmarshalTiming(lex *lexer) (stateFn, error) { var err error var td TimeDescription - td.Timing.StartTime, err = l.readUint64Field() + td.Timing.StartTime, err = lex.readUint64Field() if err != nil { return nil, err } - td.Timing.StopTime, err = l.readUint64Field() + td.Timing.StopTime, err = lex.readUint64Field() if err != nil { return nil, err } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } - l.desc.TimeDescriptions = append(l.desc.TimeDescriptions, td) + lex.desc.TimeDescriptions = append(lex.desc.TimeDescriptions, td) + return s9, nil } -func unmarshalRepeatTimes(l *lexer) (stateFn, error) { +func unmarshalRepeatTimes(lex *lexer) (stateFn, error) { var err error var newRepeatTime RepeatTime - latestTimeDesc := &l.desc.TimeDescriptions[len(l.desc.TimeDescriptions)-1] + latestTimeDesc := &lex.desc.TimeDescriptions[len(lex.desc.TimeDescriptions)-1] - field, err := l.readField() + field, err := lex.readField() if err != nil { return nil, err } @@ -662,7 +685,7 @@ func unmarshalRepeatTimes(l *lexer) (stateFn, error) { return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, field) } - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -673,7 +696,7 @@ func unmarshalRepeatTimes(l *lexer) (stateFn, error) { } for { - field, err := l.readField() + field, err := lex.readField() if err != nil { return nil, err } @@ -687,15 +710,16 @@ func unmarshalRepeatTimes(l *lexer) (stateFn, error) { newRepeatTime.Offsets = append(newRepeatTime.Offsets, offset) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } latestTimeDesc.RepeatTimes = append(latestTimeDesc.RepeatTimes, newRepeatTime) + return s9, nil } -func unmarshalTimeZones(l *lexer) (stateFn, error) { +func unmarshalTimeZones(lex *lexer) (stateFn, error) { // These fields are transimitted in pairs // z= .... // so we are making sure that there are actually multiple of 2 total. @@ -703,12 +727,12 @@ func unmarshalTimeZones(l *lexer) (stateFn, error) { var err error var timeZone TimeZone - timeZone.AdjustmentTime, err = l.readUint64Field() + timeZone.AdjustmentTime, err = lex.readUint64Field() if err != nil { return nil, err } - offset, err := l.readField() + offset, err := lex.readField() if err != nil { return nil, err } @@ -722,10 +746,10 @@ func unmarshalTimeZones(l *lexer) (stateFn, error) { return nil, err } - l.desc.TimeZones = append(l.desc.TimeZones, timeZone) + lex.desc.TimeZones = append(lex.desc.TimeZones, timeZone) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } @@ -740,6 +764,7 @@ func unmarshalSessionEncryptionKey(l *lexer) (stateFn, error) { encryptionKey := EncryptionKey(value) l.desc.EncryptionKey = &encryptionKey + return s11, nil } @@ -761,12 +786,12 @@ func unmarshalSessionAttribute(l *lexer) (stateFn, error) { return s11, nil } -func unmarshalMediaDescription(l *lexer) (stateFn, error) { - populateMediaAttributes(l.cache, l.desc) +func unmarshalMediaDescription(lex *lexer) (stateFn, error) { //nolint:cyclop + populateMediaAttributes(lex.cache, lex.desc) var newMediaDesc MediaDescription // - field, err := l.readField() + field, err := lex.readField() if err != nil { return nil, err } @@ -779,7 +804,7 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { newMediaDesc.MediaName.Media = field // - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -799,7 +824,7 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { } // - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -808,7 +833,24 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { // https://tools.ietf.org/html/rfc4566#section-5.14 // https://tools.ietf.org/html/rfc4975#section-8.1 for _, proto := range strings.Split(field, "/") { - if !anyOf(proto, "UDP", "RTP", "AVP", "SAVP", "SAVPF", "TLS", "DTLS", "SCTP", "AVPF", "TCP", "MSRP", "BFCP", "UDT", "IX", "MRCPv2") { + if !anyOf( + proto, + "UDP", + "RTP", + "AVP", + "SAVP", + "SAVPF", + "TLS", + "DTLS", + "SCTP", + "AVPF", + "TCP", + "MSRP", + "BFCP", + "UDT", + "IX", + "MRCPv2", + ) { return nil, fmt.Errorf("%w `%v`", errSDPInvalidNumericValue, field) } newMediaDesc.MediaName.Protos = append(newMediaDesc.MediaName.Protos, proto) @@ -816,7 +858,7 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { // ... for { - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -826,11 +868,12 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { newMediaDesc.MediaName.Formats = append(newMediaDesc.MediaName.Formats, field) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } - l.desc.MediaDescriptions = append(l.desc.MediaDescriptions, &newMediaDesc) + lex.desc.MediaDescriptions = append(lex.desc.MediaDescriptions, &newMediaDesc) + return s12, nil } @@ -843,6 +886,7 @@ func unmarshalMediaTitle(l *lexer) (stateFn, error) { latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1] mediaTitle := Information(value) latestMediaDesc.MediaTitle = &mediaTitle + return s16, nil } @@ -853,6 +897,7 @@ func unmarshalMediaConnectionInformation(l *lexer) (stateFn, error) { if err != nil { return nil, err } + return s15, nil } @@ -868,6 +913,7 @@ func unmarshalMediaBandwidth(l *lexer) (stateFn, error) { return nil, fmt.Errorf("%w `b=%v`", errSDPInvalidSyntax, value) } latestMediaDesc.Bandwidth = append(latestMediaDesc.Bandwidth, *bandwidth) + return s15, nil } @@ -880,6 +926,7 @@ func unmarshalMediaEncryptionKey(l *lexer) (stateFn, error) { latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1] encryptionKey := EncryptionKey(value) latestMediaDesc.EncryptionKey = &encryptionKey + return s14, nil } @@ -915,6 +962,7 @@ func parseTimeUnits(value string) (num int64, err error) { if err != nil { return 0, fmt.Errorf("%w `%v`", errSDPInvalidValue, value) } + return num * k, nil } diff --git a/unmarshal_cache.go b/unmarshal_cache.go index 728b305..478d0f7 100644 --- a/unmarshal_cache.go +++ b/unmarshal_cache.go @@ -15,6 +15,7 @@ func (c *unmarshalCache) reset() { func (c *unmarshalCache) getSessionAttribute() *Attribute { c.sessionAttributes = append(c.sessionAttributes, Attribute{}) + return &c.sessionAttributes[len(c.sessionAttributes)-1] } @@ -25,11 +26,13 @@ func (c *unmarshalCache) cloneSessionAttributes() []Attribute { s := make([]Attribute, len(c.sessionAttributes)) copy(s, c.sessionAttributes) c.sessionAttributes = c.sessionAttributes[:0] + return s } func (c *unmarshalCache) getMediaAttribute() *Attribute { c.mediaAttributes = append(c.mediaAttributes, Attribute{}) + return &c.mediaAttributes[len(c.mediaAttributes)-1] } @@ -40,5 +43,6 @@ func (c *unmarshalCache) cloneMediaAttributes() []Attribute { s := make([]Attribute, len(c.mediaAttributes)) copy(s, c.mediaAttributes) c.mediaAttributes = c.mediaAttributes[:0] + return s } diff --git a/util.go b/util.go index f0cc33e..7cf17a9 100644 --- a/util.go +++ b/util.go @@ -27,7 +27,7 @@ var ( errSyntaxError = errors.New("SyntaxError") ) -// ConnectionRole indicates which of the end points should initiate the connection establishment +// ConnectionRole indicates which of the end points should initiate the connection establishment. type ConnectionRole int const ( @@ -37,7 +37,8 @@ const ( // ConnectionRolePassive indicates the endpoint will accept an incoming connection. ConnectionRolePassive - // ConnectionRoleActpass indicates the endpoint is willing to accept an incoming connection or to initiate an outgoing connection. + // ConnectionRoleActpass indicates the endpoint is willing to accept an incoming connection or + // to initiate an outgoing connection. ConnectionRoleActpass // ConnectionRoleHoldconn indicates the endpoint does not want the connection to be established for the time being. @@ -65,10 +66,11 @@ func newSessionID() (uint64, error) { // quantity with the highest bit set to zero and the remaining 63-bits // being cryptographically random. id, err := randutil.CryptoUint64() + return id & (^(uint64(1) << 63)), err } -// Codec represents a codec +// Codec represents a codec. type Codec struct { PayloadType uint8 Name string @@ -83,7 +85,15 @@ const ( ) func (c Codec) String() string { - return fmt.Sprintf("%d %s/%d/%s (%s) [%s]", c.PayloadType, c.Name, c.ClockRate, c.EncodingParameters, c.Fmtp, strings.Join(c.RTCPFeedback, ", ")) + return fmt.Sprintf( + "%d %s/%d/%s (%s) [%s]", + c.PayloadType, + c.Name, + c.ClockRate, + c.EncodingParameters, + c.Fmtp, + strings.Join(c.RTCPFeedback, ", "), + ) } func (c *Codec) appendRTCPFeedback(rtcpFeedback string) { @@ -189,6 +199,7 @@ func parseRtcpFb(rtcpFb string) (codec Codec, isWildcard bool, err error) { } codec.RTCPFeedback = append(codec.RTCPFeedback, split[1]) + return codec, isWildcard, nil } @@ -215,7 +226,7 @@ func mergeCodecs(codec Codec, codecs map[uint8]Codec) { codecs[savedCodec.PayloadType] = savedCodec } -func (s *SessionDescription) buildCodecMap() map[uint8]Codec { +func (s *SessionDescription) buildCodecMap() map[uint8]Codec { //nolint:cyclop codecs := map[uint8]Codec{ // static codecs that do not require a rtpmap 0: { @@ -308,7 +319,7 @@ func codecsMatch(wanted, got Codec) bool { return true } -// GetCodecForPayloadType scans the SessionDescription for the given payload type and returns the codec +// GetCodecForPayloadType scans the SessionDescription for the given payload type and returns the codec. func (s *SessionDescription) GetCodecForPayloadType(payloadType uint8) (Codec, error) { codecs := s.buildCodecMap() @@ -321,7 +332,7 @@ func (s *SessionDescription) GetCodecForPayloadType(payloadType uint8) (Codec, e } // GetPayloadTypeForCodec scans the SessionDescription for a codec that matches the provided codec -// as closely as possible and returns its payload type +// as closely as possible and returns its payload type. func (s *SessionDescription) GetPayloadTypeForCodec(wanted Codec) (uint8, error) { codecs := s.buildCodecMap()