From 6b88a6e16a63fffe426abdd7ed1db8c8aa6d4e90 Mon Sep 17 00:00:00 2001 From: Aleksandr Razumov Date: Sat, 11 May 2019 15:10:14 +0300 Subject: [PATCH] dep: update gortc/ice to v0.6 --- Gopkg.lock | 11 +- Gopkg.toml | 2 +- vendor/github.com/gortc/ice/Gopkg.lock | 7 +- vendor/github.com/gortc/ice/Gopkg.toml | 5 +- vendor/github.com/gortc/ice/LICENSE | 45 ++--- vendor/github.com/gortc/ice/Makefile | 2 + vendor/github.com/gortc/ice/README.md | 15 +- vendor/github.com/gortc/ice/agent.go | 10 ++ vendor/github.com/gortc/ice/candidate.go | 148 +++++++++++++++ .../gortc/ice/candidate/candidate.go | 59 +++--- vendor/github.com/gortc/ice/checklist.go | 110 ++++++++++++ vendor/github.com/gortc/ice/gather.go | 150 +--------------- vendor/github.com/gortc/ice/gather/gather.go | 168 ++++++++++++++++++ vendor/github.com/gortc/ice/host.go | 163 +++++++++++++++++ vendor/github.com/gortc/ice/ice.go | 28 ++- vendor/github.com/gortc/ice/icecontrol.go | 16 +- vendor/github.com/gortc/ice/internal/net.go | 11 ++ vendor/github.com/gortc/ice/pair.go | 126 +++++++++++++ vendor/github.com/gortc/ice/priority.go | 10 +- vendor/github.com/gortc/ice/sdp/sdp.go | 142 +++++++++------ 20 files changed, 938 insertions(+), 290 deletions(-) create mode 100644 vendor/github.com/gortc/ice/agent.go create mode 100644 vendor/github.com/gortc/ice/candidate.go create mode 100644 vendor/github.com/gortc/ice/checklist.go create mode 100644 vendor/github.com/gortc/ice/gather/gather.go create mode 100644 vendor/github.com/gortc/ice/host.go create mode 100644 vendor/github.com/gortc/ice/internal/net.go create mode 100644 vendor/github.com/gortc/ice/pair.go diff --git a/Gopkg.lock b/Gopkg.lock index 823e23a..890e606 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -26,16 +26,18 @@ version = "v1.3.0" [[projects]] - digest = "1:6492d57459aa3e79999c58f5283f2ebfdfebeb13f834e76bab815e1b489069c9" + digest = "1:919da3b8fb3ce3cc5727081078417c95fabb7070c995e4305ab889099c476174" name = "github.com/gortc/ice" packages = [ ".", "candidate", + "gather", + "internal", "sdp", ] pruneopts = "UT" - revision = "4925c4f36fe938eb6e331db95268b8cb8129ee36" - version = "v0.5.3" + revision = "0502d448b37789b0bed1d54ccd0adefaa9cefca0" + version = "v0.6.3" [[projects]] digest = "1:4e01f79919d7c4a558229a4e33f4e89aa19b1d9bbbbace348becf9e54b3d14a7" @@ -314,7 +316,10 @@ "github.com/pkg/errors", "github.com/prometheus/client_golang/prometheus", "github.com/prometheus/client_golang/prometheus/promhttp", + "github.com/prometheus/client_model/go", + "github.com/prometheus/common/expfmt", "github.com/spf13/cobra", + "github.com/spf13/pflag", "github.com/spf13/viper", "go.uber.org/zap", "go.uber.org/zap/zapcore", diff --git a/Gopkg.toml b/Gopkg.toml index a1867c2..3505b39 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -40,7 +40,7 @@ ignored = ["github.com/chromedp/chromedp","github.com/chromedp/chromedp/runner", [[constraint]] name = "github.com/gortc/ice" - version = "0.5" + version = "0.6" [prune] go-tests = true diff --git a/vendor/github.com/gortc/ice/Gopkg.lock b/vendor/github.com/gortc/ice/Gopkg.lock index a92e2b0..05b0880 100644 --- a/vendor/github.com/gortc/ice/Gopkg.lock +++ b/vendor/github.com/gortc/ice/Gopkg.lock @@ -10,15 +10,15 @@ version = "v0.12.5" [[projects]] - digest = "1:7b37d283b79da4f3ef3668fee38e64d1ecde9b35a76e529e9b382c38a29e00b6" + digest = "1:8ff0a6a4a26da40ff5bd97e55b693edfd294800e5b8c572a53a043d524c49cc4" name = "github.com/gortc/stun" packages = [ ".", "internal/hmac", ] pruneopts = "UT" - revision = "5c00cd797895dbd61e57efeae38223d97b676439" - version = "v1.17.3" + revision = "ce9f38fbf5043cdeecb89fd74cafdfb6fb1f4351" + version = "v1.18.2" [[projects]] digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" @@ -34,7 +34,6 @@ input-imports = [ "github.com/gortc/sdp", "github.com/gortc/stun", - "github.com/pkg/errors", ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/gortc/ice/Gopkg.toml b/vendor/github.com/gortc/ice/Gopkg.toml index a8bac61..6b72632 100644 --- a/vendor/github.com/gortc/ice/Gopkg.toml +++ b/vendor/github.com/gortc/ice/Gopkg.toml @@ -26,15 +26,12 @@ [[constraint]] name = "github.com/gortc/stun" - version = "1.17.3" + version = "1.18" [[constraint]] name = "github.com/gortc/sdp" version = "0.12" -[[constraint]] - name = "github.com/pkg/errors" - version = "0.8.0" [prune] go-tests = true diff --git a/vendor/github.com/gortc/ice/LICENSE b/vendor/github.com/gortc/ice/LICENSE index e3d1a3a..0dccea6 100644 --- a/vendor/github.com/gortc/ice/LICENSE +++ b/vendor/github.com/gortc/ice/LICENSE @@ -1,27 +1,28 @@ -Copyright (c) 2016 Aleksandr Razumov, Cydev. All Rigths Reserved. +BSD 3-Clause License + +Copyright (c) 2017-2018 gortc. All Rights Reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/github.com/gortc/ice/Makefile b/vendor/github.com/gortc/ice/Makefile index 282faef..8f81f81 100644 --- a/vendor/github.com/gortc/ice/Makefile +++ b/vendor/github.com/gortc/ice/Makefile @@ -16,6 +16,7 @@ fuzz-prepare-candidate: fuzz-candidate: go-fuzz -bin=./stun-candidate-fuzz.zip -workdir=fuzz/stun-setters lint: + @gocritic check-project . @echo "linting on $(PROCS) cores" @gometalinter \ --enable-all \ @@ -27,6 +28,7 @@ lint: --disable="gochecknoglobals" \ --disable="gochecknoinits" \ --disable="maligned" \ + --disable="unparam" \ --deadline=300s \ -j $(PROCS) @echo "ok" diff --git a/vendor/github.com/gortc/ice/README.md b/vendor/github.com/gortc/ice/README.md index 8cd268a..bf1e244 100644 --- a/vendor/github.com/gortc/ice/README.md +++ b/vendor/github.com/gortc/ice/README.md @@ -6,9 +6,8 @@ [![stability-wip](https://img.shields.io/badge/stability-wip-lightgrey.svg)](/~https://github.com/mkenney/software-guides/blob/master/STABILITY-BADGES.md#work-in-progress) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fgortc%2Fice.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fgortc%2Fice?ref=badge_shield) # ICE -Package ice implements Interactive Connectivity Establishment (ICE): -A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols -[[RFC 8445](https://tools.ietf.org/html/rfc8445)]. +Package ice implements Interactive Connectivity Establishment (ICE) [[RFC8445](https://tools.ietf.org/html/rfc8445)]: +A Protocol for Network Address Translator (NAT) Traversal. Complies to [gortc principles](https://gortc.io/#principles) as core package. Currently in active development, so no guarantees for API backward @@ -19,6 +18,16 @@ compatibility. - [ ] Basic - [ ] Full - [ ] [Trickle](https://tools.ietf.org/html/draft-ietf-ice-trickle) +- [x] [RFC 8421](https://tools.ietf.org/html/rfc8421) — Guidelines for Multihomed/Dual-Stack ICE +- [ ] [ice-sip-sdp-21](https://tools.ietf.org/html/draft-ietf-mmusic-ice-sip-sdp-21) — SDP Offer/Answer for ICE ([sdp](https://godoc.org/github.com/gortc/ice/sdp) subpackage) + - [x] candidate + - [ ] remote candidate + - [ ] ice-lite + - [ ] ice-mismatch + - [ ] ice-pwd + - [ ] ice-ufrag + - [ ] ice-options + - [ ] ice-pacing - [ ] [RFC 6544](https://tools.ietf.org/html/draft-ietf-ice-rfc5245bis) — TCP Candidates with ICE - [ ] [rtcweb-19](https://tools.ietf.org/html/draft-ietf-rtcweb-overview-19) — WebRTC - [ ] [rtcweb-transports-17](https://tools.ietf.org/html/draft-ietf-rtcweb-transports-17) — Transports diff --git a/vendor/github.com/gortc/ice/agent.go b/vendor/github.com/gortc/ice/agent.go new file mode 100644 index 0000000..c53bbb5 --- /dev/null +++ b/vendor/github.com/gortc/ice/agent.go @@ -0,0 +1,10 @@ +package ice + +// Role represents ICE agent role, which can be controlling or controlled. +type Role byte + +// Possible ICE agent roles. +const ( + Controlling Role = iota + Controlled +) diff --git a/vendor/github.com/gortc/ice/candidate.go b/vendor/github.com/gortc/ice/candidate.go new file mode 100644 index 0000000..89a63ec --- /dev/null +++ b/vendor/github.com/gortc/ice/candidate.go @@ -0,0 +1,148 @@ +package ice + +import ( + "bytes" + "crypto/sha256" + "fmt" + "net" + + ct "github.com/gortc/ice/candidate" +) + +// Addr represents transport address, the combination of an IP address +// and the transport protocol (such as UDP or TCP) port. +type Addr struct { + IP net.IP + Port int + Proto ct.Protocol +} + +// Equal returns true of b equals to a. +func (a Addr) Equal(b Addr) bool { + if a.Proto != b.Proto { + return false + } + if a.Port != b.Port { + return false + } + return a.IP.Equal(b.IP) +} + +func (a Addr) String() string { + return fmt.Sprintf("%s:%d/%s", a.IP, a.Port, a.Proto) +} + +// Candidates is list of candidates ordered by priority descending. +type Candidates []Candidate + +func (c Candidates) Len() int { return len(c) } +func (c Candidates) Less(i, j int) bool { return c[i].Priority > c[j].Priority } +func (c Candidates) Swap(i, j int) { c[i], c[j] = c[j], c[i] } + +// The Candidate is a transport address that is a potential point of contact +// for receipt of data. Candidates also have properties — their type +// (server reflexive, relayed, or host), priority, foundation, and base. +type Candidate struct { + Addr Addr + Type ct.Type + Priority int + Foundation []byte + Base Addr + Related Addr + ComponentID int +} + +// Equal reports whether c equals to b. +func (c Candidate) Equal(b Candidate) bool { + if c.Type != b.Type { + return false + } + if c.Priority != b.Priority { + return false + } + if !c.Addr.Equal(b.Addr) { + return false + } + if !bytes.Equal(c.Foundation, b.Foundation) { + return false + } + if !c.Base.Equal(b.Base) { + return false + } + if !c.Related.Equal(b.Related) { + // Should we skip that check? + return false + } + if c.ComponentID != b.ComponentID { + return false + } + return true +} + +const foundationLength = 8 + +// Foundation computes foundation value for candidate. The serverAddr parameter +// is for STUN or TURN server address, zero value is valid. Will return nil if +// candidate is nil. +// +// Value is an arbitrary string used in the freezing algorithm to +// group similar candidates. It is the same for two candidates that +// have the same type, base IP address, protocol (UDP, TCP, etc.), +// and STUN or TURN server. If any of these are different, then the +// foundation will be different. +func Foundation(c *Candidate, serverAddr Addr) []byte { + if c == nil { + return nil + } + h := sha256.New() + values := [][]byte{ + {byte(c.Type)}, + c.Base.IP, + {byte(c.Addr.Proto)}, + } + if len(serverAddr.IP) > 0 { + values = append(values, + serverAddr.IP, + []byte{byte(serverAddr.Proto)}, + ) + } + h.Write(bytes.Join(values, []byte{':'})) // #nosec + return h.Sum(nil)[:foundationLength] +} + +// The RECOMMENDED values for type preferences are 126 for host +// candidates, 110 for peer-reflexive candidates, 100 for server- +// reflexive candidates, and 0 for relayed candidates. +// +// From RFC 8445 Section 5.1.2.2. +var typePreferences = map[ct.Type]int{ + ct.Host: 126, + ct.PeerReflexive: 110, + ct.ServerReflexive: 100, + ct.Relayed: 0, +} + +// TypePreference returns recommended type preference for candidate type. +func TypePreference(t ct.Type) int { return typePreferences[t] } + +// Priority calculates the priority value by RFC 8445 Section 5.1.2.1 formulae. +// +// The typePref value MUST be an integer from 0 (lowest preference) to 126 +// (highest preference) inclusive, MUST be identical for all candidates of +// the same type, and MUST be different for candidates of different types. +// +// The localPref value MUST be an integer from 0 (lowest preference) to +// 65535 (highest preference) inclusive. When there is only a single IP +// address, this value SHOULD be set to 65535. If there are multiple +// candidates for a particular component for a particular data stream +// that have the same type, the local preference MUST be unique for each +// one. If an ICE agent is dual stack, the local preference SHOULD be +// set according to the current best practice described in [RFC8421]. +// +// The component ID MUST be an integer between 1 and 256 inclusive. +func Priority(typePref, localPref, componentID int) int { + // priority = (2^24)*(type preference) + + // (2^8)*(local preference) + + // (2^0)*(256 - component ID) + return (1<<24)*typePref + (1<<8)*localPref + (1<<0)*(256-componentID) +} diff --git a/vendor/github.com/gortc/ice/candidate/candidate.go b/vendor/github.com/gortc/ice/candidate/candidate.go index 96c337d..0190651 100644 --- a/vendor/github.com/gortc/ice/candidate/candidate.go +++ b/vendor/github.com/gortc/ice/candidate/candidate.go @@ -1,26 +1,6 @@ // Package candidate contains common types for ice candidate. package candidate -// AddressType is type for SDPConnectionAddress. -type AddressType byte - -// Possible address types. -const ( - AddressIPv4 AddressType = iota - AddressIPv6 - AddressFQDN -) - -var addressTypeToStr = map[AddressType]string{ - AddressIPv4: "IPv4", - AddressIPv6: "IPv6", - AddressFQDN: "FQDN", -} - -func (a AddressType) String() string { - return strOrUnknown(addressTypeToStr[a]) -} - // Type encodes the type of candidate. This specification // defines the values "host", "srflx", "prflx", and "relay" for host, // server reflexive, peer reflexive, and relayed candidates, @@ -28,19 +8,31 @@ func (a AddressType) String() string { // future. type Type byte -// Set of candidate types. +// Set of possible candidate types. const ( - Host Type = iota // "host" - ServerReflexive // "srflx" - PeerReflexive // "prflx" - Relay // "relay" + // Host is a candidate obtained by binding to a specific port + // from an IP address on the host. This includes IP addresses on + // physical interfaces and logical ones, such as ones obtained + // through VPNs. + Host Type = iota + // ServerReflexive is a candidate whose IP address and port + // are a binding allocated by a NAT for an ICE agent after it sends a + // packet through the NAT to a server, such as a STUN server. + ServerReflexive + // PeerReflexive is a candidate whose IP address and port are + // a binding allocated by a NAT for an ICE agent after it sends a + // packet through the NAT to its peer. + PeerReflexive + // Relayed is a candidate obtained from a relay server, such as + // a TURN server. + Relayed ) var candidateTypeToStr = map[Type]string{ Host: "host", ServerReflexive: "server-reflexive", PeerReflexive: "peer-reflexive", - Relay: "relay", + Relayed: "relayed", } func strOrUnknown(str string) string { @@ -54,21 +46,20 @@ func (c Type) String() string { return strOrUnknown(candidateTypeToStr[c]) } -// TransportType is transport type for candidate. -type TransportType byte +// Protocol is protocol for address. +type Protocol byte -// Supported transport types. +// Supported protocols. const ( - TransportUDP TransportType = iota - TransportUnknown + UDP Protocol = iota + ProtocolUnknown ) -func (t TransportType) String() string { +func (t Protocol) String() string { switch t { - case TransportUDP: + case UDP: return "UDP" default: return "Unknown" } } - diff --git a/vendor/github.com/gortc/ice/checklist.go b/vendor/github.com/gortc/ice/checklist.go new file mode 100644 index 0000000..f871aea --- /dev/null +++ b/vendor/github.com/gortc/ice/checklist.go @@ -0,0 +1,110 @@ +package ice + +import "sort" + +// Checklist is set of pairs. +// +// +// From RFC 8455 Section 6.1.2: +// +// There is one checklist for each data stream. To form a checklist, +// initiating and responding ICE agents form candidate pairs, compute +// pair priorities, order pairs by priority, prune pairs, remove lower- +// priority pairs, and set checklist states. If candidates are added to +// a checklist (e.g., due to detection of peer-reflexive candidates), +// the agent will re-perform these steps for the updated checklist. +type Checklist struct { + Pairs Pairs + State ChecklistState +} + +// ChecklistState represents the Checklist State. +// +// See RFC 8445 Section 6.1.2.1 +type ChecklistState byte + +var checklistStateToStr = map[ChecklistState]string{ + ChecklistRunning: "Running", + ChecklistCompleted: "Completed", + ChecklistFailed: "Failed", +} + +func (s ChecklistState) String() string { return checklistStateToStr[s] } + +const ( + // ChecklistRunning is neither Completed nor Failed yet. Checklists are + // initially set to the Running state. + ChecklistRunning ChecklistState = iota + // ChecklistCompleted contains a nominated pair for each component of the + // data stream. + ChecklistCompleted + // ChecklistFailed does not have a valid pair for each component of the data + // stream, and all of the candidate pairs in the checklist are in either the + // Failed or the Succeeded state. In other words, at least one component of + // the checklist has candidate pairs that are all in the Failed state, which + // means the component has failed, which means the checklist has failed. + ChecklistFailed +) + +// ComputePriorities computes priorities for all pairs based on agent role. +// +// The role determines whether local candidate is from controlling or from +// controlled agent. +func (c *Checklist) ComputePriorities(role Role) { + for i := range c.Pairs { + var ( + controlling = c.Pairs[i].Local.Priority + controlled = c.Pairs[i].Remote.Priority + ) + if role == Controlled { + controlling, controlled = controlled, controlling + } + c.Pairs[i].Priority = PairPriority(controlling, controlled) + } +} + +// Order is ordering pairs by priority descending. +// First element will have highest priority. +func (c *Checklist) Order() { sort.Sort(c.Pairs) } + +// Prune removes redundant candidates. +// +// Two candidate pairs are redundant if their local candidates have the same +// base and their remote candidates are identical +func (c *Checklist) Prune() { + // Pruning algorithm is not optimal but should work for small numbers, + // where len(c.Pairs) ~ 100. + result := make(Pairs, 0, len(c.Pairs)) +Loop: + for i := range c.Pairs { + base := c.Pairs[i].Local.Base + for j := range result { + // Check if local candidates have the same base. + if !result[j].Local.Base.Equal(base) { + continue + } + // Check if remote candidates are identical. + if !result[j].Remote.Equal(c.Pairs[i].Remote) { + continue + } + // Pair is redundant, skipping. + continue Loop + } + result = append(result, c.Pairs[i]) + } + c.Pairs = result +} + +// Limit ensures maximum length of pairs, removing the pairs with least priority +// if needed. +func (c *Checklist) Limit(max int) { + if len(c.Pairs) <= max { + return + } + c.Pairs = c.Pairs[:max] +} + +// Len returns pairs count. +func (c *Checklist) Len() int { + return len(c.Pairs) +} diff --git a/vendor/github.com/gortc/ice/gather.go b/vendor/github.com/gortc/ice/gather.go index df15b95..7a5520f 100644 --- a/vendor/github.com/gortc/ice/gather.go +++ b/vendor/github.com/gortc/ice/gather.go @@ -1,154 +1,10 @@ package ice import ( - "fmt" - "net" - "sort" + "github.com/gortc/ice/gather" ) -// Gatherer is source for addresses. -// -// See RFC 8445 Section 2.1 for details on gathering. -type Gatherer interface { - Gather() ([]Addr, error) -} - -const precedencesCount = 11 - -var precedences [precedencesCount]precedenceConfig - -type precedenceConfig struct { - ipNet *net.IPNet - value int -} - -func init() { - // Initializing precedences for IP. - /* - ::1/128 50 0 - ::/0 40 1 - ::ffff:0:0/96 35 4 - 2002::/16 30 2 - 2001::/32 5 5 - fc00::/7 3 13 - ::/96 1 3 - fec0::/10 1 11 - 3ffe::/16 1 12 - */ - for i, p := range [precedencesCount]struct { - cidr string - value int - label int - }{ - {"::1/128", 50, 0}, - {"127.0.0.1/8", 45, 0}, - {"::/0", 40, 1}, - {"::ffff:0:0/96", 35, 4}, - {"fe80::/10", 33, 1}, - {"2002::/16", 30, 2}, - {"2001::/32", 5, 5}, - {"fc00::/7", 3, 13}, - {"::/96", 1, 3}, - {"fec0::/10", 1, 11}, - {"3ffe::/16", 1, 12}, - } { - _, ipNet, err := net.ParseCIDR(p.cidr) - if err != nil { - panic(err) - } - precedences[i] = precedenceConfig{ - ipNet: ipNet, - value: p.value, - } - } -} - -// Addr represents gathered address from interface. -type Addr struct { - IP net.IP - Zone string - Precedence int -} - -// Addrs is addr slice helper. -type Addrs []Addr - -func (s Addrs) Less(i, j int) bool { - return s[i].Precedence > s[j].Precedence -} - -func (s Addrs) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s Addrs) Len() int { - return len(s) -} - -func (a Addr) String() string { - if len(a.Zone) > 0 { - return fmt.Sprintf("%s (zone %s) [%d]", - a.IP, a.Zone, a.Precedence, - ) - } - return fmt.Sprintf("%s [%d]", a.IP, a.Precedence) -} - -// ZeroPortAddr return address with "0" port. -func (a Addr) ZeroPortAddr() string { - host := a.IP.String() - if len(a.Zone) > 0 { - host += "%" + a.Zone - } - return net.JoinHostPort(host, "0") -} - -type defaultGatherer struct{} - -func (defaultGatherer) precedence(ip net.IP) int { - for _, p := range precedences { - if p.ipNet.Contains(ip) { - return p.value - } - } - return 0 -} - -func (g defaultGatherer) Gather() ([]Addr, error) { - interfaces, err := net.Interfaces() - if err != nil { - return nil, err - } - addrs := make([]Addr, 0, 10) - for _, iface := range interfaces { - iAddrs, err := iface.Addrs() - if err != nil { - return addrs, err - } - for _, a := range iAddrs { - ip, _, err := net.ParseCIDR(a.String()) - if err != nil { - return addrs, err - } - addr := Addr{ - IP: ip, - Precedence: g.precedence(ip), - } - if ip.IsLinkLocalUnicast() { - // Zone must be set for link-local addresses. - addr.Zone = iface.Name - } - addrs = append(addrs, addr) - } - } - sort.Sort(Addrs(addrs)) - return addrs, nil -} - -// DefaultGatherer uses net.Interfaces to gather addresses. -var DefaultGatherer Gatherer = defaultGatherer{} - // Gather via DefaultGatherer. -func Gather() ([]Addr, error) { - return DefaultGatherer.Gather() +func Gather() ([]gather.Addr, error) { + return gather.DefaultGatherer.Gather() } diff --git a/vendor/github.com/gortc/ice/gather/gather.go b/vendor/github.com/gortc/ice/gather/gather.go new file mode 100644 index 0000000..6ef4bba --- /dev/null +++ b/vendor/github.com/gortc/ice/gather/gather.go @@ -0,0 +1,168 @@ +package gather + +import ( + "bytes" + "fmt" + "net" + "sort" + + "github.com/gortc/ice/internal" +) + +const precedencesCount = 11 + +var precedences [precedencesCount]precedenceConfig + +type precedenceConfig struct { + ipNet *net.IPNet + value int +} + +// Gatherer is source for addresses. +// +// See RFC 8445 Section 2.1 for details on gathering. +type Gatherer interface { + Gather() ([]Addr, error) +} + +func init() { + // Initializing policy table. + // See RFC 6724 Section 2.1. + /* + ::1/128 50 0 + ::/0 40 1 + ::ffff:0:0/96 35 4 + 2002::/16 30 2 + 2001::/32 5 5 + fc00::/7 3 13 + ::/96 1 3 + fec0::/10 1 11 + 3ffe::/16 1 12 + */ + for i, p := range [precedencesCount]struct { + cidr string + value int + label int + }{ + {"::1/128", 50, 0}, + {"127.0.0.1/8", 45, 0}, + {"::/0", 40, 1}, + {"::ffff:0:0/96", 35, 4}, + {"fe80::/10", 33, 1}, + {"2002::/16", 30, 2}, + {"2001::/32", 5, 5}, + {"fc00::/7", 3, 13}, + {"::/96", 1, 3}, + {"fec0::/10", 1, 11}, + {"3ffe::/16", 1, 12}, + } { + precedences[i] = precedenceConfig{ + ipNet: internal.MustParseNet(p.cidr), + value: p.value, + } + } +} + +// Addr represents gathered address from interface. +type Addr struct { + IP net.IP + Zone string + Precedence int +} + +// Addrs is addr slice helper. +type Addrs []Addr + +func (s Addrs) Less(i, j int) bool { + si, sj := s[i], s[j] + if si.Precedence == sj.Precedence { + // Comparing IP's to make stable sort. + return bytes.Compare(si.IP, sj.IP) < 0 + } + return si.Precedence > sj.Precedence +} + +func (s Addrs) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s Addrs) Len() int { + return len(s) +} + +func (a Addr) String() string { + if len(a.Zone) > 0 { + return fmt.Sprintf("%s (zone %s) [%d]", + a.IP, a.Zone, a.Precedence, + ) + } + return fmt.Sprintf("%s [%d]", a.IP, a.Precedence) +} + +// ZeroPortAddr return address with "0" port. +func (a Addr) ZeroPortAddr() string { + host := a.IP.String() + if len(a.Zone) > 0 { + host += "%" + a.Zone + } + return net.JoinHostPort(host, "0") +} + +type defaultGatherer struct{} + +func precedence(ip net.IP) int { + for _, p := range precedences { + if p.ipNet.Contains(ip) { + return p.value + } + } + return 0 +} + +type netInterface interface { + Addrs() ([]net.Addr, error) +} + +func ifaceToAddr(i netInterface, name string) ([]Addr, error) { + var addrs []Addr + netAddrs, err := i.Addrs() + if err != nil { + return addrs, err + } + for _, a := range netAddrs { + ip, _, err := net.ParseCIDR(a.String()) + if err != nil { + return addrs, err + } + addr := Addr{ + IP: ip, + Precedence: precedence(ip), + } + if ip.IsLinkLocalUnicast() { + // Zone must be set for link-local addresses. + addr.Zone = name + } + addrs = append(addrs, addr) + } + return addrs, nil +} + +func (g defaultGatherer) Gather() ([]Addr, error) { + interfaces, err := net.Interfaces() + if err != nil { + return nil, err + } + addrs := make([]Addr, 0, 10) + for _, iface := range interfaces { + ifaceAddrs, err := ifaceToAddr(&iface, iface.Name) + if err != nil { + return addrs, err + } + addrs = append(addrs, ifaceAddrs...) + } + sort.Sort(Addrs(addrs)) + return addrs, nil +} + +// DefaultGatherer uses net.Interfaces to gather addresses. +var DefaultGatherer Gatherer = defaultGatherer{} diff --git a/vendor/github.com/gortc/ice/host.go b/vendor/github.com/gortc/ice/host.go new file mode 100644 index 0000000..f6ea013 --- /dev/null +++ b/vendor/github.com/gortc/ice/host.go @@ -0,0 +1,163 @@ +package ice + +import ( + "net" + + "github.com/gortc/ice/gather" + "github.com/gortc/ice/internal" +) + +// See Deprecating Site Local Addresses [RFC3879] +var siteLocalIPv6 = internal.MustParseNet("FEC0::/10") + +// IsHostIPValid reports whether ip is valid as host address ip. +func IsHostIPValid(ip net.IP, ipv6Only bool) bool { + var ( + v4 = ip.To4() != nil + v6 = !v4 + ) + if v6 && ip.To16() == nil { + return false + } + if v4 && ipv6Only { + // IPv4-mapped IPv6 addresses SHOULD NOT be included in the address + // candidates unless the application using ICE does not support IPv4 + // (i.e., it is an IPv6-only application [RFC4038]). + return false + } + if ip.IsLoopback() { + // Addresses from a loopback interface MUST NOT be included in the + // candidate addresses. + return false + } + if siteLocalIPv6.Contains(ip) { + // Deprecated IPv4-compatible IPv6 addresses [RFC4291] and IPv6 site- + // local unicast addresses [RFC3879] MUST NOT be included in the + // address candidates. + return false + } + if ip.IsLinkLocalUnicast() && v6 { + // When host candidates corresponding to an IPv6 address generated + // using a mechanism that prevents location tracking are gathered, then + // host candidates corresponding to IPv6 link-local addresses [RFC4291] + // MUST NOT be gathered. + return false + } + return true +} + +// HostAddr wraps IP of host interface and local preference. +type HostAddr struct { + IP net.IP + LocalPreference int +} + +// v4 and v6 length must be non-zero, and len(v4) + len(v6) must be len(all). +func processDualStack(all, v4, v6 []gather.Addr) []HostAddr { + var ( + v6InARow int + ) + nHi := (len(v6) + len(v4)) / len(v4) + hostAddrs := make([]HostAddr, 0, len(all)) + for i := 0; i < len(all); i++ { + useV6 := true + if v6InARow >= nHi { + v6InARow = 0 + useV6 = false + } + pref := len(all) - i + if useV6 && len(v6) > 0 { + v6InARow++ + hostAddrs = append(hostAddrs, HostAddr{ + IP: v6[0].IP, + LocalPreference: pref, + }) + v6 = v6[1:] + } else if len(v4) > 0 { + hostAddrs = append(hostAddrs, HostAddr{ + IP: v4[0].IP, + LocalPreference: pref, + }) + v4 = v4[1:] + } + } + return hostAddrs +} + +func isV6Only(addrs []gather.Addr) bool { + v6Only := true + for _, addr := range addrs { + if addr.IP.To4() != nil { + v6Only = false + break + } + } + return v6Only +} + +func filterValid(gathered []gather.Addr) []gather.Addr { + valid := make([]gather.Addr, 0, len(gathered)) + v6Only := isV6Only(gathered) + for _, addr := range gathered { + if !IsHostIPValid(addr.IP, v6Only) { + continue + } + valid = append(valid, addr) + } + return valid +} + +const ( + // When there is only a single IP address, this value SHOULD be + // set to 65535. + singleIPAddrPreference = 65535 +) + +// HostAddresses returns valid host addresses from gathered addresses with +// calculated local preference. +// +// When gathered addresses are only IPv6, the host is considered ipv6-only. +// When there are both IPv6 and IPv4 addresses, the RFC 8421 is used to +// calculate local preferences. +func HostAddresses(gathered []gather.Addr) ([]HostAddr, error) { + if len(gathered) == 0 { + return []HostAddr{}, nil + } + validOnly := filterValid(gathered) + if len(validOnly) == 0 { + return []HostAddr{}, nil + } + if len(validOnly) == 1 { + // Setting local preference for single IP as defined + // in RFC 8445 Section 5.1.2.1. + return []HostAddr{ + { + IP: validOnly[0].IP, + LocalPreference: singleIPAddrPreference, + }, + }, nil + } + var ( + v6Addrs, v4Addrs []gather.Addr + ) + for _, addr := range validOnly { + if addr.IP.To4() == nil { + v6Addrs = append(v6Addrs, addr) + } else { + v4Addrs = append(v4Addrs, addr) + } + } + if len(v4Addrs) == 0 || len(v6Addrs) == 0 { + // Single-stack and multi-homed. + hostAddrs := make([]HostAddr, 0, len(validOnly)) + for i, a := range validOnly { + hostAddrs = append(hostAddrs, HostAddr{ + IP: a.IP, + LocalPreference: len(validOnly) - i, + }) + } + return hostAddrs, nil + } + // Dual-stack calculation as defined in RFC 8421. + return processDualStack(validOnly, v4Addrs, v6Addrs), nil +} diff --git a/vendor/github.com/gortc/ice/ice.go b/vendor/github.com/gortc/ice/ice.go index b08987a..815cae5 100644 --- a/vendor/github.com/gortc/ice/ice.go +++ b/vendor/github.com/gortc/ice/ice.go @@ -3,9 +3,31 @@ // A Protocol for Network Address Translator (NAT) Traversal package ice -import ( - "encoding/binary" -) +import "encoding/binary" // bin is shorthand for BigEndian. var bin = binary.BigEndian + +// State represents the ICE agent state. +// +// As per RFC 8445 Section 6.1.3, the ICE agent has a state determined by the +// state of the checklists. The state is Completed if all checklists are +// Completed, Failed if all checklists are Failed, or Running otherwise. +type State byte + +const ( + // Running if all checklists are nor completed not failed. + Running State = iota + // Completed if all checklists are completed. + Completed + // Failed if all checklists are failed. + Failed +) + +var stateToStr = map[State]string{ + Running: "Running", + Completed: "Completed", + Failed: "Failed", +} + +func (s State) String() string { return stateToStr[s] } diff --git a/vendor/github.com/gortc/ice/icecontrol.go b/vendor/github.com/gortc/ice/icecontrol.go index ffa285f..5d4b824 100644 --- a/vendor/github.com/gortc/ice/icecontrol.go +++ b/vendor/github.com/gortc/ice/icecontrol.go @@ -29,28 +29,28 @@ func (a *tieBreaker) GetFromAs(m *stun.Message, t stun.AttrType) error { return nil } -// Controlled represents ICE-CONTROLLED attribute. -type Controlled uint64 +// AttrControlled represents ICE-CONTROLLED attribute. +type AttrControlled uint64 // AddTo adds ICE-CONTROLLED to message. -func (c Controlled) AddTo(m *stun.Message) error { +func (c AttrControlled) AddTo(m *stun.Message) error { return tieBreaker(c).AddToAs(m, stun.AttrICEControlled) } // GetFrom decodes ICE-CONTROLLED from message. -func (c *Controlled) GetFrom(m *stun.Message) error { +func (c *AttrControlled) GetFrom(m *stun.Message) error { return (*tieBreaker)(c).GetFromAs(m, stun.AttrICEControlled) } -// Controlling represents ICE-CONTROLLING attribute. -type Controlling uint64 +// AttrControlling represents ICE-CONTROLLING attribute. +type AttrControlling uint64 // AddTo adds ICE-CONTROLLING to message. -func (c Controlling) AddTo(m *stun.Message) error { +func (c AttrControlling) AddTo(m *stun.Message) error { return tieBreaker(c).AddToAs(m, stun.AttrICEControlling) } // GetFrom decodes ICE-CONTROLLING from message. -func (c *Controlling) GetFrom(m *stun.Message) error { +func (c *AttrControlling) GetFrom(m *stun.Message) error { return (*tieBreaker)(c).GetFromAs(m, stun.AttrICEControlling) } diff --git a/vendor/github.com/gortc/ice/internal/net.go b/vendor/github.com/gortc/ice/internal/net.go new file mode 100644 index 0000000..a6f5bb0 --- /dev/null +++ b/vendor/github.com/gortc/ice/internal/net.go @@ -0,0 +1,11 @@ +package internal + +import "net" + +func MustParseNet(n string) *net.IPNet { + _, parsedNet, err := net.ParseCIDR(n) + if err != nil { + panic(err) + } + return parsedNet +} diff --git a/vendor/github.com/gortc/ice/pair.go b/vendor/github.com/gortc/ice/pair.go new file mode 100644 index 0000000..b173690 --- /dev/null +++ b/vendor/github.com/gortc/ice/pair.go @@ -0,0 +1,126 @@ +package ice + +import "net" + +func min(a, b int64) int64 { + if a < b { + return a + } + return b +} + +func max(a, b int64) int64 { + if a > b { + return a + } + return b +} + +// PairPriority computes Pair Priority as in RFC 8445 Section 6.1.2.3. +func PairPriority(controlling, controlled int) int64 { + var ( + g = int64(controlling) + d = int64(controlled) + ) + // pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0) + v := (1<<32)*min(g, d) + 2*max(g, d) + if g > d { + v++ + } + return v +} + +// Pair wraps two candidates, one is local, other is remote. +type Pair struct { + Local Candidate + Remote Candidate + Priority int64 + State PairState +} + +// PairState as defined in RFC 8445 Section 6.1.2.6. +type PairState byte + +var pairStateToStr = map[PairState]string{ + PairWaiting: "Waiting", + PairInProgress: "In-Progress", + PairSucceeded: "Succeeded", + PairFailed: "Failed", + PairFrozen: "Frozen", +} + +func (s PairState) String() string { return pairStateToStr[s] } + +const ( + // PairFrozen state: A check for this pair has not been sent, and it cannot + // be sent until the pair is unfrozen and moved into the Waiting state. + PairFrozen PairState = iota + // PairInProgress state: A check has been sent for this pair, but the + // transaction is in progress. + PairInProgress + // PairSucceeded state: A check has been sent for this pair, and it produced + // a successful result. + PairSucceeded + // PairFailed state: A check has been sent for this pair, and it failed (a + // response to the check was never received, or a failure response was + // received). + PairFailed + // PairWaiting state: A check has not been sent for this pair, but the pair + // is not Frozen. + PairWaiting +) + +// Foundation is combination of candidates foundations. +func (p Pair) Foundation() []byte { + f := make([]byte, foundationLength*2) + copy(f[:foundationLength], p.Local.Foundation) + copy(f[foundationLength:], p.Remote.Foundation) + return f +} + +// Pairs is ordered slice of Pair elements. +type Pairs []Pair + +func (p Pairs) Len() int { return len(p) } +func (p Pairs) Less(i, j int) bool { return p[i].Priority > p[j].Priority } +func (p Pairs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func sameFamily(a, b net.IP) bool { + return len(a.To4()) == len(b.To4()) +} + +// NewPairs pairs each local candidate with each remote candidate for the same +// component of the same data stream with the same IP address family. Candidates +// should be sorted by priority in descending order, which is default order for +// the Candidates type. Populates only Local and Remote fields of Pair. +// +// See RFC 8445 Section 6.1.2.2. +func NewPairs(local, remote Candidates) Pairs { + p := make(Pairs, 0, 100) + for l := range local { + for r := range remote { + // Same data stream. + if local[l].ComponentID != remote[r].ComponentID { + continue + } + var ( + ipL, ipR = local[l].Addr.IP, remote[r].Addr.IP + ) + // Same IP address family. + if !sameFamily(ipL, ipR) { + continue + } + if ipL.To4() == nil && ipL.IsLinkLocalUnicast() { + // IPv6 link-local addresses MUST NOT be paired with other + // than link-local addresses. + if !ipR.IsLinkLocalUnicast() { + continue + } + } + p = append(p, Pair{ + Local: local[l], Remote: local[r], + }) + } + } + return p +} diff --git a/vendor/github.com/gortc/ice/priority.go b/vendor/github.com/gortc/ice/priority.go index 8e70075..2756d9b 100644 --- a/vendor/github.com/gortc/ice/priority.go +++ b/vendor/github.com/gortc/ice/priority.go @@ -2,13 +2,13 @@ package ice import "github.com/gortc/stun" -// Priority represents PRIORITY attribute. -type Priority uint32 +// PriorityAttr represents PRIORITY attribute. +type PriorityAttr uint32 const prioritySize = 4 // 32 bit // AddTo adds PRIORITY attribute to message. -func (p Priority) AddTo(m *stun.Message) error { +func (p PriorityAttr) AddTo(m *stun.Message) error { v := make([]byte, prioritySize) bin.PutUint32(v, uint32(p)) m.Add(stun.AttrPriority, v) @@ -16,7 +16,7 @@ func (p Priority) AddTo(m *stun.Message) error { } // GetFrom decodes PRIORITY attribute from message. -func (p *Priority) GetFrom(m *stun.Message) error { +func (p *PriorityAttr) GetFrom(m *stun.Message) error { v, err := m.Get(stun.AttrPriority) if err != nil { return err @@ -24,6 +24,6 @@ func (p *Priority) GetFrom(m *stun.Message) error { if err = stun.CheckSize(stun.AttrPriority, len(v), prioritySize); err != nil { return err } - *p = Priority(bin.Uint32(v)) + *p = PriorityAttr(bin.Uint32(v)) return nil } diff --git a/vendor/github.com/gortc/ice/sdp/sdp.go b/vendor/github.com/gortc/ice/sdp/sdp.go index 7bab58c..3dd8a15 100644 --- a/vendor/github.com/gortc/ice/sdp/sdp.go +++ b/vendor/github.com/gortc/ice/sdp/sdp.go @@ -1,4 +1,8 @@ -// Package sdp implements SDP parsing for ICE. +// Package sdp implements Session Description Protocol (SDP) Offer/Answer +// procedures for Interactive Connectivity Establishment (ICE). +// +// Currently this implementation is based on the following Internet Draft: +// https://tools.ietf.org/html/draft-ietf-mmusic-ice-sip-sdp-21 package sdp import ( @@ -8,15 +12,41 @@ import ( "strconv" "unsafe" - c "github.com/gortc/ice/candidate" - "github.com/pkg/errors" + ct "github.com/gortc/ice/candidate" +) + +// AddressType is type for Address. +type AddressType byte + +// Possible address types. +const ( + AddressIPv4 AddressType = iota + AddressIPv6 + AddressFQDN ) +func strOrUnknown(str string) string { + if len(str) == 0 { + return "unknown" + } + return str +} + +var addressTypeToStr = map[AddressType]string{ + AddressIPv4: "IPv4", + AddressIPv6: "IPv6", + AddressFQDN: "FQDN", +} + +func (a AddressType) String() string { + return strOrUnknown(addressTypeToStr[a]) +} + // Address represents address that can be ipv4/6 or FQDN. type Address struct { Host []byte IP net.IP - Type c.AddressType + Type AddressType } // reset sets all fields to zero values. @@ -25,7 +55,7 @@ func (a *Address) reset() { for i := range a.IP { a.IP[i] = 0 } - a.Type = c.AddressIPv4 + a.Type = AddressIPv4 } // Equal returns true if b equals to a. @@ -34,7 +64,7 @@ func (a Address) Equal(b Address) bool { return false } switch a.Type { - case c.AddressFQDN: + case AddressFQDN: return bytes.Equal(a.Host, b.Host) default: return a.IP.Equal(b.IP) @@ -43,7 +73,7 @@ func (a Address) Equal(b Address) bool { func (a Address) str() string { switch a.Type { - case c.AddressFQDN: + case AddressFQDN: return string(a.Host) default: return a.IP.String() @@ -71,12 +101,12 @@ const ( type Candidate struct { ConnectionAddress Address Port int - Transport c.TransportType + Transport ct.Protocol TransportValue []byte Foundation int ComponentID int Priority int - Type c.Type + Type ct.Type RelatedAddress Address RelatedPort int @@ -89,50 +119,50 @@ type Candidate struct { } // Reset sets all fields to zero values. -func (ct *Candidate) Reset() { - ct.ConnectionAddress.reset() - ct.RelatedAddress.reset() - ct.RelatedPort = 0 - ct.NetworkCost = 0 - ct.Generation = 0 - ct.Transport = c.TransportUnknown - ct.TransportValue = ct.TransportValue[:0] - ct.Attributes = ct.Attributes[:0] -} - -// Equal returns true if b candidate is equal to c. -func (ct Candidate) Equal(b *Candidate) bool { - if !ct.ConnectionAddress.Equal(b.ConnectionAddress) { +func (c *Candidate) Reset() { + c.ConnectionAddress.reset() + c.RelatedAddress.reset() + c.RelatedPort = 0 + c.NetworkCost = 0 + c.Generation = 0 + c.Transport = ct.ProtocolUnknown + c.TransportValue = c.TransportValue[:0] + c.Attributes = c.Attributes[:0] +} + +// Equal returns true if b candidate is equal to ct. +func (c Candidate) Equal(b *Candidate) bool { + if !c.ConnectionAddress.Equal(b.ConnectionAddress) { return false } - if ct.Port != b.Port { + if c.Port != b.Port { return false } - if ct.Transport != b.Transport { + if c.Transport != b.Transport { return false } - if !bytes.Equal(ct.TransportValue, b.TransportValue) { + if !bytes.Equal(c.TransportValue, b.TransportValue) { return false } - if ct.Foundation != b.Foundation { + if c.Foundation != b.Foundation { return false } - if ct.ComponentID != b.ComponentID { + if c.ComponentID != b.ComponentID { return false } - if ct.Priority != b.Priority { + if c.Priority != b.Priority { return false } - if ct.Type != b.Type { + if c.Type != b.Type { return false } - if ct.NetworkCost != b.NetworkCost { + if c.NetworkCost != b.NetworkCost { return false } - if ct.Generation != b.Generation { + if c.Generation != b.Generation { return false } - if !ct.Attributes.Equal(b.Attributes) { + if !c.Attributes.Equal(b.Attributes) { return false } return true @@ -216,7 +246,7 @@ func parseInt(v []byte) (int, error) { func (p *candidateParser) parseFoundation(v []byte) error { i, err := parseInt(v) if err != nil { - return errors.Wrap(err, "failed to parse foundation") + return fmt.Errorf("failed to parse foundation: %v", err) } p.c.Foundation = i return nil @@ -225,7 +255,7 @@ func (p *candidateParser) parseFoundation(v []byte) error { func (p *candidateParser) parseComponentID(v []byte) error { i, err := parseInt(v) if err != nil { - return errors.Wrap(err, "failed to parse component ID") + return fmt.Errorf("failed to parse component ID: %v", err) } p.c.ComponentID = i return nil @@ -234,7 +264,7 @@ func (p *candidateParser) parseComponentID(v []byte) error { func (p *candidateParser) parsePriority(v []byte) error { i, err := parseInt(v) if err != nil { - return errors.Wrap(err, "failed to parse priority") + return fmt.Errorf("failed to parse priority: %v", err) } p.c.Priority = i return nil @@ -243,7 +273,7 @@ func (p *candidateParser) parsePriority(v []byte) error { func (p *candidateParser) parsePort(v []byte) error { i, err := parseInt(v) if err != nil { - return errors.Wrap(err, "failed to parse port") + return fmt.Errorf("failed to parse port: %v", err) } p.c.Port = i return nil @@ -252,7 +282,7 @@ func (p *candidateParser) parsePort(v []byte) error { func (p *candidateParser) parseRelatedPort(v []byte) error { i, err := parseInt(v) if err != nil { - return errors.Wrap(err, "failed to parse port") + return fmt.Errorf("failed to parse port: %v", err) } p.c.RelatedPort = i return nil @@ -275,12 +305,12 @@ func (candidateParser) parseAddress(v []byte, target *Address) error { target.IP = parseIP(target.IP, v) if target.IP == nil { target.Host = v - target.Type = c.AddressFQDN + target.Type = AddressFQDN return nil } - target.Type = c.AddressIPv6 + target.Type = AddressIPv6 if target.IP.To4() != nil { - target.Type = c.AddressIPv4 + target.Type = AddressIPv4 } return nil } @@ -295,9 +325,9 @@ func (p *candidateParser) parseRelatedAddress(v []byte) error { func (p *candidateParser) parseTransport(v []byte) error { if bytes.Equal(v, []byte("udp")) || bytes.Equal(v, []byte("UDP")) { - p.c.Transport = c.TransportUDP + p.c.Transport = ct.UDP } else { - p.c.Transport = c.TransportUnknown + p.c.Transport = ct.ProtocolUnknown p.c.TransportValue = v } return nil @@ -339,7 +369,7 @@ const ( // parse populates internal Candidate from buffer. func (p *candidateParser) parse() error { if len(p.buf) < minBufLen { - return errors.Errorf("buffer too small (%d < %d)", len(p.buf), minBufLen) + return fmt.Errorf("buffer too small (%d < %d)", len(p.buf), minBufLen) } // special cases for raw value support: if p.buf[0] == 'a' { @@ -374,8 +404,8 @@ func (p *candidateParser) parse() error { } // space character reached if err := fns[pos](p.buf[i-l : i]); err != nil { - return errors.Wrapf(err, "failed to parse char %d, pos %d", - i, pos, + return fmt.Errorf("failed to parse char %d, pos %d: %v", + i, pos, err, ) } pos++ // next element @@ -432,8 +462,8 @@ func (p *candidateParser) parse() error { Value: buf[vStart:i], } if err := p.parseAttribute(a); err != nil { - return errors.Wrapf(err, "failed to parse attribute at char %d", - i+last, + return fmt.Errorf("failed to parse attribute at char %d: %v", + i+last, err, ) } // reset offset @@ -447,7 +477,7 @@ func (p *candidateParser) parse() error { func (p *candidateParser) parseNetworkCost(v []byte) error { i, err := parseInt(v) if err != nil { - return errors.Wrap(err, "failed to parse network cost") + return fmt.Errorf("failed to parse network cost: %v", err) } p.c.NetworkCost = i return nil @@ -456,7 +486,7 @@ func (p *candidateParser) parseNetworkCost(v []byte) error { func (p *candidateParser) parseGeneration(v []byte) error { i, err := parseInt(v) if err != nil { - return errors.Wrap(err, "failed to parse generation") + return fmt.Errorf("failed to parse generation: %v", err) } p.c.Generation = i return nil @@ -465,20 +495,20 @@ func (p *candidateParser) parseGeneration(v []byte) error { func (p *candidateParser) parseType(v []byte) error { switch string(v) { case sdpCandidateHost: - p.c.Type = c.Host + p.c.Type = ct.Host case sdpCandidatePeerReflexive: - p.c.Type = c.PeerReflexive + p.c.Type = ct.PeerReflexive case sdpCandidateRelay: - p.c.Type = c.Relay + p.c.Type = ct.Relayed case sdpCandidateServerReflexive: - p.c.Type = c.ServerReflexive + p.c.Type = ct.ServerReflexive default: - return errors.Errorf("unknown candidate %q", v) + return fmt.Errorf("unknown candidate %q", v) } return nil } -// ParseAttribute parses v into c and returns error if any. +// ParseAttribute parses v into ct and returns error if any. func ParseAttribute(v []byte, c *Candidate) error { p := candidateParser{ buf: v,