mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
For regression test, add srs-bench to 3rdparty
This commit is contained in:
parent
de87dd427d
commit
876210f6c9
1158 changed files with 256967 additions and 3 deletions
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.gitignore
generated
vendored
Normal file
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
### JetBrains IDE ###
|
||||
#####################
|
||||
.idea/
|
||||
|
||||
### Emacs Temporary Files ###
|
||||
#############################
|
||||
*~
|
||||
|
||||
### Folders ###
|
||||
###############
|
||||
bin/
|
||||
vendor/
|
||||
node_modules/
|
||||
|
||||
### Files ###
|
||||
#############
|
||||
*.ivf
|
||||
*.ogg
|
||||
tags
|
||||
cover.out
|
||||
*.sw[poe]
|
||||
*.wasm
|
||||
examples/sfu-ws/cert.pem
|
||||
examples/sfu-ws/key.pem
|
89
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.golangci.yml
generated
vendored
Normal file
89
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.golangci.yml
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
misspell:
|
||||
locale: US
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
gomodguard:
|
||||
blocked:
|
||||
modules:
|
||||
- github.com/pkg/errors:
|
||||
recommendations:
|
||||
- errors
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
|
||||
- bodyclose # checks whether HTTP response body is closed successfully
|
||||
- deadcode # Finds unused code
|
||||
- depguard # Go linter that checks if package imports are in a list of acceptable packages
|
||||
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
|
||||
- dupl # Tool for code clone detection
|
||||
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
|
||||
- exhaustive # check exhaustiveness of enum switch statements
|
||||
- exportloopref # checks for pointers to enclosing loop variables
|
||||
- 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
|
||||
- godox # Tool for detection of FIXME, TODO and other comment keywords
|
||||
- goerr113 # 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
|
||||
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
||||
- 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
|
||||
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||
- ineffassign # Detects when assignments to existing variables are not used
|
||||
- misspell # Finds commonly misspelled English words in comments
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||
- noctx # noctx finds sending http request without context.Context
|
||||
- scopelint # Scopelint checks for unpinned variables in go programs
|
||||
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
|
||||
- structcheck # Finds unused struct fields
|
||||
- stylecheck # Stylecheck is a replacement for golint
|
||||
- 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
|
||||
- varcheck # Finds unused global variables and constants
|
||||
- whitespace # Tool for detection of leading and trailing whitespace
|
||||
disable:
|
||||
- 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.
|
||||
- lll # Reports long lines
|
||||
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted
|
||||
- nestif # Reports deeply nested if statements
|
||||
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity
|
||||
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||
- prealloc # Finds slice declarations that could potentially be preallocated
|
||||
- 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
|
||||
- wsl # Whitespace Linter - Forces you to use empty lines!
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
exclude-rules:
|
||||
# Allow complex tests, better to be self contained
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
# Allow complex main function in examples
|
||||
- path: examples
|
||||
text: "of func `main` is high"
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
run:
|
||||
skip-dirs-use-default: false
|
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/LICENSE
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
66
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/README.md
generated
vendored
Normal file
66
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/README.md
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
<h1 align="center">
|
||||
<br>
|
||||
Pion ICE
|
||||
<br>
|
||||
</h1>
|
||||
<h4 align="center">A Go implementation of ICE</h4>
|
||||
<p align="center">
|
||||
<a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-ice-gray.svg?longCache=true&colorB=brightgreen" alt="Pion transport"></a>
|
||||
<a href="http://gophers.slack.com/messages/pion"><img src="https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen" alt="Slack Widget"></a>
|
||||
<br>
|
||||
<a href="https://travis-ci.org/pion/ice"><img src="https://travis-ci.org/pion/ice.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/ice"><img src="https://godoc.org/github.com/pion/ice?status.svg" alt="GoDoc"></a>
|
||||
<a href="https://codecov.io/gh/pion/ice"><img src="https://codecov.io/gh/pion/ice/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/ice"><img src="https://goreportcard.com/badge/github.com/pion/ice" alt="Go Report Card"></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
||||
</p>
|
||||
<br>
|
||||
|
||||
### Roadmap
|
||||
The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones.
|
||||
|
||||
### Community
|
||||
Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion).
|
||||
|
||||
We are always looking to support **your projects**. Please reach out if you have something to build!
|
||||
|
||||
If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly)
|
||||
|
||||
### Contributing
|
||||
Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible:
|
||||
|
||||
* [John Bradley](https://github.com/kc5nra) - *Original Author*
|
||||
* [Sean DuBois](https://github.com/Sean-Der) - *Original Author*
|
||||
* [Michael MacDonald](https://github.com/mjmac) - *Original Author*
|
||||
* [Michiel De Backker](https://github.com/backkem) - *Original Author*
|
||||
* [Konstantin Itskov](https://github.com/trivigy) - *Original Author*
|
||||
* [Luke Curley](https://github.com/kixelated)
|
||||
* [Hugo Arregui](https://github.com/hugoArregui)
|
||||
* [Adam Kiss](https://github.com/masterada)
|
||||
* [Aleksandr Razumov](https://github.com/ernado)
|
||||
* [Yutaka Takeda](https://github.com/enobufs)
|
||||
* [Atsushi Watanabe](https://github.com/at-wat)
|
||||
* [Robert Eperjesi](https://github.com/epes)
|
||||
* [Sebastian Waisbrot](https://github.com/seppo0010)
|
||||
* [Zizheng Tai](https://github.com/ZizhengTai)
|
||||
* [Aaron France](https://github.com/AeroNotix)
|
||||
* [Chao Yuan](https://github.com/yuanchao0310)
|
||||
* [Jason Maldonis](https://github.com/jjmaldonis)
|
||||
* [Nevio Vesic](https://github.com/0x19)
|
||||
* [David Hamilton](https://github.com/dihamilton)
|
||||
* [adwpc](https://github.com/adwpc)
|
||||
* [Ori Bernstein](https://eigenstate.org)
|
||||
* [Sam Lancia](https://github.com/nerd2)
|
||||
* [Lander Noterman](https://github.com/LanderN)
|
||||
* [BUPTCZQ](https://github.com/buptczq)
|
||||
* [Henry](https://github.com/cryptix)
|
||||
* [Jerko Steiner](https://github.com/jeremija)
|
||||
* [Sidney San Martín](https://github.com/s4y)
|
||||
* [JooYoung Lim](https://github.com/DevRockstarZ)
|
||||
* [Kory Miller](https://github.com/korymiller1489)
|
||||
* [ZHENK](https://github.com/scorpionknifes)
|
||||
* [Assad Obaid](https://github.com/assadobaid)
|
||||
* [Antoine Baché](https://github.com/Antonito)
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
1233
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent.go
generated
vendored
Normal file
1233
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
252
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_config.go
generated
vendored
Normal file
252
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_config.go
generated
vendored
Normal file
|
@ -0,0 +1,252 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/transport/vnet"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultCheckInterval is the interval at which the agent performs candidate checks in the connecting phase
|
||||
defaultCheckInterval = 200 * time.Millisecond
|
||||
|
||||
// keepaliveInterval used to keep candidates alive
|
||||
defaultKeepaliveInterval = 2 * time.Second
|
||||
|
||||
// defaultDisconnectedTimeout is the default time till an Agent transitions disconnected
|
||||
defaultDisconnectedTimeout = 5 * time.Second
|
||||
|
||||
// defaultFailedTimeout is the default time till an Agent transitions to failed after disconnected
|
||||
defaultFailedTimeout = 25 * time.Second
|
||||
|
||||
// wait time before nominating a host candidate
|
||||
defaultHostAcceptanceMinWait = 0
|
||||
|
||||
// wait time before nominating a srflx candidate
|
||||
defaultSrflxAcceptanceMinWait = 500 * time.Millisecond
|
||||
|
||||
// wait time before nominating a prflx candidate
|
||||
defaultPrflxAcceptanceMinWait = 1000 * time.Millisecond
|
||||
|
||||
// wait time before nominating a relay candidate
|
||||
defaultRelayAcceptanceMinWait = 2000 * time.Millisecond
|
||||
|
||||
// max binding request before considering a pair failed
|
||||
defaultMaxBindingRequests = 7
|
||||
|
||||
// the number of bytes that can be buffered before we start to error
|
||||
maxBufferSize = 1000 * 1000 // 1MB
|
||||
|
||||
// wait time before binding requests can be deleted
|
||||
maxBindingRequestTimeout = 4000 * time.Millisecond
|
||||
)
|
||||
|
||||
func defaultCandidateTypes() []CandidateType {
|
||||
return []CandidateType{CandidateTypeHost, CandidateTypeServerReflexive, CandidateTypeRelay}
|
||||
}
|
||||
|
||||
// AgentConfig collects the arguments to ice.Agent construction into
|
||||
// a single structure, for future-proofness of the interface
|
||||
type AgentConfig struct {
|
||||
Urls []*URL
|
||||
|
||||
// PortMin and PortMax are optional. Leave them 0 for the default UDP port allocation strategy.
|
||||
PortMin uint16
|
||||
PortMax uint16
|
||||
|
||||
// LocalUfrag and LocalPwd values used to perform connectivity
|
||||
// checks. The values MUST be unguessable, with at least 128 bits of
|
||||
// random number generator output used to generate the password, and
|
||||
// at least 24 bits of output to generate the username fragment.
|
||||
LocalUfrag string
|
||||
LocalPwd string
|
||||
|
||||
// MulticastDNSMode controls mDNS behavior for the ICE agent
|
||||
MulticastDNSMode MulticastDNSMode
|
||||
|
||||
// MulticastDNSHostName controls the hostname for this agent. If none is specified a random one will be generated
|
||||
MulticastDNSHostName string
|
||||
|
||||
// DisconnectedTimeout defaults to 5 seconds when this property is nil.
|
||||
// If the duration is 0, the ICE Agent will never go to disconnected
|
||||
DisconnectedTimeout *time.Duration
|
||||
|
||||
// FailedTimeout defaults to 25 seconds when this property is nil.
|
||||
// If the duration is 0, we will never go to failed.
|
||||
FailedTimeout *time.Duration
|
||||
|
||||
// KeepaliveInterval determines how often should we send ICE
|
||||
// keepalives (should be less then connectiontimeout above)
|
||||
// when this is nil, it defaults to 10 seconds.
|
||||
// A keepalive interval of 0 means we never send keepalive packets
|
||||
KeepaliveInterval *time.Duration
|
||||
|
||||
// NetworkTypes is an optional configuration for disabling or enabling
|
||||
// support for specific network types.
|
||||
NetworkTypes []NetworkType
|
||||
|
||||
// CandidateTypes is an optional configuration for disabling or enabling
|
||||
// support for specific candidate types.
|
||||
CandidateTypes []CandidateType
|
||||
|
||||
LoggerFactory logging.LoggerFactory
|
||||
|
||||
// checkInterval controls how often our internal task loop runs when
|
||||
// in the connecting state. Only useful for testing.
|
||||
checkInterval time.Duration
|
||||
|
||||
// MaxBindingRequests is the max amount of binding requests the agent will send
|
||||
// over a candidate pair for validation or nomination, if after MaxBindingRequests
|
||||
// the candidate is yet to answer a binding request or a nomination we set the pair as failed
|
||||
MaxBindingRequests *uint16
|
||||
|
||||
// Lite agents do not perform connectivity check and only provide host candidates.
|
||||
Lite bool
|
||||
|
||||
// NAT1To1IPCandidateType is used along with NAT1To1IPs to specify which candidate type
|
||||
// the 1:1 NAT IP addresses should be mapped to.
|
||||
// If unspecified or CandidateTypeHost, NAT1To1IPs are used to replace host candidate IPs.
|
||||
// If CandidateTypeServerReflexive, it will insert a srflx candidate (as if it was dervied
|
||||
// from a STUN server) with its port number being the one for the actual host candidate.
|
||||
// Other values will result in an error.
|
||||
NAT1To1IPCandidateType CandidateType
|
||||
|
||||
// NAT1To1IPs contains a list of public IP addresses that are to be used as a host
|
||||
// candidate or srflx candidate. This is used typically for servers that are behind
|
||||
// 1:1 D-NAT (e.g. AWS EC2 instances) and to eliminate the need of server reflexisive
|
||||
// candidate gathering.
|
||||
NAT1To1IPs []string
|
||||
|
||||
// HostAcceptanceMinWait specify a minimum wait time before selecting host candidates
|
||||
HostAcceptanceMinWait *time.Duration
|
||||
// HostAcceptanceMinWait specify a minimum wait time before selecting srflx candidates
|
||||
SrflxAcceptanceMinWait *time.Duration
|
||||
// HostAcceptanceMinWait specify a minimum wait time before selecting prflx candidates
|
||||
PrflxAcceptanceMinWait *time.Duration
|
||||
// HostAcceptanceMinWait specify a minimum wait time before selecting relay candidates
|
||||
RelayAcceptanceMinWait *time.Duration
|
||||
|
||||
// Net is the our abstracted network interface for internal development purpose only
|
||||
// (see github.com/pion/transport/vnet)
|
||||
Net *vnet.Net
|
||||
|
||||
// InterfaceFilter is a function that you can use in order to whitelist or blacklist
|
||||
// the interfaces which are used to gather ICE candidates.
|
||||
InterfaceFilter func(string) bool
|
||||
|
||||
// InsecureSkipVerify controls if self-signed certificates are accepted when connecting
|
||||
// to TURN servers via TLS or DTLS
|
||||
InsecureSkipVerify bool
|
||||
|
||||
// TCPMux will be used for multiplexing incoming TCP connections for ICE TCP.
|
||||
// Currently only passive candidates are supported. This functionality is
|
||||
// experimental and the API might change in the future.
|
||||
TCPMux TCPMux
|
||||
|
||||
// Proxy Dialer is a dialer that should be implemented by the user based on golang.org/x/net/proxy
|
||||
// dial interface in order to support corporate proxies
|
||||
ProxyDialer proxy.Dialer
|
||||
}
|
||||
|
||||
// initWithDefaults populates an agent and falls back to defaults if fields are unset
|
||||
func (config *AgentConfig) initWithDefaults(a *Agent) {
|
||||
if config.MaxBindingRequests == nil {
|
||||
a.maxBindingRequests = defaultMaxBindingRequests
|
||||
} else {
|
||||
a.maxBindingRequests = *config.MaxBindingRequests
|
||||
}
|
||||
|
||||
if config.HostAcceptanceMinWait == nil {
|
||||
a.hostAcceptanceMinWait = defaultHostAcceptanceMinWait
|
||||
} else {
|
||||
a.hostAcceptanceMinWait = *config.HostAcceptanceMinWait
|
||||
}
|
||||
|
||||
if config.SrflxAcceptanceMinWait == nil {
|
||||
a.srflxAcceptanceMinWait = defaultSrflxAcceptanceMinWait
|
||||
} else {
|
||||
a.srflxAcceptanceMinWait = *config.SrflxAcceptanceMinWait
|
||||
}
|
||||
|
||||
if config.PrflxAcceptanceMinWait == nil {
|
||||
a.prflxAcceptanceMinWait = defaultPrflxAcceptanceMinWait
|
||||
} else {
|
||||
a.prflxAcceptanceMinWait = *config.PrflxAcceptanceMinWait
|
||||
}
|
||||
|
||||
if config.RelayAcceptanceMinWait == nil {
|
||||
a.relayAcceptanceMinWait = defaultRelayAcceptanceMinWait
|
||||
} else {
|
||||
a.relayAcceptanceMinWait = *config.RelayAcceptanceMinWait
|
||||
}
|
||||
|
||||
if config.DisconnectedTimeout == nil {
|
||||
a.disconnectedTimeout = defaultDisconnectedTimeout
|
||||
} else {
|
||||
a.disconnectedTimeout = *config.DisconnectedTimeout
|
||||
}
|
||||
|
||||
if config.FailedTimeout == nil {
|
||||
a.failedTimeout = defaultFailedTimeout
|
||||
} else {
|
||||
a.failedTimeout = *config.FailedTimeout
|
||||
}
|
||||
|
||||
if config.KeepaliveInterval == nil {
|
||||
a.keepaliveInterval = defaultKeepaliveInterval
|
||||
} else {
|
||||
a.keepaliveInterval = *config.KeepaliveInterval
|
||||
}
|
||||
|
||||
if config.checkInterval == 0 {
|
||||
a.checkInterval = defaultCheckInterval
|
||||
} else {
|
||||
a.checkInterval = config.checkInterval
|
||||
}
|
||||
|
||||
if config.CandidateTypes == nil || len(config.CandidateTypes) == 0 {
|
||||
a.candidateTypes = defaultCandidateTypes()
|
||||
} else {
|
||||
a.candidateTypes = config.CandidateTypes
|
||||
}
|
||||
}
|
||||
|
||||
func (config *AgentConfig) initExtIPMapping(a *Agent) error {
|
||||
var err error
|
||||
a.extIPMapper, err = newExternalIPMapper(config.NAT1To1IPCandidateType, config.NAT1To1IPs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if a.extIPMapper == nil {
|
||||
return nil // this may happen when config.NAT1To1IPs is an empty array
|
||||
}
|
||||
if a.extIPMapper.candidateType == CandidateTypeHost {
|
||||
if a.mDNSMode == MulticastDNSModeQueryAndGather {
|
||||
return ErrMulticastDNSWithNAT1To1IPMapping
|
||||
}
|
||||
candiHostEnabled := false
|
||||
for _, candiType := range a.candidateTypes {
|
||||
if candiType == CandidateTypeHost {
|
||||
candiHostEnabled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !candiHostEnabled {
|
||||
return ErrIneffectiveNAT1To1IPMappingHost
|
||||
}
|
||||
} else if a.extIPMapper.candidateType == CandidateTypeServerReflexive {
|
||||
candiSrflxEnabled := false
|
||||
for _, candiType := range a.candidateTypes {
|
||||
if candiType == CandidateTypeServerReflexive {
|
||||
candiSrflxEnabled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !candiSrflxEnabled {
|
||||
return ErrIneffectiveNAT1To1IPMappingSrflx
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
113
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go
generated
vendored
Normal file
113
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetCandidatePairsStats returns a list of candidate pair stats
|
||||
func (a *Agent) GetCandidatePairsStats() []CandidatePairStats {
|
||||
var res []CandidatePairStats
|
||||
err := a.run(a.context(), func(ctx context.Context, agent *Agent) {
|
||||
result := make([]CandidatePairStats, 0, len(agent.checklist))
|
||||
for _, cp := range agent.checklist {
|
||||
stat := CandidatePairStats{
|
||||
Timestamp: time.Now(),
|
||||
LocalCandidateID: cp.local.ID(),
|
||||
RemoteCandidateID: cp.remote.ID(),
|
||||
State: cp.state,
|
||||
Nominated: cp.nominated,
|
||||
// PacketsSent uint32
|
||||
// PacketsReceived uint32
|
||||
// BytesSent uint64
|
||||
// BytesReceived uint64
|
||||
// LastPacketSentTimestamp time.Time
|
||||
// LastPacketReceivedTimestamp time.Time
|
||||
// FirstRequestTimestamp time.Time
|
||||
// LastRequestTimestamp time.Time
|
||||
// LastResponseTimestamp time.Time
|
||||
// TotalRoundTripTime float64
|
||||
// CurrentRoundTripTime float64
|
||||
// AvailableOutgoingBitrate float64
|
||||
// AvailableIncomingBitrate float64
|
||||
// CircuitBreakerTriggerCount uint32
|
||||
// RequestsReceived uint64
|
||||
// RequestsSent uint64
|
||||
// ResponsesReceived uint64
|
||||
// ResponsesSent uint64
|
||||
// RetransmissionsReceived uint64
|
||||
// RetransmissionsSent uint64
|
||||
// ConsentRequestsSent uint64
|
||||
// ConsentExpiredTimestamp time.Time
|
||||
}
|
||||
result = append(result, stat)
|
||||
}
|
||||
res = result
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Errorf("error getting candidate pairs stats %v", err)
|
||||
return []CandidatePairStats{}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// GetLocalCandidatesStats returns a list of local candidates stats
|
||||
func (a *Agent) GetLocalCandidatesStats() []CandidateStats {
|
||||
var res []CandidateStats
|
||||
err := a.run(a.context(), func(ctx context.Context, agent *Agent) {
|
||||
result := make([]CandidateStats, 0, len(agent.localCandidates))
|
||||
for networkType, localCandidates := range agent.localCandidates {
|
||||
for _, c := range localCandidates {
|
||||
stat := CandidateStats{
|
||||
Timestamp: time.Now(),
|
||||
ID: c.ID(),
|
||||
NetworkType: networkType,
|
||||
IP: c.Address(),
|
||||
Port: c.Port(),
|
||||
CandidateType: c.Type(),
|
||||
Priority: c.Priority(),
|
||||
// URL string
|
||||
RelayProtocol: "udp",
|
||||
// Deleted bool
|
||||
}
|
||||
result = append(result, stat)
|
||||
}
|
||||
}
|
||||
res = result
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Errorf("error getting candidate pairs stats %v", err)
|
||||
return []CandidateStats{}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// GetRemoteCandidatesStats returns a list of remote candidates stats
|
||||
func (a *Agent) GetRemoteCandidatesStats() []CandidateStats {
|
||||
var res []CandidateStats
|
||||
err := a.run(a.context(), func(ctx context.Context, agent *Agent) {
|
||||
result := make([]CandidateStats, 0, len(agent.remoteCandidates))
|
||||
for networkType, localCandidates := range agent.remoteCandidates {
|
||||
for _, c := range localCandidates {
|
||||
stat := CandidateStats{
|
||||
Timestamp: time.Now(),
|
||||
ID: c.ID(),
|
||||
NetworkType: networkType,
|
||||
IP: c.Address(),
|
||||
Port: c.Port(),
|
||||
CandidateType: c.Type(),
|
||||
Priority: c.Priority(),
|
||||
// URL string
|
||||
RelayProtocol: "udp",
|
||||
}
|
||||
result = append(result, stat)
|
||||
}
|
||||
}
|
||||
res = result
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Errorf("error getting candidate pairs stats %v", err)
|
||||
return []CandidateStats{}
|
||||
}
|
||||
return res
|
||||
}
|
68
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate.go
generated
vendored
Normal file
68
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
receiveMTU = 8192
|
||||
defaultLocalPreference = 65535
|
||||
|
||||
// ComponentRTP indicates that the candidate is used for RTP
|
||||
ComponentRTP uint16 = 1
|
||||
// ComponentRTCP indicates that the candidate is used for RTCP
|
||||
ComponentRTCP
|
||||
)
|
||||
|
||||
// Candidate represents an ICE candidate
|
||||
type Candidate interface {
|
||||
// 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.
|
||||
Foundation() string
|
||||
|
||||
// ID is a unique identifier for just this candidate
|
||||
// Unlike the foundation this is different for each candidate
|
||||
ID() string
|
||||
|
||||
// A component is a piece of a data stream.
|
||||
// An example is one for RTP, and one for RTCP
|
||||
Component() uint16
|
||||
SetComponent(uint16)
|
||||
|
||||
// The last time this candidate received traffic
|
||||
LastReceived() time.Time
|
||||
|
||||
// The last time this candidate sent traffic
|
||||
LastSent() time.Time
|
||||
|
||||
NetworkType() NetworkType
|
||||
Address() string
|
||||
Port() int
|
||||
|
||||
Priority() uint32
|
||||
|
||||
// A transport address related to a
|
||||
// candidate, which is useful for diagnostics and other purposes
|
||||
RelatedAddress() *CandidateRelatedAddress
|
||||
|
||||
String() string
|
||||
Type() CandidateType
|
||||
TCPType() TCPType
|
||||
|
||||
Equal(other Candidate) bool
|
||||
|
||||
Marshal() string
|
||||
|
||||
addr() net.Addr
|
||||
agent() *Agent
|
||||
context() context.Context
|
||||
|
||||
close() error
|
||||
seen(outbound bool)
|
||||
start(a *Agent, conn net.PacketConn, initializedCh <-chan struct{})
|
||||
writeTo(raw []byte, dst Candidate) (int, error)
|
||||
}
|
496
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go
generated
vendored
Normal file
496
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go
generated
vendored
Normal file
|
@ -0,0 +1,496 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
type candidateBase struct {
|
||||
id string
|
||||
networkType NetworkType
|
||||
candidateType CandidateType
|
||||
|
||||
component uint16
|
||||
address string
|
||||
port int
|
||||
relatedAddress *CandidateRelatedAddress
|
||||
tcpType TCPType
|
||||
|
||||
resolvedAddr net.Addr
|
||||
|
||||
lastSent atomic.Value
|
||||
lastReceived atomic.Value
|
||||
conn net.PacketConn
|
||||
|
||||
currAgent *Agent
|
||||
closeCh chan struct{}
|
||||
closedCh chan struct{}
|
||||
|
||||
foundationOverride string
|
||||
priorityOverride uint32
|
||||
}
|
||||
|
||||
// Done implements context.Context
|
||||
func (c *candidateBase) Done() <-chan struct{} {
|
||||
return c.closeCh
|
||||
}
|
||||
|
||||
// Err implements context.Context
|
||||
func (c *candidateBase) Err() error {
|
||||
select {
|
||||
case <-c.closedCh:
|
||||
return ErrRunCanceled
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Deadline implements context.Context
|
||||
func (c *candidateBase) Deadline() (deadline time.Time, ok bool) {
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
// Value implements context.Context
|
||||
func (c *candidateBase) Value(key interface{}) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ID returns Candidate ID
|
||||
func (c *candidateBase) ID() string {
|
||||
return c.id
|
||||
}
|
||||
|
||||
func (c *candidateBase) Foundation() string {
|
||||
if c.foundationOverride != "" {
|
||||
return c.foundationOverride
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(c.Type().String()+c.address+c.networkType.String())))
|
||||
}
|
||||
|
||||
// Address returns Candidate Address
|
||||
func (c *candidateBase) Address() string {
|
||||
return c.address
|
||||
}
|
||||
|
||||
// Port returns Candidate Port
|
||||
func (c *candidateBase) Port() int {
|
||||
return c.port
|
||||
}
|
||||
|
||||
// Type returns candidate type
|
||||
func (c *candidateBase) Type() CandidateType {
|
||||
return c.candidateType
|
||||
}
|
||||
|
||||
// NetworkType returns candidate NetworkType
|
||||
func (c *candidateBase) NetworkType() NetworkType {
|
||||
return c.networkType
|
||||
}
|
||||
|
||||
// Component returns candidate component
|
||||
func (c *candidateBase) Component() uint16 {
|
||||
return c.component
|
||||
}
|
||||
|
||||
func (c *candidateBase) SetComponent(component uint16) {
|
||||
c.component = component
|
||||
}
|
||||
|
||||
// LocalPreference returns the local preference for this candidate
|
||||
func (c *candidateBase) LocalPreference() uint16 {
|
||||
if c.NetworkType().IsTCP() {
|
||||
// RFC 6544, section 4.2
|
||||
//
|
||||
// In Section 4.1.2.1 of [RFC5245], a recommended formula for UDP ICE
|
||||
// candidate prioritization is defined. For TCP candidates, the same
|
||||
// formula and candidate type preferences SHOULD be used, and the
|
||||
// RECOMMENDED type preferences for the new candidate types defined in
|
||||
// this document (see Section 5) are 105 for NAT-assisted candidates and
|
||||
// 75 for UDP-tunneled candidates.
|
||||
//
|
||||
// (...)
|
||||
//
|
||||
// With TCP candidates, the local preference part of the recommended
|
||||
// priority formula is updated to also include the directionality
|
||||
// (active, passive, or simultaneous-open) of the TCP connection. The
|
||||
// RECOMMENDED local preference is then defined as:
|
||||
//
|
||||
// local preference = (2^13) * direction-pref + other-pref
|
||||
//
|
||||
// The direction-pref MUST be between 0 and 7 (both inclusive), with 7
|
||||
// being the most preferred. The other-pref MUST be between 0 and 8191
|
||||
// (both inclusive), with 8191 being the most preferred. It is
|
||||
// RECOMMENDED that the host, UDP-tunneled, and relayed TCP candidates
|
||||
// have the direction-pref assigned as follows: 6 for active, 4 for
|
||||
// passive, and 2 for S-O. For the NAT-assisted and server reflexive
|
||||
// candidates, the RECOMMENDED values are: 6 for S-O, 4 for active, and
|
||||
// 2 for passive.
|
||||
//
|
||||
// (...)
|
||||
//
|
||||
// If any two candidates have the same type-preference and direction-
|
||||
// pref, they MUST have a unique other-pref. With this specification,
|
||||
// this usually only happens with multi-homed hosts, in which case
|
||||
// other-pref is the preference for the particular IP address from which
|
||||
// the candidate was obtained. When there is only a single IP address,
|
||||
// this value SHOULD be set to the maximum allowed value (8191).
|
||||
var otherPref uint16 = 8191
|
||||
|
||||
directionPref := func() uint16 {
|
||||
switch c.Type() {
|
||||
case CandidateTypeHost, CandidateTypeRelay:
|
||||
switch c.tcpType {
|
||||
case TCPTypeActive:
|
||||
return 6
|
||||
case TCPTypePassive:
|
||||
return 4
|
||||
case TCPTypeSimultaneousOpen:
|
||||
return 2
|
||||
case TCPTypeUnspecified:
|
||||
return 0
|
||||
}
|
||||
case CandidateTypePeerReflexive, CandidateTypeServerReflexive:
|
||||
switch c.tcpType {
|
||||
case TCPTypeSimultaneousOpen:
|
||||
return 6
|
||||
case TCPTypeActive:
|
||||
return 4
|
||||
case TCPTypePassive:
|
||||
return 2
|
||||
case TCPTypeUnspecified:
|
||||
return 0
|
||||
}
|
||||
case CandidateTypeUnspecified:
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}()
|
||||
|
||||
return (1<<13)*directionPref + otherPref
|
||||
}
|
||||
|
||||
return defaultLocalPreference
|
||||
}
|
||||
|
||||
// RelatedAddress returns *CandidateRelatedAddress
|
||||
func (c *candidateBase) RelatedAddress() *CandidateRelatedAddress {
|
||||
return c.relatedAddress
|
||||
}
|
||||
|
||||
func (c *candidateBase) TCPType() TCPType {
|
||||
return c.tcpType
|
||||
}
|
||||
|
||||
// start runs the candidate using the provided connection
|
||||
func (c *candidateBase) start(a *Agent, conn net.PacketConn, initializedCh <-chan struct{}) {
|
||||
if c.conn != nil {
|
||||
c.agent().log.Warn("Can't start already started candidateBase")
|
||||
return
|
||||
}
|
||||
c.currAgent = a
|
||||
c.conn = conn
|
||||
c.closeCh = make(chan struct{})
|
||||
c.closedCh = make(chan struct{})
|
||||
|
||||
go c.recvLoop(initializedCh)
|
||||
}
|
||||
|
||||
func (c *candidateBase) recvLoop(initializedCh <-chan struct{}) {
|
||||
defer func() {
|
||||
close(c.closedCh)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-initializedCh:
|
||||
case <-c.closeCh:
|
||||
return
|
||||
}
|
||||
|
||||
log := c.agent().log
|
||||
buffer := make([]byte, receiveMTU)
|
||||
for {
|
||||
n, srcAddr, err := c.conn.ReadFrom(buffer)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
handleInboundCandidateMsg(c, c, buffer[:n], srcAddr, log)
|
||||
}
|
||||
}
|
||||
|
||||
func handleInboundCandidateMsg(ctx context.Context, c Candidate, buffer []byte, srcAddr net.Addr, log logging.LeveledLogger) {
|
||||
if stun.IsMessage(buffer) {
|
||||
m := &stun.Message{
|
||||
Raw: make([]byte, len(buffer)),
|
||||
}
|
||||
// Explicitly copy raw buffer so Message can own the memory.
|
||||
copy(m.Raw, buffer)
|
||||
if err := m.Decode(); err != nil {
|
||||
log.Warnf("Failed to handle decode ICE from %s to %s: %v", c.addr(), srcAddr, err)
|
||||
return
|
||||
}
|
||||
err := c.agent().run(ctx, func(ctx context.Context, agent *Agent) {
|
||||
agent.handleInbound(m, c, srcAddr)
|
||||
})
|
||||
if err != nil {
|
||||
log.Warnf("Failed to handle message: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !c.agent().validateNonSTUNTraffic(c, srcAddr) {
|
||||
log.Warnf("Discarded message from %s, not a valid remote candidate", c.addr())
|
||||
return
|
||||
}
|
||||
|
||||
// NOTE This will return packetio.ErrFull if the buffer ever manages to fill up.
|
||||
if _, err := c.agent().buffer.Write(buffer); err != nil {
|
||||
log.Warnf("failed to write packet")
|
||||
}
|
||||
}
|
||||
|
||||
// close stops the recvLoop
|
||||
func (c *candidateBase) close() error {
|
||||
// If conn has never been started will be nil
|
||||
if c.Done() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Assert that conn has not already been closed
|
||||
select {
|
||||
case <-c.Done():
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
|
||||
var firstErr error
|
||||
|
||||
// Unblock recvLoop
|
||||
close(c.closeCh)
|
||||
if err := c.conn.SetDeadline(time.Now()); err != nil {
|
||||
firstErr = err
|
||||
}
|
||||
|
||||
// Close the conn
|
||||
if err := c.conn.Close(); err != nil && firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
|
||||
if firstErr != nil {
|
||||
return firstErr
|
||||
}
|
||||
|
||||
// Wait until the recvLoop is closed
|
||||
<-c.closedCh
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *candidateBase) writeTo(raw []byte, dst Candidate) (int, error) {
|
||||
n, err := c.conn.WriteTo(raw, dst.addr())
|
||||
if err != nil {
|
||||
c.agent().log.Warnf("%s: %v", errSendPacket, err)
|
||||
return n, nil
|
||||
}
|
||||
c.seen(true)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Priority computes the priority for this ICE Candidate
|
||||
func (c *candidateBase) Priority() uint32 {
|
||||
if c.priorityOverride != 0 {
|
||||
return c.priorityOverride
|
||||
}
|
||||
|
||||
// The local preference 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.
|
||||
return (1<<24)*uint32(c.Type().Preference()) +
|
||||
(1<<8)*uint32(c.LocalPreference()) +
|
||||
uint32(256-c.Component())
|
||||
}
|
||||
|
||||
// Equal is used to compare two candidateBases
|
||||
func (c *candidateBase) Equal(other Candidate) bool {
|
||||
return c.NetworkType() == other.NetworkType() &&
|
||||
c.Type() == other.Type() &&
|
||||
c.Address() == other.Address() &&
|
||||
c.Port() == other.Port() &&
|
||||
c.TCPType() == other.TCPType() &&
|
||||
c.RelatedAddress().Equal(other.RelatedAddress())
|
||||
}
|
||||
|
||||
// String makes the candidateBase printable
|
||||
func (c *candidateBase) String() string {
|
||||
return fmt.Sprintf("%s %s %s:%d%s", c.NetworkType(), c.Type(), c.Address(), c.Port(), c.relatedAddress)
|
||||
}
|
||||
|
||||
// LastReceived returns a time.Time indicating the last time
|
||||
// this candidate was received
|
||||
func (c *candidateBase) LastReceived() time.Time {
|
||||
lastReceived := c.lastReceived.Load()
|
||||
if lastReceived == nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return lastReceived.(time.Time)
|
||||
}
|
||||
|
||||
func (c *candidateBase) setLastReceived(t time.Time) {
|
||||
c.lastReceived.Store(t)
|
||||
}
|
||||
|
||||
// LastSent returns a time.Time indicating the last time
|
||||
// this candidate was sent
|
||||
func (c *candidateBase) LastSent() time.Time {
|
||||
lastSent := c.lastSent.Load()
|
||||
if lastSent == nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return lastSent.(time.Time)
|
||||
}
|
||||
|
||||
func (c *candidateBase) setLastSent(t time.Time) {
|
||||
c.lastSent.Store(t)
|
||||
}
|
||||
|
||||
func (c *candidateBase) seen(outbound bool) {
|
||||
if outbound {
|
||||
c.setLastSent(time.Now())
|
||||
} else {
|
||||
c.setLastReceived(time.Now())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *candidateBase) addr() net.Addr {
|
||||
return c.resolvedAddr
|
||||
}
|
||||
|
||||
func (c *candidateBase) agent() *Agent {
|
||||
return c.currAgent
|
||||
}
|
||||
|
||||
func (c *candidateBase) context() context.Context {
|
||||
return c
|
||||
}
|
||||
|
||||
// Marshal returns the string representation of the ICECandidate
|
||||
func (c *candidateBase) Marshal() string {
|
||||
val := fmt.Sprintf("%s %d %s %d %s %d typ %s",
|
||||
c.Foundation(),
|
||||
c.Component(),
|
||||
c.NetworkType().NetworkShort(),
|
||||
c.Priority(),
|
||||
c.Address(),
|
||||
c.Port(),
|
||||
c.Type())
|
||||
|
||||
if c.tcpType != TCPTypeUnspecified {
|
||||
val += fmt.Sprintf(" tcptype %s", c.tcpType.String())
|
||||
}
|
||||
|
||||
if c.RelatedAddress() != nil {
|
||||
val = fmt.Sprintf("%s raddr %s rport %d",
|
||||
val,
|
||||
c.RelatedAddress().Address,
|
||||
c.RelatedAddress().Port)
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
// UnmarshalCandidate creates a Candidate from its string representation
|
||||
func UnmarshalCandidate(raw string) (Candidate, error) {
|
||||
split := strings.Fields(raw)
|
||||
if len(split) < 8 {
|
||||
return nil, fmt.Errorf("%w (%d)", errAttributeTooShortICECandidate, len(split))
|
||||
}
|
||||
|
||||
// Foundation
|
||||
foundation := split[0]
|
||||
|
||||
// Component
|
||||
rawComponent, err := strconv.ParseUint(split[1], 10, 16)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParseComponent, err)
|
||||
}
|
||||
component := uint16(rawComponent)
|
||||
|
||||
// Protocol
|
||||
protocol := split[2]
|
||||
|
||||
// Priority
|
||||
priorityRaw, err := strconv.ParseUint(split[3], 10, 32)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParsePriority, err)
|
||||
}
|
||||
priority := uint32(priorityRaw)
|
||||
|
||||
// Address
|
||||
address := split[4]
|
||||
|
||||
// Port
|
||||
rawPort, err := strconv.ParseUint(split[5], 10, 16)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParsePort, err)
|
||||
}
|
||||
port := int(rawPort)
|
||||
typ := split[7]
|
||||
|
||||
relatedAddress := ""
|
||||
relatedPort := 0
|
||||
tcpType := TCPTypeUnspecified
|
||||
|
||||
if len(split) > 8 {
|
||||
split = split[8:]
|
||||
|
||||
if split[0] == "raddr" {
|
||||
if len(split) < 4 {
|
||||
return nil, fmt.Errorf("%w: incorrect length", errParseRelatedAddr)
|
||||
}
|
||||
|
||||
// RelatedAddress
|
||||
relatedAddress = split[1]
|
||||
|
||||
// RelatedPort
|
||||
rawRelatedPort, parseErr := strconv.ParseUint(split[3], 10, 16)
|
||||
if parseErr != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParsePort, parseErr)
|
||||
}
|
||||
relatedPort = int(rawRelatedPort)
|
||||
} else if split[0] == "tcptype" {
|
||||
if len(split) < 2 {
|
||||
return nil, fmt.Errorf("%w: incorrect length", errParseTypType)
|
||||
}
|
||||
|
||||
tcpType = NewTCPType(split[1])
|
||||
}
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case "host":
|
||||
return NewCandidateHost(&CandidateHostConfig{"", protocol, address, port, component, priority, foundation, tcpType})
|
||||
case "srflx":
|
||||
return NewCandidateServerReflexive(&CandidateServerReflexiveConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort})
|
||||
case "prflx":
|
||||
return NewCandidatePeerReflexive(&CandidatePeerReflexiveConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort})
|
||||
case "relay":
|
||||
return NewCandidateRelay(&CandidateRelayConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort, nil})
|
||||
default:
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w (%s)", errUnknownCandidateTyp, typ)
|
||||
}
|
76
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_host.go
generated
vendored
Normal file
76
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_host.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CandidateHost is a candidate of type host
|
||||
type CandidateHost struct {
|
||||
candidateBase
|
||||
|
||||
network string
|
||||
}
|
||||
|
||||
// CandidateHostConfig is the config required to create a new CandidateHost
|
||||
type CandidateHostConfig struct {
|
||||
CandidateID string
|
||||
Network string
|
||||
Address string
|
||||
Port int
|
||||
Component uint16
|
||||
Priority uint32
|
||||
Foundation string
|
||||
TCPType TCPType
|
||||
}
|
||||
|
||||
// NewCandidateHost creates a new host candidate
|
||||
func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) {
|
||||
candidateID := config.CandidateID
|
||||
|
||||
if candidateID == "" {
|
||||
candidateID = globalCandidateIDGenerator.Generate()
|
||||
}
|
||||
|
||||
c := &CandidateHost{
|
||||
candidateBase: candidateBase{
|
||||
id: candidateID,
|
||||
address: config.Address,
|
||||
candidateType: CandidateTypeHost,
|
||||
component: config.Component,
|
||||
port: config.Port,
|
||||
tcpType: config.TCPType,
|
||||
foundationOverride: config.Foundation,
|
||||
priorityOverride: config.Priority,
|
||||
},
|
||||
network: config.Network,
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(config.Address, ".local") {
|
||||
ip := net.ParseIP(config.Address)
|
||||
if ip == nil {
|
||||
return nil, ErrAddressParseFailed
|
||||
}
|
||||
|
||||
if err := c.setIP(ip); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Until mDNS candidate is resolved assume it is UDPv4
|
||||
c.candidateBase.networkType = NetworkTypeUDP4
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *CandidateHost) setIP(ip net.IP) error {
|
||||
networkType, err := determineNetworkType(c.network, ip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.candidateBase.networkType = networkType
|
||||
c.candidateBase.resolvedAddr = createAddr(networkType, ip, c.port)
|
||||
|
||||
return nil
|
||||
}
|
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_peer_reflexive.go
generated
vendored
Normal file
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_peer_reflexive.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Package ice ...
|
||||
//nolint:dupl
|
||||
package ice
|
||||
|
||||
import "net"
|
||||
|
||||
// CandidatePeerReflexive ...
|
||||
type CandidatePeerReflexive struct {
|
||||
candidateBase
|
||||
}
|
||||
|
||||
// CandidatePeerReflexiveConfig is the config required to create a new CandidatePeerReflexive
|
||||
type CandidatePeerReflexiveConfig struct {
|
||||
CandidateID string
|
||||
Network string
|
||||
Address string
|
||||
Port int
|
||||
Component uint16
|
||||
Priority uint32
|
||||
Foundation string
|
||||
RelAddr string
|
||||
RelPort int
|
||||
}
|
||||
|
||||
// NewCandidatePeerReflexive creates a new peer reflective candidate
|
||||
func NewCandidatePeerReflexive(config *CandidatePeerReflexiveConfig) (*CandidatePeerReflexive, error) {
|
||||
ip := net.ParseIP(config.Address)
|
||||
if ip == nil {
|
||||
return nil, ErrAddressParseFailed
|
||||
}
|
||||
|
||||
networkType, err := determineNetworkType(config.Network, ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
candidateID := config.CandidateID
|
||||
candidateIDGenerator := newCandidateIDGenerator()
|
||||
if candidateID == "" {
|
||||
candidateID = candidateIDGenerator.Generate()
|
||||
}
|
||||
|
||||
return &CandidatePeerReflexive{
|
||||
candidateBase: candidateBase{
|
||||
id: candidateID,
|
||||
networkType: networkType,
|
||||
candidateType: CandidateTypePeerReflexive,
|
||||
address: config.Address,
|
||||
port: config.Port,
|
||||
resolvedAddr: createAddr(networkType, ip, config.Port),
|
||||
component: config.Component,
|
||||
foundationOverride: config.Foundation,
|
||||
priorityOverride: config.Priority,
|
||||
relatedAddress: &CandidateRelatedAddress{
|
||||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
73
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_relay.go
generated
vendored
Normal file
73
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_relay.go
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// CandidateRelay ...
|
||||
type CandidateRelay struct {
|
||||
candidateBase
|
||||
|
||||
onClose func() error
|
||||
}
|
||||
|
||||
// CandidateRelayConfig is the config required to create a new CandidateRelay
|
||||
type CandidateRelayConfig struct {
|
||||
CandidateID string
|
||||
Network string
|
||||
Address string
|
||||
Port int
|
||||
Component uint16
|
||||
Priority uint32
|
||||
Foundation string
|
||||
RelAddr string
|
||||
RelPort int
|
||||
OnClose func() error
|
||||
}
|
||||
|
||||
// NewCandidateRelay creates a new relay candidate
|
||||
func NewCandidateRelay(config *CandidateRelayConfig) (*CandidateRelay, error) {
|
||||
candidateID := config.CandidateID
|
||||
|
||||
if candidateID == "" {
|
||||
candidateID = globalCandidateIDGenerator.Generate()
|
||||
}
|
||||
|
||||
ip := net.ParseIP(config.Address)
|
||||
if ip == nil {
|
||||
return nil, ErrAddressParseFailed
|
||||
}
|
||||
|
||||
networkType, err := determineNetworkType(config.Network, ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CandidateRelay{
|
||||
candidateBase: candidateBase{
|
||||
id: candidateID,
|
||||
networkType: networkType,
|
||||
candidateType: CandidateTypeRelay,
|
||||
address: config.Address,
|
||||
port: config.Port,
|
||||
resolvedAddr: &net.UDPAddr{IP: ip, Port: config.Port},
|
||||
component: config.Component,
|
||||
foundationOverride: config.Foundation,
|
||||
priorityOverride: config.Priority,
|
||||
relatedAddress: &CandidateRelatedAddress{
|
||||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
},
|
||||
onClose: config.OnClose,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *CandidateRelay) close() error {
|
||||
err := c.candidateBase.close()
|
||||
if c.onClose != nil {
|
||||
err = c.onClose()
|
||||
c.onClose = nil
|
||||
}
|
||||
return err
|
||||
}
|
59
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_server_reflexive.go
generated
vendored
Normal file
59
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_server_reflexive.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Package ice ...
|
||||
//nolint:dupl
|
||||
package ice
|
||||
|
||||
import "net"
|
||||
|
||||
// CandidateServerReflexive ...
|
||||
type CandidateServerReflexive struct {
|
||||
candidateBase
|
||||
}
|
||||
|
||||
// CandidateServerReflexiveConfig is the config required to create a new CandidateServerReflexive
|
||||
type CandidateServerReflexiveConfig struct {
|
||||
CandidateID string
|
||||
Network string
|
||||
Address string
|
||||
Port int
|
||||
Component uint16
|
||||
Priority uint32
|
||||
Foundation string
|
||||
RelAddr string
|
||||
RelPort int
|
||||
}
|
||||
|
||||
// NewCandidateServerReflexive creates a new server reflective candidate
|
||||
func NewCandidateServerReflexive(config *CandidateServerReflexiveConfig) (*CandidateServerReflexive, error) {
|
||||
ip := net.ParseIP(config.Address)
|
||||
if ip == nil {
|
||||
return nil, ErrAddressParseFailed
|
||||
}
|
||||
|
||||
networkType, err := determineNetworkType(config.Network, ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
candidateID := config.CandidateID
|
||||
if candidateID == "" {
|
||||
candidateID = globalCandidateIDGenerator.Generate()
|
||||
}
|
||||
|
||||
return &CandidateServerReflexive{
|
||||
candidateBase: candidateBase{
|
||||
id: candidateID,
|
||||
networkType: networkType,
|
||||
candidateType: CandidateTypeServerReflexive,
|
||||
address: config.Address,
|
||||
port: config.Port,
|
||||
resolvedAddr: &net.UDPAddr{IP: ip, Port: config.Port},
|
||||
component: config.Component,
|
||||
foundationOverride: config.Foundation,
|
||||
priorityOverride: config.Priority,
|
||||
relatedAddress: &CandidateRelatedAddress{
|
||||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
94
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go
generated
vendored
Normal file
94
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
func newCandidatePair(local, remote Candidate, controlling bool) *candidatePair {
|
||||
return &candidatePair{
|
||||
iceRoleControlling: controlling,
|
||||
remote: remote,
|
||||
local: local,
|
||||
state: CandidatePairStateWaiting,
|
||||
}
|
||||
}
|
||||
|
||||
// candidatePair represents a combination of a local and remote candidate
|
||||
type candidatePair struct {
|
||||
iceRoleControlling bool
|
||||
remote Candidate
|
||||
local Candidate
|
||||
bindingRequestCount uint16
|
||||
state CandidatePairState
|
||||
nominated bool
|
||||
}
|
||||
|
||||
func (p *candidatePair) String() string {
|
||||
return fmt.Sprintf("prio %d (local, prio %d) %s <-> %s (remote, prio %d)",
|
||||
p.Priority(), p.local.Priority(), p.local, p.remote, p.remote.Priority())
|
||||
}
|
||||
|
||||
func (p *candidatePair) Equal(other *candidatePair) bool {
|
||||
if p == nil && other == nil {
|
||||
return true
|
||||
}
|
||||
if p == nil || other == nil {
|
||||
return false
|
||||
}
|
||||
return p.local.Equal(other.local) && p.remote.Equal(other.remote)
|
||||
}
|
||||
|
||||
// RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs
|
||||
// Let G be the priority for the candidate provided by the controlling
|
||||
// agent. Let D be the priority for the candidate provided by the
|
||||
// controlled agent.
|
||||
// pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)
|
||||
func (p *candidatePair) Priority() uint64 {
|
||||
var g uint32
|
||||
var d uint32
|
||||
if p.iceRoleControlling {
|
||||
g = p.local.Priority()
|
||||
d = p.remote.Priority()
|
||||
} else {
|
||||
g = p.remote.Priority()
|
||||
d = p.local.Priority()
|
||||
}
|
||||
|
||||
// Just implement these here rather
|
||||
// than fooling around with the math package
|
||||
min := func(x, y uint32) uint64 {
|
||||
if x < y {
|
||||
return uint64(x)
|
||||
}
|
||||
return uint64(y)
|
||||
}
|
||||
max := func(x, y uint32) uint64 {
|
||||
if x > y {
|
||||
return uint64(x)
|
||||
}
|
||||
return uint64(y)
|
||||
}
|
||||
cmp := func(x, y uint32) uint64 {
|
||||
if x > y {
|
||||
return uint64(1)
|
||||
}
|
||||
return uint64(0)
|
||||
}
|
||||
|
||||
// 1<<32 overflows uint32; and if both g && d are
|
||||
// maxUint32, this result would overflow uint64
|
||||
return (1<<32-1)*min(g, d) + 2*max(g, d) + cmp(g, d)
|
||||
}
|
||||
|
||||
func (p *candidatePair) Write(b []byte) (int, error) {
|
||||
return p.local.writeTo(b, p.remote)
|
||||
}
|
||||
|
||||
func (a *Agent) sendSTUN(msg *stun.Message, local, remote Candidate) {
|
||||
_, err := local.writeTo(msg.Raw, remote)
|
||||
if err != nil {
|
||||
a.log.Tracef("failed to send STUN message: %s", err)
|
||||
}
|
||||
}
|
37
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair_state.go
generated
vendored
Normal file
37
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair_state.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
package ice
|
||||
|
||||
// CandidatePairState represent the ICE candidate pair state
|
||||
type CandidatePairState int
|
||||
|
||||
const (
|
||||
// CandidatePairStateWaiting means a check has not been performed for
|
||||
// this pair
|
||||
CandidatePairStateWaiting = iota + 1
|
||||
|
||||
// CandidatePairStateInProgress means a check has been sent for this pair,
|
||||
// but the transaction is in progress.
|
||||
CandidatePairStateInProgress
|
||||
|
||||
// CandidatePairStateFailed means a check for this pair was already done
|
||||
// and failed, either never producing any response or producing an unrecoverable
|
||||
// failure response.
|
||||
CandidatePairStateFailed
|
||||
|
||||
// CandidatePairStateSucceeded means a check for this pair was already
|
||||
// done and produced a successful result.
|
||||
CandidatePairStateSucceeded
|
||||
)
|
||||
|
||||
func (c CandidatePairState) String() string {
|
||||
switch c {
|
||||
case CandidatePairStateWaiting:
|
||||
return "waiting"
|
||||
case CandidatePairStateInProgress:
|
||||
return "in-progress"
|
||||
case CandidatePairStateFailed:
|
||||
return "failed"
|
||||
case CandidatePairStateSucceeded:
|
||||
return "succeeded"
|
||||
}
|
||||
return "Unknown candidate pair state"
|
||||
}
|
30
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidaterelatedaddress.go
generated
vendored
Normal file
30
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidaterelatedaddress.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
package ice
|
||||
|
||||
import "fmt"
|
||||
|
||||
// CandidateRelatedAddress convey transport addresses related to the
|
||||
// candidate, useful for diagnostics and other purposes.
|
||||
type CandidateRelatedAddress struct {
|
||||
Address string
|
||||
Port int
|
||||
}
|
||||
|
||||
// String makes CandidateRelatedAddress printable
|
||||
func (c *CandidateRelatedAddress) String() string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf(" related %s:%d", c.Address, c.Port)
|
||||
}
|
||||
|
||||
// Equal allows comparing two CandidateRelatedAddresses.
|
||||
// The CandidateRelatedAddress are allowed to be nil.
|
||||
func (c *CandidateRelatedAddress) Equal(other *CandidateRelatedAddress) bool {
|
||||
if c == nil && other == nil {
|
||||
return true
|
||||
}
|
||||
return c != nil && other != nil &&
|
||||
c.Address == other.Address &&
|
||||
c.Port == other.Port
|
||||
}
|
62
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatetype.go
generated
vendored
Normal file
62
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatetype.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
package ice
|
||||
|
||||
// CandidateType represents the type of candidate
|
||||
type CandidateType byte
|
||||
|
||||
// CandidateType enum
|
||||
const (
|
||||
CandidateTypeUnspecified CandidateType = iota
|
||||
CandidateTypeHost
|
||||
CandidateTypeServerReflexive
|
||||
CandidateTypePeerReflexive
|
||||
CandidateTypeRelay
|
||||
)
|
||||
|
||||
// String makes CandidateType printable
|
||||
func (c CandidateType) String() string {
|
||||
switch c {
|
||||
case CandidateTypeHost:
|
||||
return "host"
|
||||
case CandidateTypeServerReflexive:
|
||||
return "srflx"
|
||||
case CandidateTypePeerReflexive:
|
||||
return "prflx"
|
||||
case CandidateTypeRelay:
|
||||
return "relay"
|
||||
case CandidateTypeUnspecified:
|
||||
return "Unknown candidate type"
|
||||
}
|
||||
return "Unknown candidate type"
|
||||
}
|
||||
|
||||
// Preference returns the preference weight of a CandidateType
|
||||
//
|
||||
// 4.1.2.2. Guidelines for Choosing Type and Local Preferences
|
||||
// The RECOMMENDED values are 126 for host candidates, 100
|
||||
// for server reflexive candidates, 110 for peer reflexive candidates,
|
||||
// and 0 for relayed candidates.
|
||||
func (c CandidateType) Preference() uint16 {
|
||||
switch c {
|
||||
case CandidateTypeHost:
|
||||
return 126
|
||||
case CandidateTypePeerReflexive:
|
||||
return 110
|
||||
case CandidateTypeServerReflexive:
|
||||
return 100
|
||||
case CandidateTypeRelay, CandidateTypeUnspecified:
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func containsCandidateType(candidateType CandidateType, candidateTypeList []CandidateType) bool {
|
||||
if candidateTypeList == nil {
|
||||
return false
|
||||
}
|
||||
for _, ct := range candidateTypeList {
|
||||
if ct == candidateType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/codecov.yml
generated
vendored
Normal file
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/codecov.yml
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# DO NOT EDIT THIS FILE
|
||||
#
|
||||
# It is automatically copied from https://github.com/pion/.goassets repository.
|
||||
#
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
# Allow decreasing 2% of total coverage to avoid noise.
|
||||
threshold: 2%
|
||||
patch:
|
||||
default:
|
||||
target: 70%
|
||||
only_pulls: true
|
||||
|
||||
ignore:
|
||||
- "examples/*"
|
||||
- "examples/**/*"
|
37
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go
generated
vendored
Normal file
37
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (a *Agent) context() context.Context {
|
||||
return agentContext(a.done)
|
||||
}
|
||||
|
||||
type agentContext chan struct{}
|
||||
|
||||
// Done implements context.Context
|
||||
func (a agentContext) Done() <-chan struct{} {
|
||||
return (chan struct{})(a)
|
||||
}
|
||||
|
||||
// Err implements context.Context
|
||||
func (a agentContext) Err() error {
|
||||
select {
|
||||
case <-(chan struct{})(a):
|
||||
return ErrRunCanceled
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Deadline implements context.Context
|
||||
func (a agentContext) Deadline() (deadline time.Time, ok bool) {
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
// Value implements context.Context
|
||||
func (a agentContext) Value(key interface{}) interface{} {
|
||||
return nil
|
||||
}
|
132
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/errors.go
generated
vendored
Normal file
132
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
package ice
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrUnknownType indicates an error with Unknown info.
|
||||
ErrUnknownType = errors.New("Unknown")
|
||||
|
||||
// ErrSchemeType indicates the scheme type could not be parsed.
|
||||
ErrSchemeType = errors.New("unknown scheme type")
|
||||
|
||||
// ErrSTUNQuery indicates query arguments are provided in a STUN URL.
|
||||
ErrSTUNQuery = errors.New("queries not supported in stun address")
|
||||
|
||||
// ErrInvalidQuery indicates an malformed query is provided.
|
||||
ErrInvalidQuery = errors.New("invalid query")
|
||||
|
||||
// ErrHost indicates malformed hostname is provided.
|
||||
ErrHost = errors.New("invalid hostname")
|
||||
|
||||
// ErrPort indicates malformed port is provided.
|
||||
ErrPort = errors.New("invalid port")
|
||||
|
||||
// ErrLocalUfragInsufficientBits indicates local username fragment insufficient bits are provided.
|
||||
// Have to be at least 24 bits long
|
||||
ErrLocalUfragInsufficientBits = errors.New("local username fragment is less than 24 bits long")
|
||||
|
||||
// ErrLocalPwdInsufficientBits indicates local passoword insufficient bits are provided.
|
||||
// Have to be at least 128 bits long
|
||||
ErrLocalPwdInsufficientBits = errors.New("local password is less than 128 bits long")
|
||||
|
||||
// ErrProtoType indicates an unsupported transport type was provided.
|
||||
ErrProtoType = errors.New("invalid transport protocol type")
|
||||
|
||||
// ErrClosed indicates the agent is closed
|
||||
ErrClosed = errors.New("the agent is closed")
|
||||
|
||||
// ErrNoCandidatePairs indicates agent does not have a valid candidate pair
|
||||
ErrNoCandidatePairs = errors.New("no candidate pairs available")
|
||||
|
||||
// ErrCanceledByCaller indicates agent connection was canceled by the caller
|
||||
ErrCanceledByCaller = errors.New("connecting canceled by caller")
|
||||
|
||||
// ErrMultipleStart indicates agent was started twice
|
||||
ErrMultipleStart = errors.New("attempted to start agent twice")
|
||||
|
||||
// ErrRemoteUfragEmpty indicates agent was started with an empty remote ufrag
|
||||
ErrRemoteUfragEmpty = errors.New("remote ufrag is empty")
|
||||
|
||||
// ErrRemotePwdEmpty indicates agent was started with an empty remote pwd
|
||||
ErrRemotePwdEmpty = errors.New("remote pwd is empty")
|
||||
|
||||
// ErrNoOnCandidateHandler indicates agent was started without OnCandidate
|
||||
ErrNoOnCandidateHandler = errors.New("no OnCandidate provided")
|
||||
|
||||
// ErrMultipleGatherAttempted indicates GatherCandidates has been called multiple times
|
||||
ErrMultipleGatherAttempted = errors.New("attempting to gather candidates during gathering state")
|
||||
|
||||
// ErrUsernameEmpty indicates agent was give TURN URL with an empty Username
|
||||
ErrUsernameEmpty = errors.New("username is empty")
|
||||
|
||||
// ErrPasswordEmpty indicates agent was give TURN URL with an empty Password
|
||||
ErrPasswordEmpty = errors.New("password is empty")
|
||||
|
||||
// ErrAddressParseFailed indicates we were unable to parse a candidate address
|
||||
ErrAddressParseFailed = errors.New("failed to parse address")
|
||||
|
||||
// ErrLiteUsingNonHostCandidates indicates non host candidates were selected for a lite agent
|
||||
ErrLiteUsingNonHostCandidates = errors.New("lite agents must only use host candidates")
|
||||
|
||||
// ErrUselessUrlsProvided indicates that one or more URL was provided to the agent but no host
|
||||
// candidate required them
|
||||
ErrUselessUrlsProvided = errors.New("agent does not need URL with selected candidate types")
|
||||
|
||||
// ErrUnsupportedNAT1To1IPCandidateType indicates that the specified NAT1To1IPCandidateType is
|
||||
// unsupported
|
||||
ErrUnsupportedNAT1To1IPCandidateType = errors.New("unsupported 1:1 NAT IP candidate type")
|
||||
|
||||
// ErrInvalidNAT1To1IPMapping indicates that the given 1:1 NAT IP mapping is invalid
|
||||
ErrInvalidNAT1To1IPMapping = errors.New("invalid 1:1 NAT IP mapping")
|
||||
|
||||
// ErrExternalMappedIPNotFound in NAT1To1IPMapping
|
||||
ErrExternalMappedIPNotFound = errors.New("external mapped IP not found")
|
||||
|
||||
// ErrMulticastDNSWithNAT1To1IPMapping indicates that the mDNS gathering cannot be used along
|
||||
// with 1:1 NAT IP mapping for host candidate.
|
||||
ErrMulticastDNSWithNAT1To1IPMapping = errors.New("mDNS gathering cannot be used with 1:1 NAT IP mapping for host candidate")
|
||||
|
||||
// ErrIneffectiveNAT1To1IPMappingHost indicates that 1:1 NAT IP mapping for host candidate is
|
||||
// requested, but the host candidate type is disabled.
|
||||
ErrIneffectiveNAT1To1IPMappingHost = errors.New("1:1 NAT IP mapping for host candidate ineffective")
|
||||
|
||||
// ErrIneffectiveNAT1To1IPMappingSrflx indicates that 1:1 NAT IP mapping for srflx candidate is
|
||||
// requested, but the srflx candidate type is disabled.
|
||||
ErrIneffectiveNAT1To1IPMappingSrflx = errors.New("1:1 NAT IP mapping for srflx candidate ineffective")
|
||||
|
||||
// ErrInvalidMulticastDNSHostName indicates an invalid MulticastDNSHostName
|
||||
ErrInvalidMulticastDNSHostName = errors.New("invalid mDNS HostName, must end with .local and can only contain a single '.'")
|
||||
|
||||
// ErrRestartWhenGathering indicates Restart was called when Agent is in GatheringStateGathering
|
||||
ErrRestartWhenGathering = errors.New("ICE Agent can not be restarted when gathering")
|
||||
|
||||
// ErrRunCanceled indicates a run operation was canceled by its individual done
|
||||
ErrRunCanceled = errors.New("run was canceled by done")
|
||||
|
||||
// ErrTCPMuxNotInitialized indicates TCPMux is not initialized and that invalidTCPMux is used.
|
||||
ErrTCPMuxNotInitialized = errors.New("TCPMux is not initialized")
|
||||
|
||||
// ErrTCPRemoteAddrAlreadyExists indicates we already have the connection with same remote addr.
|
||||
ErrTCPRemoteAddrAlreadyExists = errors.New("conn with same remote addr already exists")
|
||||
|
||||
errSendPacket = errors.New("failed to send packet")
|
||||
errAttributeTooShortICECandidate = errors.New("attribute not long enough to be ICE candidate")
|
||||
errParseComponent = errors.New("could not parse component")
|
||||
errParsePriority = errors.New("could not parse priority")
|
||||
errParsePort = errors.New("could not parse port")
|
||||
errParseRelatedAddr = errors.New("could not parse related addresses")
|
||||
errParseTypType = errors.New("could not parse typtype")
|
||||
errUnknownCandidateTyp = errors.New("unknown candidate typ")
|
||||
errGetXorMappedAddrResponse = errors.New("failed to get XOR-MAPPED-ADDRESS response")
|
||||
errConnectionAddrAlreadyExist = errors.New("connection with same remote address already exists")
|
||||
errReadingStreamingPacket = errors.New("error reading streaming packet")
|
||||
errWriting = errors.New("error writing to")
|
||||
errClosingConnection = errors.New("error closing connection")
|
||||
errDetermineNetworkType = errors.New("unable to determine networkType")
|
||||
errMissingProtocolScheme = errors.New("missing protocol scheme")
|
||||
errTooManyColonsAddr = errors.New("too many colons in address")
|
||||
errRead = errors.New("unexpected error trying to read")
|
||||
errUnknownRole = errors.New("unknown role")
|
||||
errMismatchUsername = errors.New("username mismatch")
|
||||
errICEWriteSTUNMessage = errors.New("the ICE conn can't write STUN messages")
|
||||
)
|
143
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/external_ip_mapper.go
generated
vendored
Normal file
143
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/external_ip_mapper.go
generated
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func validateIPString(ipStr string) (net.IP, bool, error) {
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip == nil {
|
||||
return nil, false, ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
return ip, (ip.To4() != nil), nil
|
||||
}
|
||||
|
||||
// ipMapping holds the mapping of local and external IP address for a particular IP family
|
||||
type ipMapping struct {
|
||||
ipSole net.IP // when non-nil, this is the sole external IP for one local IP assumed
|
||||
ipMap map[string]net.IP // local-to-external IP mapping (k: local, v: external)
|
||||
}
|
||||
|
||||
func (m *ipMapping) setSoleIP(ip net.IP) error {
|
||||
if m.ipSole != nil || len(m.ipMap) > 0 {
|
||||
return ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
|
||||
m.ipSole = ip
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ipMapping) addIPMapping(locIP, extIP net.IP) error {
|
||||
if m.ipSole != nil {
|
||||
return ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
|
||||
locIPStr := locIP.String()
|
||||
|
||||
// check if dup of local IP
|
||||
if _, ok := m.ipMap[locIPStr]; ok {
|
||||
return ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
|
||||
m.ipMap[locIPStr] = extIP
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ipMapping) findExternalIP(locIP net.IP) (net.IP, error) {
|
||||
if m.ipSole != nil {
|
||||
return m.ipSole, nil
|
||||
}
|
||||
|
||||
extIP, ok := m.ipMap[locIP.String()]
|
||||
if !ok {
|
||||
return nil, ErrExternalMappedIPNotFound
|
||||
}
|
||||
|
||||
return extIP, nil
|
||||
}
|
||||
|
||||
type externalIPMapper struct {
|
||||
ipv4Mapping ipMapping
|
||||
ipv6Mapping ipMapping
|
||||
candidateType CandidateType
|
||||
}
|
||||
|
||||
func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIPMapper, error) { //nolint:gocognit
|
||||
if len(ips) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if candidateType == CandidateTypeUnspecified {
|
||||
candidateType = CandidateTypeHost // defaults to host
|
||||
} else if candidateType != CandidateTypeHost && candidateType != CandidateTypeServerReflexive {
|
||||
return nil, ErrUnsupportedNAT1To1IPCandidateType
|
||||
}
|
||||
|
||||
m := &externalIPMapper{
|
||||
ipv4Mapping: ipMapping{ipMap: map[string]net.IP{}},
|
||||
ipv6Mapping: ipMapping{ipMap: map[string]net.IP{}},
|
||||
candidateType: candidateType,
|
||||
}
|
||||
|
||||
for _, extIPStr := range ips {
|
||||
ipPair := strings.Split(extIPStr, "/")
|
||||
if len(ipPair) == 0 || len(ipPair) > 2 {
|
||||
return nil, ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
|
||||
extIP, isExtIPv4, err := validateIPString(ipPair[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ipPair) == 1 {
|
||||
if isExtIPv4 {
|
||||
if err := m.ipv4Mapping.setSoleIP(extIP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := m.ipv6Mapping.setSoleIP(extIP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
locIP, isLocIPv4, err := validateIPString(ipPair[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isExtIPv4 {
|
||||
if !isLocIPv4 {
|
||||
return nil, ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
|
||||
if err := m.ipv4Mapping.addIPMapping(locIP, extIP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if isLocIPv4 {
|
||||
return nil, ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
|
||||
if err := m.ipv6Mapping.addIPMapping(locIP, extIP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *externalIPMapper) findExternalIP(localIPStr string) (net.IP, error) {
|
||||
locIP, isLocIPv4, err := validateIPString(localIPStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isLocIPv4 {
|
||||
return m.ipv4Mapping.findExternalIP(locIP)
|
||||
}
|
||||
|
||||
return m.ipv6Mapping.findExternalIP(locIP)
|
||||
}
|
497
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/gather.go
generated
vendored
Normal file
497
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/gather.go
generated
vendored
Normal file
|
@ -0,0 +1,497 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/dtls/v2"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/turn/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
stunGatherTimeout = time.Second * 5
|
||||
)
|
||||
|
||||
type closeable interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Close a net.Conn and log if we have a failure
|
||||
func closeConnAndLog(c closeable, log logging.LeveledLogger, msg string) {
|
||||
if c == nil || (reflect.ValueOf(c).Kind() == reflect.Ptr && reflect.ValueOf(c).IsNil()) {
|
||||
log.Warnf("Conn is not allocated (%s)", msg)
|
||||
return
|
||||
}
|
||||
|
||||
log.Warnf(msg)
|
||||
if err := c.Close(); err != nil {
|
||||
log.Warnf("Failed to close conn: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// fakePacketConn wraps a net.Conn and emulates net.PacketConn
|
||||
type fakePacketConn struct {
|
||||
nextConn net.Conn
|
||||
}
|
||||
|
||||
func (f *fakePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
n, err = f.nextConn.Read(p)
|
||||
addr = f.nextConn.RemoteAddr()
|
||||
return
|
||||
}
|
||||
func (f *fakePacketConn) Close() error { return f.nextConn.Close() }
|
||||
func (f *fakePacketConn) LocalAddr() net.Addr { return f.nextConn.LocalAddr() }
|
||||
func (f *fakePacketConn) SetDeadline(t time.Time) error { return f.nextConn.SetDeadline(t) }
|
||||
func (f *fakePacketConn) SetReadDeadline(t time.Time) error { return f.nextConn.SetReadDeadline(t) }
|
||||
func (f *fakePacketConn) SetWriteDeadline(t time.Time) error { return f.nextConn.SetWriteDeadline(t) }
|
||||
func (f *fakePacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
return f.nextConn.Write(p)
|
||||
}
|
||||
|
||||
// GatherCandidates initiates the trickle based gathering process.
|
||||
func (a *Agent) GatherCandidates() error {
|
||||
var gatherErr error
|
||||
|
||||
if runErr := a.run(a.context(), func(ctx context.Context, agent *Agent) {
|
||||
if a.gatheringState != GatheringStateNew {
|
||||
gatherErr = ErrMultipleGatherAttempted
|
||||
return
|
||||
} else if a.onCandidateHdlr.Load() == nil {
|
||||
gatherErr = ErrNoOnCandidateHandler
|
||||
return
|
||||
}
|
||||
|
||||
a.gatherCandidateCancel() // Cancel previous gathering routine
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
a.gatherCandidateCancel = cancel
|
||||
|
||||
go a.gatherCandidates(ctx)
|
||||
}); runErr != nil {
|
||||
return runErr
|
||||
}
|
||||
return gatherErr
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidates(ctx context.Context) {
|
||||
if err := a.setGatheringState(GatheringStateGathering); err != nil {
|
||||
a.log.Warnf("failed to set gatheringState to GatheringStateGathering: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for _, t := range a.candidateTypes {
|
||||
switch t {
|
||||
case CandidateTypeHost:
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
a.gatherCandidatesLocal(ctx, a.networkTypes)
|
||||
wg.Done()
|
||||
}()
|
||||
case CandidateTypeServerReflexive:
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
a.gatherCandidatesSrflx(ctx, a.urls, a.networkTypes)
|
||||
wg.Done()
|
||||
}()
|
||||
if a.extIPMapper != nil && a.extIPMapper.candidateType == CandidateTypeServerReflexive {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
a.gatherCandidatesSrflxMapped(ctx, a.networkTypes)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
case CandidateTypeRelay:
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
a.gatherCandidatesRelay(ctx, a.urls)
|
||||
wg.Done()
|
||||
}()
|
||||
case CandidateTypePeerReflexive, CandidateTypeUnspecified:
|
||||
}
|
||||
}
|
||||
// Block until all STUN and TURN URLs have been gathered (or timed out)
|
||||
wg.Wait()
|
||||
|
||||
if err := a.setGatheringState(GatheringStateComplete); err != nil {
|
||||
a.log.Warnf("failed to set gatheringState to GatheringStateComplete: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []NetworkType) { //nolint:gocognit
|
||||
networks := map[string]struct{}{}
|
||||
for _, networkType := range networkTypes {
|
||||
if networkType.IsTCP() {
|
||||
networks[tcp] = struct{}{}
|
||||
} else {
|
||||
networks[udp] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
localIPs, err := localInterfaces(a.net, a.interfaceFilter, networkTypes)
|
||||
if err != nil {
|
||||
a.log.Warnf("failed to iterate local interfaces, host candidates will not be gathered %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, ip := range localIPs {
|
||||
mappedIP := ip
|
||||
if a.mDNSMode != MulticastDNSModeQueryAndGather && a.extIPMapper != nil && a.extIPMapper.candidateType == CandidateTypeHost {
|
||||
if _mappedIP, err := a.extIPMapper.findExternalIP(ip.String()); err == nil {
|
||||
mappedIP = _mappedIP
|
||||
} else {
|
||||
a.log.Warnf("1:1 NAT mapping is enabled but no external IP is found for %s\n", ip.String())
|
||||
}
|
||||
}
|
||||
|
||||
address := mappedIP.String()
|
||||
if a.mDNSMode == MulticastDNSModeQueryAndGather {
|
||||
address = a.mDNSName
|
||||
}
|
||||
|
||||
for network := range networks {
|
||||
var port int
|
||||
var conn net.PacketConn
|
||||
var err error
|
||||
|
||||
var tcpType TCPType
|
||||
switch network {
|
||||
case tcp:
|
||||
// Handle ICE TCP passive mode
|
||||
|
||||
a.log.Debugf("GetConn by ufrag: %s\n", a.localUfrag)
|
||||
conn, err = a.tcpMux.GetConnByUfrag(a.localUfrag)
|
||||
if err != nil {
|
||||
if !errors.Is(err, ErrTCPMuxNotInitialized) {
|
||||
a.log.Warnf("error getting tcp conn by ufrag: %s %s %s\n", network, ip, a.localUfrag)
|
||||
}
|
||||
continue
|
||||
}
|
||||
port = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
tcpType = TCPTypePassive
|
||||
// is there a way to verify that the listen address is even
|
||||
// accessible from the current interface.
|
||||
case udp:
|
||||
conn, err = listenUDPInPortRange(a.net, a.log, int(a.portmax), int(a.portmin), network, &net.UDPAddr{IP: ip, Port: 0})
|
||||
if err != nil {
|
||||
a.log.Warnf("could not listen %s %s\n", network, ip)
|
||||
continue
|
||||
}
|
||||
|
||||
port = conn.LocalAddr().(*net.UDPAddr).Port
|
||||
}
|
||||
hostConfig := CandidateHostConfig{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Port: port,
|
||||
Component: ComponentRTP,
|
||||
TCPType: tcpType,
|
||||
}
|
||||
|
||||
c, err := NewCandidateHost(&hostConfig)
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, fmt.Sprintf("Failed to create host candidate: %s %s %d: %v\n", network, mappedIP, port, err))
|
||||
continue
|
||||
}
|
||||
|
||||
if a.mDNSMode == MulticastDNSModeQueryAndGather {
|
||||
if err = c.setIP(ip); err != nil {
|
||||
closeConnAndLog(conn, a.log, fmt.Sprintf("Failed to create host candidate: %s %s %d: %v\n", network, mappedIP, port, err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err := a.addCandidate(ctx, c, conn); err != nil {
|
||||
if closeErr := c.close(); closeErr != nil {
|
||||
a.log.Warnf("Failed to close candidate: %v", closeErr)
|
||||
}
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes []NetworkType) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
for _, networkType := range networkTypes {
|
||||
if networkType.IsTCP() {
|
||||
continue
|
||||
}
|
||||
|
||||
network := networkType.String()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
conn, err := listenUDPInPortRange(a.net, a.log, int(a.portmax), int(a.portmin), network, &net.UDPAddr{IP: nil, Port: 0})
|
||||
if err != nil {
|
||||
a.log.Warnf("Failed to listen %s: %v\n", network, err)
|
||||
return
|
||||
}
|
||||
|
||||
laddr := conn.LocalAddr().(*net.UDPAddr)
|
||||
mappedIP, err := a.extIPMapper.findExternalIP(laddr.IP.String())
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, fmt.Sprintf("1:1 NAT mapping is enabled but no external IP is found for %s\n", laddr.IP.String()))
|
||||
return
|
||||
}
|
||||
|
||||
srflxConfig := CandidateServerReflexiveConfig{
|
||||
Network: network,
|
||||
Address: mappedIP.String(),
|
||||
Port: laddr.Port,
|
||||
Component: ComponentRTP,
|
||||
RelAddr: laddr.IP.String(),
|
||||
RelPort: laddr.Port,
|
||||
}
|
||||
c, err := NewCandidateServerReflexive(&srflxConfig)
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, fmt.Sprintf("Failed to create server reflexive candidate: %s %s %d: %v\n",
|
||||
network,
|
||||
mappedIP.String(),
|
||||
laddr.Port,
|
||||
err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.addCandidate(ctx, c, conn); err != nil {
|
||||
if closeErr := c.close(); closeErr != nil {
|
||||
a.log.Warnf("Failed to close candidate: %v", closeErr)
|
||||
}
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v\n", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkTypes []NetworkType) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
for _, networkType := range networkTypes {
|
||||
if networkType.IsTCP() {
|
||||
continue
|
||||
}
|
||||
|
||||
for i := range urls {
|
||||
wg.Add(1)
|
||||
go func(url URL, network string) {
|
||||
defer wg.Done()
|
||||
hostPort := fmt.Sprintf("%s:%d", url.Host, url.Port)
|
||||
serverAddr, err := a.net.ResolveUDPAddr(network, hostPort)
|
||||
if err != nil {
|
||||
a.log.Warnf("failed to resolve stun host: %s: %v", hostPort, err)
|
||||
return
|
||||
}
|
||||
|
||||
conn, err := listenUDPInPortRange(a.net, a.log, int(a.portmax), int(a.portmin), network, &net.UDPAddr{IP: nil, Port: 0})
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, fmt.Sprintf("Failed to listen for %s: %v\n", serverAddr.String(), err))
|
||||
return
|
||||
}
|
||||
|
||||
xoraddr, err := getXORMappedAddr(conn, serverAddr, stunGatherTimeout)
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, fmt.Sprintf("could not get server reflexive address %s %s: %v\n", network, url, err))
|
||||
return
|
||||
}
|
||||
|
||||
ip := xoraddr.IP
|
||||
port := xoraddr.Port
|
||||
|
||||
laddr := conn.LocalAddr().(*net.UDPAddr)
|
||||
srflxConfig := CandidateServerReflexiveConfig{
|
||||
Network: network,
|
||||
Address: ip.String(),
|
||||
Port: port,
|
||||
Component: ComponentRTP,
|
||||
RelAddr: laddr.IP.String(),
|
||||
RelPort: laddr.Port,
|
||||
}
|
||||
c, err := NewCandidateServerReflexive(&srflxConfig)
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, fmt.Sprintf("Failed to create server reflexive candidate: %s %s %d: %v\n", network, ip, port, err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.addCandidate(ctx, c, conn); err != nil {
|
||||
if closeErr := c.close(); closeErr != nil {
|
||||
a.log.Warnf("Failed to close candidate: %v", closeErr)
|
||||
}
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v\n", err)
|
||||
}
|
||||
}(*urls[i], networkType.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //nolint:gocognit
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
network := NetworkTypeUDP4.String()
|
||||
for i := range urls {
|
||||
switch {
|
||||
case urls[i].Scheme != SchemeTypeTURN && urls[i].Scheme != SchemeTypeTURNS:
|
||||
continue
|
||||
case urls[i].Username == "":
|
||||
a.log.Errorf("Failed to gather relay candidates: %v", ErrUsernameEmpty)
|
||||
return
|
||||
case urls[i].Password == "":
|
||||
a.log.Errorf("Failed to gather relay candidates: %v", ErrPasswordEmpty)
|
||||
return
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(url URL) {
|
||||
defer wg.Done()
|
||||
TURNServerAddr := fmt.Sprintf("%s:%d", url.Host, url.Port)
|
||||
var (
|
||||
locConn net.PacketConn
|
||||
err error
|
||||
RelAddr string
|
||||
RelPort int
|
||||
)
|
||||
|
||||
switch {
|
||||
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURN:
|
||||
if locConn, err = a.net.ListenPacket(network, "0.0.0.0:0"); err != nil {
|
||||
a.log.Warnf("Failed to listen %s: %v\n", network, err)
|
||||
return
|
||||
}
|
||||
|
||||
RelAddr = locConn.LocalAddr().(*net.UDPAddr).IP.String()
|
||||
RelPort = locConn.LocalAddr().(*net.UDPAddr).Port
|
||||
case a.proxyDialer != nil && url.Proto == ProtoTypeTCP &&
|
||||
(url.Scheme == SchemeTypeTURN || url.Scheme == SchemeTypeTURNS):
|
||||
conn, connectErr := a.proxyDialer.Dial(NetworkTypeTCP4.String(), TURNServerAddr)
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to Dial TCP Addr %s via proxy dialer: %v\n", TURNServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
RelAddr = conn.LocalAddr().(*net.TCPAddr).IP.String()
|
||||
RelPort = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
locConn = turn.NewSTUNConn(conn)
|
||||
|
||||
case url.Proto == ProtoTypeTCP && url.Scheme == SchemeTypeTURN:
|
||||
tcpAddr, connectErr := net.ResolveTCPAddr(NetworkTypeTCP4.String(), TURNServerAddr)
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to resolve TCP Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
conn, connectErr := net.DialTCP(NetworkTypeTCP4.String(), nil, tcpAddr)
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to Dial TCP Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
RelAddr = conn.LocalAddr().(*net.TCPAddr).IP.String()
|
||||
RelPort = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
locConn = turn.NewSTUNConn(conn)
|
||||
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURNS:
|
||||
udpAddr, connectErr := net.ResolveUDPAddr(network, TURNServerAddr)
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to resolve UDP Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
conn, connectErr := dtls.Dial(network, udpAddr, &dtls.Config{
|
||||
InsecureSkipVerify: a.insecureSkipVerify, //nolint:gosec
|
||||
})
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to Dial DTLS Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
RelAddr = conn.LocalAddr().(*net.UDPAddr).IP.String()
|
||||
RelPort = conn.LocalAddr().(*net.UDPAddr).Port
|
||||
locConn = &fakePacketConn{conn}
|
||||
case url.Proto == ProtoTypeTCP && url.Scheme == SchemeTypeTURNS:
|
||||
conn, connectErr := tls.Dial(NetworkTypeTCP4.String(), TURNServerAddr, &tls.Config{
|
||||
InsecureSkipVerify: a.insecureSkipVerify, //nolint:gosec
|
||||
})
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to Dial TLS Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
RelAddr = conn.LocalAddr().(*net.TCPAddr).IP.String()
|
||||
RelPort = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
locConn = turn.NewSTUNConn(conn)
|
||||
default:
|
||||
a.log.Warnf("Unable to handle URL in gatherCandidatesRelay %v\n", url)
|
||||
return
|
||||
}
|
||||
|
||||
client, err := turn.NewClient(&turn.ClientConfig{
|
||||
TURNServerAddr: TURNServerAddr,
|
||||
Conn: locConn,
|
||||
Username: url.Username,
|
||||
Password: url.Password,
|
||||
LoggerFactory: a.loggerFactory,
|
||||
Net: a.net,
|
||||
})
|
||||
if err != nil {
|
||||
closeConnAndLog(locConn, a.log, fmt.Sprintf("Failed to build new turn.Client %s %s\n", TURNServerAddr, err))
|
||||
return
|
||||
}
|
||||
|
||||
if err = client.Listen(); err != nil {
|
||||
client.Close()
|
||||
closeConnAndLog(locConn, a.log, fmt.Sprintf("Failed to listen on turn.Client %s %s\n", TURNServerAddr, err))
|
||||
return
|
||||
}
|
||||
|
||||
relayConn, err := client.Allocate()
|
||||
if err != nil {
|
||||
client.Close()
|
||||
closeConnAndLog(locConn, a.log, fmt.Sprintf("Failed to allocate on turn.Client %s %s\n", TURNServerAddr, err))
|
||||
return
|
||||
}
|
||||
|
||||
raddr := relayConn.LocalAddr().(*net.UDPAddr)
|
||||
relayConfig := CandidateRelayConfig{
|
||||
Network: network,
|
||||
Component: ComponentRTP,
|
||||
Address: raddr.IP.String(),
|
||||
Port: raddr.Port,
|
||||
RelAddr: RelAddr,
|
||||
RelPort: RelPort,
|
||||
OnClose: func() error {
|
||||
client.Close()
|
||||
return locConn.Close()
|
||||
},
|
||||
}
|
||||
relayConnClose := func() {
|
||||
if relayConErr := relayConn.Close(); relayConErr != nil {
|
||||
a.log.Warnf("Failed to close relay %v", relayConErr)
|
||||
}
|
||||
}
|
||||
candidate, err := NewCandidateRelay(&relayConfig)
|
||||
if err != nil {
|
||||
relayConnClose()
|
||||
|
||||
client.Close()
|
||||
closeConnAndLog(locConn, a.log, fmt.Sprintf("Failed to create relay candidate: %s %s: %v\n", network, raddr.String(), err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.addCandidate(ctx, candidate, relayConn); err != nil {
|
||||
relayConnClose()
|
||||
|
||||
if closeErr := candidate.close(); closeErr != nil {
|
||||
a.log.Warnf("Failed to close candidate: %v", closeErr)
|
||||
}
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v\n", err)
|
||||
}
|
||||
}(*urls[i])
|
||||
}
|
||||
}
|
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/go.mod
generated
vendored
Normal file
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
module github.com/pion/ice/v2
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/pion/dtls/v2 v2.0.4
|
||||
github.com/pion/logging v0.2.2
|
||||
github.com/pion/mdns v0.0.4
|
||||
github.com/pion/randutil v0.1.0
|
||||
github.com/pion/stun v0.3.5
|
||||
github.com/pion/transport v0.12.0
|
||||
github.com/pion/turn/v2 v2.0.5
|
||||
github.com/stretchr/testify v1.6.1
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7
|
||||
)
|
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/go.sum
generated
vendored
Normal file
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/pion/dtls/v2 v2.0.4 h1:WuUcqi6oYMu/noNTz92QrF1DaFj4eXbhQ6dzaaAwOiI=
|
||||
github.com/pion/dtls/v2 v2.0.4/go.mod h1:qAkFscX0ZHoI1E07RfYPoRw3manThveu+mlTDdOxoGI=
|
||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/mdns v0.0.4 h1:O4vvVqr4DGX63vzmO6Fw9vpy3lfztVWHGCQfyw0ZLSY=
|
||||
github.com/pion/mdns v0.0.4/go.mod h1:R1sL0p50l42S5lJs91oNdUL58nm0QHrhxnSegr++qC0=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg=
|
||||
github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA=
|
||||
github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRhSzR+CZ8=
|
||||
github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE=
|
||||
github.com/pion/transport v0.10.1 h1:2W+yJT+0mOQ160ThZYUx5Zp2skzshiNgxrNE9GUfhJM=
|
||||
github.com/pion/transport v0.10.1/go.mod h1:PBis1stIILMiis0PewDw91WJeLJkyIMcEk+DwKOzf4A=
|
||||
github.com/pion/transport v0.12.0 h1:UFmOBBZkTZ3LgvLRf/NGrfWdZEubcU6zkLU3PsA9YvU=
|
||||
github.com/pion/transport v0.12.0/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA=
|
||||
github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyrTqMw=
|
||||
github.com/pion/udp v0.1.0 h1:uGxQsNyrqG3GLINv36Ff60covYmfrLoxzwnCsIYspXI=
|
||||
github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7 h1:3uJsdck53FDIpWwLeAXlia9p4C8j0BO2xZrqzKpL0D8=
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
76
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/ice.go
generated
vendored
Normal file
76
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/ice.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
package ice
|
||||
|
||||
// ConnectionState is an enum showing the state of a ICE Connection
|
||||
type ConnectionState int
|
||||
|
||||
// List of supported States
|
||||
const (
|
||||
// ConnectionStateNew ICE agent is gathering addresses
|
||||
ConnectionStateNew = iota + 1
|
||||
|
||||
// ConnectionStateChecking ICE agent has been given local and remote candidates, and is attempting to find a match
|
||||
ConnectionStateChecking
|
||||
|
||||
// ConnectionStateConnected ICE agent has a pairing, but is still checking other pairs
|
||||
ConnectionStateConnected
|
||||
|
||||
// ConnectionStateCompleted ICE agent has finished
|
||||
ConnectionStateCompleted
|
||||
|
||||
// ConnectionStateFailed ICE agent never could successfully connect
|
||||
ConnectionStateFailed
|
||||
|
||||
// ConnectionStateDisconnected ICE agent connected successfully, but has entered a failed state
|
||||
ConnectionStateDisconnected
|
||||
|
||||
// ConnectionStateClosed ICE agent has finished and is no longer handling requests
|
||||
ConnectionStateClosed
|
||||
)
|
||||
|
||||
func (c ConnectionState) String() string {
|
||||
switch c {
|
||||
case ConnectionStateNew:
|
||||
return "New"
|
||||
case ConnectionStateChecking:
|
||||
return "Checking"
|
||||
case ConnectionStateConnected:
|
||||
return "Connected"
|
||||
case ConnectionStateCompleted:
|
||||
return "Completed"
|
||||
case ConnectionStateFailed:
|
||||
return "Failed"
|
||||
case ConnectionStateDisconnected:
|
||||
return "Disconnected"
|
||||
case ConnectionStateClosed:
|
||||
return "Closed"
|
||||
default:
|
||||
return "Invalid"
|
||||
}
|
||||
}
|
||||
|
||||
// GatheringState describes the state of the candidate gathering process
|
||||
type GatheringState int
|
||||
|
||||
const (
|
||||
// GatheringStateNew indicates candidate gatering is not yet started
|
||||
GatheringStateNew GatheringState = iota + 1
|
||||
|
||||
// GatheringStateGathering indicates candidate gatering is ongoing
|
||||
GatheringStateGathering
|
||||
|
||||
// GatheringStateComplete indicates candidate gatering has been completed
|
||||
GatheringStateComplete
|
||||
)
|
||||
|
||||
func (t GatheringState) String() string {
|
||||
switch t {
|
||||
case GatheringStateNew:
|
||||
return "new"
|
||||
case GatheringStateGathering:
|
||||
return "gathering"
|
||||
case GatheringStateComplete:
|
||||
return "complete"
|
||||
default:
|
||||
return ErrUnknownType.Error()
|
||||
}
|
||||
}
|
87
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/icecontrol.go
generated
vendored
Normal file
87
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/icecontrol.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
// tiebreaker is common helper for ICE-{CONTROLLED,CONTROLLING}
|
||||
// and represents the so-called tiebreaker number.
|
||||
type tiebreaker uint64
|
||||
|
||||
const tiebreakerSize = 8 // 64 bit
|
||||
|
||||
// AddToAs adds tiebreaker value to m as t attribute.
|
||||
func (a tiebreaker) AddToAs(m *stun.Message, t stun.AttrType) error {
|
||||
v := make([]byte, tiebreakerSize)
|
||||
binary.BigEndian.PutUint64(v, uint64(a))
|
||||
m.Add(t, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFromAs decodes tiebreaker value in message getting it as for t type.
|
||||
func (a *tiebreaker) GetFromAs(m *stun.Message, t stun.AttrType) error {
|
||||
v, err := m.Get(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stun.CheckSize(t, len(v), tiebreakerSize); err != nil {
|
||||
return err
|
||||
}
|
||||
*a = tiebreaker(binary.BigEndian.Uint64(v))
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttrControlled represents ICE-CONTROLLED attribute.
|
||||
type AttrControlled uint64
|
||||
|
||||
// AddTo adds ICE-CONTROLLED to message.
|
||||
func (c AttrControlled) AddTo(m *stun.Message) error {
|
||||
return tiebreaker(c).AddToAs(m, stun.AttrICEControlled)
|
||||
}
|
||||
|
||||
// GetFrom decodes ICE-CONTROLLED from message.
|
||||
func (c *AttrControlled) GetFrom(m *stun.Message) error {
|
||||
return (*tiebreaker)(c).GetFromAs(m, stun.AttrICEControlled)
|
||||
}
|
||||
|
||||
// AttrControlling represents ICE-CONTROLLING attribute.
|
||||
type AttrControlling uint64
|
||||
|
||||
// AddTo adds ICE-CONTROLLING to message.
|
||||
func (c AttrControlling) AddTo(m *stun.Message) error {
|
||||
return tiebreaker(c).AddToAs(m, stun.AttrICEControlling)
|
||||
}
|
||||
|
||||
// GetFrom decodes ICE-CONTROLLING from message.
|
||||
func (c *AttrControlling) GetFrom(m *stun.Message) error {
|
||||
return (*tiebreaker)(c).GetFromAs(m, stun.AttrICEControlling)
|
||||
}
|
||||
|
||||
// AttrControl is helper that wraps ICE-{CONTROLLED,CONTROLLING}.
|
||||
type AttrControl struct {
|
||||
Role Role
|
||||
Tiebreaker uint64
|
||||
}
|
||||
|
||||
// AddTo adds ICE-CONTROLLED or ICE-CONTROLLING attribute depending on Role.
|
||||
func (c AttrControl) AddTo(m *stun.Message) error {
|
||||
if c.Role == Controlling {
|
||||
return tiebreaker(c.Tiebreaker).AddToAs(m, stun.AttrICEControlling)
|
||||
}
|
||||
return tiebreaker(c.Tiebreaker).AddToAs(m, stun.AttrICEControlled)
|
||||
}
|
||||
|
||||
// GetFrom decodes Role and Tiebreaker value from message.
|
||||
func (c *AttrControl) GetFrom(m *stun.Message) error {
|
||||
if m.Contains(stun.AttrICEControlling) {
|
||||
c.Role = Controlling
|
||||
return (*tiebreaker)(&c.Tiebreaker).GetFromAs(m, stun.AttrICEControlling)
|
||||
}
|
||||
if m.Contains(stun.AttrICEControlled) {
|
||||
c.Role = Controlled
|
||||
return (*tiebreaker)(&c.Tiebreaker).GetFromAs(m, stun.AttrICEControlled)
|
||||
}
|
||||
return stun.ErrAttributeNotFound
|
||||
}
|
63
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go
generated
vendored
Normal file
63
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/mdns"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
// MulticastDNSMode represents the different Multicast modes ICE can run in
|
||||
type MulticastDNSMode byte
|
||||
|
||||
// MulticastDNSMode enum
|
||||
const (
|
||||
// MulticastDNSModeDisabled means remote mDNS candidates will be discarded, and local host candidates will use IPs
|
||||
MulticastDNSModeDisabled MulticastDNSMode = iota + 1
|
||||
|
||||
// MulticastDNSModeQueryOnly means remote mDNS candidates will be accepted, and local host candidates will use IPs
|
||||
MulticastDNSModeQueryOnly
|
||||
|
||||
// MulticastDNSModeQueryAndGather means remote mDNS candidates will be accepted, and local host candidates will use mDNS
|
||||
MulticastDNSModeQueryAndGather
|
||||
)
|
||||
|
||||
func generateMulticastDNSName() (string, error) {
|
||||
// https://tools.ietf.org/id/draft-ietf-rtcweb-mdns-ice-candidates-02.html#gathering
|
||||
// The unique name MUST consist of a version 4 UUID as defined in [RFC4122], followed by “.local”.
|
||||
u, err := uuid.NewRandom()
|
||||
return u.String() + ".local", err
|
||||
}
|
||||
|
||||
func createMulticastDNS(mDNSMode MulticastDNSMode, mDNSName string, log logging.LeveledLogger) (*mdns.Conn, MulticastDNSMode, error) {
|
||||
if mDNSMode == MulticastDNSModeDisabled {
|
||||
return nil, mDNSMode, nil
|
||||
}
|
||||
|
||||
addr, mdnsErr := net.ResolveUDPAddr("udp4", mdns.DefaultAddress)
|
||||
if mdnsErr != nil {
|
||||
return nil, mDNSMode, mdnsErr
|
||||
}
|
||||
|
||||
l, mdnsErr := net.ListenUDP("udp4", addr)
|
||||
if mdnsErr != nil {
|
||||
// If ICE fails to start MulticastDNS server just warn the user and continue
|
||||
log.Errorf("Failed to enable mDNS, continuing in mDNS disabled mode: (%s)", mdnsErr)
|
||||
return nil, MulticastDNSModeDisabled, nil
|
||||
}
|
||||
|
||||
switch mDNSMode {
|
||||
case MulticastDNSModeQueryOnly:
|
||||
conn, err := mdns.Server(ipv4.NewPacketConn(l), &mdns.Config{})
|
||||
return conn, mDNSMode, err
|
||||
case MulticastDNSModeQueryAndGather:
|
||||
conn, err := mdns.Server(ipv4.NewPacketConn(l), &mdns.Config{
|
||||
LocalNames: []string{mDNSName},
|
||||
})
|
||||
return conn, mDNSMode, err
|
||||
default:
|
||||
return nil, mDNSMode, nil
|
||||
}
|
||||
}
|
130
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/networktype.go
generated
vendored
Normal file
130
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/networktype.go
generated
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
udp = "udp"
|
||||
tcp = "tcp"
|
||||
)
|
||||
|
||||
func supportedNetworkTypes() []NetworkType {
|
||||
return []NetworkType{
|
||||
NetworkTypeUDP4,
|
||||
NetworkTypeUDP6,
|
||||
NetworkTypeTCP4,
|
||||
NetworkTypeTCP6,
|
||||
}
|
||||
}
|
||||
|
||||
// NetworkType represents the type of network
|
||||
type NetworkType int
|
||||
|
||||
const (
|
||||
// NetworkTypeUDP4 indicates UDP over IPv4.
|
||||
NetworkTypeUDP4 NetworkType = iota + 1
|
||||
|
||||
// NetworkTypeUDP6 indicates UDP over IPv6.
|
||||
NetworkTypeUDP6
|
||||
|
||||
// NetworkTypeTCP4 indicates TCP over IPv4.
|
||||
NetworkTypeTCP4
|
||||
|
||||
// NetworkTypeTCP6 indicates TCP over IPv6.
|
||||
NetworkTypeTCP6
|
||||
)
|
||||
|
||||
func (t NetworkType) String() string {
|
||||
switch t {
|
||||
case NetworkTypeUDP4:
|
||||
return "udp4"
|
||||
case NetworkTypeUDP6:
|
||||
return "udp6"
|
||||
case NetworkTypeTCP4:
|
||||
return "tcp4"
|
||||
case NetworkTypeTCP6:
|
||||
return "tcp6"
|
||||
default:
|
||||
return ErrUnknownType.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// IsUDP returns true when network is UDP4 or UDP6.
|
||||
func (t NetworkType) IsUDP() bool {
|
||||
return t == NetworkTypeUDP4 || t == NetworkTypeUDP6
|
||||
}
|
||||
|
||||
// IsTCP returns true when network is TCP4 or TCP6.
|
||||
func (t NetworkType) IsTCP() bool {
|
||||
return t == NetworkTypeTCP4 || t == NetworkTypeTCP6
|
||||
}
|
||||
|
||||
// NetworkShort returns the short network description
|
||||
func (t NetworkType) NetworkShort() string {
|
||||
switch t {
|
||||
case NetworkTypeUDP4, NetworkTypeUDP6:
|
||||
return udp
|
||||
case NetworkTypeTCP4, NetworkTypeTCP6:
|
||||
return tcp
|
||||
default:
|
||||
return ErrUnknownType.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// IsReliable returns true if the network is reliable
|
||||
func (t NetworkType) IsReliable() bool {
|
||||
switch t {
|
||||
case NetworkTypeUDP4, NetworkTypeUDP6:
|
||||
return false
|
||||
case NetworkTypeTCP4, NetworkTypeTCP6:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsIPv4 returns whether the network type is IPv4 or not.
|
||||
func (t NetworkType) IsIPv4() bool {
|
||||
switch t {
|
||||
case NetworkTypeUDP4, NetworkTypeTCP4:
|
||||
return true
|
||||
case NetworkTypeUDP6, NetworkTypeTCP6:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsIPv6 returns whether the network type is IPv6 or not.
|
||||
func (t NetworkType) IsIPv6() bool {
|
||||
switch t {
|
||||
case NetworkTypeUDP4, NetworkTypeTCP4:
|
||||
return false
|
||||
case NetworkTypeUDP6, NetworkTypeTCP6:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// determineNetworkType determines the type of network based on
|
||||
// the short network string and an IP address.
|
||||
func determineNetworkType(network string, ip net.IP) (NetworkType, error) {
|
||||
ipv4 := ip.To4() != nil
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(strings.ToLower(network), udp):
|
||||
if ipv4 {
|
||||
return NetworkTypeUDP4, nil
|
||||
}
|
||||
return NetworkTypeUDP6, nil
|
||||
|
||||
case strings.HasPrefix(strings.ToLower(network), tcp):
|
||||
if ipv4 {
|
||||
return NetworkTypeTCP4, nil
|
||||
}
|
||||
return NetworkTypeTCP6, nil
|
||||
}
|
||||
|
||||
return NetworkType(0), fmt.Errorf("%w from %s %s", errDetermineNetworkType, network, ip)
|
||||
}
|
33
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/priority.go
generated
vendored
Normal file
33
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/priority.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
// PriorityAttr represents PRIORITY attribute.
|
||||
type PriorityAttr uint32
|
||||
|
||||
const prioritySize = 4 // 32 bit
|
||||
|
||||
// AddTo adds PRIORITY attribute to message.
|
||||
func (p PriorityAttr) AddTo(m *stun.Message) error {
|
||||
v := make([]byte, prioritySize)
|
||||
binary.BigEndian.PutUint32(v, uint32(p))
|
||||
m.Add(stun.AttrPriority, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFrom decodes PRIORITY attribute from message.
|
||||
func (p *PriorityAttr) GetFrom(m *stun.Message) error {
|
||||
v, err := m.Get(stun.AttrPriority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stun.CheckSize(stun.AttrPriority, len(v), prioritySize); err != nil {
|
||||
return err
|
||||
}
|
||||
*p = PriorityAttr(binary.BigEndian.Uint32(v))
|
||||
return nil
|
||||
}
|
53
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/rand.go
generated
vendored
Normal file
53
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/rand.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
package ice
|
||||
|
||||
import "github.com/pion/randutil"
|
||||
|
||||
const (
|
||||
runesAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
runesDigit = "0123456789"
|
||||
runesCandidateIDFoundation = runesAlpha + runesDigit + "+/"
|
||||
|
||||
lenUFrag = 16
|
||||
lenPwd = 32
|
||||
)
|
||||
|
||||
// Seeding random generator each time limits number of generated sequence to 31-bits,
|
||||
// and causes collision on low time accuracy environments.
|
||||
// Use global random generator seeded by crypto grade random.
|
||||
var (
|
||||
globalMathRandomGenerator = randutil.NewMathRandomGenerator() //nolint:gochecknoglobals
|
||||
globalCandidateIDGenerator = candidateIDGenerator{globalMathRandomGenerator} //nolint:gochecknoglobals
|
||||
)
|
||||
|
||||
// candidateIDGenerator is a random candidate ID generator.
|
||||
// Candidate ID is used in SDP and always shared to the other peer.
|
||||
// It doesn't require cryptographic random.
|
||||
type candidateIDGenerator struct {
|
||||
randutil.MathRandomGenerator
|
||||
}
|
||||
|
||||
func newCandidateIDGenerator() *candidateIDGenerator {
|
||||
return &candidateIDGenerator{
|
||||
randutil.NewMathRandomGenerator(),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *candidateIDGenerator) Generate() string {
|
||||
// https://tools.ietf.org/html/rfc5245#section-15.1
|
||||
// candidate-id = "candidate" ":" foundation
|
||||
// foundation = 1*32ice-char
|
||||
// ice-char = ALPHA / DIGIT / "+" / "/"
|
||||
return "candidate:" + g.MathRandomGenerator.GenerateString(32, runesCandidateIDFoundation)
|
||||
}
|
||||
|
||||
// generatePwd generates ICE pwd.
|
||||
// This internally uses generateCryptoRandomString.
|
||||
func generatePwd() (string, error) {
|
||||
return randutil.GenerateCryptoRandomString(lenPwd, runesAlpha)
|
||||
}
|
||||
|
||||
// generateUFrag generates ICE user fragment.
|
||||
// This internally uses generateCryptoRandomString.
|
||||
func generateUFrag() (string, error) {
|
||||
return randutil.GenerateCryptoRandomString(lenUFrag, runesAlpha)
|
||||
}
|
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/renovate.json
generated
vendored
Normal file
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/renovate.json
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
],
|
||||
"commitBody": "Generated by renovateBot",
|
||||
"packageRules": [
|
||||
{
|
||||
"packagePatterns": ["^golang.org/x/"],
|
||||
"schedule": ["on the first day of the month"]
|
||||
}
|
||||
]
|
||||
}
|
43
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/role.go
generated
vendored
Normal file
43
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/role.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Role represents ICE agent role, which can be controlling or controlled.
|
||||
type Role byte
|
||||
|
||||
// Possible ICE agent roles.
|
||||
const (
|
||||
Controlling Role = iota
|
||||
Controlled
|
||||
)
|
||||
|
||||
// UnmarshalText implements TextUnmarshaler.
|
||||
func (r *Role) UnmarshalText(text []byte) error {
|
||||
switch string(text) {
|
||||
case "controlling":
|
||||
*r = Controlling
|
||||
case "controlled":
|
||||
*r = Controlled
|
||||
default:
|
||||
return fmt.Errorf("%w %q", errUnknownRole, text)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText implements TextMarshaler.
|
||||
func (r Role) MarshalText() (text []byte, err error) {
|
||||
return []byte(r.String()), nil
|
||||
}
|
||||
|
||||
func (r Role) String() string {
|
||||
switch r {
|
||||
case Controlling:
|
||||
return "controlling"
|
||||
case Controlled:
|
||||
return "controlled"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
287
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/selection.go
generated
vendored
Normal file
287
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/selection.go
generated
vendored
Normal file
|
@ -0,0 +1,287 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
type pairCandidateSelector interface {
|
||||
Start()
|
||||
ContactCandidates()
|
||||
PingCandidate(local, remote Candidate)
|
||||
HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr)
|
||||
HandleBindingRequest(m *stun.Message, local, remote Candidate)
|
||||
}
|
||||
|
||||
type controllingSelector struct {
|
||||
startTime time.Time
|
||||
agent *Agent
|
||||
nominatedPair *candidatePair
|
||||
log logging.LeveledLogger
|
||||
}
|
||||
|
||||
func (s *controllingSelector) Start() {
|
||||
s.startTime = time.Now()
|
||||
s.nominatedPair = nil
|
||||
}
|
||||
|
||||
func (s *controllingSelector) isNominatable(c Candidate) bool {
|
||||
switch {
|
||||
case c.Type() == CandidateTypeHost:
|
||||
return time.Since(s.startTime).Nanoseconds() > s.agent.hostAcceptanceMinWait.Nanoseconds()
|
||||
case c.Type() == CandidateTypeServerReflexive:
|
||||
return time.Since(s.startTime).Nanoseconds() > s.agent.srflxAcceptanceMinWait.Nanoseconds()
|
||||
case c.Type() == CandidateTypePeerReflexive:
|
||||
return time.Since(s.startTime).Nanoseconds() > s.agent.prflxAcceptanceMinWait.Nanoseconds()
|
||||
case c.Type() == CandidateTypeRelay:
|
||||
return time.Since(s.startTime).Nanoseconds() > s.agent.relayAcceptanceMinWait.Nanoseconds()
|
||||
}
|
||||
|
||||
s.log.Errorf("isNominatable invalid candidate type %s", c.Type().String())
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *controllingSelector) ContactCandidates() {
|
||||
switch {
|
||||
case s.agent.getSelectedPair() != nil:
|
||||
if s.agent.validateSelectedPair() {
|
||||
s.log.Trace("checking keepalive")
|
||||
s.agent.checkKeepalive()
|
||||
}
|
||||
case s.nominatedPair != nil:
|
||||
s.nominatePair(s.nominatedPair)
|
||||
default:
|
||||
p := s.agent.getBestValidCandidatePair()
|
||||
if p != nil && s.isNominatable(p.local) && s.isNominatable(p.remote) {
|
||||
s.log.Tracef("Nominatable pair found, nominating (%s, %s)", p.local.String(), p.remote.String())
|
||||
p.nominated = true
|
||||
s.nominatedPair = p
|
||||
s.nominatePair(p)
|
||||
return
|
||||
}
|
||||
s.agent.pingAllCandidates()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *controllingSelector) nominatePair(pair *candidatePair) {
|
||||
// The controlling agent MUST include the USE-CANDIDATE attribute in
|
||||
// order to nominate a candidate pair (Section 8.1.1). The controlled
|
||||
// agent MUST NOT include the USE-CANDIDATE attribute in a Binding
|
||||
// request.
|
||||
msg, err := stun.Build(stun.BindingRequest, stun.TransactionID,
|
||||
stun.NewUsername(s.agent.remoteUfrag+":"+s.agent.localUfrag),
|
||||
UseCandidate(),
|
||||
AttrControlling(s.agent.tieBreaker),
|
||||
PriorityAttr(pair.local.Priority()),
|
||||
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
||||
stun.Fingerprint,
|
||||
)
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
s.log.Tracef("ping STUN (nominate candidate pair) from %s to %s\n", pair.local.String(), pair.remote.String())
|
||||
s.agent.sendBindingRequest(msg, pair.local, pair.remote)
|
||||
}
|
||||
|
||||
func (s *controllingSelector) HandleBindingRequest(m *stun.Message, local, remote Candidate) {
|
||||
s.agent.sendBindingSuccess(m, local, remote)
|
||||
|
||||
p := s.agent.findPair(local, remote)
|
||||
|
||||
if p == nil {
|
||||
s.agent.addPair(local, remote)
|
||||
return
|
||||
}
|
||||
|
||||
if p.state == CandidatePairStateSucceeded && s.nominatedPair == nil && s.agent.getSelectedPair() == nil {
|
||||
bestPair := s.agent.getBestAvailableCandidatePair()
|
||||
if bestPair == nil {
|
||||
s.log.Tracef("No best pair available\n")
|
||||
} else if bestPair.Equal(p) && s.isNominatable(p.local) && s.isNominatable(p.remote) {
|
||||
s.log.Tracef("The candidate (%s, %s) is the best candidate available, marking it as nominated\n",
|
||||
p.local.String(), p.remote.String())
|
||||
s.nominatedPair = p
|
||||
s.nominatePair(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *controllingSelector) HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr) {
|
||||
ok, pendingRequest := s.agent.handleInboundBindingSuccess(m.TransactionID)
|
||||
if !ok {
|
||||
s.log.Warnf("discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID)
|
||||
return
|
||||
}
|
||||
|
||||
transactionAddr := pendingRequest.destination
|
||||
|
||||
// Assert that NAT is not symmetric
|
||||
// https://tools.ietf.org/html/rfc8445#section-7.2.5.2.1
|
||||
if !addrEqual(transactionAddr, remoteAddr) {
|
||||
s.log.Debugf("discard message: transaction source and destination does not match expected(%s), actual(%s)", transactionAddr, remote)
|
||||
return
|
||||
}
|
||||
|
||||
s.log.Tracef("inbound STUN (SuccessResponse) from %s to %s", remote.String(), local.String())
|
||||
p := s.agent.findPair(local, remote)
|
||||
|
||||
if p == nil {
|
||||
// This shouldn't happen
|
||||
s.log.Error("Success response from invalid candidate pair")
|
||||
return
|
||||
}
|
||||
|
||||
p.state = CandidatePairStateSucceeded
|
||||
s.log.Tracef("Found valid candidate pair: %s", p)
|
||||
if pendingRequest.isUseCandidate && s.agent.getSelectedPair() == nil {
|
||||
s.agent.setSelectedPair(p)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *controllingSelector) PingCandidate(local, remote Candidate) {
|
||||
msg, err := stun.Build(stun.BindingRequest, stun.TransactionID,
|
||||
stun.NewUsername(s.agent.remoteUfrag+":"+s.agent.localUfrag),
|
||||
AttrControlling(s.agent.tieBreaker),
|
||||
PriorityAttr(local.Priority()),
|
||||
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
||||
stun.Fingerprint,
|
||||
)
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
s.agent.sendBindingRequest(msg, local, remote)
|
||||
}
|
||||
|
||||
type controlledSelector struct {
|
||||
agent *Agent
|
||||
log logging.LeveledLogger
|
||||
}
|
||||
|
||||
func (s *controlledSelector) Start() {
|
||||
}
|
||||
|
||||
func (s *controlledSelector) ContactCandidates() {
|
||||
if s.agent.getSelectedPair() != nil {
|
||||
if s.agent.validateSelectedPair() {
|
||||
s.log.Trace("checking keepalive")
|
||||
s.agent.checkKeepalive()
|
||||
}
|
||||
} else {
|
||||
s.agent.pingAllCandidates()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *controlledSelector) PingCandidate(local, remote Candidate) {
|
||||
msg, err := stun.Build(stun.BindingRequest, stun.TransactionID,
|
||||
stun.NewUsername(s.agent.remoteUfrag+":"+s.agent.localUfrag),
|
||||
AttrControlled(s.agent.tieBreaker),
|
||||
PriorityAttr(local.Priority()),
|
||||
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
||||
stun.Fingerprint,
|
||||
)
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
s.agent.sendBindingRequest(msg, local, remote)
|
||||
}
|
||||
|
||||
func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr) {
|
||||
// nolint:godox
|
||||
// TODO according to the standard we should specifically answer a failed nomination:
|
||||
// https://tools.ietf.org/html/rfc8445#section-7.3.1.5
|
||||
// If the controlled agent does not accept the request from the
|
||||
// controlling agent, the controlled agent MUST reject the nomination
|
||||
// request with an appropriate error code response (e.g., 400)
|
||||
// [RFC5389].
|
||||
|
||||
ok, pendingRequest := s.agent.handleInboundBindingSuccess(m.TransactionID)
|
||||
if !ok {
|
||||
s.log.Warnf("discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID)
|
||||
return
|
||||
}
|
||||
|
||||
transactionAddr := pendingRequest.destination
|
||||
|
||||
// Assert that NAT is not symmetric
|
||||
// https://tools.ietf.org/html/rfc8445#section-7.2.5.2.1
|
||||
if !addrEqual(transactionAddr, remoteAddr) {
|
||||
s.log.Debugf("discard message: transaction source and destination does not match expected(%s), actual(%s)", transactionAddr, remote)
|
||||
return
|
||||
}
|
||||
|
||||
s.log.Tracef("inbound STUN (SuccessResponse) from %s to %s", remote.String(), local.String())
|
||||
|
||||
p := s.agent.findPair(local, remote)
|
||||
if p == nil {
|
||||
// This shouldn't happen
|
||||
s.log.Error("Success response from invalid candidate pair")
|
||||
return
|
||||
}
|
||||
|
||||
p.state = CandidatePairStateSucceeded
|
||||
s.log.Tracef("Found valid candidate pair: %s", p)
|
||||
}
|
||||
|
||||
func (s *controlledSelector) HandleBindingRequest(m *stun.Message, local, remote Candidate) {
|
||||
useCandidate := m.Contains(stun.AttrUseCandidate)
|
||||
|
||||
p := s.agent.findPair(local, remote)
|
||||
|
||||
if p == nil {
|
||||
p = s.agent.addPair(local, remote)
|
||||
}
|
||||
|
||||
if useCandidate {
|
||||
// https://tools.ietf.org/html/rfc8445#section-7.3.1.5
|
||||
|
||||
if p.state == CandidatePairStateSucceeded {
|
||||
// If the state of this pair is Succeeded, it means that the check
|
||||
// previously sent by this pair produced a successful response and
|
||||
// generated a valid pair (Section 7.2.5.3.2). The agent sets the
|
||||
// nominated flag value of the valid pair to true.
|
||||
if selectedPair := s.agent.getSelectedPair(); selectedPair == nil {
|
||||
s.agent.setSelectedPair(p)
|
||||
}
|
||||
s.agent.sendBindingSuccess(m, local, remote)
|
||||
} else {
|
||||
// If the received Binding request triggered a new check to be
|
||||
// enqueued in the triggered-check queue (Section 7.3.1.4), once the
|
||||
// check is sent and if it generates a successful response, and
|
||||
// generates a valid pair, the agent sets the nominated flag of the
|
||||
// pair to true. If the request fails (Section 7.2.5.2), the agent
|
||||
// MUST remove the candidate pair from the valid list, set the
|
||||
// candidate pair state to Failed, and set the checklist state to
|
||||
// Failed.
|
||||
s.PingCandidate(local, remote)
|
||||
}
|
||||
} else {
|
||||
s.agent.sendBindingSuccess(m, local, remote)
|
||||
s.PingCandidate(local, remote)
|
||||
}
|
||||
}
|
||||
|
||||
type liteSelector struct {
|
||||
pairCandidateSelector
|
||||
}
|
||||
|
||||
// A lite selector should not contact candidates
|
||||
func (s *liteSelector) ContactCandidates() {
|
||||
if _, ok := s.pairCandidateSelector.(*controllingSelector); ok {
|
||||
// nolint:godox
|
||||
// pion/ice#96
|
||||
// TODO: implement lite controlling agent. For now falling back to full agent.
|
||||
// This only happens if both peers are lite. See RFC 8445 S6.1.1 and S6.2
|
||||
s.pairCandidateSelector.ContactCandidates()
|
||||
} else if v, ok := s.pairCandidateSelector.(*controlledSelector); ok {
|
||||
v.agent.validateSelectedPair()
|
||||
}
|
||||
}
|
177
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stats.go
generated
vendored
Normal file
177
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stats.go
generated
vendored
Normal file
|
@ -0,0 +1,177 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// CandidatePairStats contains ICE candidate pair statistics
|
||||
type CandidatePairStats struct {
|
||||
// Timestamp is the timestamp associated with this object.
|
||||
Timestamp time.Time
|
||||
|
||||
// LocalCandidateID is the ID of the local candidate
|
||||
LocalCandidateID string
|
||||
|
||||
// RemoteCandidateID is the ID of the remote candidate
|
||||
RemoteCandidateID string
|
||||
|
||||
// State represents the state of the checklist for the local and remote
|
||||
// candidates in a pair.
|
||||
State CandidatePairState
|
||||
|
||||
// Nominated is true when this valid pair that should be used for media
|
||||
// if it is the highest-priority one amongst those whose nominated flag is set
|
||||
Nominated bool
|
||||
|
||||
// PacketsSent represents the total number of packets sent on this candidate pair.
|
||||
PacketsSent uint32
|
||||
|
||||
// PacketsReceived represents the total number of packets received on this candidate pair.
|
||||
PacketsReceived uint32
|
||||
|
||||
// BytesSent represents the total number of payload bytes sent on this candidate pair
|
||||
// not including headers or padding.
|
||||
BytesSent uint64
|
||||
|
||||
// BytesReceived represents the total number of payload bytes received on this candidate pair
|
||||
// not including headers or padding.
|
||||
BytesReceived uint64
|
||||
|
||||
// LastPacketSentTimestamp represents the timestamp at which the last packet was
|
||||
// sent on this particular candidate pair, excluding STUN packets.
|
||||
LastPacketSentTimestamp time.Time
|
||||
|
||||
// LastPacketReceivedTimestamp represents the timestamp at which the last packet
|
||||
// was received on this particular candidate pair, excluding STUN packets.
|
||||
LastPacketReceivedTimestamp time.Time
|
||||
|
||||
// FirstRequestTimestamp represents the timestamp at which the first STUN request
|
||||
// was sent on this particular candidate pair.
|
||||
FirstRequestTimestamp time.Time
|
||||
|
||||
// LastRequestTimestamp represents the timestamp at which the last STUN request
|
||||
// was sent on this particular candidate pair. The average interval between two
|
||||
// consecutive connectivity checks sent can be calculated with
|
||||
// (LastRequestTimestamp - FirstRequestTimestamp) / RequestsSent.
|
||||
LastRequestTimestamp time.Time
|
||||
|
||||
// LastResponseTimestamp represents the timestamp at which the last STUN response
|
||||
// was received on this particular candidate pair.
|
||||
LastResponseTimestamp time.Time
|
||||
|
||||
// TotalRoundTripTime represents the sum of all round trip time measurements
|
||||
// in seconds since the beginning of the session, based on STUN connectivity
|
||||
// check responses (ResponsesReceived), including those that reply to requests
|
||||
// that are sent in order to verify consent. The average round trip time can
|
||||
// be computed from TotalRoundTripTime by dividing it by ResponsesReceived.
|
||||
TotalRoundTripTime float64
|
||||
|
||||
// CurrentRoundTripTime represents the latest round trip time measured in seconds,
|
||||
// computed from both STUN connectivity checks, including those that are sent
|
||||
// for consent verification.
|
||||
CurrentRoundTripTime float64
|
||||
|
||||
// AvailableOutgoingBitrate is calculated by the underlying congestion control
|
||||
// by combining the available bitrate for all the outgoing RTP streams using
|
||||
// this candidate pair. The bitrate measurement does not count the size of the
|
||||
// IP or other transport layers like TCP or UDP. It is similar to the TIAS defined
|
||||
// in RFC 3890, i.e., it is measured in bits per second and the bitrate is calculated
|
||||
// over a 1 second window.
|
||||
AvailableOutgoingBitrate float64
|
||||
|
||||
// AvailableIncomingBitrate is calculated by the underlying congestion control
|
||||
// by combining the available bitrate for all the incoming RTP streams using
|
||||
// this candidate pair. The bitrate measurement does not count the size of the
|
||||
// IP or other transport layers like TCP or UDP. It is similar to the TIAS defined
|
||||
// in RFC 3890, i.e., it is measured in bits per second and the bitrate is
|
||||
// calculated over a 1 second window.
|
||||
AvailableIncomingBitrate float64
|
||||
|
||||
// CircuitBreakerTriggerCount represents the number of times the circuit breaker
|
||||
// is triggered for this particular 5-tuple, ceasing transmission.
|
||||
CircuitBreakerTriggerCount uint32
|
||||
|
||||
// RequestsReceived represents the total number of connectivity check requests
|
||||
// received (including retransmissions). It is impossible for the receiver to
|
||||
// tell whether the request was sent in order to check connectivity or check
|
||||
// consent, so all connectivity checks requests are counted here.
|
||||
RequestsReceived uint64
|
||||
|
||||
// RequestsSent represents the total number of connectivity check requests
|
||||
// sent (not including retransmissions).
|
||||
RequestsSent uint64
|
||||
|
||||
// ResponsesReceived represents the total number of connectivity check responses received.
|
||||
ResponsesReceived uint64
|
||||
|
||||
// ResponsesSent epresents the total number of connectivity check responses sent.
|
||||
// Since we cannot distinguish connectivity check requests and consent requests,
|
||||
// all responses are counted.
|
||||
ResponsesSent uint64
|
||||
|
||||
// RetransmissionsReceived represents the total number of connectivity check
|
||||
// request retransmissions received.
|
||||
RetransmissionsReceived uint64
|
||||
|
||||
// RetransmissionsSent represents the total number of connectivity check
|
||||
// request retransmissions sent.
|
||||
RetransmissionsSent uint64
|
||||
|
||||
// ConsentRequestsSent represents the total number of consent requests sent.
|
||||
ConsentRequestsSent uint64
|
||||
|
||||
// ConsentExpiredTimestamp represents the timestamp at which the latest valid
|
||||
// STUN binding response expired.
|
||||
ConsentExpiredTimestamp time.Time
|
||||
}
|
||||
|
||||
// CandidateStats contains ICE candidate statistics related to the ICETransport objects.
|
||||
type CandidateStats struct {
|
||||
// Timestamp is the timestamp associated with this object.
|
||||
Timestamp time.Time
|
||||
|
||||
// ID is the candidate ID
|
||||
ID string
|
||||
|
||||
// NetworkType represents the type of network interface used by the base of a
|
||||
// local candidate (the address the ICE agent sends from). Only present for
|
||||
// local candidates; it's not possible to know what type of network interface
|
||||
// a remote candidate is using.
|
||||
//
|
||||
// Note:
|
||||
// This stat only tells you about the network interface used by the first "hop";
|
||||
// it's possible that a connection will be bottlenecked by another type of network.
|
||||
// For example, when using Wi-Fi tethering, the networkType of the relevant candidate
|
||||
// would be "wifi", even when the next hop is over a cellular connection.
|
||||
NetworkType NetworkType
|
||||
|
||||
// IP is the IP address of the candidate, allowing for IPv4 addresses and
|
||||
// IPv6 addresses, but fully qualified domain names (FQDNs) are not allowed.
|
||||
IP string
|
||||
|
||||
// Port is the port number of the candidate.
|
||||
Port int
|
||||
|
||||
// CandidateType is the "Type" field of the ICECandidate.
|
||||
CandidateType CandidateType
|
||||
|
||||
// Priority is the "Priority" field of the ICECandidate.
|
||||
Priority uint32
|
||||
|
||||
// URL is the URL of the TURN or STUN server indicated in the that translated
|
||||
// this IP address. It is the URL address surfaced in an PeerConnectionICEEvent.
|
||||
URL string
|
||||
|
||||
// RelayProtocol is the protocol used by the endpoint to communicate with the
|
||||
// TURN server. This is only present for local candidates. Valid values for
|
||||
// the TURN URL protocol is one of udp, tcp, or tls.
|
||||
RelayProtocol string
|
||||
|
||||
// Deleted is true if the candidate has been deleted/freed. For host candidates,
|
||||
// this means that any network resources (typically a socket) associated with the
|
||||
// candidate have been released. For TURN candidates, this means the TURN allocation
|
||||
// is no longer active.
|
||||
//
|
||||
// Only defined for local candidates. For remote candidates, this property is not applicable.
|
||||
Deleted bool
|
||||
}
|
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stun.go
generated
vendored
Normal file
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stun.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
func assertInboundUsername(m *stun.Message, expectedUsername string) error {
|
||||
var username stun.Username
|
||||
if err := username.GetFrom(m); err != nil {
|
||||
return err
|
||||
}
|
||||
if string(username) != expectedUsername {
|
||||
return fmt.Errorf("%w expected(%x) actual(%x)", errMismatchUsername, expectedUsername, string(username))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func assertInboundMessageIntegrity(m *stun.Message, key []byte) error {
|
||||
messageIntegrityAttr := stun.MessageIntegrity(key)
|
||||
return messageIntegrityAttr.Check(m)
|
||||
}
|
295
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux.go
generated
vendored
Normal file
295
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux.go
generated
vendored
Normal file
|
@ -0,0 +1,295 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
// TCPMux is allows grouping multiple TCP net.Conns and using them like UDP
|
||||
// net.PacketConns. The main implementation of this is TCPMuxDefault, and this
|
||||
// interface exists to:
|
||||
// 1. prevent SEGV panics when TCPMuxDefault is not initialized by using the
|
||||
// invalidTCPMux implementation, and
|
||||
// 2. allow mocking in tests.
|
||||
type TCPMux interface {
|
||||
io.Closer
|
||||
GetConnByUfrag(ufrag string) (net.PacketConn, error)
|
||||
RemoveConnByUfrag(ufrag string)
|
||||
}
|
||||
|
||||
// invalidTCPMux is an implementation of TCPMux that always returns ErroTCPMuxNotInitialized.
|
||||
type invalidTCPMux struct {
|
||||
}
|
||||
|
||||
func newInvalidTCPMux() *invalidTCPMux {
|
||||
return &invalidTCPMux{}
|
||||
}
|
||||
|
||||
// Close implements TCPMux interface.
|
||||
func (m *invalidTCPMux) Close() error {
|
||||
return ErrTCPMuxNotInitialized
|
||||
}
|
||||
|
||||
// GetConnByUfrag implements TCPMux interface.
|
||||
func (m *invalidTCPMux) GetConnByUfrag(ufrag string) (net.PacketConn, error) {
|
||||
return nil, ErrTCPMuxNotInitialized
|
||||
}
|
||||
|
||||
// RemoveConnByUfrag implements TCPMux interface.
|
||||
func (m *invalidTCPMux) RemoveConnByUfrag(ufrag string) {}
|
||||
|
||||
// TCPMuxDefault muxes TCP net.Conns into net.PacketConns and groups them by
|
||||
// Ufrag. It is a default implementation of TCPMux interface.
|
||||
type TCPMuxDefault struct {
|
||||
params *TCPMuxParams
|
||||
closed bool
|
||||
|
||||
// conns is a map of all tcpPacketConns indexed by ufrag
|
||||
conns map[string]*tcpPacketConn
|
||||
|
||||
mu sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// TCPMuxParams are parameters for TCPMux.
|
||||
type TCPMuxParams struct {
|
||||
Listener net.Listener
|
||||
Logger logging.LeveledLogger
|
||||
ReadBufferSize int
|
||||
}
|
||||
|
||||
// NewTCPMuxDefault creates a new instance of TCPMuxDefault.
|
||||
func NewTCPMuxDefault(params TCPMuxParams) *TCPMuxDefault {
|
||||
if params.Logger == nil {
|
||||
params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice")
|
||||
}
|
||||
|
||||
m := &TCPMuxDefault{
|
||||
params: ¶ms,
|
||||
|
||||
conns: map[string]*tcpPacketConn{},
|
||||
}
|
||||
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
defer m.wg.Done()
|
||||
m.start()
|
||||
}()
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) start() {
|
||||
m.params.Logger.Infof("Listening TCP on %s\n", m.params.Listener.Addr())
|
||||
for {
|
||||
conn, err := m.params.Listener.Accept()
|
||||
if err != nil {
|
||||
m.params.Logger.Infof("Error accepting connection: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
m.params.Logger.Debugf("Accepted connection from: %s to %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
defer m.wg.Done()
|
||||
m.handleConn(conn)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// LocalAddr returns the listening address of this TCPMuxDefault.
|
||||
func (m *TCPMuxDefault) LocalAddr() net.Addr {
|
||||
return m.params.Listener.Addr()
|
||||
}
|
||||
|
||||
// GetConnByUfrag retrieves an existing or creates a new net.PacketConn.
|
||||
func (m *TCPMuxDefault) GetConnByUfrag(ufrag string) (net.PacketConn, error) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if m.closed {
|
||||
return nil, io.ErrClosedPipe
|
||||
}
|
||||
|
||||
conn, ok := m.conns[ufrag]
|
||||
|
||||
if ok {
|
||||
return conn, nil
|
||||
// return nil, fmt.Errorf("duplicate ufrag %v", ufrag)
|
||||
}
|
||||
|
||||
conn = m.createConn(ufrag, m.LocalAddr())
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) createConn(ufrag string, localAddr net.Addr) *tcpPacketConn {
|
||||
conn := newTCPPacketConn(tcpPacketParams{
|
||||
ReadBuffer: m.params.ReadBufferSize,
|
||||
LocalAddr: localAddr,
|
||||
Logger: m.params.Logger,
|
||||
})
|
||||
m.conns[ufrag] = conn
|
||||
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
defer m.wg.Done()
|
||||
<-conn.CloseChannel()
|
||||
m.RemoveConnByUfrag(ufrag)
|
||||
}()
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) closeAndLogError(closer io.Closer) {
|
||||
err := closer.Close()
|
||||
if err != nil {
|
||||
m.params.Logger.Warnf("Error closing connection: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) handleConn(conn net.Conn) {
|
||||
buf := make([]byte, receiveMTU)
|
||||
|
||||
n, err := readStreamingPacket(conn, buf)
|
||||
if err != nil {
|
||||
m.params.Logger.Warnf("Error reading first packet: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
buf = buf[:n]
|
||||
|
||||
msg := &stun.Message{
|
||||
Raw: make([]byte, len(buf)),
|
||||
}
|
||||
// Explicitly copy raw buffer so Message can own the memory.
|
||||
copy(msg.Raw, buf)
|
||||
if err = msg.Decode(); err != nil {
|
||||
m.closeAndLogError(conn)
|
||||
m.params.Logger.Warnf("Failed to handle decode ICE from %s to %s: %v\n", conn.RemoteAddr(), conn.LocalAddr(), err)
|
||||
return
|
||||
}
|
||||
|
||||
if m == nil || msg.Type.Method != stun.MethodBinding { // not a stun
|
||||
m.closeAndLogError(conn)
|
||||
m.params.Logger.Warnf("Not a STUN message from %s to %s\n", conn.RemoteAddr(), conn.LocalAddr())
|
||||
return
|
||||
}
|
||||
|
||||
for _, attr := range msg.Attributes {
|
||||
m.params.Logger.Debugf("msg attr: %s\n", attr.String())
|
||||
}
|
||||
|
||||
attr, err := msg.Get(stun.AttrUsername)
|
||||
if err != nil {
|
||||
m.closeAndLogError(conn)
|
||||
m.params.Logger.Warnf("No Username attribute in STUN message from %s to %s\n", conn.RemoteAddr(), conn.LocalAddr())
|
||||
return
|
||||
}
|
||||
|
||||
ufrag := strings.Split(string(attr), ":")[0]
|
||||
m.params.Logger.Debugf("Ufrag: %s\n", ufrag)
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
packetConn, ok := m.conns[ufrag]
|
||||
if !ok {
|
||||
packetConn = m.createConn(ufrag, conn.LocalAddr())
|
||||
}
|
||||
|
||||
if err := packetConn.AddConn(conn, buf); err != nil {
|
||||
m.closeAndLogError(conn)
|
||||
m.params.Logger.Warnf("Error adding conn to tcpPacketConn from %s to %s: %s\n", conn.RemoteAddr(), conn.LocalAddr(), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the listener and waits for all goroutines to exit.
|
||||
func (m *TCPMuxDefault) Close() error {
|
||||
m.mu.Lock()
|
||||
m.closed = true
|
||||
|
||||
for _, conn := range m.conns {
|
||||
m.closeAndLogError(conn)
|
||||
}
|
||||
m.conns = map[string]*tcpPacketConn{}
|
||||
|
||||
err := m.params.Listener.Close()
|
||||
|
||||
m.mu.Unlock()
|
||||
|
||||
m.wg.Wait()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveConnByUfrag closes and removes a net.PacketConn by Ufrag.
|
||||
func (m *TCPMuxDefault) RemoveConnByUfrag(ufrag string) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if conn, ok := m.conns[ufrag]; ok {
|
||||
m.closeAndLogError(conn)
|
||||
delete(m.conns, ufrag)
|
||||
}
|
||||
}
|
||||
|
||||
const streamingPacketHeaderLen = 2
|
||||
|
||||
// readStreamingPacket reads 1 packet from stream
|
||||
// read packet bytes https://tools.ietf.org/html/rfc4571#section-2
|
||||
// 2-byte length header prepends each packet:
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// -----------------------------------------------------------------
|
||||
// | LENGTH | RTP or RTCP packet ... |
|
||||
// -----------------------------------------------------------------
|
||||
func readStreamingPacket(conn net.Conn, buf []byte) (int, error) {
|
||||
header := make([]byte, streamingPacketHeaderLen)
|
||||
var bytesRead, n int
|
||||
var err error
|
||||
|
||||
for bytesRead < streamingPacketHeaderLen {
|
||||
if n, err = conn.Read(header[bytesRead:streamingPacketHeaderLen]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
bytesRead += n
|
||||
}
|
||||
|
||||
length := int(binary.BigEndian.Uint16(header))
|
||||
|
||||
if length > cap(buf) {
|
||||
return length, io.ErrShortBuffer
|
||||
}
|
||||
|
||||
bytesRead = 0
|
||||
for bytesRead < length {
|
||||
if n, err = conn.Read(buf[bytesRead:length]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
bytesRead += n
|
||||
}
|
||||
|
||||
return bytesRead, nil
|
||||
}
|
||||
|
||||
func writeStreamingPacket(conn net.Conn, buf []byte) (int, error) {
|
||||
bufferCopy := make([]byte, streamingPacketHeaderLen+len(buf))
|
||||
binary.BigEndian.PutUint16(bufferCopy, uint16(len(buf)))
|
||||
copy(bufferCopy[2:], buf)
|
||||
|
||||
n, err := conn.Write(bufferCopy)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return n - streamingPacketHeaderLen, nil
|
||||
}
|
240
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_packet_conn.go
generated
vendored
Normal file
240
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_packet_conn.go
generated
vendored
Normal file
|
@ -0,0 +1,240 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
)
|
||||
|
||||
type tcpPacketConn struct {
|
||||
params *tcpPacketParams
|
||||
|
||||
// conns is a map of net.Conns indexed by remote net.Addr.String()
|
||||
conns map[string]net.Conn
|
||||
|
||||
recvChan chan streamingPacket
|
||||
|
||||
mu sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
closedChan chan struct{}
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
type streamingPacket struct {
|
||||
Data []byte
|
||||
RAddr net.Addr
|
||||
Err error
|
||||
}
|
||||
|
||||
type tcpPacketParams struct {
|
||||
ReadBuffer int
|
||||
LocalAddr net.Addr
|
||||
Logger logging.LeveledLogger
|
||||
}
|
||||
|
||||
func newTCPPacketConn(params tcpPacketParams) *tcpPacketConn {
|
||||
p := &tcpPacketConn{
|
||||
params: ¶ms,
|
||||
|
||||
conns: map[string]net.Conn{},
|
||||
|
||||
recvChan: make(chan streamingPacket, params.ReadBuffer),
|
||||
closedChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) AddConn(conn net.Conn, firstPacketData []byte) error {
|
||||
t.params.Logger.Infof("AddConn: %s %s", conn.RemoteAddr().Network(), conn.RemoteAddr())
|
||||
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
select {
|
||||
case <-t.closedChan:
|
||||
return io.ErrClosedPipe
|
||||
default:
|
||||
}
|
||||
|
||||
if _, ok := t.conns[conn.RemoteAddr().String()]; ok {
|
||||
return fmt.Errorf("%w: %s", errConnectionAddrAlreadyExist, conn.RemoteAddr().String())
|
||||
}
|
||||
|
||||
t.conns[conn.RemoteAddr().String()] = conn
|
||||
|
||||
t.wg.Add(1)
|
||||
go func() {
|
||||
if firstPacketData != nil {
|
||||
t.recvChan <- streamingPacket{firstPacketData, conn.RemoteAddr(), nil}
|
||||
}
|
||||
defer t.wg.Done()
|
||||
t.startReading(conn)
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) startReading(conn net.Conn) {
|
||||
buf := make([]byte, receiveMTU)
|
||||
|
||||
for {
|
||||
n, err := readStreamingPacket(conn, buf)
|
||||
// t.params.Logger.Infof("readStreamingPacket read %d bytes", n)
|
||||
if err != nil {
|
||||
t.params.Logger.Infof("%w: %s\n", errReadingStreamingPacket, err)
|
||||
t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err})
|
||||
t.removeConn(conn)
|
||||
return
|
||||
}
|
||||
|
||||
data := make([]byte, n)
|
||||
copy(data, buf[:n])
|
||||
|
||||
// t.params.Logger.Infof("Writing read streaming packet to recvChan: %d bytes", len(data))
|
||||
t.handleRecv(streamingPacket{data, conn.RemoteAddr(), nil})
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) handleRecv(pkt streamingPacket) {
|
||||
t.mu.Lock()
|
||||
|
||||
recvChan := t.recvChan
|
||||
if t.isClosed() {
|
||||
recvChan = nil
|
||||
}
|
||||
|
||||
t.mu.Unlock()
|
||||
|
||||
select {
|
||||
case recvChan <- pkt:
|
||||
case <-t.closedChan:
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) isClosed() bool {
|
||||
select {
|
||||
case <-t.closedChan:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// WriteTo is for passive and s-o candidates.
|
||||
func (t *tcpPacketConn) ReadFrom(b []byte) (n int, raddr net.Addr, err error) {
|
||||
pkt, ok := <-t.recvChan
|
||||
|
||||
if !ok {
|
||||
return 0, nil, io.ErrClosedPipe
|
||||
}
|
||||
|
||||
if pkt.Err != nil {
|
||||
return 0, pkt.RAddr, pkt.Err
|
||||
}
|
||||
|
||||
if cap(b) < len(pkt.Data) {
|
||||
return 0, pkt.RAddr, io.ErrShortBuffer
|
||||
}
|
||||
|
||||
n = len(pkt.Data)
|
||||
copy(b, pkt.Data[:n])
|
||||
return n, pkt.RAddr, err
|
||||
}
|
||||
|
||||
// WriteTo is for active and s-o candidates.
|
||||
func (t *tcpPacketConn) WriteTo(buf []byte, raddr net.Addr) (n int, err error) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
conn, ok := t.conns[raddr.String()]
|
||||
if !ok {
|
||||
return 0, io.ErrClosedPipe
|
||||
// conn, err := net.DialTCP(tcp, nil, raddr.(*net.TCPAddr))
|
||||
|
||||
// if err != nil {
|
||||
// t.params.Logger.Tracef("DialTCP error: %s", err)
|
||||
// return 0, err
|
||||
// }
|
||||
|
||||
// go t.startReading(conn)
|
||||
// t.conns[raddr.String()] = conn
|
||||
}
|
||||
|
||||
n, err = writeStreamingPacket(conn, buf)
|
||||
if err != nil {
|
||||
t.params.Logger.Tracef("%w %s\n", errWriting, raddr)
|
||||
return n, err
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) closeAndLogError(closer io.Closer) {
|
||||
err := closer.Close()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnf("%w: %s", errClosingConnection, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) removeConn(conn net.Conn) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
t.closeAndLogError(conn)
|
||||
|
||||
delete(t.conns, conn.RemoteAddr().String())
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) Close() error {
|
||||
t.mu.Lock()
|
||||
|
||||
var shouldCloseRecvChan bool
|
||||
t.closeOnce.Do(func() {
|
||||
close(t.closedChan)
|
||||
shouldCloseRecvChan = true
|
||||
})
|
||||
|
||||
for _, conn := range t.conns {
|
||||
t.closeAndLogError(conn)
|
||||
delete(t.conns, conn.RemoteAddr().String())
|
||||
}
|
||||
|
||||
t.mu.Unlock()
|
||||
|
||||
t.wg.Wait()
|
||||
|
||||
if shouldCloseRecvChan {
|
||||
close(t.recvChan)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) LocalAddr() net.Addr {
|
||||
return t.params.LocalAddr
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) SetDeadline(tm time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) SetReadDeadline(tm time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) SetWriteDeadline(tm time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) CloseChannel() <-chan struct{} {
|
||||
return t.closedChan
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) String() string {
|
||||
return fmt.Sprintf("tcpPacketConn{LocalAddr: %s}", t.params.LocalAddr)
|
||||
}
|
48
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcptype.go
generated
vendored
Normal file
48
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcptype.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package ice
|
||||
|
||||
import "strings"
|
||||
|
||||
// TCPType is the type of ICE TCP candidate as described in
|
||||
// ttps://tools.ietf.org/html/rfc6544#section-4.5
|
||||
type TCPType int
|
||||
|
||||
const (
|
||||
// TCPTypeUnspecified is the default value. For example UDP candidates do not
|
||||
// need this field.
|
||||
TCPTypeUnspecified TCPType = iota
|
||||
// TCPTypeActive is active TCP candidate, which initiates TCP connections.
|
||||
TCPTypeActive
|
||||
// TCPTypePassive is passive TCP candidate, only accepts TCP connections.
|
||||
TCPTypePassive
|
||||
// TCPTypeSimultaneousOpen is like active and passive at the same time.
|
||||
TCPTypeSimultaneousOpen
|
||||
)
|
||||
|
||||
// NewTCPType creates a new TCPType from string.
|
||||
func NewTCPType(value string) TCPType {
|
||||
switch strings.ToLower(value) {
|
||||
case "active":
|
||||
return TCPTypeActive
|
||||
case "passive":
|
||||
return TCPTypePassive
|
||||
case "so":
|
||||
return TCPTypeSimultaneousOpen
|
||||
default:
|
||||
return TCPTypeUnspecified
|
||||
}
|
||||
}
|
||||
|
||||
func (t TCPType) String() string {
|
||||
switch t {
|
||||
case TCPTypeUnspecified:
|
||||
return ""
|
||||
case TCPTypeActive:
|
||||
return "active"
|
||||
case TCPTypePassive:
|
||||
return "passive"
|
||||
case TCPTypeSimultaneousOpen:
|
||||
return "so"
|
||||
default:
|
||||
return ErrUnknownType.Error()
|
||||
}
|
||||
}
|
145
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/transport.go
generated
vendored
Normal file
145
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/transport.go
generated
vendored
Normal file
|
@ -0,0 +1,145 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
// Dial connects to the remote agent, acting as the controlling ice agent.
|
||||
// Dial blocks until at least one ice candidate pair has successfully connected.
|
||||
func (a *Agent) Dial(ctx context.Context, remoteUfrag, remotePwd string) (*Conn, error) {
|
||||
return a.connect(ctx, true, remoteUfrag, remotePwd)
|
||||
}
|
||||
|
||||
// Accept connects to the remote agent, acting as the controlled ice agent.
|
||||
// Accept blocks until at least one ice candidate pair has successfully connected.
|
||||
func (a *Agent) Accept(ctx context.Context, remoteUfrag, remotePwd string) (*Conn, error) {
|
||||
return a.connect(ctx, false, remoteUfrag, remotePwd)
|
||||
}
|
||||
|
||||
// Conn represents the ICE connection.
|
||||
// At the moment the lifetime of the Conn is equal to the Agent.
|
||||
type Conn struct {
|
||||
bytesReceived uint64
|
||||
bytesSent uint64
|
||||
agent *Agent
|
||||
}
|
||||
|
||||
// BytesSent returns the number of bytes sent
|
||||
func (c *Conn) BytesSent() uint64 {
|
||||
return atomic.LoadUint64(&c.bytesSent)
|
||||
}
|
||||
|
||||
// BytesReceived returns the number of bytes received
|
||||
func (c *Conn) BytesReceived() uint64 {
|
||||
return atomic.LoadUint64(&c.bytesReceived)
|
||||
}
|
||||
|
||||
func (a *Agent) connect(ctx context.Context, isControlling bool, remoteUfrag, remotePwd string) (*Conn, error) {
|
||||
err := a.ok()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = a.startConnectivityChecks(isControlling, remoteUfrag, remotePwd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// block until pair selected
|
||||
select {
|
||||
case <-a.done:
|
||||
return nil, a.getErr()
|
||||
case <-ctx.Done():
|
||||
return nil, ErrCanceledByCaller
|
||||
case <-a.onConnected:
|
||||
}
|
||||
|
||||
return &Conn{
|
||||
agent: a,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Read implements the Conn Read method.
|
||||
func (c *Conn) Read(p []byte) (int, error) {
|
||||
err := c.agent.ok()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n, err := c.agent.buffer.Read(p)
|
||||
atomic.AddUint64(&c.bytesReceived, uint64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Write implements the Conn Write method.
|
||||
func (c *Conn) Write(p []byte) (int, error) {
|
||||
err := c.agent.ok()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if stun.IsMessage(p) {
|
||||
return 0, errICEWriteSTUNMessage
|
||||
}
|
||||
|
||||
pair := c.agent.getSelectedPair()
|
||||
if pair == nil {
|
||||
if err = c.agent.run(c.agent.context(), func(ctx context.Context, a *Agent) {
|
||||
pair = a.getBestValidCandidatePair()
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if pair == nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
atomic.AddUint64(&c.bytesSent, uint64(len(p)))
|
||||
return pair.Write(p)
|
||||
}
|
||||
|
||||
// Close implements the Conn Close method. It is used to close
|
||||
// the connection. Any calls to Read and Write will be unblocked and return an error.
|
||||
func (c *Conn) Close() error {
|
||||
return c.agent.Close()
|
||||
}
|
||||
|
||||
// LocalAddr returns the local address of the current selected pair or nil if there is none.
|
||||
func (c *Conn) LocalAddr() net.Addr {
|
||||
pair := c.agent.getSelectedPair()
|
||||
if pair == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return pair.local.addr()
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote address of the current selected pair or nil if there is none.
|
||||
func (c *Conn) RemoteAddr() net.Addr {
|
||||
pair := c.agent.getSelectedPair()
|
||||
if pair == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return pair.remote.addr()
|
||||
}
|
||||
|
||||
// SetDeadline is a stub
|
||||
func (c *Conn) SetDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetReadDeadline is a stub
|
||||
func (c *Conn) SetReadDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWriteDeadline is a stub
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
225
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/url.go
generated
vendored
Normal file
225
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/url.go
generated
vendored
Normal file
|
@ -0,0 +1,225 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// SchemeType indicates the type of server used in the ice.URL structure.
|
||||
type SchemeType int
|
||||
|
||||
// Unknown defines default public constant to use for "enum" like struct
|
||||
// comparisons when no value was defined.
|
||||
const Unknown = iota
|
||||
|
||||
const (
|
||||
// SchemeTypeSTUN indicates the URL represents a STUN server.
|
||||
SchemeTypeSTUN SchemeType = iota + 1
|
||||
|
||||
// SchemeTypeSTUNS indicates the URL represents a STUNS (secure) server.
|
||||
SchemeTypeSTUNS
|
||||
|
||||
// SchemeTypeTURN indicates the URL represents a TURN server.
|
||||
SchemeTypeTURN
|
||||
|
||||
// SchemeTypeTURNS indicates the URL represents a TURNS (secure) server.
|
||||
SchemeTypeTURNS
|
||||
)
|
||||
|
||||
// NewSchemeType defines a procedure for creating a new SchemeType from a raw
|
||||
// string naming the scheme type.
|
||||
func NewSchemeType(raw string) SchemeType {
|
||||
switch raw {
|
||||
case "stun":
|
||||
return SchemeTypeSTUN
|
||||
case "stuns":
|
||||
return SchemeTypeSTUNS
|
||||
case "turn":
|
||||
return SchemeTypeTURN
|
||||
case "turns":
|
||||
return SchemeTypeTURNS
|
||||
default:
|
||||
return SchemeType(Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
func (t SchemeType) String() string {
|
||||
switch t {
|
||||
case SchemeTypeSTUN:
|
||||
return "stun"
|
||||
case SchemeTypeSTUNS:
|
||||
return "stuns"
|
||||
case SchemeTypeTURN:
|
||||
return "turn"
|
||||
case SchemeTypeTURNS:
|
||||
return "turns"
|
||||
default:
|
||||
return ErrUnknownType.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// ProtoType indicates the transport protocol type that is used in the ice.URL
|
||||
// structure.
|
||||
type ProtoType int
|
||||
|
||||
const (
|
||||
// ProtoTypeUDP indicates the URL uses a UDP transport.
|
||||
ProtoTypeUDP ProtoType = iota + 1
|
||||
|
||||
// ProtoTypeTCP indicates the URL uses a TCP transport.
|
||||
ProtoTypeTCP
|
||||
)
|
||||
|
||||
// NewProtoType defines a procedure for creating a new ProtoType from a raw
|
||||
// string naming the transport protocol type.
|
||||
func NewProtoType(raw string) ProtoType {
|
||||
switch raw {
|
||||
case "udp":
|
||||
return ProtoTypeUDP
|
||||
case "tcp":
|
||||
return ProtoTypeTCP
|
||||
default:
|
||||
return ProtoType(Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
func (t ProtoType) String() string {
|
||||
switch t {
|
||||
case ProtoTypeUDP:
|
||||
return "udp"
|
||||
case ProtoTypeTCP:
|
||||
return "tcp"
|
||||
default:
|
||||
return ErrUnknownType.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// URL represents a STUN (rfc7064) or TURN (rfc7065) URL
|
||||
type URL struct {
|
||||
Scheme SchemeType
|
||||
Host string
|
||||
Port int
|
||||
Username string
|
||||
Password string
|
||||
Proto ProtoType
|
||||
}
|
||||
|
||||
// ParseURL parses a STUN or TURN urls following the ABNF syntax described in
|
||||
// https://tools.ietf.org/html/rfc7064 and https://tools.ietf.org/html/rfc7065
|
||||
// respectively.
|
||||
func ParseURL(raw string) (*URL, error) { //nolint:gocognit
|
||||
rawParts, err := url.Parse(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var u URL
|
||||
u.Scheme = NewSchemeType(rawParts.Scheme)
|
||||
if u.Scheme == SchemeType(Unknown) {
|
||||
return nil, ErrSchemeType
|
||||
}
|
||||
|
||||
var rawPort string
|
||||
if u.Host, rawPort, err = net.SplitHostPort(rawParts.Opaque); err != nil {
|
||||
if e, ok := err.(*net.AddrError); ok {
|
||||
if e.Err == "missing port in address" {
|
||||
nextRawURL := u.Scheme.String() + ":" + rawParts.Opaque
|
||||
switch {
|
||||
case u.Scheme == SchemeTypeSTUN || u.Scheme == SchemeTypeTURN:
|
||||
nextRawURL += ":3478"
|
||||
if rawParts.RawQuery != "" {
|
||||
nextRawURL += "?" + rawParts.RawQuery
|
||||
}
|
||||
return ParseURL(nextRawURL)
|
||||
case u.Scheme == SchemeTypeSTUNS || u.Scheme == SchemeTypeTURNS:
|
||||
nextRawURL += ":5349"
|
||||
if rawParts.RawQuery != "" {
|
||||
nextRawURL += "?" + rawParts.RawQuery
|
||||
}
|
||||
return ParseURL(nextRawURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if u.Host == "" {
|
||||
return nil, ErrHost
|
||||
}
|
||||
|
||||
if u.Port, err = strconv.Atoi(rawPort); err != nil {
|
||||
return nil, ErrPort
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case SchemeTypeSTUN:
|
||||
qArgs, err := url.ParseQuery(rawParts.RawQuery)
|
||||
if err != nil || len(qArgs) > 0 {
|
||||
return nil, ErrSTUNQuery
|
||||
}
|
||||
u.Proto = ProtoTypeUDP
|
||||
case SchemeTypeSTUNS:
|
||||
qArgs, err := url.ParseQuery(rawParts.RawQuery)
|
||||
if err != nil || len(qArgs) > 0 {
|
||||
return nil, ErrSTUNQuery
|
||||
}
|
||||
u.Proto = ProtoTypeTCP
|
||||
case SchemeTypeTURN:
|
||||
proto, err := parseProto(rawParts.RawQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.Proto = proto
|
||||
if u.Proto == ProtoType(Unknown) {
|
||||
u.Proto = ProtoTypeUDP
|
||||
}
|
||||
case SchemeTypeTURNS:
|
||||
proto, err := parseProto(rawParts.RawQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u.Proto = proto
|
||||
if u.Proto == ProtoType(Unknown) {
|
||||
u.Proto = ProtoTypeTCP
|
||||
}
|
||||
}
|
||||
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func parseProto(raw string) (ProtoType, error) {
|
||||
qArgs, err := url.ParseQuery(raw)
|
||||
if err != nil || len(qArgs) > 1 {
|
||||
return ProtoType(Unknown), ErrInvalidQuery
|
||||
}
|
||||
|
||||
var proto ProtoType
|
||||
if rawProto := qArgs.Get("transport"); rawProto != "" {
|
||||
if proto = NewProtoType(rawProto); proto == ProtoType(0) {
|
||||
return ProtoType(Unknown), ErrProtoType
|
||||
}
|
||||
return proto, nil
|
||||
}
|
||||
|
||||
if len(qArgs) > 0 {
|
||||
return ProtoType(Unknown), ErrInvalidQuery
|
||||
}
|
||||
|
||||
return proto, nil
|
||||
}
|
||||
|
||||
func (u URL) String() string {
|
||||
rawURL := u.Scheme.String() + ":" + net.JoinHostPort(u.Host, strconv.Itoa(u.Port))
|
||||
if u.Scheme == SchemeTypeTURN || u.Scheme == SchemeTypeTURNS {
|
||||
rawURL += "?transport=" + u.Proto.String()
|
||||
}
|
||||
return rawURL
|
||||
}
|
||||
|
||||
// IsSecure returns whether the this URL's scheme describes secure scheme or not.
|
||||
func (u URL) IsSecure() bool {
|
||||
return u.Scheme == SchemeTypeSTUNS || u.Scheme == SchemeTypeTURNS
|
||||
}
|
23
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/usecandidate.go
generated
vendored
Normal file
23
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/usecandidate.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
package ice
|
||||
|
||||
import "github.com/pion/stun"
|
||||
|
||||
// UseCandidateAttr represents USE-CANDIDATE attribute.
|
||||
type UseCandidateAttr struct{}
|
||||
|
||||
// AddTo adds USE-CANDIDATE attribute to message.
|
||||
func (UseCandidateAttr) AddTo(m *stun.Message) error {
|
||||
m.Add(stun.AttrUseCandidate, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsSet returns true if USE-CANDIDATE attribute is set.
|
||||
func (UseCandidateAttr) IsSet(m *stun.Message) bool {
|
||||
_, err := m.Get(stun.AttrUseCandidate)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// UseCandidate is shorthand for UseCandidateAttr.
|
||||
func UseCandidate() UseCandidateAttr {
|
||||
return UseCandidateAttr{}
|
||||
}
|
233
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/util.go
generated
vendored
Normal file
233
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/util.go
generated
vendored
Normal file
|
@ -0,0 +1,233 @@
|
|||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
"github.com/pion/transport/vnet"
|
||||
)
|
||||
|
||||
type atomicError struct{ v atomic.Value }
|
||||
|
||||
func (a *atomicError) Store(err error) {
|
||||
a.v.Store(struct{ error }{err})
|
||||
}
|
||||
|
||||
func (a *atomicError) Load() error {
|
||||
err, _ := a.v.Load().(struct{ error })
|
||||
return err.error
|
||||
}
|
||||
|
||||
// The conditions of invalidation written below are defined in
|
||||
// https://tools.ietf.org/html/rfc8445#section-5.1.1.1
|
||||
func isSupportedIPv6(ip net.IP) bool {
|
||||
if len(ip) != net.IPv6len ||
|
||||
isZeros(ip[0:12]) || // !(IPv4-compatible IPv6)
|
||||
ip[0] == 0xfe && ip[1]&0xc0 == 0xc0 || // !(IPv6 site-local unicast)
|
||||
ip.IsLinkLocalUnicast() ||
|
||||
ip.IsLinkLocalMulticast() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isZeros(ip net.IP) bool {
|
||||
for i := 0; i < len(ip); i++ {
|
||||
if ip[i] != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func parseAddr(in net.Addr) (net.IP, int, NetworkType, bool) {
|
||||
switch addr := in.(type) {
|
||||
case *net.UDPAddr:
|
||||
return addr.IP, addr.Port, NetworkTypeUDP4, true
|
||||
case *net.TCPAddr:
|
||||
return addr.IP, addr.Port, NetworkTypeTCP4, true
|
||||
}
|
||||
return nil, 0, 0, false
|
||||
}
|
||||
|
||||
func createAddr(network NetworkType, ip net.IP, port int) net.Addr {
|
||||
switch {
|
||||
case network.IsTCP():
|
||||
return &net.TCPAddr{IP: ip, Port: port}
|
||||
default:
|
||||
return &net.UDPAddr{IP: ip, Port: port}
|
||||
}
|
||||
}
|
||||
|
||||
func addrEqual(a, b net.Addr) bool {
|
||||
aIP, aPort, aType, aOk := parseAddr(a)
|
||||
if !aOk {
|
||||
return false
|
||||
}
|
||||
|
||||
bIP, bPort, bType, bOk := parseAddr(b)
|
||||
if !bOk {
|
||||
return false
|
||||
}
|
||||
|
||||
return aType == bType && aIP.Equal(bIP) && aPort == bPort
|
||||
}
|
||||
|
||||
// getXORMappedAddr initiates a stun requests to serverAddr using conn, reads the response and returns
|
||||
// the XORMappedAddress returned by the stun server.
|
||||
//
|
||||
// Adapted from stun v0.2.
|
||||
func getXORMappedAddr(conn net.PacketConn, serverAddr net.Addr, deadline time.Duration) (*stun.XORMappedAddress, error) {
|
||||
if deadline > 0 {
|
||||
if err := conn.SetReadDeadline(time.Now().Add(deadline)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
if deadline > 0 {
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
}
|
||||
}()
|
||||
resp, err := stunRequest(
|
||||
func(p []byte) (int, error) {
|
||||
n, _, errr := conn.ReadFrom(p)
|
||||
return n, errr
|
||||
},
|
||||
func(b []byte) (int, error) {
|
||||
return conn.WriteTo(b, serverAddr)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var addr stun.XORMappedAddress
|
||||
if err = addr.GetFrom(resp); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errGetXorMappedAddrResponse, err)
|
||||
}
|
||||
return &addr, nil
|
||||
}
|
||||
|
||||
func stunRequest(read func([]byte) (int, error), write func([]byte) (int, error)) (*stun.Message, error) {
|
||||
req, err := stun.Build(stun.BindingRequest, stun.TransactionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = write(req.Raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
const maxMessageSize = 1280
|
||||
bs := make([]byte, maxMessageSize)
|
||||
n, err := read(bs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := &stun.Message{Raw: bs[:n]}
|
||||
if err := res.Decode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func localInterfaces(vnet *vnet.Net, interfaceFilter func(string) bool, networkTypes []NetworkType) ([]net.IP, error) { //nolint:gocognit
|
||||
ips := []net.IP{}
|
||||
ifaces, err := vnet.Interfaces()
|
||||
if err != nil {
|
||||
return ips, err
|
||||
}
|
||||
|
||||
var IPv4Requested, IPv6Requested bool
|
||||
for _, typ := range networkTypes {
|
||||
if typ.IsIPv4() {
|
||||
IPv4Requested = true
|
||||
}
|
||||
|
||||
if typ.IsIPv6() {
|
||||
IPv6Requested = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
if iface.Flags&net.FlagUp == 0 {
|
||||
continue // interface down
|
||||
}
|
||||
if iface.Flags&net.FlagLoopback != 0 {
|
||||
continue // loopback interface
|
||||
}
|
||||
|
||||
if interfaceFilter != nil && !interfaceFilter(iface.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch addr := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = addr.IP
|
||||
case *net.IPAddr:
|
||||
ip = addr.IP
|
||||
}
|
||||
if ip == nil || ip.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipv4 := ip.To4(); ipv4 == nil {
|
||||
if !IPv6Requested {
|
||||
continue
|
||||
} else if !isSupportedIPv6(ip) {
|
||||
continue
|
||||
}
|
||||
} else if !IPv4Requested {
|
||||
continue
|
||||
}
|
||||
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func listenUDPInPortRange(vnet *vnet.Net, log logging.LeveledLogger, portMax, portMin int, network string, laddr *net.UDPAddr) (vnet.UDPPacketConn, error) {
|
||||
if (laddr.Port != 0) || ((portMin == 0) && (portMax == 0)) {
|
||||
return vnet.ListenUDP(network, laddr)
|
||||
}
|
||||
var i, j int
|
||||
i = portMin
|
||||
if i == 0 {
|
||||
i = 1
|
||||
}
|
||||
j = portMax
|
||||
if j == 0 {
|
||||
j = 0xFFFF
|
||||
}
|
||||
if i > j {
|
||||
return nil, ErrPort
|
||||
}
|
||||
|
||||
portStart := globalMathRandomGenerator.Intn(j-i+1) + i
|
||||
portCurrent := portStart
|
||||
for {
|
||||
laddr = &net.UDPAddr{IP: laddr.IP, Port: portCurrent}
|
||||
c, e := vnet.ListenUDP(network, laddr)
|
||||
if e == nil {
|
||||
return c, e
|
||||
}
|
||||
log.Debugf("failed to listen %s: %v", laddr.String(), e)
|
||||
portCurrent++
|
||||
if portCurrent > j {
|
||||
portCurrent = i
|
||||
}
|
||||
if portCurrent == portStart {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, ErrPort
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue