mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
TEST: Upgrade pion to v3.2.9. (#3567)
------ Co-authored-by: chundonglinlin <chundonglinlin@163.com>
This commit is contained in:
parent
900c4cdd97
commit
1545425e06
1383 changed files with 118469 additions and 41421 deletions
4
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.gitignore
generated
vendored
4
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.gitignore
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
### JetBrains IDE ###
|
||||
#####################
|
||||
.idea/
|
||||
|
@ -22,3 +25,4 @@ cover.out
|
|||
*.wasm
|
||||
examples/sfu-ws/cert.pem
|
||||
examples/sfu-ws/key.pem
|
||||
wasm_exec.js
|
||||
|
|
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.golangci.yml
generated
vendored
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.golangci.yml
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
|
@ -10,19 +13,34 @@ linters-settings:
|
|||
modules:
|
||||
- github.com/pkg/errors:
|
||||
recommendations:
|
||||
- errors
|
||||
- errors
|
||||
forbidigo:
|
||||
forbid:
|
||||
- ^fmt.Print(f|ln)?$
|
||||
- ^log.(Panic|Fatal|Print)(f|ln)?$
|
||||
- ^os.Exit$
|
||||
- ^panic$
|
||||
- ^print(ln)?$
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
|
||||
- bidichk # Checks for dangerous unicode character sequences
|
||||
- bodyclose # checks whether HTTP response body is closed successfully
|
||||
- deadcode # Finds unused code
|
||||
- contextcheck # check the function whether use a non-inherited context
|
||||
- decorder # check declaration order and count of types, constants, variables and functions
|
||||
- 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
|
||||
- durationcheck # check for two durations multiplied together
|
||||
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
|
||||
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted.
|
||||
- errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`.
|
||||
- errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13.
|
||||
- exhaustive # check exhaustiveness of enum switch statements
|
||||
- exportloopref # checks for pointers to enclosing loop variables
|
||||
- forbidigo # Forbids identifiers
|
||||
- forcetypeassert # finds forced type assertions
|
||||
- gci # Gci control golang package import order and make it always deterministic.
|
||||
- gochecknoglobals # Checks that no globals are present in Go code
|
||||
- gochecknoinits # Checks that no init functions are present in Go code
|
||||
|
@ -35,40 +53,59 @@ linters:
|
|||
- 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
|
||||
- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod.
|
||||
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations.
|
||||
- goprintffuncname # Checks that printf-like functions are named with `f` at the end
|
||||
- gosec # Inspects source code for security problems
|
||||
- gosimple # Linter for Go source code that specializes in simplifying a code
|
||||
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||
- grouper # An analyzer to analyze expression groups.
|
||||
- importas # Enforces consistent import aliases
|
||||
- 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
|
||||
- nilerr # Finds the code that returns nil even if it checks that the error is not nil.
|
||||
- nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value.
|
||||
- noctx # noctx finds sending http request without context.Context
|
||||
- scopelint # Scopelint checks for unpinned variables in go programs
|
||||
- predeclared # find code that shadows one of Go's predeclared identifiers
|
||||
- revive # golint replacement, finds style mistakes
|
||||
- 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
|
||||
- tagliatelle # Checks the struct tags.
|
||||
- tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17
|
||||
- tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes
|
||||
- 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
|
||||
- wastedassign # wastedassign finds wasted assignment statements
|
||||
- whitespace # Tool for detection of leading and trailing whitespace
|
||||
disable:
|
||||
- containedctx # containedctx is a linter that detects struct contained context.Context field
|
||||
- cyclop # checks function and package cyclomatic complexity
|
||||
- exhaustivestruct # Checks if all struct's fields are initialized
|
||||
- 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.
|
||||
- ifshort # Checks that your code uses short syntax for if-statements whenever possible
|
||||
- ireturn # Accept Interfaces, Return Concrete Types
|
||||
- lll # Reports long lines
|
||||
- maintidx # maintidx measures the maintainability index of each function.
|
||||
- makezero # Finds slice declarations with non-zero initial length
|
||||
- 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
|
||||
- paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test
|
||||
- prealloc # Finds slice declarations that could potentially be preallocated
|
||||
- promlinter # Check Prometheus metrics naming via promlint
|
||||
- rowserrcheck # checks whether Err of rows is checked successfully
|
||||
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed.
|
||||
- testpackage # linter that makes you use a separate _test package
|
||||
- thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers
|
||||
- varnamelen # checks that the length of a variable's name matches its scope
|
||||
- wrapcheck # Checks that errors returned from external packages are wrapped
|
||||
- wsl # Whitespace Linter - Forces you to use empty lines!
|
||||
|
||||
issues:
|
||||
|
@ -78,12 +115,23 @@ issues:
|
|||
- path: _test\.go
|
||||
linters:
|
||||
- gocognit
|
||||
- forbidigo
|
||||
|
||||
# Allow complex main function in examples
|
||||
- path: examples
|
||||
text: "of func `main` is high"
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
# Allow forbidden identifiers in examples
|
||||
- path: examples
|
||||
linters:
|
||||
- forbidigo
|
||||
|
||||
# Allow forbidden identifiers in CLI commands
|
||||
- path: cmd
|
||||
linters:
|
||||
- forbidigo
|
||||
|
||||
run:
|
||||
skip-dirs-use-default: false
|
||||
|
|
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.goreleaser.yml
generated
vendored
Normal file
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.goreleaser.yml
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
builds:
|
||||
- skip: true
|
65
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/AUTHORS.txt
generated
vendored
Normal file
65
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/AUTHORS.txt
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
# Thank you to everyone that made Pion possible. If you are interested in contributing
|
||||
# we would love to have you https://github.com/pion/webrtc/wiki/Contributing
|
||||
#
|
||||
# This file is auto generated, using git to list all individuals contributors.
|
||||
# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting
|
||||
Aaron France <aaron.l.france@gmail.com>
|
||||
Adam Kiss <masterada@gmail.com>
|
||||
adwpc <adwpc@hotmail.com>
|
||||
Aleksandr Razumov <ar@gortc.io>
|
||||
aler9 <46489434+aler9@users.noreply.github.com>
|
||||
Antoine Baché <antoine@tenten.app>
|
||||
Artur Shellunts <shellunts.artur@gmail.com>
|
||||
Assad Obaid <assad@lap5cg901003r.se.axis.com>
|
||||
Atsushi Watanabe <atsushi.w@ieee.org>
|
||||
backkem <mail@backkem.me>
|
||||
buptczq <czq@qq.com>
|
||||
cgojin <gongjin21@hotmail.com>
|
||||
Chao Yuan <yuanchao0310@163.com>
|
||||
cnderrauber <zengjie9004@gmail.com>
|
||||
David Hamilton <davidhamiltron@gmail.com>
|
||||
David Zhao <david@davidzhao.com>
|
||||
David Zhao <dz@livekit.io>
|
||||
Eric Daniels <eric@erdaniels.com>
|
||||
Genteure <github@genteure.com>
|
||||
Henry <cryptix@riseup.net>
|
||||
hexiang <hexiang.zhang@chukong-inc.com>
|
||||
hn8 <10730886+hn8@users.noreply.github.com>
|
||||
Hugo Arregui <hugo.arregui@gmail.com>
|
||||
Hugo Arregui <hugo@decentraland.org>
|
||||
Jason Maldonis <jason.maldonis@i3pd.com>
|
||||
Jerko Steiner <jerko.steiner@gmail.com>
|
||||
JooYoung <qkdlql@naver.com>
|
||||
Juliusz Chroboczek <jch@irif.fr>
|
||||
Kacper Bąk <56700396+53jk1@users.noreply.github.com>
|
||||
Kevin Caffrey <kcaffrey@gmail.com>
|
||||
Konstantin Itskov <konstantin.itskov@kovits.com>
|
||||
korymiller1489 <kmiller@unwiredrevolution.com>
|
||||
Kyle Carberry <kyle@carberry.com>
|
||||
Lander Noterman <lander.noterman@basalte.be>
|
||||
Luke Curley <kixelated@gmail.com>
|
||||
Meelap Shah <meelapshah@gmail.com>
|
||||
Michael MacDonald <github@macdonald.cx>
|
||||
Michael MacDonald <mike.macdonald@savantsystems.com>
|
||||
Mikhail Bragin <misha@wiretrustee.com>
|
||||
Miroslav Šedivý <sedivy.miro@gmail.com>
|
||||
Nevio Vesic <nevio@subspace.com>
|
||||
Ori Bernstein <ori@eigenstate.org>
|
||||
Rasmus Hanning <rasmus@hanning.se>
|
||||
Robert Eperjesi <eperjesi@uber.com>
|
||||
Sam Lancia <sam@gpsm.co.uk>
|
||||
Sam Lancia <sam@vaion.com>
|
||||
San9H0 <lucian@hpcnt.com>
|
||||
Sean DuBois <seaduboi@amazon.com>
|
||||
Sean DuBois <sean@siobud.com>
|
||||
Sebastian Waisbrot <seppo0010@gmail.com>
|
||||
Sidney San Martín <sidney@s4y.us>
|
||||
Steffen Vogel <post@steffenvogel.de>
|
||||
Will Forcey <wsforc3y@gmail.com>
|
||||
Woodrow Douglass <wdouglass@carnegierobotics.com>
|
||||
Yutaka Takeda <yt0916@gmail.com>
|
||||
ZHENK <chengzhenyang@gmail.com>
|
||||
Zizheng Tai <me@zizheng.me>
|
||||
|
||||
# List of contributors not appearing in Git history
|
||||
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/LICENSE
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/LICENSE
generated
vendored
|
@ -1,21 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018
|
||||
Copyright (c) 2023 The Pion community <https://pion.ly>
|
||||
|
||||
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:
|
||||
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 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.
|
||||
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.
|
||||
|
|
47
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/README.md
generated
vendored
47
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/README.md
generated
vendored
|
@ -5,11 +5,11 @@
|
|||
</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="https://pion.ly"><img src="https://img.shields.io/badge/pion-ice-gray.svg?longCache=true&colorB=brightgreen" alt="Pion ICE"></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>
|
||||
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/pion/ice/test.yaml">
|
||||
<a href="https://pkg.go.dev/github.com/pion/ice/v2"><img src="https://pkg.go.dev/badge/github.com/pion/ice/v2.svg" alt="Go Reference"></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>
|
||||
|
@ -20,48 +20,15 @@
|
|||
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).
|
||||
Pion has an active community on the [Slack](https://pion.ly/slack).
|
||||
|
||||
Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news.
|
||||
|
||||
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)
|
||||
* [Will Forcey](https://github.com/wawesomeNOGUI)
|
||||
Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt)
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
||||
|
|
71
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/addr.go
generated
vendored
Normal file
71
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/addr.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func parseMulticastAnswerAddr(in net.Addr) (net.IP, bool) {
|
||||
switch addr := in.(type) {
|
||||
case *net.IPAddr:
|
||||
return addr.IP, true
|
||||
case *net.UDPAddr:
|
||||
return addr.IP, true
|
||||
case *net.TCPAddr:
|
||||
return addr.IP, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// AddrPort is an IP and a port number.
|
||||
type AddrPort [18]byte
|
||||
|
||||
func toAddrPort(addr net.Addr) AddrPort {
|
||||
var ap AddrPort
|
||||
switch addr := addr.(type) {
|
||||
case *net.UDPAddr:
|
||||
copy(ap[:16], addr.IP.To16())
|
||||
ap[16] = uint8(addr.Port >> 8)
|
||||
ap[17] = uint8(addr.Port)
|
||||
case *net.TCPAddr:
|
||||
copy(ap[:16], addr.IP.To16())
|
||||
ap[16] = uint8(addr.Port >> 8)
|
||||
ap[17] = uint8(addr.Port)
|
||||
}
|
||||
return ap
|
||||
}
|
397
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent.go
generated
vendored
397
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent.go
generated
vendored
|
@ -1,20 +1,28 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package ice implements the Interactive Connectivity Establishment (ICE)
|
||||
// protocol defined in rfc5245.
|
||||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
atomicx "github.com/pion/ice/v2/internal/atomic"
|
||||
stunx "github.com/pion/ice/v2/internal/stun"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/mdns"
|
||||
"github.com/pion/stun"
|
||||
"github.com/pion/transport/packetio"
|
||||
"github.com/pion/transport/vnet"
|
||||
"github.com/pion/transport/v2"
|
||||
"github.com/pion/transport/v2/packetio"
|
||||
"github.com/pion/transport/v2/stdnet"
|
||||
"github.com/pion/transport/v2/vnet"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
|
@ -39,7 +47,7 @@ type Agent struct {
|
|||
onConnected chan struct{}
|
||||
onConnectedOnce sync.Once
|
||||
|
||||
// force candidate to be contacted immediately (instead of waiting for task ticker)
|
||||
// Force candidate to be contacted immediately (instead of waiting for task ticker)
|
||||
forceCandidateContact chan bool
|
||||
|
||||
tieBreaker uint64
|
||||
|
@ -64,8 +72,8 @@ type Agent struct {
|
|||
prflxAcceptanceMinWait time.Duration
|
||||
relayAcceptanceMinWait time.Duration
|
||||
|
||||
portmin uint16
|
||||
portmax uint16
|
||||
portMin uint16
|
||||
portMax uint16
|
||||
|
||||
candidateTypes []CandidateType
|
||||
|
||||
|
@ -92,15 +100,15 @@ type Agent struct {
|
|||
remotePwd string
|
||||
remoteCandidates map[NetworkType][]Candidate
|
||||
|
||||
checklist []*candidatePair
|
||||
checklist []*CandidatePair
|
||||
selector pairCandidateSelector
|
||||
|
||||
selectedPair atomic.Value // *candidatePair
|
||||
selectedPair atomic.Value // *CandidatePair
|
||||
|
||||
urls []*URL
|
||||
urls []*stun.URI
|
||||
networkTypes []NetworkType
|
||||
|
||||
buffer *packetio.Buffer
|
||||
buf *packetio.Buffer
|
||||
|
||||
// LRU of outbound Binding request Transaction IDs
|
||||
pendingBindingRequests []bindingRequest
|
||||
|
@ -109,22 +117,28 @@ type Agent struct {
|
|||
extIPMapper *externalIPMapper
|
||||
|
||||
// State for closing
|
||||
done chan struct{}
|
||||
err atomicError
|
||||
done chan struct{}
|
||||
taskLoopDone chan struct{}
|
||||
err atomicx.Error
|
||||
|
||||
gatherCandidateCancel func()
|
||||
gatherCandidateDone chan struct{}
|
||||
|
||||
chanCandidate chan Candidate
|
||||
chanCandidatePair chan *candidatePair
|
||||
chanCandidatePair chan *CandidatePair
|
||||
chanState chan ConnectionState
|
||||
|
||||
loggerFactory logging.LoggerFactory
|
||||
log logging.LeveledLogger
|
||||
|
||||
net *vnet.Net
|
||||
tcpMux TCPMux
|
||||
net transport.Net
|
||||
tcpMux TCPMux
|
||||
udpMux UDPMux
|
||||
udpMuxSrflx UniversalUDPMux
|
||||
|
||||
interfaceFilter func(string) bool
|
||||
ipFilter func(net.IP) bool
|
||||
includeLoopback bool
|
||||
|
||||
insecureSkipVerify bool
|
||||
|
||||
|
@ -200,8 +214,8 @@ func (a *Agent) taskLoop() {
|
|||
a.deleteAllCandidates()
|
||||
a.startedFn()
|
||||
|
||||
if err := a.buffer.Close(); err != nil {
|
||||
a.log.Warnf("failed to close buffer: %v", err)
|
||||
if err := a.buf.Close(); err != nil {
|
||||
a.log.Warnf("Failed to close buffer: %v", err)
|
||||
}
|
||||
|
||||
a.closeMulticastConn()
|
||||
|
@ -212,6 +226,7 @@ func (a *Agent) taskLoop() {
|
|||
close(a.chanState)
|
||||
close(a.chanCandidate)
|
||||
close(a.chanCandidatePair)
|
||||
close(a.taskLoopDone)
|
||||
}()
|
||||
|
||||
for {
|
||||
|
@ -255,28 +270,13 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit
|
|||
}
|
||||
log := loggerFactory.NewLogger("ice")
|
||||
|
||||
var mDNSConn *mdns.Conn
|
||||
mDNSConn, mDNSMode, err = createMulticastDNS(mDNSMode, mDNSName, log)
|
||||
// Opportunistic mDNS: If we can't open the connection, that's ok: we
|
||||
// can continue without it.
|
||||
if err != nil {
|
||||
log.Warnf("Failed to initialize mDNS %s: %v", mDNSName, err)
|
||||
}
|
||||
closeMDNSConn := func() {
|
||||
if mDNSConn != nil {
|
||||
if mdnsCloseErr := mDNSConn.Close(); mdnsCloseErr != nil {
|
||||
log.Warnf("Failed to close mDNS: %v", mdnsCloseErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startedCtx, startedFn := context.WithCancel(context.Background())
|
||||
|
||||
a := &Agent{
|
||||
chanTask: make(chan task),
|
||||
chanState: make(chan ConnectionState),
|
||||
chanCandidate: make(chan Candidate),
|
||||
chanCandidatePair: make(chan *candidatePair),
|
||||
chanCandidatePair: make(chan *CandidatePair),
|
||||
tieBreaker: globalMathRandomGenerator.Uint64(),
|
||||
lite: config.Lite,
|
||||
gatheringState: GatheringStateNew,
|
||||
|
@ -286,20 +286,23 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit
|
|||
urls: config.Urls,
|
||||
networkTypes: config.NetworkTypes,
|
||||
onConnected: make(chan struct{}),
|
||||
buffer: packetio.NewBuffer(),
|
||||
buf: packetio.NewBuffer(),
|
||||
done: make(chan struct{}),
|
||||
taskLoopDone: make(chan struct{}),
|
||||
startedCh: startedCtx.Done(),
|
||||
startedFn: startedFn,
|
||||
portmin: config.PortMin,
|
||||
portmax: config.PortMax,
|
||||
portMin: config.PortMin,
|
||||
portMax: config.PortMax,
|
||||
loggerFactory: loggerFactory,
|
||||
log: log,
|
||||
net: config.Net,
|
||||
proxyDialer: config.ProxyDialer,
|
||||
tcpMux: config.TCPMux,
|
||||
udpMux: config.UDPMux,
|
||||
udpMuxSrflx: config.UDPMuxSrflx,
|
||||
|
||||
mDNSMode: mDNSMode,
|
||||
mDNSName: mDNSName,
|
||||
mDNSConn: mDNSConn,
|
||||
|
||||
gatherCandidateCancel: func() {},
|
||||
|
||||
|
@ -307,21 +310,29 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit
|
|||
|
||||
interfaceFilter: config.InterfaceFilter,
|
||||
|
||||
insecureSkipVerify: config.InsecureSkipVerify,
|
||||
}
|
||||
ipFilter: config.IPFilter,
|
||||
|
||||
a.tcpMux = config.TCPMux
|
||||
if a.tcpMux == nil {
|
||||
a.tcpMux = newInvalidTCPMux()
|
||||
insecureSkipVerify: config.InsecureSkipVerify,
|
||||
|
||||
includeLoopback: config.IncludeLoopback,
|
||||
}
|
||||
|
||||
if a.net == nil {
|
||||
a.net = vnet.NewNet(nil)
|
||||
} else if a.net.IsVirtual() {
|
||||
a.log.Warn("vnet is enabled")
|
||||
if a.mDNSMode != MulticastDNSModeDisabled {
|
||||
a.log.Warn("vnet does not support mDNS yet")
|
||||
a.net, err = stdnet.NewNet()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create network: %w", err)
|
||||
}
|
||||
} else if _, isVirtual := a.net.(*vnet.Net); isVirtual {
|
||||
a.log.Warn("Virtual network is enabled")
|
||||
if a.mDNSMode != MulticastDNSModeDisabled {
|
||||
a.log.Warn("Virtual network does not support mDNS yet")
|
||||
}
|
||||
}
|
||||
|
||||
// Opportunistic mDNS: If we can't open the connection, that's ok: we
|
||||
// can continue without it.
|
||||
if a.mDNSConn, a.mDNSMode, err = createMulticastDNS(a.net, mDNSMode, mDNSName, log); err != nil {
|
||||
log.Warnf("Failed to initialize mDNS %s: %v", mDNSName, err)
|
||||
}
|
||||
|
||||
config.initWithDefaults(a)
|
||||
|
@ -329,29 +340,35 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit
|
|||
// Make sure the buffer doesn't grow indefinitely.
|
||||
// NOTE: We actually won't get anywhere close to this limit.
|
||||
// SRTP will constantly read from the endpoint and drop packets if it's full.
|
||||
a.buffer.SetLimitSize(maxBufferSize)
|
||||
a.buf.SetLimitSize(maxBufferSize)
|
||||
|
||||
if a.lite && (len(a.candidateTypes) != 1 || a.candidateTypes[0] != CandidateTypeHost) {
|
||||
closeMDNSConn()
|
||||
a.closeMulticastConn()
|
||||
return nil, ErrLiteUsingNonHostCandidates
|
||||
}
|
||||
|
||||
if config.Urls != nil && len(config.Urls) > 0 && !containsCandidateType(CandidateTypeServerReflexive, a.candidateTypes) && !containsCandidateType(CandidateTypeRelay, a.candidateTypes) {
|
||||
closeMDNSConn()
|
||||
a.closeMulticastConn()
|
||||
return nil, ErrUselessUrlsProvided
|
||||
}
|
||||
|
||||
if err = config.initExtIPMapping(a); err != nil {
|
||||
closeMDNSConn()
|
||||
a.closeMulticastConn()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go a.taskLoop()
|
||||
a.startOnConnectionStateChangeRoutine()
|
||||
|
||||
// CandidatePair and ConnectionState are usually changed at once.
|
||||
// Blocking one by the other one causes deadlock.
|
||||
// Hence, we call handlers from independent Goroutines.
|
||||
go a.candidatePairRoutine()
|
||||
go a.connectionStateRoutine()
|
||||
go a.candidateRoutine()
|
||||
|
||||
// Restart is also used to initialize the agent for the first time
|
||||
if err := a.Restart(config.LocalUfrag, config.LocalPwd); err != nil {
|
||||
closeMDNSConn()
|
||||
a.closeMulticastConn()
|
||||
_ = a.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
@ -359,81 +376,6 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit
|
|||
return a, nil
|
||||
}
|
||||
|
||||
// OnConnectionStateChange sets a handler that is fired when the connection state changes
|
||||
func (a *Agent) OnConnectionStateChange(f func(ConnectionState)) error {
|
||||
a.onConnectionStateChangeHdlr.Store(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnSelectedCandidatePairChange sets a handler that is fired when the final candidate
|
||||
// pair is selected
|
||||
func (a *Agent) OnSelectedCandidatePairChange(f func(Candidate, Candidate)) error {
|
||||
a.onSelectedCandidatePairChangeHdlr.Store(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnCandidate sets a handler that is fired when new candidates gathered. When
|
||||
// the gathering process complete the last candidate is nil.
|
||||
func (a *Agent) OnCandidate(f func(Candidate)) error {
|
||||
a.onCandidateHdlr.Store(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) onSelectedCandidatePairChange(p *candidatePair) {
|
||||
if h, ok := a.onSelectedCandidatePairChangeHdlr.Load().(func(Candidate, Candidate)); ok {
|
||||
h(p.local, p.remote)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) onCandidate(c Candidate) {
|
||||
if onCandidateHdlr, ok := a.onCandidateHdlr.Load().(func(Candidate)); ok {
|
||||
onCandidateHdlr(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) onConnectionStateChange(s ConnectionState) {
|
||||
if hdlr, ok := a.onConnectionStateChangeHdlr.Load().(func(ConnectionState)); ok {
|
||||
hdlr(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) startOnConnectionStateChangeRoutine() {
|
||||
go func() {
|
||||
for {
|
||||
// CandidatePair and ConnectionState are usually changed at once.
|
||||
// Blocking one by the other one causes deadlock.
|
||||
p, isOpen := <-a.chanCandidatePair
|
||||
if !isOpen {
|
||||
return
|
||||
}
|
||||
a.onSelectedCandidatePairChange(p)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case s, isOpen := <-a.chanState:
|
||||
if !isOpen {
|
||||
for c := range a.chanCandidate {
|
||||
a.onCandidate(c)
|
||||
}
|
||||
return
|
||||
}
|
||||
a.onConnectionStateChange(s)
|
||||
|
||||
case c, isOpen := <-a.chanCandidate:
|
||||
if !isOpen {
|
||||
for s := range a.chanState {
|
||||
a.onConnectionStateChange(s)
|
||||
}
|
||||
return
|
||||
}
|
||||
a.onCandidate(c)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (a *Agent) startConnectivityChecks(isControlling bool, remoteUfrag, remotePwd string) error {
|
||||
a.muHaveStarted.Lock()
|
||||
defer a.muHaveStarted.Unlock()
|
||||
|
@ -442,7 +384,7 @@ func (a *Agent) startConnectivityChecks(isControlling bool, remoteUfrag, remoteP
|
|||
return ErrMultipleStart
|
||||
default:
|
||||
}
|
||||
if err := a.SetRemoteCredentials(remoteUfrag, remotePwd); err != nil {
|
||||
if err := a.SetRemoteCredentials(remoteUfrag, remotePwd); err != nil { //nolint:contextcheck
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -469,7 +411,7 @@ func (a *Agent) startConnectivityChecks(isControlling bool, remoteUfrag, remoteP
|
|||
agent.updateConnectionState(ConnectionStateChecking)
|
||||
|
||||
a.requestConnectivityCheck()
|
||||
go a.connectivityChecks()
|
||||
go a.connectivityChecks() //nolint:contextcheck
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -499,11 +441,12 @@ func (a *Agent) connectivityChecks() {
|
|||
a.updateConnectionState(ConnectionStateFailed)
|
||||
return
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
a.selector.ContactCandidates()
|
||||
}); err != nil {
|
||||
a.log.Warnf("taskLoop failed: %v", err)
|
||||
a.log.Warnf("Failed to start connectivity checks: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,29 +502,27 @@ func (a *Agent) updateConnectionState(newState ConnectionState) {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *Agent) setSelectedPair(p *candidatePair) {
|
||||
a.log.Tracef("Set selected candidate pair: %s", p)
|
||||
|
||||
func (a *Agent) setSelectedPair(p *CandidatePair) {
|
||||
if p == nil {
|
||||
var nilPair *candidatePair
|
||||
var nilPair *CandidatePair
|
||||
a.selectedPair.Store(nilPair)
|
||||
a.log.Tracef("Unset selected candidate pair")
|
||||
return
|
||||
}
|
||||
|
||||
p.nominated = true
|
||||
a.selectedPair.Store(p)
|
||||
a.log.Tracef("Set selected candidate pair: %s", p)
|
||||
|
||||
a.updateConnectionState(ConnectionStateConnected)
|
||||
|
||||
// Notify when the selected pair changes
|
||||
if p != nil {
|
||||
a.afterRun(func(ctx context.Context) {
|
||||
select {
|
||||
case a.chanCandidatePair <- p:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
})
|
||||
}
|
||||
a.afterRun(func(ctx context.Context) {
|
||||
select {
|
||||
case a.chanCandidatePair <- p:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
})
|
||||
|
||||
// Signal connected
|
||||
a.onConnectedOnce.Do(func() { close(a.onConnected) })
|
||||
|
@ -591,7 +532,7 @@ func (a *Agent) pingAllCandidates() {
|
|||
a.log.Trace("pinging all candidates")
|
||||
|
||||
if len(a.checklist) == 0 {
|
||||
a.log.Warn("pingAllCandidates called with no candidate pairs. Connection is not possible yet.")
|
||||
a.log.Warn("Failed to ping without candidate pairs. Connection is not possible yet.")
|
||||
}
|
||||
|
||||
for _, p := range a.checklist {
|
||||
|
@ -602,17 +543,17 @@ func (a *Agent) pingAllCandidates() {
|
|||
}
|
||||
|
||||
if p.bindingRequestCount > a.maxBindingRequests {
|
||||
a.log.Tracef("max requests reached for pair %s, marking it as failed\n", p)
|
||||
a.log.Tracef("max requests reached for pair %s, marking it as failed", p)
|
||||
p.state = CandidatePairStateFailed
|
||||
} else {
|
||||
a.selector.PingCandidate(p.local, p.remote)
|
||||
a.selector.PingCandidate(p.Local, p.Remote)
|
||||
p.bindingRequestCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) getBestAvailableCandidatePair() *candidatePair {
|
||||
var best *candidatePair
|
||||
func (a *Agent) getBestAvailableCandidatePair() *CandidatePair {
|
||||
var best *CandidatePair
|
||||
for _, p := range a.checklist {
|
||||
if p.state == CandidatePairStateFailed {
|
||||
continue
|
||||
|
@ -620,15 +561,15 @@ func (a *Agent) getBestAvailableCandidatePair() *candidatePair {
|
|||
|
||||
if best == nil {
|
||||
best = p
|
||||
} else if best.Priority() < p.Priority() {
|
||||
} else if best.priority() < p.priority() {
|
||||
best = p
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
func (a *Agent) getBestValidCandidatePair() *candidatePair {
|
||||
var best *candidatePair
|
||||
func (a *Agent) getBestValidCandidatePair() *CandidatePair {
|
||||
var best *CandidatePair
|
||||
for _, p := range a.checklist {
|
||||
if p.state != CandidatePairStateSucceeded {
|
||||
continue
|
||||
|
@ -636,22 +577,22 @@ func (a *Agent) getBestValidCandidatePair() *candidatePair {
|
|||
|
||||
if best == nil {
|
||||
best = p
|
||||
} else if best.Priority() < p.Priority() {
|
||||
} else if best.priority() < p.priority() {
|
||||
best = p
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
func (a *Agent) addPair(local, remote Candidate) *candidatePair {
|
||||
func (a *Agent) addPair(local, remote Candidate) *CandidatePair {
|
||||
p := newCandidatePair(local, remote, a.isControlling)
|
||||
a.checklist = append(a.checklist, p)
|
||||
return p
|
||||
}
|
||||
|
||||
func (a *Agent) findPair(local, remote Candidate) *candidatePair {
|
||||
func (a *Agent) findPair(local, remote Candidate) *CandidatePair {
|
||||
for _, p := range a.checklist {
|
||||
if p.local.Equal(local) && p.remote.Equal(remote) {
|
||||
if p.Local.Equal(local) && p.Remote.Equal(remote) {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
@ -666,7 +607,7 @@ func (a *Agent) validateSelectedPair() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
disconnectedTime := time.Since(selectedPair.remote.LastReceived())
|
||||
disconnectedTime := time.Since(selectedPair.Remote.LastReceived())
|
||||
|
||||
// Only allow transitions to failed if a.failedTimeout is non-zero
|
||||
totalTimeToFailure := a.failedTimeout
|
||||
|
@ -696,11 +637,11 @@ func (a *Agent) checkKeepalive() {
|
|||
}
|
||||
|
||||
if (a.keepaliveInterval != 0) &&
|
||||
((time.Since(selectedPair.local.LastSent()) > a.keepaliveInterval) ||
|
||||
(time.Since(selectedPair.remote.LastReceived()) > a.keepaliveInterval)) {
|
||||
// we use binding request instead of indication to support refresh consent schemas
|
||||
((time.Since(selectedPair.Local.LastSent()) > a.keepaliveInterval) ||
|
||||
(time.Since(selectedPair.Remote.LastReceived()) > a.keepaliveInterval)) {
|
||||
// We use binding request instead of indication to support refresh consent schemas
|
||||
// see https://tools.ietf.org/html/rfc7675
|
||||
a.selector.PingCandidate(selectedPair.local, selectedPair.remote)
|
||||
a.selector.PingCandidate(selectedPair.Local, selectedPair.Remote)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,10 +651,10 @@ func (a *Agent) AddRemoteCandidate(c Candidate) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// cannot check for network yet because it might not be applied
|
||||
// when mDNS hostame is used.
|
||||
// Cannot check for network yet because it might not be applied
|
||||
// when mDNS hostname is used.
|
||||
if c.TCPType() == TCPTypeActive {
|
||||
// TCP Candidates with tcptype active will probe server passive ones, so
|
||||
// TCP Candidates with TCP type active will probe server passive ones, so
|
||||
// no need to do anything with them.
|
||||
a.log.Infof("Ignoring remote candidate with tcpType active: %s", c)
|
||||
return nil
|
||||
|
@ -722,7 +663,7 @@ func (a *Agent) AddRemoteCandidate(c Candidate) error {
|
|||
// If we have a mDNS Candidate lets fully resolve it before adding it locally
|
||||
if c.Type() == CandidateTypeHost && strings.HasSuffix(c.Address(), ".local") {
|
||||
if a.mDNSMode == MulticastDNSModeDisabled {
|
||||
a.log.Warnf("remote mDNS candidate added, but mDNS is disabled: (%s)", c.Address())
|
||||
a.log.Warnf("Remote mDNS candidate added, but mDNS is disabled: (%s)", c.Address())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -756,8 +697,8 @@ func (a *Agent) resolveAndAddMulticastCandidate(c *CandidateHost) {
|
|||
return
|
||||
}
|
||||
|
||||
ip, _, _, _ := parseAddr(src) //nolint:dogsled
|
||||
if ip == nil {
|
||||
ip, ipOk := parseMulticastAnswerAddr(src)
|
||||
if !ipOk {
|
||||
a.log.Warnf("Failed to discover mDNS candidate %s: failed to parse IP", c.Address())
|
||||
return
|
||||
}
|
||||
|
@ -806,18 +747,22 @@ func (a *Agent) addRemoteCandidate(c Candidate) {
|
|||
|
||||
func (a *Agent) addCandidate(ctx context.Context, c Candidate, candidateConn net.PacketConn) error {
|
||||
return a.run(ctx, func(ctx context.Context, agent *Agent) {
|
||||
c.start(a, candidateConn, a.startedCh)
|
||||
|
||||
set := a.localCandidates[c.NetworkType()]
|
||||
for _, candidate := range set {
|
||||
if candidate.Equal(c) {
|
||||
a.log.Debugf("Ignore duplicate candidate: %s", c.String())
|
||||
if err := c.close(); err != nil {
|
||||
a.log.Warnf("Failed to close duplicate candidate: %v", err)
|
||||
}
|
||||
if err := candidateConn.Close(); err != nil {
|
||||
a.log.Warnf("Failed to close duplicate candidate connection: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.start(a, candidateConn, a.startedCh)
|
||||
|
||||
set = append(set, c)
|
||||
a.localCandidates[c.NetworkType()] = set
|
||||
|
||||
|
@ -881,26 +826,36 @@ func (a *Agent) GetRemoteUserCredentials() (frag string, pwd string, err error)
|
|||
return
|
||||
}
|
||||
|
||||
func (a *Agent) removeUfragFromMux() {
|
||||
if a.tcpMux != nil {
|
||||
a.tcpMux.RemoveConnByUfrag(a.localUfrag)
|
||||
}
|
||||
if a.udpMux != nil {
|
||||
a.udpMux.RemoveConnByUfrag(a.localUfrag)
|
||||
}
|
||||
if a.udpMuxSrflx != nil {
|
||||
a.udpMuxSrflx.RemoveConnByUfrag(a.localUfrag)
|
||||
}
|
||||
}
|
||||
|
||||
// Close cleans up the Agent
|
||||
func (a *Agent) Close() error {
|
||||
if err := a.ok(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
|
||||
a.afterRun(func(context.Context) {
|
||||
close(done)
|
||||
a.gatherCandidateCancel()
|
||||
if a.gatherCandidateDone != nil {
|
||||
<-a.gatherCandidateDone
|
||||
}
|
||||
})
|
||||
|
||||
a.gatherCandidateCancel()
|
||||
a.err.Store(ErrClosed)
|
||||
|
||||
a.tcpMux.RemoveConnByUfrag(a.localUfrag)
|
||||
a.removeUfragFromMux()
|
||||
|
||||
close(a.done)
|
||||
|
||||
<-done
|
||||
<-a.taskLoopDone
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -930,7 +885,7 @@ func (a *Agent) deleteAllCandidates() {
|
|||
func (a *Agent) findRemoteCandidate(networkType NetworkType, addr net.Addr) Candidate {
|
||||
ip, port, _, ok := parseAddr(addr)
|
||||
if !ok {
|
||||
a.log.Warnf("Error parsing addr: %s", addr)
|
||||
a.log.Warnf("Failed to parse address: %s", addr)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -944,7 +899,7 @@ func (a *Agent) findRemoteCandidate(networkType NetworkType, addr net.Addr) Cand
|
|||
}
|
||||
|
||||
func (a *Agent) sendBindingRequest(m *stun.Message, local, remote Candidate) {
|
||||
a.log.Tracef("ping STUN from %s to %s\n", local.String(), remote.String())
|
||||
a.log.Tracef("ping STUN from %s to %s", local.String(), remote.String())
|
||||
|
||||
a.invalidatePendingBindingRequests(time.Now())
|
||||
a.pendingBindingRequests = append(a.pendingBindingRequests, bindingRequest{
|
||||
|
@ -962,7 +917,7 @@ func (a *Agent) sendBindingSuccess(m *stun.Message, local, remote Candidate) {
|
|||
|
||||
ip, port, _, ok := parseAddr(base.addr())
|
||||
if !ok {
|
||||
a.log.Warnf("Error parsing addr: %s", base.addr())
|
||||
a.log.Warnf("Failed to parse address: %s", base.addr())
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -980,12 +935,11 @@ func (a *Agent) sendBindingSuccess(m *stun.Message, local, remote Candidate) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Removes pending binding requests that are over maxBindingRequestTimeout old
|
||||
|
||||
Let HTO be the transaction timeout, which SHOULD be 2*RTT if
|
||||
RTT is known or 500 ms otherwise.
|
||||
https://tools.ietf.org/html/rfc8445#appendix-B.1
|
||||
*/
|
||||
// Removes pending binding requests that are over maxBindingRequestTimeout old
|
||||
//
|
||||
// Let HTO be the transaction timeout, which SHOULD be 2*RTT if
|
||||
// RTT is known or 500 ms otherwise.
|
||||
// https://tools.ietf.org/html/rfc8445#appendix-B.1
|
||||
func (a *Agent) invalidatePendingBindingRequests(filterTime time.Time) {
|
||||
initialSize := len(a.pendingBindingRequests)
|
||||
|
||||
|
@ -1033,38 +987,38 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr)
|
|||
|
||||
if a.isControlling {
|
||||
if m.Contains(stun.AttrICEControlling) {
|
||||
a.log.Debug("inbound isControlling && a.isControlling == true")
|
||||
a.log.Debug("Inbound STUN message: isControlling && a.isControlling == true")
|
||||
return
|
||||
} else if m.Contains(stun.AttrUseCandidate) {
|
||||
a.log.Debug("useCandidate && a.isControlling == true")
|
||||
a.log.Debug("Inbound STUN message: useCandidate && a.isControlling == true")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if m.Contains(stun.AttrICEControlled) {
|
||||
a.log.Debug("inbound isControlled && a.isControlling == false")
|
||||
a.log.Debug("Inbound STUN message: isControlled && a.isControlling == false")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
remoteCandidate := a.findRemoteCandidate(local.NetworkType(), remote)
|
||||
if m.Type.Class == stun.ClassSuccessResponse {
|
||||
if err = assertInboundMessageIntegrity(m, []byte(a.remotePwd)); err != nil {
|
||||
a.log.Warnf("discard message from (%s), %v", remote, err)
|
||||
if err = stun.MessageIntegrity([]byte(a.remotePwd)).Check(m); err != nil {
|
||||
a.log.Warnf("Discard message from (%s), %v", remote, err)
|
||||
return
|
||||
}
|
||||
|
||||
if remoteCandidate == nil {
|
||||
a.log.Warnf("discard success message from (%s), no such remote", remote)
|
||||
a.log.Warnf("Discard success message from (%s), no such remote", remote)
|
||||
return
|
||||
}
|
||||
|
||||
a.selector.HandleSuccessResponse(m, local, remoteCandidate, remote)
|
||||
} else if m.Type.Class == stun.ClassRequest {
|
||||
if err = assertInboundUsername(m, a.localUfrag+":"+a.remoteUfrag); err != nil {
|
||||
a.log.Warnf("discard message from (%s), %v", remote, err)
|
||||
if err = stunx.AssertUsername(m, a.localUfrag+":"+a.remoteUfrag); err != nil {
|
||||
a.log.Warnf("Discard message from (%s), %v", remote, err)
|
||||
return
|
||||
} else if err = assertInboundMessageIntegrity(m, []byte(a.localPwd)); err != nil {
|
||||
a.log.Warnf("discard message from (%s), %v", remote, err)
|
||||
} else if err = stun.MessageIntegrity([]byte(a.localPwd)).Check(m); err != nil {
|
||||
a.log.Warnf("Discard message from (%s), %v", remote, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1091,7 +1045,7 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr)
|
|||
}
|
||||
remoteCandidate = prflxCandidate
|
||||
|
||||
a.log.Debugf("adding a new peer-reflexive candidate: %s ", remote)
|
||||
a.log.Debugf("Adding a new peer-reflexive candidate: %s ", remote)
|
||||
a.addRemoteCandidate(remoteCandidate)
|
||||
}
|
||||
|
||||
|
@ -1107,35 +1061,52 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr)
|
|||
|
||||
// validateNonSTUNTraffic processes non STUN traffic from a remote candidate,
|
||||
// and returns true if it is an actual remote candidate
|
||||
func (a *Agent) validateNonSTUNTraffic(local Candidate, remote net.Addr) bool {
|
||||
var isValidCandidate uint64
|
||||
func (a *Agent) validateNonSTUNTraffic(local Candidate, remote net.Addr) (Candidate, bool) {
|
||||
var remoteCandidate Candidate
|
||||
if err := a.run(local.context(), func(ctx context.Context, agent *Agent) {
|
||||
remoteCandidate := a.findRemoteCandidate(local.NetworkType(), remote)
|
||||
remoteCandidate = a.findRemoteCandidate(local.NetworkType(), remote)
|
||||
if remoteCandidate != nil {
|
||||
remoteCandidate.seen(false)
|
||||
atomic.AddUint64(&isValidCandidate, 1)
|
||||
}
|
||||
}); err != nil {
|
||||
a.log.Warnf("failed to validate remote candidate: %v", err)
|
||||
a.log.Warnf("Failed to validate remote candidate: %v", err)
|
||||
}
|
||||
|
||||
return atomic.LoadUint64(&isValidCandidate) == 1
|
||||
return remoteCandidate, remoteCandidate != nil
|
||||
}
|
||||
|
||||
func (a *Agent) getSelectedPair() *candidatePair {
|
||||
selectedPair := a.selectedPair.Load()
|
||||
|
||||
// GetSelectedCandidatePair returns the selected pair or nil if there is none
|
||||
func (a *Agent) GetSelectedCandidatePair() (*CandidatePair, error) {
|
||||
selectedPair := a.getSelectedPair()
|
||||
if selectedPair == nil {
|
||||
return nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
|
||||
return selectedPair.(*candidatePair)
|
||||
local, err := selectedPair.Local.copy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
remote, err := selectedPair.Remote.copy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CandidatePair{Local: local, Remote: remote}, nil
|
||||
}
|
||||
|
||||
func (a *Agent) getSelectedPair() *CandidatePair {
|
||||
if selectedPair, ok := a.selectedPair.Load().(*CandidatePair); ok {
|
||||
return selectedPair
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) closeMulticastConn() {
|
||||
if a.mDNSConn != nil {
|
||||
if err := a.mDNSConn.Close(); err != nil {
|
||||
a.log.Warnf("failed to close mDNS Conn: %v", err)
|
||||
a.log.Warnf("Failed to close mDNS Conn: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1158,8 +1129,10 @@ func (a *Agent) SetRemoteCredentials(remoteUfrag, remotePwd string) error {
|
|||
// Restart restarts the ICE Agent with the provided ufrag/pwd
|
||||
// If no ufrag/pwd is provided the Agent will generate one itself
|
||||
//
|
||||
// Restart must only be called when GatheringState is GatheringStateComplete
|
||||
// a user must then call GatherCandidates explicitly to start generating new ones
|
||||
// If there is a gatherer routine currently running, Restart will
|
||||
// cancel it.
|
||||
// After a Restart, the user must then call GatherCandidates explicitly
|
||||
// to start generating new ones.
|
||||
func (a *Agent) Restart(ufrag, pwd string) error {
|
||||
if ufrag == "" {
|
||||
var err error
|
||||
|
@ -1186,17 +1159,17 @@ func (a *Agent) Restart(ufrag, pwd string) error {
|
|||
var err error
|
||||
if runErr := a.run(a.context(), func(ctx context.Context, agent *Agent) {
|
||||
if agent.gatheringState == GatheringStateGathering {
|
||||
err = ErrRestartWhenGathering
|
||||
return
|
||||
agent.gatherCandidateCancel()
|
||||
}
|
||||
|
||||
// Clear all agent needed to take back to fresh state
|
||||
a.removeUfragFromMux()
|
||||
agent.localUfrag = ufrag
|
||||
agent.localPwd = pwd
|
||||
agent.remoteUfrag = ""
|
||||
agent.remotePwd = ""
|
||||
a.gatheringState = GatheringStateNew
|
||||
a.checklist = make([]*candidatePair, 0)
|
||||
a.checklist = make([]*CandidatePair, 0)
|
||||
a.pendingBindingRequests = make([]bindingRequest, 0)
|
||||
a.setSelectedPair(nil)
|
||||
a.deleteAllCandidates()
|
||||
|
|
68
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_config.go
generated
vendored
68
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_config.go
generated
vendored
|
@ -1,10 +1,15 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/transport/vnet"
|
||||
"github.com/pion/stun"
|
||||
"github.com/pion/transport/v2"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
|
@ -21,25 +26,25 @@ const (
|
|||
// 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 is the wait time before nominating a host candidate
|
||||
defaultHostAcceptanceMinWait = 0
|
||||
|
||||
// wait time before nominating a srflx candidate
|
||||
// defaultSrflxAcceptanceMinWait is the wait time before nominating a srflx candidate
|
||||
defaultSrflxAcceptanceMinWait = 500 * time.Millisecond
|
||||
|
||||
// wait time before nominating a prflx candidate
|
||||
// defaultPrflxAcceptanceMinWait is the wait time before nominating a prflx candidate
|
||||
defaultPrflxAcceptanceMinWait = 1000 * time.Millisecond
|
||||
|
||||
// wait time before nominating a relay candidate
|
||||
// defaultRelayAcceptanceMinWait is the wait time before nominating a relay candidate
|
||||
defaultRelayAcceptanceMinWait = 2000 * time.Millisecond
|
||||
|
||||
// max binding request before considering a pair failed
|
||||
// defaultMaxBindingRequests is the maximum number of binding requests before considering a pair failed
|
||||
defaultMaxBindingRequests = 7
|
||||
|
||||
// the number of bytes that can be buffered before we start to error
|
||||
// maxBufferSize is 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 is the wait time before binding requests can be deleted
|
||||
maxBindingRequestTimeout = 4000 * time.Millisecond
|
||||
)
|
||||
|
||||
|
@ -50,7 +55,7 @@ func defaultCandidateTypes() []CandidateType {
|
|||
// AgentConfig collects the arguments to ice.Agent construction into
|
||||
// a single structure, for future-proofness of the interface
|
||||
type AgentConfig struct {
|
||||
Urls []*URL
|
||||
Urls []*stun.URI
|
||||
|
||||
// PortMin and PortMax are optional. Leave them 0 for the default UDP port allocation strategy.
|
||||
PortMin uint16
|
||||
|
@ -83,6 +88,10 @@ type AgentConfig struct {
|
|||
// A keepalive interval of 0 means we never send keepalive packets
|
||||
KeepaliveInterval *time.Duration
|
||||
|
||||
// CheckInterval controls how often our task loop runs when in the
|
||||
// connecting state.
|
||||
CheckInterval *time.Duration
|
||||
|
||||
// NetworkTypes is an optional configuration for disabling or enabling
|
||||
// support for specific network types.
|
||||
NetworkTypes []NetworkType
|
||||
|
@ -93,10 +102,6 @@ type AgentConfig struct {
|
|||
|
||||
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
|
||||
|
@ -108,14 +113,14 @@ type AgentConfig struct {
|
|||
// 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
|
||||
// If CandidateTypeServerReflexive, it will insert a srflx candidate (as if it was derived
|
||||
// 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
|
||||
// 1:1 D-NAT (e.g. AWS EC2 instances) and to eliminate the need of server reflexive
|
||||
// candidate gathering.
|
||||
NAT1To1IPs []string
|
||||
|
||||
|
@ -129,13 +134,17 @@ type AgentConfig struct {
|
|||
RelayAcceptanceMinWait *time.Duration
|
||||
|
||||
// Net is the our abstracted network interface for internal development purpose only
|
||||
// (see github.com/pion/transport/vnet)
|
||||
Net *vnet.Net
|
||||
// (see https://github.com/pion/transport)
|
||||
Net transport.Net
|
||||
|
||||
// InterfaceFilter is a function that you can use in order to whitelist or blacklist
|
||||
// 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
|
||||
|
||||
// IPFilter is a function that you can use in order to whitelist or blacklist
|
||||
// the ips which are used to gather ICE candidates.
|
||||
IPFilter func(net.IP) bool
|
||||
|
||||
// InsecureSkipVerify controls if self-signed certificates are accepted when connecting
|
||||
// to TURN servers via TLS or DTLS
|
||||
InsecureSkipVerify bool
|
||||
|
@ -145,9 +154,26 @@ type AgentConfig struct {
|
|||
// experimental and the API might change in the future.
|
||||
TCPMux TCPMux
|
||||
|
||||
// UDPMux is used for multiplexing multiple incoming UDP connections on a single port
|
||||
// when this is set, the agent ignores PortMin and PortMax configurations and will
|
||||
// defer to UDPMux for incoming connections
|
||||
UDPMux UDPMux
|
||||
|
||||
// UDPMuxSrflx is used for multiplexing multiple incoming UDP connections of server reflexive candidates
|
||||
// on a single port when this is set, the agent ignores PortMin and PortMax configurations and will
|
||||
// defer to UDPMuxSrflx for incoming connections
|
||||
// It embeds UDPMux to do the actual connection multiplexing
|
||||
UDPMuxSrflx UniversalUDPMux
|
||||
|
||||
// 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
|
||||
|
||||
// Deprecated: AcceptAggressiveNomination always enabled.
|
||||
AcceptAggressiveNomination bool
|
||||
|
||||
// Include loopback addresses in the candidate list.
|
||||
IncludeLoopback bool
|
||||
}
|
||||
|
||||
// initWithDefaults populates an agent and falls back to defaults if fields are unset
|
||||
|
@ -200,10 +226,10 @@ func (config *AgentConfig) initWithDefaults(a *Agent) {
|
|||
a.keepaliveInterval = *config.KeepaliveInterval
|
||||
}
|
||||
|
||||
if config.checkInterval == 0 {
|
||||
if config.CheckInterval == nil {
|
||||
a.checkInterval = defaultCheckInterval
|
||||
} else {
|
||||
a.checkInterval = config.checkInterval
|
||||
a.checkInterval = *config.CheckInterval
|
||||
}
|
||||
|
||||
if config.CandidateTypes == nil || len(config.CandidateTypes) == 0 {
|
||||
|
@ -220,7 +246,7 @@ func (config *AgentConfig) initExtIPMapping(a *Agent) error {
|
|||
return err
|
||||
}
|
||||
if a.extIPMapper == nil {
|
||||
return nil // this may happen when config.NAT1To1IPs is an empty array
|
||||
return nil // This may happen when config.NAT1To1IPs is an empty array
|
||||
}
|
||||
if a.extIPMapper.candidateType == CandidateTypeHost {
|
||||
if a.mDNSMode == MulticastDNSModeQueryAndGather {
|
||||
|
|
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_handlers.go
generated
vendored
Normal file
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_handlers.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
// OnConnectionStateChange sets a handler that is fired when the connection state changes
|
||||
func (a *Agent) OnConnectionStateChange(f func(ConnectionState)) error {
|
||||
a.onConnectionStateChangeHdlr.Store(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnSelectedCandidatePairChange sets a handler that is fired when the final candidate
|
||||
// pair is selected
|
||||
func (a *Agent) OnSelectedCandidatePairChange(f func(Candidate, Candidate)) error {
|
||||
a.onSelectedCandidatePairChangeHdlr.Store(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnCandidate sets a handler that is fired when new candidates gathered. When
|
||||
// the gathering process complete the last candidate is nil.
|
||||
func (a *Agent) OnCandidate(f func(Candidate)) error {
|
||||
a.onCandidateHdlr.Store(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) onSelectedCandidatePairChange(p *CandidatePair) {
|
||||
if h, ok := a.onSelectedCandidatePairChangeHdlr.Load().(func(Candidate, Candidate)); ok {
|
||||
h(p.Local, p.Remote)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) onCandidate(c Candidate) {
|
||||
if onCandidateHdlr, ok := a.onCandidateHdlr.Load().(func(Candidate)); ok {
|
||||
onCandidateHdlr(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) onConnectionStateChange(s ConnectionState) {
|
||||
if hdlr, ok := a.onConnectionStateChangeHdlr.Load().(func(ConnectionState)); ok {
|
||||
hdlr(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) candidatePairRoutine() {
|
||||
for p := range a.chanCandidatePair {
|
||||
a.onSelectedCandidatePairChange(p)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) connectionStateRoutine() {
|
||||
for s := range a.chanState {
|
||||
go a.onConnectionStateChange(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) candidateRoutine() {
|
||||
for c := range a.chanCandidate {
|
||||
a.onCandidate(c)
|
||||
}
|
||||
}
|
27
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go
generated
vendored
27
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -13,8 +16,8 @@ func (a *Agent) GetCandidatePairsStats() []CandidatePairStats {
|
|||
for _, cp := range agent.checklist {
|
||||
stat := CandidatePairStats{
|
||||
Timestamp: time.Now(),
|
||||
LocalCandidateID: cp.local.ID(),
|
||||
RemoteCandidateID: cp.remote.ID(),
|
||||
LocalCandidateID: cp.Local.ID(),
|
||||
RemoteCandidateID: cp.Remote.ID(),
|
||||
State: cp.state,
|
||||
Nominated: cp.nominated,
|
||||
// PacketsSent uint32
|
||||
|
@ -45,7 +48,7 @@ func (a *Agent) GetCandidatePairsStats() []CandidatePairStats {
|
|||
res = result
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Errorf("error getting candidate pairs stats %v", err)
|
||||
a.log.Errorf("Failed to get candidate pairs stats: %v", err)
|
||||
return []CandidatePairStats{}
|
||||
}
|
||||
return res
|
||||
|
@ -58,6 +61,12 @@ func (a *Agent) GetLocalCandidatesStats() []CandidateStats {
|
|||
result := make([]CandidateStats, 0, len(agent.localCandidates))
|
||||
for networkType, localCandidates := range agent.localCandidates {
|
||||
for _, c := range localCandidates {
|
||||
relayProtocol := ""
|
||||
if c.Type() == CandidateTypeRelay {
|
||||
if cRelay, ok := c.(*CandidateRelay); ok {
|
||||
relayProtocol = cRelay.RelayProtocol()
|
||||
}
|
||||
}
|
||||
stat := CandidateStats{
|
||||
Timestamp: time.Now(),
|
||||
ID: c.ID(),
|
||||
|
@ -67,7 +76,7 @@ func (a *Agent) GetLocalCandidatesStats() []CandidateStats {
|
|||
CandidateType: c.Type(),
|
||||
Priority: c.Priority(),
|
||||
// URL string
|
||||
RelayProtocol: "udp",
|
||||
RelayProtocol: relayProtocol,
|
||||
// Deleted bool
|
||||
}
|
||||
result = append(result, stat)
|
||||
|
@ -76,7 +85,7 @@ func (a *Agent) GetLocalCandidatesStats() []CandidateStats {
|
|||
res = result
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Errorf("error getting candidate pairs stats %v", err)
|
||||
a.log.Errorf("Failed to get candidate pair stats: %v", err)
|
||||
return []CandidateStats{}
|
||||
}
|
||||
return res
|
||||
|
@ -87,8 +96,8 @@ 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 {
|
||||
for networkType, remoteCandidates := range agent.remoteCandidates {
|
||||
for _, c := range remoteCandidates {
|
||||
stat := CandidateStats{
|
||||
Timestamp: time.Now(),
|
||||
ID: c.ID(),
|
||||
|
@ -98,7 +107,7 @@ func (a *Agent) GetRemoteCandidatesStats() []CandidateStats {
|
|||
CandidateType: c.Type(),
|
||||
Priority: c.Priority(),
|
||||
// URL string
|
||||
RelayProtocol: "udp",
|
||||
RelayProtocol: "",
|
||||
}
|
||||
result = append(result, stat)
|
||||
}
|
||||
|
@ -106,7 +115,7 @@ func (a *Agent) GetRemoteCandidatesStats() []CandidateStats {
|
|||
res = result
|
||||
})
|
||||
if err != nil {
|
||||
a.log.Errorf("error getting candidate pairs stats %v", err)
|
||||
a.log.Errorf("Failed to get candidate pair stats: %v", err)
|
||||
return []CandidateStats{}
|
||||
}
|
||||
return res
|
||||
|
|
4
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate.go
generated
vendored
4
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -62,6 +65,7 @@ type Candidate interface {
|
|||
context() context.Context
|
||||
|
||||
close() error
|
||||
copy() (Candidate, error)
|
||||
seen(outbound bool)
|
||||
start(a *Agent, conn net.PacketConn, initializedCh <-chan struct{})
|
||||
writeTo(raw []byte, dst Candidate) (int, error)
|
||||
|
|
141
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go
generated
vendored
141
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go
generated
vendored
|
@ -1,16 +1,20 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
|
@ -37,6 +41,8 @@ type candidateBase struct {
|
|||
|
||||
foundationOverride string
|
||||
priorityOverride uint32
|
||||
|
||||
remoteCandidateCaches map[AddrPort]Candidate
|
||||
}
|
||||
|
||||
// Done implements context.Context
|
||||
|
@ -60,7 +66,7 @@ func (c *candidateBase) Deadline() (deadline time.Time, ok bool) {
|
|||
}
|
||||
|
||||
// Value implements context.Context
|
||||
func (c *candidateBase) Value(key interface{}) interface{} {
|
||||
func (c *candidateBase) Value(interface{}) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -206,9 +212,9 @@ func (c *candidateBase) start(a *Agent, conn net.PacketConn, initializedCh <-cha
|
|||
}
|
||||
|
||||
func (c *candidateBase) recvLoop(initializedCh <-chan struct{}) {
|
||||
defer func() {
|
||||
close(c.closedCh)
|
||||
}()
|
||||
a := c.agent()
|
||||
|
||||
defer close(c.closedCh)
|
||||
|
||||
select {
|
||||
case <-initializedCh:
|
||||
|
@ -216,47 +222,73 @@ func (c *candidateBase) recvLoop(initializedCh <-chan struct{}) {
|
|||
return
|
||||
}
|
||||
|
||||
log := c.agent().log
|
||||
buffer := make([]byte, receiveMTU)
|
||||
buf := make([]byte, receiveMTU)
|
||||
for {
|
||||
n, srcAddr, err := c.conn.ReadFrom(buffer)
|
||||
n, srcAddr, err := c.conn.ReadFrom(buf)
|
||||
if err != nil {
|
||||
if !(errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed)) {
|
||||
a.log.Warnf("Failed to read from candidate %s: %v", c, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
handleInboundCandidateMsg(c, c, buffer[:n], srcAddr, log)
|
||||
c.handleInboundPacket(buf[:n], srcAddr)
|
||||
}
|
||||
}
|
||||
|
||||
func handleInboundCandidateMsg(ctx context.Context, c Candidate, buffer []byte, srcAddr net.Addr, log logging.LeveledLogger) {
|
||||
if stun.IsMessage(buffer) {
|
||||
func (c *candidateBase) validateSTUNTrafficCache(addr net.Addr) bool {
|
||||
if candidate, ok := c.remoteCandidateCaches[toAddrPort(addr)]; ok {
|
||||
candidate.seen(false)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *candidateBase) addRemoteCandidateCache(candidate Candidate, srcAddr net.Addr) {
|
||||
if c.validateSTUNTrafficCache(srcAddr) {
|
||||
return
|
||||
}
|
||||
c.remoteCandidateCaches[toAddrPort(srcAddr)] = candidate
|
||||
}
|
||||
|
||||
func (c *candidateBase) handleInboundPacket(buf []byte, srcAddr net.Addr) {
|
||||
a := c.agent()
|
||||
|
||||
if stun.IsMessage(buf) {
|
||||
m := &stun.Message{
|
||||
Raw: make([]byte, len(buffer)),
|
||||
Raw: make([]byte, len(buf)),
|
||||
}
|
||||
|
||||
// Explicitly copy raw buffer so Message can own the memory.
|
||||
copy(m.Raw, buffer)
|
||||
copy(m.Raw, buf)
|
||||
|
||||
if err := m.Decode(); err != nil {
|
||||
log.Warnf("Failed to handle decode ICE from %s to %s: %v", c.addr(), srcAddr, err)
|
||||
a.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)
|
||||
|
||||
if err := a.run(c, func(ctx context.Context, a *Agent) {
|
||||
a.handleInbound(m, c, srcAddr)
|
||||
}); err != nil {
|
||||
a.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
|
||||
if !c.validateSTUNTrafficCache(srcAddr) {
|
||||
remoteCandidate, valid := a.validateNonSTUNTraffic(c, srcAddr) //nolint:contextcheck
|
||||
if !valid {
|
||||
a.log.Warnf("Discarded message from %s, not a valid remote candidate", c.addr())
|
||||
return
|
||||
}
|
||||
c.addRemoteCandidateCache(remoteCandidate, srcAddr)
|
||||
}
|
||||
|
||||
// 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")
|
||||
// Note: This will return packetio.ErrFull if the buffer ever manages to fill up.
|
||||
if _, err := a.buf.Write(buf); err != nil {
|
||||
a.log.Warnf("Failed to write packet: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +332,11 @@ func (c *candidateBase) close() error {
|
|||
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)
|
||||
// If the connection is closed, we should return the error
|
||||
if errors.Is(err, io.ErrClosedPipe) {
|
||||
return n, err
|
||||
}
|
||||
c.agent().log.Infof("%s: %v", errSendPacket, err)
|
||||
return n, nil
|
||||
}
|
||||
c.seen(true)
|
||||
|
@ -336,17 +372,16 @@ func (c *candidateBase) Equal(other Candidate) bool {
|
|||
|
||||
// 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)
|
||||
return fmt.Sprintf("%s %s %s%s", c.NetworkType(), c.Type(), net.JoinHostPort(c.Address(), strconv.Itoa(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{}
|
||||
if lastReceived, ok := c.lastReceived.Load().(time.Time); ok {
|
||||
return lastReceived
|
||||
}
|
||||
return lastReceived.(time.Time)
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (c *candidateBase) setLastReceived(t time.Time) {
|
||||
|
@ -356,11 +391,10 @@ func (c *candidateBase) setLastReceived(t time.Time) {
|
|||
// 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{}
|
||||
if lastSent, ok := c.lastSent.Load().(time.Time); ok {
|
||||
return lastSent
|
||||
}
|
||||
return lastSent.(time.Time)
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (c *candidateBase) setLastSent(t time.Time) {
|
||||
|
@ -387,10 +421,19 @@ func (c *candidateBase) context() context.Context {
|
|||
return c
|
||||
}
|
||||
|
||||
func (c *candidateBase) copy() (Candidate, error) {
|
||||
return UnmarshalCandidate(c.Marshal())
|
||||
}
|
||||
|
||||
// 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(),
|
||||
val := c.Foundation()
|
||||
if val == " " {
|
||||
val = ""
|
||||
}
|
||||
|
||||
val = fmt.Sprintf("%s %d %s %d %s %d typ %s",
|
||||
val,
|
||||
c.Component(),
|
||||
c.NetworkType().NetworkShort(),
|
||||
c.Priority(),
|
||||
|
@ -402,11 +445,11 @@ func (c *candidateBase) Marshal() string {
|
|||
val += fmt.Sprintf(" tcptype %s", c.tcpType.String())
|
||||
}
|
||||
|
||||
if c.RelatedAddress() != nil {
|
||||
if r := c.RelatedAddress(); r != nil && r.Address != "" && r.Port != 0 {
|
||||
val = fmt.Sprintf("%s raddr %s rport %d",
|
||||
val,
|
||||
c.RelatedAddress().Address,
|
||||
c.RelatedAddress().Port)
|
||||
r.Address,
|
||||
r.Port)
|
||||
}
|
||||
|
||||
return val
|
||||
|
@ -415,6 +458,10 @@ func (c *candidateBase) Marshal() string {
|
|||
// UnmarshalCandidate creates a Candidate from its string representation
|
||||
func UnmarshalCandidate(raw string) (Candidate, error) {
|
||||
split := strings.Fields(raw)
|
||||
// Foundation not specified: not RFC 8445 compliant but seen in the wild
|
||||
if len(raw) != 0 && raw[0] == ' ' {
|
||||
split = append([]string{" "}, split...)
|
||||
}
|
||||
if len(split) < 8 {
|
||||
return nil, fmt.Errorf("%w (%d)", errAttributeTooShortICECandidate, len(split))
|
||||
}
|
||||
|
@ -425,7 +472,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||
// Component
|
||||
rawComponent, err := strconv.ParseUint(split[1], 10, 16)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParseComponent, err)
|
||||
return nil, fmt.Errorf("%w: %v", errParseComponent, err) //nolint:errorlint
|
||||
}
|
||||
component := uint16(rawComponent)
|
||||
|
||||
|
@ -435,7 +482,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||
// Priority
|
||||
priorityRaw, err := strconv.ParseUint(split[3], 10, 32)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParsePriority, err)
|
||||
return nil, fmt.Errorf("%w: %v", errParsePriority, err) //nolint:errorlint
|
||||
}
|
||||
priority := uint32(priorityRaw)
|
||||
|
||||
|
@ -445,7 +492,7 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||
// Port
|
||||
rawPort, err := strconv.ParseUint(split[5], 10, 16)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParsePort, err)
|
||||
return nil, fmt.Errorf("%w: %v", errParsePort, err) //nolint:errorlint
|
||||
}
|
||||
port := int(rawPort)
|
||||
typ := split[7]
|
||||
|
@ -468,12 +515,12 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||
// RelatedPort
|
||||
rawRelatedPort, parseErr := strconv.ParseUint(split[3], 10, 16)
|
||||
if parseErr != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errParsePort, parseErr)
|
||||
return nil, fmt.Errorf("%w: %v", errParsePort, parseErr) //nolint:errorlint
|
||||
}
|
||||
relatedPort = int(rawRelatedPort)
|
||||
} else if split[0] == "tcptype" {
|
||||
if len(split) < 2 {
|
||||
return nil, fmt.Errorf("%w: incorrect length", errParseTypType)
|
||||
return nil, fmt.Errorf("%w: incorrect length", errParseTCPType)
|
||||
}
|
||||
|
||||
tcpType = NewTCPType(split[1])
|
||||
|
@ -488,9 +535,9 @@ func UnmarshalCandidate(raw string) (Candidate, error) {
|
|||
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})
|
||||
return NewCandidateRelay(&CandidateRelayConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort, "", nil})
|
||||
default:
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w (%s)", errUnknownCandidateTyp, typ)
|
||||
return nil, fmt.Errorf("%w (%s)", ErrUnknownCandidateTyp, typ)
|
||||
}
|
||||
|
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_host.go
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_host.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -34,14 +37,15 @@ func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) {
|
|||
|
||||
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,
|
||||
id: candidateID,
|
||||
address: config.Address,
|
||||
candidateType: CandidateTypeHost,
|
||||
component: config.Component,
|
||||
port: config.Port,
|
||||
tcpType: config.TCPType,
|
||||
foundationOverride: config.Foundation,
|
||||
priorityOverride: config.Priority,
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
network: config.Network,
|
||||
}
|
||||
|
|
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_peer_reflexive.go
generated
vendored
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_peer_reflexive.go
generated
vendored
|
@ -1,4 +1,8 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package ice ...
|
||||
//
|
||||
//nolint:dupl
|
||||
package ice
|
||||
|
||||
|
@ -55,6 +59,7 @@ func NewCandidatePeerReflexive(config *CandidatePeerReflexiveConfig) (*Candidate
|
|||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
49
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_relay.go
generated
vendored
49
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_relay.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -8,21 +11,23 @@ import (
|
|||
type CandidateRelay struct {
|
||||
candidateBase
|
||||
|
||||
onClose func() error
|
||||
relayProtocol string
|
||||
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
|
||||
CandidateID string
|
||||
Network string
|
||||
Address string
|
||||
Port int
|
||||
Component uint16
|
||||
Priority uint32
|
||||
Foundation string
|
||||
RelAddr string
|
||||
RelPort int
|
||||
RelayProtocol string
|
||||
OnClose func() error
|
||||
}
|
||||
|
||||
// NewCandidateRelay creates a new relay candidate
|
||||
|
@ -58,11 +63,18 @@ func NewCandidateRelay(config *CandidateRelayConfig) (*CandidateRelay, error) {
|
|||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
onClose: config.OnClose,
|
||||
relayProtocol: config.RelayProtocol,
|
||||
onClose: config.OnClose,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RelayProtocol returns the protocol used between the endpoint and the relay server.
|
||||
func (c *CandidateRelay) RelayProtocol() string {
|
||||
return c.relayProtocol
|
||||
}
|
||||
|
||||
func (c *CandidateRelay) close() error {
|
||||
err := c.candidateBase.close()
|
||||
if c.onClose != nil {
|
||||
|
@ -71,3 +83,16 @@ func (c *CandidateRelay) close() error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *CandidateRelay) copy() (Candidate, error) {
|
||||
cc, err := c.candidateBase.copy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ccr, ok := cc.(*CandidateRelay); ok {
|
||||
ccr.relayProtocol = c.relayProtocol
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
|
6
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_server_reflexive.go
generated
vendored
6
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_server_reflexive.go
generated
vendored
|
@ -1,5 +1,6 @@
|
|||
// Package ice ...
|
||||
//nolint:dupl
|
||||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import "net"
|
||||
|
@ -54,6 +55,7 @@ func NewCandidateServerReflexive(config *CandidateServerReflexiveConfig) (*Candi
|
|||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go
generated
vendored
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -6,42 +9,44 @@ import (
|
|||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
func newCandidatePair(local, remote Candidate, controlling bool) *candidatePair {
|
||||
return &candidatePair{
|
||||
func newCandidatePair(local, remote Candidate, controlling bool) *CandidatePair {
|
||||
return &CandidatePair{
|
||||
iceRoleControlling: controlling,
|
||||
remote: remote,
|
||||
local: local,
|
||||
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
|
||||
// CandidatePair is a combination of a
|
||||
// local and remote candidate
|
||||
type CandidatePair struct {
|
||||
iceRoleControlling bool
|
||||
Remote Candidate
|
||||
Local Candidate
|
||||
bindingRequestCount uint16
|
||||
state CandidatePairState
|
||||
nominated bool
|
||||
nominateOnBindingSuccess bool
|
||||
}
|
||||
|
||||
func (p *candidatePair) String() string {
|
||||
func (p *CandidatePair) String() string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
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())
|
||||
p.priority(), p.Local.Priority(), p.Local, p.Remote, p.Remote.Priority())
|
||||
}
|
||||
|
||||
func (p *candidatePair) Equal(other *candidatePair) bool {
|
||||
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)
|
||||
return p.Local.Equal(other.Local) && p.Remote.Equal(other.Remote)
|
||||
}
|
||||
|
||||
// RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs
|
||||
|
@ -49,15 +54,14 @@ func (p *candidatePair) Equal(other *candidatePair) bool {
|
|||
// 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
|
||||
func (p *CandidatePair) priority() uint64 {
|
||||
var g, d uint32
|
||||
if p.iceRoleControlling {
|
||||
g = p.local.Priority()
|
||||
d = p.remote.Priority()
|
||||
g = p.Local.Priority()
|
||||
d = p.Remote.Priority()
|
||||
} else {
|
||||
g = p.remote.Priority()
|
||||
d = p.local.Priority()
|
||||
g = p.Remote.Priority()
|
||||
d = p.Local.Priority()
|
||||
}
|
||||
|
||||
// Just implement these here rather
|
||||
|
@ -86,8 +90,8 @@ func (p *candidatePair) Priority() 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 (p *CandidatePair) Write(b []byte) (int, error) {
|
||||
return p.Local.writeTo(b, p.Remote)
|
||||
}
|
||||
|
||||
func (a *Agent) sendSTUN(msg *stun.Message, local, remote Candidate) {
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair_state.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair_state.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
// CandidatePairState represent the ICE candidate pair state
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidaterelatedaddress.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidaterelatedaddress.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import "fmt"
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatetype.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatetype.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
// CandidateType represents the type of candidate
|
||||
|
|
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/codecov.yml
generated
vendored
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/codecov.yml
generated
vendored
|
@ -3,6 +3,8 @@
|
|||
#
|
||||
# It is automatically copied from https://github.com/pion/.goassets repository.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
coverage:
|
||||
status:
|
||||
|
|
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go
generated
vendored
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -32,6 +35,6 @@ func (a agentContext) Deadline() (deadline time.Time, ok bool) {
|
|||
}
|
||||
|
||||
// Value implements context.Context
|
||||
func (a agentContext) Value(key interface{}) interface{} {
|
||||
func (a agentContext) Value(interface{}) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
|
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/errors.go
generated
vendored
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/errors.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import "errors"
|
||||
|
@ -10,7 +13,7 @@ var (
|
|||
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")
|
||||
ErrSTUNQuery = errors.New("queries not supported in STUN address")
|
||||
|
||||
// ErrInvalidQuery indicates an malformed query is provided.
|
||||
ErrInvalidQuery = errors.New("invalid query")
|
||||
|
@ -25,7 +28,7 @@ var (
|
|||
// 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.
|
||||
// ErrLocalPwdInsufficientBits indicates local password insufficient bits are provided.
|
||||
// Have to be at least 128 bits long
|
||||
ErrLocalPwdInsufficientBits = errors.New("local password is less than 128 bits long")
|
||||
|
||||
|
@ -97,36 +100,43 @@ var (
|
|||
// 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")
|
||||
|
||||
// ErrUnknownCandidateTyp indicates that a candidate had a unknown type value.
|
||||
ErrUnknownCandidateTyp = errors.New("unknown candidate typ")
|
||||
|
||||
// ErrDetermineNetworkType indicates that the NetworkType was not able to be parsed
|
||||
ErrDetermineNetworkType = errors.New("unable to determine networkType")
|
||||
|
||||
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")
|
||||
errParseTCPType = errors.New("could not parse TCP type")
|
||||
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")
|
||||
errUDPMuxDisabled = errors.New("UDPMux is not enabled")
|
||||
errNoXorAddrMapping = errors.New("no address mapping")
|
||||
errSendSTUNPacket = errors.New("failed to send STUN packet")
|
||||
errXORMappedAddrTimeout = errors.New("timeout while waiting for XORMappedAddr")
|
||||
errNotImplemented = errors.New("not implemented yet")
|
||||
errNoUDPMuxAvailable = errors.New("no UDP mux is available")
|
||||
errNoTCPMuxAvailable = errors.New("no TCP mux is available")
|
||||
errInvalidAddress = errors.New("invalid address")
|
||||
|
||||
// UDPMuxDefault should not listen on unspecified address, but to keep backward compatibility, don't return error now.
|
||||
// will be used in the future.
|
||||
// errListenUnspecified = errors.New("can't listen on unspecified address")
|
||||
)
|
||||
|
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/external_ip_mapper.go
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/external_ip_mapper.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -15,8 +18,9 @@ func validateIPString(ipStr string) (net.IP, bool, error) {
|
|||
|
||||
// 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)
|
||||
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)
|
||||
valid bool // If not set any external IP, valid is false
|
||||
}
|
||||
|
||||
func (m *ipMapping) setSoleIP(ip net.IP) error {
|
||||
|
@ -25,6 +29,7 @@ func (m *ipMapping) setSoleIP(ip net.IP) error {
|
|||
}
|
||||
|
||||
m.ipSole = ip
|
||||
m.valid = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -36,17 +41,22 @@ func (m *ipMapping) addIPMapping(locIP, extIP net.IP) error {
|
|||
|
||||
locIPStr := locIP.String()
|
||||
|
||||
// check if dup of local IP
|
||||
// Check if dup of local IP
|
||||
if _, ok := m.ipMap[locIPStr]; ok {
|
||||
return ErrInvalidNAT1To1IPMapping
|
||||
}
|
||||
|
||||
m.ipMap[locIPStr] = extIP
|
||||
m.valid = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ipMapping) findExternalIP(locIP net.IP) (net.IP, error) {
|
||||
if !m.valid {
|
||||
return locIP, nil
|
||||
}
|
||||
|
||||
if m.ipSole != nil {
|
||||
return m.ipSole, nil
|
||||
}
|
||||
|
@ -67,10 +77,10 @@ type externalIPMapper struct {
|
|||
|
||||
func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIPMapper, error) { //nolint:gocognit
|
||||
if len(ips) == 0 {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
}
|
||||
if candidateType == CandidateTypeUnspecified {
|
||||
candidateType = CandidateTypeHost // defaults to host
|
||||
candidateType = CandidateTypeHost // Defaults to host
|
||||
} else if candidateType != CandidateTypeHost && candidateType != CandidateTypeServerReflexive {
|
||||
return nil, ErrUnsupportedNAT1To1IPCandidateType
|
||||
}
|
||||
|
|
539
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/gather.go
generated
vendored
539
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/gather.go
generated
vendored
|
@ -1,17 +1,23 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/dtls/v2"
|
||||
"github.com/pion/ice/v2/internal/fakenet"
|
||||
stunx "github.com/pion/ice/v2/internal/stun"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
"github.com/pion/turn/v2"
|
||||
)
|
||||
|
||||
|
@ -19,42 +25,19 @@ 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) {
|
||||
func closeConnAndLog(c io.Closer, log logging.LeveledLogger, msg string, args ...interface{}) {
|
||||
if c == nil || (reflect.ValueOf(c).Kind() == reflect.Ptr && reflect.ValueOf(c).IsNil()) {
|
||||
log.Warnf("Conn is not allocated (%s)", msg)
|
||||
log.Warnf("Connection is not allocated: "+msg, args...)
|
||||
return
|
||||
}
|
||||
|
||||
log.Warnf(msg)
|
||||
if err := c.Close(); err != nil {
|
||||
log.Warnf("Failed to close conn: %v", err)
|
||||
log.Warnf("Failed to close connection: %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
|
||||
|
@ -71,17 +54,20 @@ func (a *Agent) GatherCandidates() error {
|
|||
a.gatherCandidateCancel() // Cancel previous gathering routine
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
a.gatherCandidateCancel = cancel
|
||||
done := make(chan struct{})
|
||||
a.gatherCandidateDone = done
|
||||
|
||||
go a.gatherCandidates(ctx)
|
||||
go a.gatherCandidates(ctx, done)
|
||||
}); 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)
|
||||
func (a *Agent) gatherCandidates(ctx context.Context, done chan struct{}) {
|
||||
defer close(done)
|
||||
if err := a.setGatheringState(GatheringStateGathering); err != nil { //nolint:contextcheck
|
||||
a.log.Warnf("Failed to set gatheringState to GatheringStateGathering: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -97,7 +83,11 @@ func (a *Agent) gatherCandidates(ctx context.Context) {
|
|||
case CandidateTypeServerReflexive:
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
a.gatherCandidatesSrflx(ctx, a.urls, a.networkTypes)
|
||||
if a.udpMuxSrflx != nil {
|
||||
a.gatherCandidatesSrflxUDPMux(ctx, a.urls, a.networkTypes)
|
||||
} else {
|
||||
a.gatherCandidatesSrflx(ctx, a.urls, a.networkTypes)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
if a.extIPMapper != nil && a.extIPMapper.candidateType == CandidateTypeServerReflexive {
|
||||
|
@ -116,11 +106,12 @@ func (a *Agent) gatherCandidates(ctx context.Context) {
|
|||
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)
|
||||
if err := a.setGatheringState(GatheringStateComplete); err != nil { //nolint:contextcheck
|
||||
a.log.Warnf("Failed to set gatheringState to GatheringStateComplete: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,19 +125,27 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ
|
|||
}
|
||||
}
|
||||
|
||||
localIPs, err := localInterfaces(a.net, a.interfaceFilter, networkTypes)
|
||||
// When UDPMux is enabled, skip other UDP candidates
|
||||
if a.udpMux != nil {
|
||||
if err := a.gatherCandidatesLocalUDPMux(ctx); err != nil {
|
||||
a.log.Warnf("Failed to create host candidate for UDPMux: %s", err)
|
||||
}
|
||||
delete(networks, udp)
|
||||
}
|
||||
|
||||
localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, networkTypes, a.includeLoopback)
|
||||
if err != nil {
|
||||
a.log.Warnf("failed to iterate local interfaces, host candidates will not be gathered %s", err)
|
||||
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 {
|
||||
if _mappedIP, innerErr := a.extIPMapper.findExternalIP(ip.String()); innerErr == nil {
|
||||
mappedIP = _mappedIP
|
||||
} else {
|
||||
a.log.Warnf("1:1 NAT mapping is enabled but no external IP is found for %s\n", ip.String())
|
||||
a.log.Warnf("1:1 NAT mapping is enabled but no external IP is found for %s", ip.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,67 +155,168 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ
|
|||
}
|
||||
|
||||
for network := range networks {
|
||||
var port int
|
||||
var conn net.PacketConn
|
||||
var err error
|
||||
type connAndPort struct {
|
||||
conn net.PacketConn
|
||||
port int
|
||||
}
|
||||
var (
|
||||
conns []connAndPort
|
||||
tcpType TCPType
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
if a.tcpMux == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Handle ICE TCP passive mode
|
||||
var muxConns []net.PacketConn
|
||||
if multi, ok := a.tcpMux.(AllConnsGetter); ok {
|
||||
a.log.Debugf("GetAllConns by ufrag: %s", a.localUfrag)
|
||||
muxConns, err = multi.GetAllConns(a.localUfrag, mappedIP.To4() == nil, ip)
|
||||
if err != nil {
|
||||
a.log.Warnf("Failed to get all TCP connections by ufrag: %s %s %s", network, ip, a.localUfrag)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
a.log.Debugf("GetConn by ufrag: %s", a.localUfrag)
|
||||
conn, err := a.tcpMux.GetConnByUfrag(a.localUfrag, mappedIP.To4() == nil, ip)
|
||||
if err != nil {
|
||||
a.log.Warnf("Failed to get TCP connections by ufrag: %s %s %s", network, ip, a.localUfrag)
|
||||
continue
|
||||
}
|
||||
muxConns = []net.PacketConn{conn}
|
||||
}
|
||||
|
||||
// Extract the port for each PacketConn we got.
|
||||
for _, conn := range muxConns {
|
||||
if tcpConn, ok := conn.LocalAddr().(*net.TCPAddr); ok {
|
||||
conns = append(conns, connAndPort{conn, tcpConn.Port})
|
||||
} else {
|
||||
a.log.Warnf("Failed to get port of connection from TCPMux: %s %s %s", network, ip, a.localUfrag)
|
||||
}
|
||||
}
|
||||
if len(conns) == 0 {
|
||||
// Didn't succeed with any, try the next network.
|
||||
continue
|
||||
}
|
||||
port = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
tcpType = TCPTypePassive
|
||||
// is there a way to verify that the listen address is even
|
||||
// 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})
|
||||
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)
|
||||
a.log.Warnf("Failed to listen %s %s", 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))
|
||||
if udpConn, ok := conn.LocalAddr().(*net.UDPAddr); ok {
|
||||
conns = append(conns, connAndPort{conn, udpConn.Port})
|
||||
} else {
|
||||
a.log.Warnf("Failed to get port of UDPAddr from ListenUDPInPortRange: %s %s %s", network, ip, a.localUfrag)
|
||||
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)
|
||||
for _, connAndPort := range conns {
|
||||
hostConfig := CandidateHostConfig{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Port: connAndPort.port,
|
||||
Component: ComponentRTP,
|
||||
TCPType: tcpType,
|
||||
}
|
||||
|
||||
c, err := NewCandidateHost(&hostConfig)
|
||||
if err != nil {
|
||||
closeConnAndLog(connAndPort.conn, a.log, "failed to create host candidate: %s %s %d: %v", network, mappedIP, connAndPort.port, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if a.mDNSMode == MulticastDNSModeQueryAndGather {
|
||||
if err = c.setIP(ip); err != nil {
|
||||
closeConnAndLog(connAndPort.conn, a.log, "failed to create host candidate: %s %s %d: %v", network, mappedIP, connAndPort.port, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err := a.addCandidate(ctx, c, connAndPort.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", err)
|
||||
}
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesLocalUDPMux(ctx context.Context) error { //nolint:gocognit
|
||||
if a.udpMux == nil {
|
||||
return errUDPMuxDisabled
|
||||
}
|
||||
|
||||
localAddresses := a.udpMux.GetListenAddresses()
|
||||
existingConfigs := make(map[CandidateHostConfig]struct{})
|
||||
|
||||
for _, addr := range localAddresses {
|
||||
udpAddr, ok := addr.(*net.UDPAddr)
|
||||
if !ok {
|
||||
return errInvalidAddress
|
||||
}
|
||||
candidateIP := udpAddr.IP
|
||||
if a.extIPMapper != nil && a.extIPMapper.candidateType == CandidateTypeHost {
|
||||
mappedIP, err := a.extIPMapper.findExternalIP(candidateIP.String())
|
||||
if err != nil {
|
||||
a.log.Warnf("1:1 NAT mapping is enabled but no external IP is found for %s", candidateIP.String())
|
||||
continue
|
||||
}
|
||||
|
||||
candidateIP = mappedIP
|
||||
}
|
||||
|
||||
hostConfig := CandidateHostConfig{
|
||||
Network: udp,
|
||||
Address: candidateIP.String(),
|
||||
Port: udpAddr.Port,
|
||||
Component: ComponentRTP,
|
||||
}
|
||||
|
||||
// Detect a duplicate candidate before calling addCandidate().
|
||||
// otherwise, addCandidate() detects the duplicate candidate
|
||||
// and close its connection, invalidating all candidates
|
||||
// that share the same connection.
|
||||
if _, ok := existingConfigs[hostConfig]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
conn, err := a.udpMux.GetConn(a.localUfrag, udpAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := NewCandidateHost(&hostConfig)
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, "failed to create host mux candidate: %s %d: %v", candidateIP, udpAddr.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)
|
||||
}
|
||||
|
||||
closeConnAndLog(conn, a.log, "failed to add candidate: %s %d: %v", candidateIP, udpAddr.Port, err)
|
||||
continue
|
||||
}
|
||||
|
||||
existingConfigs[hostConfig] = struct{}{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes []NetworkType) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
@ -230,34 +330,40 @@ func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes []
|
|||
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})
|
||||
|
||||
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)
|
||||
a.log.Warnf("Failed to listen %s: %v", network, err)
|
||||
return
|
||||
}
|
||||
|
||||
laddr := conn.LocalAddr().(*net.UDPAddr)
|
||||
mappedIP, err := a.extIPMapper.findExternalIP(laddr.IP.String())
|
||||
lAddr, ok := conn.LocalAddr().(*net.UDPAddr)
|
||||
if !ok {
|
||||
closeConnAndLog(conn, a.log, "1:1 NAT mapping is enabled but LocalAddr is not a UDPAddr")
|
||||
return
|
||||
}
|
||||
|
||||
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()))
|
||||
closeConnAndLog(conn, a.log, "1:1 NAT mapping is enabled but no external IP is found for %s", lAddr.IP.String())
|
||||
return
|
||||
}
|
||||
|
||||
srflxConfig := CandidateServerReflexiveConfig{
|
||||
Network: network,
|
||||
Address: mappedIP.String(),
|
||||
Port: laddr.Port,
|
||||
Port: lAddr.Port,
|
||||
Component: ComponentRTP,
|
||||
RelAddr: laddr.IP.String(),
|
||||
RelPort: laddr.Port,
|
||||
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",
|
||||
closeConnAndLog(conn, a.log, "failed to create server reflexive candidate: %s %s %d: %v",
|
||||
network,
|
||||
mappedIP.String(),
|
||||
laddr.Port,
|
||||
err))
|
||||
lAddr.Port,
|
||||
err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -265,13 +371,81 @@ func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes []
|
|||
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)
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkTypes []NetworkType) {
|
||||
func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { //nolint:gocognit
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
for _, networkType := range networkTypes {
|
||||
if networkType.IsTCP() {
|
||||
continue
|
||||
}
|
||||
|
||||
for i := range urls {
|
||||
for _, listenAddr := range a.udpMuxSrflx.GetListenAddresses() {
|
||||
udpAddr, ok := listenAddr.(*net.UDPAddr)
|
||||
if !ok {
|
||||
a.log.Warn("Failed to cast udpMuxSrflx listen address to UDPAddr")
|
||||
continue
|
||||
}
|
||||
wg.Add(1)
|
||||
go func(url stun.URI, network string, localAddr *net.UDPAddr) {
|
||||
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
|
||||
}
|
||||
|
||||
xorAddr, err := a.udpMuxSrflx.GetXORMappedAddr(serverAddr, stunGatherTimeout)
|
||||
if err != nil {
|
||||
a.log.Warnf("Failed get server reflexive address %s %s: %v", network, url, err)
|
||||
return
|
||||
}
|
||||
|
||||
conn, err := a.udpMuxSrflx.GetConnForURL(a.localUfrag, url.String(), localAddr)
|
||||
if err != nil {
|
||||
a.log.Warnf("Failed to find connection in UDPMuxSrflx %s %s: %v", network, url, err)
|
||||
return
|
||||
}
|
||||
|
||||
ip := xorAddr.IP
|
||||
port := xorAddr.Port
|
||||
|
||||
srflxConfig := CandidateServerReflexiveConfig{
|
||||
Network: network,
|
||||
Address: ip.String(),
|
||||
Port: port,
|
||||
Component: ComponentRTP,
|
||||
RelAddr: localAddr.IP.String(),
|
||||
RelPort: localAddr.Port,
|
||||
}
|
||||
c, err := NewCandidateServerReflexive(&srflxConfig)
|
||||
if err != nil {
|
||||
closeConnAndLog(conn, a.log, "failed to create server reflexive candidate: %s %s %d: %v", 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", err)
|
||||
}
|
||||
}(*urls[i], networkType.String(), udpAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { //nolint:gocognit
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
|
@ -282,42 +456,55 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkT
|
|||
|
||||
for i := range urls {
|
||||
wg.Add(1)
|
||||
go func(url URL, network string) {
|
||||
go func(url stun.URI, 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)
|
||||
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})
|
||||
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))
|
||||
closeConnAndLog(conn, a.log, "failed to listen for %s: %v", serverAddr.String(), err)
|
||||
return
|
||||
}
|
||||
// If the agent closes midway through the connection
|
||||
// we end it early to prevent close delay.
|
||||
cancelCtx, cancelFunc := context.WithCancel(ctx)
|
||||
defer cancelFunc()
|
||||
go func() {
|
||||
select {
|
||||
case <-cancelCtx.Done():
|
||||
return
|
||||
case <-a.done:
|
||||
_ = conn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
xoraddr, err := getXORMappedAddr(conn, serverAddr, stunGatherTimeout)
|
||||
xorAddr, err := stunx.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))
|
||||
closeConnAndLog(conn, a.log, "failed to get server reflexive address %s %s: %v", network, url, err)
|
||||
return
|
||||
}
|
||||
|
||||
ip := xoraddr.IP
|
||||
port := xoraddr.Port
|
||||
ip := xorAddr.IP
|
||||
port := xorAddr.Port
|
||||
|
||||
laddr := conn.LocalAddr().(*net.UDPAddr)
|
||||
lAddr := conn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert
|
||||
srflxConfig := CandidateServerReflexiveConfig{
|
||||
Network: network,
|
||||
Address: ip.String(),
|
||||
Port: port,
|
||||
Component: ComponentRTP,
|
||||
RelAddr: laddr.IP.String(),
|
||||
RelPort: laddr.Port,
|
||||
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))
|
||||
closeConnAndLog(conn, a.log, "failed to create server reflexive candidate: %s %s %d: %v", network, ip, port, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -325,21 +512,21 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkT
|
|||
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)
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v", err)
|
||||
}
|
||||
}(*urls[i], networkType.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //nolint:gocognit
|
||||
func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { //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:
|
||||
case urls[i].Scheme != stun.SchemeTypeTURN && urls[i].Scheme != stun.SchemeTypeTURNS:
|
||||
continue
|
||||
case urls[i].Username == "":
|
||||
a.log.Errorf("Failed to gather relay candidates: %v", ErrUsernameEmpty)
|
||||
|
@ -350,89 +537,124 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
|
|||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(url URL) {
|
||||
go func(url stun.URI) {
|
||||
defer wg.Done()
|
||||
TURNServerAddr := fmt.Sprintf("%s:%d", url.Host, url.Port)
|
||||
turnServerAddr := fmt.Sprintf("%s:%d", url.Host, url.Port)
|
||||
var (
|
||||
locConn net.PacketConn
|
||||
err error
|
||||
RelAddr string
|
||||
RelPort int
|
||||
locConn net.PacketConn
|
||||
err error
|
||||
relAddr string
|
||||
relPort int
|
||||
relayProtocol string
|
||||
)
|
||||
|
||||
switch {
|
||||
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURN:
|
||||
case url.Proto == stun.ProtoTypeUDP && url.Scheme == stun.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)
|
||||
a.log.Warnf("Failed to listen %s: %v", 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)
|
||||
relAddr = locConn.LocalAddr().(*net.UDPAddr).IP.String() //nolint:forcetypeassert
|
||||
relPort = locConn.LocalAddr().(*net.UDPAddr).Port //nolint:forcetypeassert
|
||||
relayProtocol = udp
|
||||
case a.proxyDialer != nil && url.Proto == stun.ProtoTypeTCP &&
|
||||
(url.Scheme == stun.SchemeTypeTURN || url.Scheme == stun.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)
|
||||
a.log.Warnf("Failed to dial TCP address %s via proxy dialer: %v", turnServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
RelAddr = conn.LocalAddr().(*net.TCPAddr).IP.String()
|
||||
RelPort = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
relAddr = conn.LocalAddr().(*net.TCPAddr).IP.String() //nolint:forcetypeassert
|
||||
relPort = conn.LocalAddr().(*net.TCPAddr).Port //nolint:forcetypeassert
|
||||
if url.Scheme == stun.SchemeTypeTURN {
|
||||
relayProtocol = tcp
|
||||
} else if url.Scheme == stun.SchemeTypeTURNS {
|
||||
relayProtocol = "tls"
|
||||
}
|
||||
locConn = turn.NewSTUNConn(conn)
|
||||
|
||||
case url.Proto == ProtoTypeTCP && url.Scheme == SchemeTypeTURN:
|
||||
tcpAddr, connectErr := net.ResolveTCPAddr(NetworkTypeTCP4.String(), TURNServerAddr)
|
||||
case url.Proto == stun.ProtoTypeTCP && url.Scheme == stun.SchemeTypeTURN:
|
||||
tcpAddr, connectErr := a.net.ResolveTCPAddr(NetworkTypeTCP4.String(), turnServerAddr)
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to resolve TCP Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
a.log.Warnf("Failed to resolve TCP address %s: %v", turnServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
conn, connectErr := net.DialTCP(NetworkTypeTCP4.String(), nil, tcpAddr)
|
||||
conn, connectErr := a.net.DialTCP(NetworkTypeTCP4.String(), nil, tcpAddr)
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to Dial TCP Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
a.log.Warnf("Failed to dial TCP address %s: %v", turnServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
RelAddr = conn.LocalAddr().(*net.TCPAddr).IP.String()
|
||||
RelPort = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
relAddr = conn.LocalAddr().(*net.TCPAddr).IP.String() //nolint:forcetypeassert
|
||||
relPort = conn.LocalAddr().(*net.TCPAddr).Port //nolint:forcetypeassert
|
||||
relayProtocol = tcp
|
||||
locConn = turn.NewSTUNConn(conn)
|
||||
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURNS:
|
||||
udpAddr, connectErr := net.ResolveUDPAddr(network, TURNServerAddr)
|
||||
case url.Proto == stun.ProtoTypeUDP && url.Scheme == stun.SchemeTypeTURNS:
|
||||
udpAddr, connectErr := a.net.ResolveUDPAddr(network, turnServerAddr)
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to resolve UDP Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
a.log.Warnf("Failed to resolve UDP address %s: %v", turnServerAddr, connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
conn, connectErr := dtls.Dial(network, udpAddr, &dtls.Config{
|
||||
udpConn, dialErr := a.net.DialUDP("udp", nil, udpAddr)
|
||||
if dialErr != nil {
|
||||
a.log.Warnf("Failed to dial DTLS address %s: %v", turnServerAddr, dialErr)
|
||||
return
|
||||
}
|
||||
|
||||
conn, connectErr := dtls.ClientWithContext(ctx, udpConn, &dtls.Config{
|
||||
ServerName: url.Host,
|
||||
InsecureSkipVerify: a.insecureSkipVerify, //nolint:gosec
|
||||
})
|
||||
if connectErr != nil {
|
||||
a.log.Warnf("Failed to Dial DTLS Addr %s: %v\n", TURNServerAddr, connectErr)
|
||||
a.log.Warnf("Failed to create DTLS client: %v", 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)
|
||||
relAddr = conn.LocalAddr().(*net.UDPAddr).IP.String() //nolint:forcetypeassert
|
||||
relPort = conn.LocalAddr().(*net.UDPAddr).Port //nolint:forcetypeassert
|
||||
relayProtocol = "dtls"
|
||||
locConn = &fakenet.PacketConn{Conn: conn}
|
||||
case url.Proto == stun.ProtoTypeTCP && url.Scheme == stun.SchemeTypeTURNS:
|
||||
tcpAddr, resolvErr := a.net.ResolveTCPAddr(NetworkTypeTCP4.String(), turnServerAddr)
|
||||
if resolvErr != nil {
|
||||
a.log.Warnf("Failed to resolve relay address %s: %v", turnServerAddr, resolvErr)
|
||||
return
|
||||
}
|
||||
RelAddr = conn.LocalAddr().(*net.TCPAddr).IP.String()
|
||||
RelPort = conn.LocalAddr().(*net.TCPAddr).Port
|
||||
|
||||
tcpConn, dialErr := a.net.DialTCP(NetworkTypeTCP4.String(), nil, tcpAddr)
|
||||
if dialErr != nil {
|
||||
a.log.Warnf("Failed to connect to relay: %v", dialErr)
|
||||
return
|
||||
}
|
||||
|
||||
conn := tls.Client(tcpConn, &tls.Config{
|
||||
ServerName: url.Host,
|
||||
InsecureSkipVerify: a.insecureSkipVerify, //nolint:gosec
|
||||
})
|
||||
|
||||
if hsErr := conn.HandshakeContext(ctx); hsErr != nil {
|
||||
if closeErr := tcpConn.Close(); closeErr != nil {
|
||||
a.log.Errorf("Failed to close relay connection: %v", closeErr)
|
||||
}
|
||||
a.log.Warnf("Failed to connect to relay: %v", hsErr)
|
||||
return
|
||||
}
|
||||
|
||||
relAddr = conn.LocalAddr().(*net.TCPAddr).IP.String() //nolint:forcetypeassert
|
||||
relPort = conn.LocalAddr().(*net.TCPAddr).Port //nolint:forcetypeassert
|
||||
relayProtocol = "tls"
|
||||
locConn = turn.NewSTUNConn(conn)
|
||||
default:
|
||||
a.log.Warnf("Unable to handle URL in gatherCandidatesRelay %v\n", url)
|
||||
a.log.Warnf("Unable to handle URL in gatherCandidatesRelay %v", url)
|
||||
return
|
||||
}
|
||||
|
||||
client, err := turn.NewClient(&turn.ClientConfig{
|
||||
TURNServerAddr: TURNServerAddr,
|
||||
TURNServerAddr: turnServerAddr,
|
||||
Conn: locConn,
|
||||
Username: url.Username,
|
||||
Password: url.Password,
|
||||
|
@ -440,31 +662,32 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
|
|||
Net: a.net,
|
||||
})
|
||||
if err != nil {
|
||||
closeConnAndLog(locConn, a.log, fmt.Sprintf("Failed to build new turn.Client %s %s\n", TURNServerAddr, err))
|
||||
closeConnAndLog(locConn, a.log, "failed to create new TURN client %s %s", 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))
|
||||
closeConnAndLog(locConn, a.log, "failed to listen on TURN client %s %s", 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))
|
||||
closeConnAndLog(locConn, a.log, "failed to allocate on TURN client %s %s", turnServerAddr, err)
|
||||
return
|
||||
}
|
||||
|
||||
raddr := relayConn.LocalAddr().(*net.UDPAddr)
|
||||
rAddr := relayConn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert
|
||||
relayConfig := CandidateRelayConfig{
|
||||
Network: network,
|
||||
Component: ComponentRTP,
|
||||
Address: raddr.IP.String(),
|
||||
Port: raddr.Port,
|
||||
RelAddr: RelAddr,
|
||||
RelPort: RelPort,
|
||||
Network: network,
|
||||
Component: ComponentRTP,
|
||||
Address: rAddr.IP.String(),
|
||||
Port: rAddr.Port,
|
||||
RelAddr: relAddr,
|
||||
RelPort: relPort,
|
||||
RelayProtocol: relayProtocol,
|
||||
OnClose: func() error {
|
||||
client.Close()
|
||||
return locConn.Close()
|
||||
|
@ -480,7 +703,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
|
|||
relayConnClose()
|
||||
|
||||
client.Close()
|
||||
closeConnAndLog(locConn, a.log, fmt.Sprintf("Failed to create relay candidate: %s %s: %v\n", network, raddr.String(), err))
|
||||
closeConnAndLog(locConn, a.log, "failed to create relay candidate: %s %s: %v", network, rAddr.String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -490,7 +713,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
|
|||
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)
|
||||
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v", err)
|
||||
}
|
||||
}(*urls[i])
|
||||
}
|
||||
|
|
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/go.mod
generated
vendored
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/go.mod
generated
vendored
|
@ -1,16 +0,0 @@
|
|||
module github.com/pion/ice/v2
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.1.5
|
||||
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.1
|
||||
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
60
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/go.sum
generated
vendored
|
@ -1,60 +0,0 @@
|
|||
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.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I=
|
||||
github.com/google/uuid v1.1.5/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.1 h1:6v8lxQGVZpwSICEZjhl/CCv6aErINZlrm3O5ncFXj/c=
|
||||
github.com/pion/transport v0.12.1/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=
|
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/ice.go
generated
vendored
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/ice.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
// ConnectionState is an enum showing the state of a ICE Connection
|
||||
|
@ -5,8 +8,11 @@ type ConnectionState int
|
|||
|
||||
// List of supported States
|
||||
const (
|
||||
// ConnectionStateUnknown represents an unknown state
|
||||
ConnectionStateUnknown ConnectionState = iota
|
||||
|
||||
// ConnectionStateNew ICE agent is gathering addresses
|
||||
ConnectionStateNew = iota + 1
|
||||
ConnectionStateNew
|
||||
|
||||
// ConnectionStateChecking ICE agent has been given local and remote candidates, and is attempting to find a match
|
||||
ConnectionStateChecking
|
||||
|
@ -52,13 +58,16 @@ func (c ConnectionState) String() string {
|
|||
type GatheringState int
|
||||
|
||||
const (
|
||||
// GatheringStateNew indicates candidate gatering is not yet started
|
||||
GatheringStateNew GatheringState = iota + 1
|
||||
// GatheringStateUnknown represents an unknown state
|
||||
GatheringStateUnknown GatheringState = iota
|
||||
|
||||
// GatheringStateGathering indicates candidate gatering is ongoing
|
||||
// GatheringStateNew indicates candidate gathering is not yet started
|
||||
GatheringStateNew
|
||||
|
||||
// GatheringStateGathering indicates candidate gathering is ongoing
|
||||
GatheringStateGathering
|
||||
|
||||
// GatheringStateComplete indicates candidate gatering has been completed
|
||||
// GatheringStateComplete indicates candidate gathering has been completed
|
||||
GatheringStateComplete
|
||||
)
|
||||
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/icecontrol.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/icecontrol.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
|
23
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/atomic/atomic.go
generated
vendored
Normal file
23
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/atomic/atomic.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package atomic contains custom atomic types
|
||||
package atomic
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// Error is an atomic error
|
||||
type Error struct {
|
||||
v atomic.Value
|
||||
}
|
||||
|
||||
// Store updates the value of the atomic variable
|
||||
func (a *Error) Store(err error) {
|
||||
a.v.Store(struct{ error }{err})
|
||||
}
|
||||
|
||||
// Load retrieves the current value of the atomic variable
|
||||
func (a *Error) Load() error {
|
||||
err, _ := a.v.Load().(struct{ error })
|
||||
return err.error
|
||||
}
|
23
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/mock_conn.go
generated
vendored
Normal file
23
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/mock_conn.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build !js
|
||||
// +build !js
|
||||
|
||||
package fakenet
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MockPacketConn for tests
|
||||
type MockPacketConn struct{}
|
||||
|
||||
func (m *MockPacketConn) ReadFrom([]byte) (n int, addr net.Addr, err error) { return 0, nil, nil } //nolint:revive
|
||||
func (m *MockPacketConn) WriteTo([]byte, net.Addr) (n int, err error) { return 0, nil } //nolint:revive
|
||||
func (m *MockPacketConn) Close() error { return nil } //nolint:revive
|
||||
func (m *MockPacketConn) LocalAddr() net.Addr { return nil } //nolint:revive
|
||||
func (m *MockPacketConn) SetDeadline(time.Time) error { return nil } //nolint:revive
|
||||
func (m *MockPacketConn) SetReadDeadline(time.Time) error { return nil } //nolint:revive
|
||||
func (m *MockPacketConn) SetWriteDeadline(time.Time) error { return nil } //nolint:revive
|
29
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/packet_conn.go
generated
vendored
Normal file
29
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/packet_conn.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package fakenet contains fake network abstractions
|
||||
package fakenet
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// Compile-time assertion
|
||||
var _ net.PacketConn = (*PacketConn)(nil)
|
||||
|
||||
// PacketConn wraps a net.Conn and emulates net.PacketConn
|
||||
type PacketConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
// ReadFrom reads a packet from the connection,
|
||||
func (f *PacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
n, err = f.Conn.Read(p)
|
||||
addr = f.Conn.RemoteAddr()
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTo writes a packet with payload p to addr.
|
||||
func (f *PacketConn) WriteTo(p []byte, _ net.Addr) (int, error) {
|
||||
return f.Conn.Write(p)
|
||||
}
|
72
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/stun/stun.go
generated
vendored
Normal file
72
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/stun/stun.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Package stun contains ICE specific STUN code
|
||||
package stun
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
var (
|
||||
errGetXorMappedAddrResponse = errors.New("failed to get XOR-MAPPED-ADDRESS response")
|
||||
errMismatchUsername = errors.New("username mismatch")
|
||||
)
|
||||
|
||||
// GetXORMappedAddr initiates a STUN requests to serverAddr using conn, reads the response and returns
|
||||
// the XORMappedAddress returned by the STUN server.
|
||||
func GetXORMappedAddr(conn net.PacketConn, serverAddr net.Addr, timeout time.Duration) (*stun.XORMappedAddress, error) {
|
||||
if timeout > 0 {
|
||||
if err := conn.SetReadDeadline(time.Now().Add(timeout)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Reset timeout after completion
|
||||
defer conn.SetReadDeadline(time.Time{}) //nolint:errcheck
|
||||
}
|
||||
|
||||
req, err := stun.Build(stun.BindingRequest, stun.TransactionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = conn.WriteTo(req.Raw, serverAddr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
const maxMessageSize = 1280
|
||||
buf := make([]byte, maxMessageSize)
|
||||
n, _, err := conn.ReadFrom(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &stun.Message{Raw: buf[:n]}
|
||||
if err = res.Decode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var addr stun.XORMappedAddress
|
||||
if err = addr.GetFrom(res); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errGetXorMappedAddrResponse, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
return &addr, nil
|
||||
}
|
||||
|
||||
// AssertUsername checks that the given STUN message m has a USERNAME attribute with a given value
|
||||
func AssertUsername(m *stun.Message, expectedUsername string) error {
|
||||
var username stun.Username
|
||||
if err := username.GetFrom(m); err != nil {
|
||||
return err
|
||||
} else if string(username) != expectedUsername {
|
||||
return fmt.Errorf("%w expected(%x) actual(%x)", errMismatchUsername, expectedUsername, string(username))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
12
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go
generated
vendored
12
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go
generated
vendored
|
@ -1,11 +1,13 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/mdns"
|
||||
"github.com/pion/transport/v2"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
|
@ -31,17 +33,17 @@ func generateMulticastDNSName() (string, error) {
|
|||
return u.String() + ".local", err
|
||||
}
|
||||
|
||||
func createMulticastDNS(mDNSMode MulticastDNSMode, mDNSName string, log logging.LeveledLogger) (*mdns.Conn, MulticastDNSMode, error) {
|
||||
func createMulticastDNS(n transport.Net, 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)
|
||||
addr, mdnsErr := n.ResolveUDPAddr("udp4", mdns.DefaultAddress)
|
||||
if mdnsErr != nil {
|
||||
return nil, mDNSMode, mdnsErr
|
||||
}
|
||||
|
||||
l, mdnsErr := net.ListenUDP("udp4", addr)
|
||||
l, mdnsErr := n.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)
|
||||
|
|
137
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/net.go
generated
vendored
Normal file
137
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/net.go
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/transport/v2"
|
||||
)
|
||||
|
||||
// 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 localInterfaces(n transport.Net, interfaceFilter func(string) bool, ipFilter func(net.IP) bool, networkTypes []NetworkType, includeLoopback bool) ([]net.IP, error) { //nolint:gocognit
|
||||
ips := []net.IP{}
|
||||
ifaces, err := n.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) && !includeLoopback {
|
||||
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() && !includeLoopback) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipv4 := ip.To4(); ipv4 == nil {
|
||||
if !IPv6Requested {
|
||||
continue
|
||||
} else if !isSupportedIPv6(ip) {
|
||||
continue
|
||||
}
|
||||
} else if !IPv4Requested {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipFilter != nil && !ipFilter(ip) {
|
||||
continue
|
||||
}
|
||||
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func listenUDPInPortRange(n transport.Net, log logging.LeveledLogger, portMax, portMin int, network string, lAddr *net.UDPAddr) (transport.UDPConn, error) {
|
||||
if (lAddr.Port != 0) || ((portMin == 0) && (portMax == 0)) {
|
||||
return n.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 := n.ListenUDP(network, lAddr)
|
||||
if e == nil {
|
||||
return c, e //nolint:nilerr
|
||||
}
|
||||
log.Debugf("Failed to listen %s: %v", lAddr.String(), e)
|
||||
portCurrent++
|
||||
if portCurrent > j {
|
||||
portCurrent = i
|
||||
}
|
||||
if portCurrent == portStart {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, ErrPort
|
||||
}
|
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/networktype.go
generated
vendored
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/networktype.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -7,8 +10,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
udp = "udp"
|
||||
tcp = "tcp"
|
||||
udp = "udp"
|
||||
tcp = "tcp"
|
||||
udp4 = "udp4"
|
||||
udp6 = "udp6"
|
||||
tcp4 = "tcp4"
|
||||
tcp6 = "tcp6"
|
||||
)
|
||||
|
||||
func supportedNetworkTypes() []NetworkType {
|
||||
|
@ -40,13 +47,13 @@ const (
|
|||
func (t NetworkType) String() string {
|
||||
switch t {
|
||||
case NetworkTypeUDP4:
|
||||
return "udp4"
|
||||
return udp4
|
||||
case NetworkTypeUDP6:
|
||||
return "udp6"
|
||||
return udp6
|
||||
case NetworkTypeTCP4:
|
||||
return "tcp4"
|
||||
return tcp4
|
||||
case NetworkTypeTCP6:
|
||||
return "tcp6"
|
||||
return tcp6
|
||||
default:
|
||||
return ErrUnknownType.Error()
|
||||
}
|
||||
|
@ -126,5 +133,5 @@ func determineNetworkType(network string, ip net.IP) (NetworkType, error) {
|
|||
return NetworkTypeTCP6, nil
|
||||
}
|
||||
|
||||
return NetworkType(0), fmt.Errorf("%w from %s %s", errDetermineNetworkType, network, ip)
|
||||
return NetworkType(0), fmt.Errorf("%w from %s %s", ErrDetermineNetworkType, network, ip)
|
||||
}
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/priority.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/priority.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/rand.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/rand.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import "github.com/pion/randutil"
|
||||
|
|
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/renovate.json
generated
vendored
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/renovate.json
generated
vendored
|
@ -1,15 +1,6 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
],
|
||||
"commitBody": "Generated by renovateBot",
|
||||
"packageRules": [
|
||||
{
|
||||
"packagePatterns": ["^golang.org/x/"],
|
||||
"schedule": ["on the first day of the month"]
|
||||
}
|
||||
"github>pion/renovate-config"
|
||||
]
|
||||
}
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/role.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/role.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
|
64
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/selection.go
generated
vendored
64
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/selection.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -19,7 +22,7 @@ type pairCandidateSelector interface {
|
|||
type controllingSelector struct {
|
||||
startTime time.Time
|
||||
agent *Agent
|
||||
nominatedPair *candidatePair
|
||||
nominatedPair *CandidatePair
|
||||
log logging.LeveledLogger
|
||||
}
|
||||
|
||||
|
@ -40,7 +43,7 @@ func (s *controllingSelector) isNominatable(c Candidate) bool {
|
|||
return time.Since(s.startTime).Nanoseconds() > s.agent.relayAcceptanceMinWait.Nanoseconds()
|
||||
}
|
||||
|
||||
s.log.Errorf("isNominatable invalid candidate type %s", c.Type().String())
|
||||
s.log.Errorf("Invalid candidate type: %s", c.Type())
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -55,8 +58,8 @@ func (s *controllingSelector) ContactCandidates() {
|
|||
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())
|
||||
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)
|
||||
|
@ -66,7 +69,7 @@ func (s *controllingSelector) ContactCandidates() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *controllingSelector) nominatePair(pair *candidatePair) {
|
||||
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
|
||||
|
@ -75,7 +78,7 @@ func (s *controllingSelector) nominatePair(pair *candidatePair) {
|
|||
stun.NewUsername(s.agent.remoteUfrag+":"+s.agent.localUfrag),
|
||||
UseCandidate(),
|
||||
AttrControlling(s.agent.tieBreaker),
|
||||
PriorityAttr(pair.local.Priority()),
|
||||
PriorityAttr(pair.Local.Priority()),
|
||||
stun.NewShortTermIntegrity(s.agent.remotePwd),
|
||||
stun.Fingerprint,
|
||||
)
|
||||
|
@ -84,8 +87,8 @@ func (s *controllingSelector) nominatePair(pair *candidatePair) {
|
|||
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)
|
||||
s.log.Tracef("ping STUN (nominate candidate pair) from %s to %s", pair.Local.String(), pair.Remote.String())
|
||||
s.agent.sendBindingRequest(msg, pair.Local, pair.Remote)
|
||||
}
|
||||
|
||||
func (s *controllingSelector) HandleBindingRequest(m *stun.Message, local, remote Candidate) {
|
||||
|
@ -101,10 +104,10 @@ func (s *controllingSelector) HandleBindingRequest(m *stun.Message, local, remot
|
|||
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.log.Tracef("No best pair available")
|
||||
} 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",
|
||||
p.Local.String(), p.Remote.String())
|
||||
s.nominatedPair = p
|
||||
s.nominatePair(p)
|
||||
}
|
||||
|
@ -114,7 +117,7 @@ func (s *controllingSelector) HandleBindingRequest(m *stun.Message, local, remot
|
|||
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)
|
||||
s.log.Warnf("Discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -123,7 +126,7 @@ func (s *controllingSelector) HandleSuccessResponse(m *stun.Message, local, remo
|
|||
// 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)
|
||||
s.log.Debugf("Discard message: transaction source and destination does not match expected(%s), actual(%s)", transactionAddr, remote)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -195,7 +198,7 @@ func (s *controlledSelector) PingCandidate(local, remote Candidate) {
|
|||
}
|
||||
|
||||
func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr) {
|
||||
// nolint:godox
|
||||
//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
|
||||
|
@ -205,7 +208,7 @@ func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remot
|
|||
|
||||
ok, pendingRequest := s.agent.handleInboundBindingSuccess(m.TransactionID)
|
||||
if !ok {
|
||||
s.log.Warnf("discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID)
|
||||
s.log.Warnf("Discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -214,7 +217,7 @@ func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remot
|
|||
// 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)
|
||||
s.log.Debugf("Discard message: transaction source and destination does not match expected(%s), actual(%s)", transactionAddr, remote)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -229,13 +232,20 @@ func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remot
|
|||
|
||||
p.state = CandidatePairStateSucceeded
|
||||
s.log.Tracef("Found valid candidate pair: %s", p)
|
||||
if p.nominateOnBindingSuccess {
|
||||
if selectedPair := s.agent.getSelectedPair(); selectedPair == nil ||
|
||||
(selectedPair != p && selectedPair.priority() <= p.priority()) {
|
||||
s.agent.setSelectedPair(p)
|
||||
} else if selectedPair != p {
|
||||
s.log.Tracef("ignore nominate new pair %s, already nominated pair %s", p, selectedPair)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -248,10 +258,12 @@ func (s *controlledSelector) HandleBindingRequest(m *stun.Message, local, remote
|
|||
// 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 {
|
||||
if selectedPair := s.agent.getSelectedPair(); selectedPair == nil ||
|
||||
(selectedPair != p && selectedPair.priority() <= p.priority()) {
|
||||
s.agent.setSelectedPair(p)
|
||||
} else if selectedPair != p {
|
||||
s.log.Tracef("ignore nominate new pair %s, already nominated pair %s", p, selectedPair)
|
||||
}
|
||||
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
|
||||
|
@ -261,12 +273,12 @@ func (s *controlledSelector) HandleBindingRequest(m *stun.Message, local, remote
|
|||
// 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)
|
||||
p.nominateOnBindingSuccess = true
|
||||
}
|
||||
} else {
|
||||
s.agent.sendBindingSuccess(m, local, remote)
|
||||
s.PingCandidate(local, remote)
|
||||
}
|
||||
|
||||
s.agent.sendBindingSuccess(m, local, remote)
|
||||
s.PingCandidate(local, remote)
|
||||
}
|
||||
|
||||
type liteSelector struct {
|
||||
|
@ -276,8 +288,8 @@ type liteSelector struct {
|
|||
// A lite selector should not contact candidates
|
||||
func (s *liteSelector) ContactCandidates() {
|
||||
if _, ok := s.pairCandidateSelector.(*controllingSelector); ok {
|
||||
// nolint:godox
|
||||
// pion/ice#96
|
||||
//nolint:godox
|
||||
// https://github.com/pion/ice/issues/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()
|
||||
|
|
7
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stats.go
generated
vendored
7
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stats.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -104,7 +107,7 @@ type CandidatePairStats struct {
|
|||
// ResponsesReceived represents the total number of connectivity check responses received.
|
||||
ResponsesReceived uint64
|
||||
|
||||
// ResponsesSent epresents the total number of connectivity check responses sent.
|
||||
// ResponsesSent represents the total number of connectivity check responses sent.
|
||||
// Since we cannot distinguish connectivity check requests and consent requests,
|
||||
// all responses are counted.
|
||||
ResponsesSent uint64
|
||||
|
@ -164,7 +167,7 @@ type CandidateStats struct {
|
|||
|
||||
// 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.
|
||||
// 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,
|
||||
|
|
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stun.go
generated
vendored
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stun.go
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
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)
|
||||
}
|
245
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux.go
generated
vendored
245
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux.go
generated
vendored
|
@ -1,7 +1,11 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
|
@ -11,38 +15,19 @@ import (
|
|||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
// ErrGetTransportAddress can't convert net.Addr to underlying type (UDPAddr or TCPAddr).
|
||||
var ErrGetTransportAddress = errors.New("failed to get local transport address")
|
||||
|
||||
// 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.
|
||||
// interface exists to allow mocking in tests.
|
||||
type TCPMux interface {
|
||||
io.Closer
|
||||
GetConnByUfrag(ufrag string) (net.PacketConn, error)
|
||||
GetConnByUfrag(ufrag string, isIPv6 bool, local net.IP) (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) {}
|
||||
type ipAddr string
|
||||
|
||||
// TCPMuxDefault muxes TCP net.Conns into net.PacketConns and groups them by
|
||||
// Ufrag. It is a default implementation of TCPMux interface.
|
||||
|
@ -50,8 +35,8 @@ type TCPMuxDefault struct {
|
|||
params *TCPMuxParams
|
||||
closed bool
|
||||
|
||||
// conns is a map of all tcpPacketConns indexed by ufrag
|
||||
conns map[string]*tcpPacketConn
|
||||
// connsIPv4 and connsIPv6 are maps of all tcpPacketConns indexed by ufrag and local address
|
||||
connsIPv4, connsIPv6 map[string]map[ipAddr]*tcpPacketConn
|
||||
|
||||
mu sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
|
@ -62,6 +47,11 @@ type TCPMuxParams struct {
|
|||
Listener net.Listener
|
||||
Logger logging.LeveledLogger
|
||||
ReadBufferSize int
|
||||
|
||||
// Maximum buffer size for write op. 0 means no write buffer, the write op will block until the whole packet is written
|
||||
// if the write buffer is full, the subsequent write packet will be dropped until it has enough space.
|
||||
// a default 4MB is recommended.
|
||||
WriteBufferSize int
|
||||
}
|
||||
|
||||
// NewTCPMuxDefault creates a new instance of TCPMuxDefault.
|
||||
|
@ -73,7 +63,8 @@ func NewTCPMuxDefault(params TCPMuxParams) *TCPMuxDefault {
|
|||
m := &TCPMuxDefault{
|
||||
params: ¶ms,
|
||||
|
||||
conns: map[string]*tcpPacketConn{},
|
||||
connsIPv4: map[string]map[ipAddr]*tcpPacketConn{},
|
||||
connsIPv6: map[string]map[ipAddr]*tcpPacketConn{},
|
||||
}
|
||||
|
||||
m.wg.Add(1)
|
||||
|
@ -86,11 +77,11 @@ func NewTCPMuxDefault(params TCPMuxParams) *TCPMuxDefault {
|
|||
}
|
||||
|
||||
func (m *TCPMuxDefault) start() {
|
||||
m.params.Logger.Infof("Listening TCP on %s\n", m.params.Listener.Addr())
|
||||
m.params.Logger.Infof("Listening TCP on %s", m.params.Listener.Addr())
|
||||
for {
|
||||
conn, err := m.params.Listener.Accept()
|
||||
if err != nil {
|
||||
m.params.Logger.Infof("Error accepting connection: %s\n", err)
|
||||
m.params.Logger.Infof("Error accepting connection: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -110,7 +101,7 @@ func (m *TCPMuxDefault) LocalAddr() net.Addr {
|
|||
}
|
||||
|
||||
// GetConnByUfrag retrieves an existing or creates a new net.PacketConn.
|
||||
func (m *TCPMuxDefault) GetConnByUfrag(ufrag string) (net.PacketConn, error) {
|
||||
func (m *TCPMuxDefault) GetConnByUfrag(ufrag string, isIPv6 bool, local net.IP) (net.PacketConn, error) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
|
@ -118,34 +109,50 @@ func (m *TCPMuxDefault) GetConnByUfrag(ufrag string) (net.PacketConn, error) {
|
|||
return nil, io.ErrClosedPipe
|
||||
}
|
||||
|
||||
conn, ok := m.conns[ufrag]
|
||||
|
||||
if ok {
|
||||
if conn, ok := m.getConn(ufrag, isIPv6, local); ok {
|
||||
return conn, nil
|
||||
// return nil, fmt.Errorf("duplicate ufrag %v", ufrag)
|
||||
}
|
||||
|
||||
conn = m.createConn(ufrag, m.LocalAddr())
|
||||
|
||||
return conn, nil
|
||||
return m.createConn(ufrag, isIPv6, local)
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) createConn(ufrag string, localAddr net.Addr) *tcpPacketConn {
|
||||
func (m *TCPMuxDefault) createConn(ufrag string, isIPv6 bool, local net.IP) (*tcpPacketConn, error) {
|
||||
addr, ok := m.LocalAddr().(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, ErrGetTransportAddress
|
||||
}
|
||||
localAddr := *addr
|
||||
localAddr.IP = local
|
||||
|
||||
conn := newTCPPacketConn(tcpPacketParams{
|
||||
ReadBuffer: m.params.ReadBufferSize,
|
||||
LocalAddr: localAddr,
|
||||
Logger: m.params.Logger,
|
||||
ReadBuffer: m.params.ReadBufferSize,
|
||||
WriteBuffer: m.params.WriteBufferSize,
|
||||
LocalAddr: &localAddr,
|
||||
Logger: m.params.Logger,
|
||||
})
|
||||
m.conns[ufrag] = conn
|
||||
|
||||
var conns map[ipAddr]*tcpPacketConn
|
||||
if isIPv6 {
|
||||
if conns, ok = m.connsIPv6[ufrag]; !ok {
|
||||
conns = make(map[ipAddr]*tcpPacketConn)
|
||||
m.connsIPv6[ufrag] = conns
|
||||
}
|
||||
} else {
|
||||
if conns, ok = m.connsIPv4[ufrag]; !ok {
|
||||
conns = make(map[ipAddr]*tcpPacketConn)
|
||||
m.connsIPv4[ufrag] = conns
|
||||
}
|
||||
}
|
||||
conns[ipAddr(local.String())] = conn
|
||||
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
defer m.wg.Done()
|
||||
<-conn.CloseChannel()
|
||||
m.RemoveConnByUfrag(ufrag)
|
||||
m.removeConnByUfragAndLocalHost(ufrag, local)
|
||||
}()
|
||||
|
||||
return conn
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) closeAndLogError(closer io.Closer) {
|
||||
|
@ -160,7 +167,7 @@ func (m *TCPMuxDefault) handleConn(conn net.Conn) {
|
|||
|
||||
n, err := readStreamingPacket(conn, buf)
|
||||
if err != nil {
|
||||
m.params.Logger.Warnf("Error reading first packet: %s", err)
|
||||
m.params.Logger.Warnf("Error reading first packet from %s: %s", conn.RemoteAddr().String(), err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -173,41 +180,61 @@ func (m *TCPMuxDefault) handleConn(conn net.Conn) {
|
|||
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)
|
||||
m.params.Logger.Warnf("Failed to handle decode ICE from %s to %s: %v", conn.RemoteAddr(), conn.LocalAddr(), err)
|
||||
return
|
||||
}
|
||||
|
||||
if m == nil || msg.Type.Method != stun.MethodBinding { // not a stun
|
||||
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())
|
||||
m.params.Logger.Warnf("Not a STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
return
|
||||
}
|
||||
|
||||
for _, attr := range msg.Attributes {
|
||||
m.params.Logger.Debugf("msg attr: %s\n", attr.String())
|
||||
m.params.Logger.Debugf("msg attr: %s", 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())
|
||||
m.params.Logger.Warnf("No Username attribute in STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
return
|
||||
}
|
||||
|
||||
ufrag := strings.Split(string(attr), ":")[0]
|
||||
m.params.Logger.Debugf("Ufrag: %s\n", ufrag)
|
||||
m.params.Logger.Debugf("Ufrag: %s", ufrag)
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
packetConn, ok := m.conns[ufrag]
|
||||
host, _, err := net.SplitHostPort(conn.RemoteAddr().String())
|
||||
if err != nil {
|
||||
m.closeAndLogError(conn)
|
||||
m.params.Logger.Warnf("Failed to get host in STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
return
|
||||
}
|
||||
|
||||
isIPv6 := net.ParseIP(host).To4() == nil
|
||||
|
||||
localAddr, ok := conn.LocalAddr().(*net.TCPAddr)
|
||||
if !ok {
|
||||
packetConn = m.createConn(ufrag, conn.LocalAddr())
|
||||
m.closeAndLogError(conn)
|
||||
m.params.Logger.Warnf("Failed to get local tcp address in STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
return
|
||||
}
|
||||
packetConn, ok := m.getConn(ufrag, isIPv6, localAddr.IP)
|
||||
if !ok {
|
||||
packetConn, err = m.createConn(ufrag, isIPv6, localAddr.IP)
|
||||
if err != nil {
|
||||
m.closeAndLogError(conn)
|
||||
m.params.Logger.Warnf("Failed to create packetConn for STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
m.params.Logger.Warnf("Error adding conn to tcpPacketConn from %s to %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -217,10 +244,19 @@ func (m *TCPMuxDefault) Close() error {
|
|||
m.mu.Lock()
|
||||
m.closed = true
|
||||
|
||||
for _, conn := range m.conns {
|
||||
m.closeAndLogError(conn)
|
||||
for _, conns := range m.connsIPv4 {
|
||||
for _, conn := range conns {
|
||||
m.closeAndLogError(conn)
|
||||
}
|
||||
}
|
||||
m.conns = map[string]*tcpPacketConn{}
|
||||
for _, conns := range m.connsIPv6 {
|
||||
for _, conn := range conns {
|
||||
m.closeAndLogError(conn)
|
||||
}
|
||||
}
|
||||
|
||||
m.connsIPv4 = map[string]map[ipAddr]*tcpPacketConn{}
|
||||
m.connsIPv6 = map[string]map[ipAddr]*tcpPacketConn{}
|
||||
|
||||
err := m.params.Listener.Close()
|
||||
|
||||
|
@ -233,13 +269,77 @@ func (m *TCPMuxDefault) Close() error {
|
|||
|
||||
// RemoveConnByUfrag closes and removes a net.PacketConn by Ufrag.
|
||||
func (m *TCPMuxDefault) RemoveConnByUfrag(ufrag string) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
removedConns := make([]*tcpPacketConn, 0, 4)
|
||||
|
||||
if conn, ok := m.conns[ufrag]; ok {
|
||||
m.closeAndLogError(conn)
|
||||
delete(m.conns, ufrag)
|
||||
// Keep lock section small to avoid deadlock with conn lock
|
||||
m.mu.Lock()
|
||||
if conns, ok := m.connsIPv4[ufrag]; ok {
|
||||
delete(m.connsIPv4, ufrag)
|
||||
for _, conn := range conns {
|
||||
removedConns = append(removedConns, conn)
|
||||
}
|
||||
}
|
||||
if conns, ok := m.connsIPv6[ufrag]; ok {
|
||||
delete(m.connsIPv6, ufrag)
|
||||
for _, conn := range conns {
|
||||
removedConns = append(removedConns, conn)
|
||||
}
|
||||
}
|
||||
|
||||
m.mu.Unlock()
|
||||
|
||||
// Close the connections outside the critical section to avoid
|
||||
// deadlocking TCP mux if (*tcpPacketConn).Close() blocks.
|
||||
for _, conn := range removedConns {
|
||||
m.closeAndLogError(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) removeConnByUfragAndLocalHost(ufrag string, local net.IP) {
|
||||
removedConns := make([]*tcpPacketConn, 0, 4)
|
||||
|
||||
localIP := ipAddr(local.String())
|
||||
// Keep lock section small to avoid deadlock with conn lock
|
||||
m.mu.Lock()
|
||||
if conns, ok := m.connsIPv4[ufrag]; ok {
|
||||
if conn, ok := conns[localIP]; ok {
|
||||
delete(conns, localIP)
|
||||
if len(conns) == 0 {
|
||||
delete(m.connsIPv4, ufrag)
|
||||
}
|
||||
removedConns = append(removedConns, conn)
|
||||
}
|
||||
}
|
||||
if conns, ok := m.connsIPv6[ufrag]; ok {
|
||||
if conn, ok := conns[localIP]; ok {
|
||||
delete(conns, localIP)
|
||||
if len(conns) == 0 {
|
||||
delete(m.connsIPv6, ufrag)
|
||||
}
|
||||
removedConns = append(removedConns, conn)
|
||||
}
|
||||
}
|
||||
m.mu.Unlock()
|
||||
|
||||
// Close the connections outside the critical section to avoid
|
||||
// deadlocking TCP mux if (*tcpPacketConn).Close() blocks.
|
||||
for _, conn := range removedConns {
|
||||
m.closeAndLogError(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *TCPMuxDefault) getConn(ufrag string, isIPv6 bool, local net.IP) (val *tcpPacketConn, ok bool) {
|
||||
var conns map[ipAddr]*tcpPacketConn
|
||||
if isIPv6 {
|
||||
conns, ok = m.connsIPv6[ufrag]
|
||||
} else {
|
||||
conns, ok = m.connsIPv4[ufrag]
|
||||
}
|
||||
if conns != nil {
|
||||
val, ok = conns[ipAddr(local.String())]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const streamingPacketHeaderLen = 2
|
||||
|
@ -247,11 +347,12 @@ 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 ... |
|
||||
// -----------------------------------------------------------------
|
||||
//
|
||||
// 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
|
||||
|
@ -282,11 +383,11 @@ func readStreamingPacket(conn net.Conn, buf []byte) (int, error) {
|
|||
}
|
||||
|
||||
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)
|
||||
bufCopy := make([]byte, streamingPacketHeaderLen+len(buf))
|
||||
binary.BigEndian.PutUint16(bufCopy, uint16(len(buf)))
|
||||
copy(bufCopy[2:], buf)
|
||||
|
||||
n, err := conn.Write(bufferCopy)
|
||||
n, err := conn.Write(bufCopy)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
81
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux_multi.go
generated
vendored
Normal file
81
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux_multi.go
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import "net"
|
||||
|
||||
// AllConnsGetter allows multiple fixed TCP ports to be used,
|
||||
// each of which is multiplexed like TCPMux. AllConnsGetter also acts as
|
||||
// a TCPMux, in which case it will return a single connection for one
|
||||
// of the ports.
|
||||
type AllConnsGetter interface {
|
||||
GetAllConns(ufrag string, isIPv6 bool, localIP net.IP) ([]net.PacketConn, error)
|
||||
}
|
||||
|
||||
// MultiTCPMuxDefault implements both TCPMux and AllConnsGetter,
|
||||
// allowing users to pass multiple TCPMux instances to the ICE agent
|
||||
// configuration.
|
||||
type MultiTCPMuxDefault struct {
|
||||
muxes []TCPMux
|
||||
}
|
||||
|
||||
// NewMultiTCPMuxDefault creates an instance of MultiTCPMuxDefault that
|
||||
// uses the provided TCPMux instances.
|
||||
func NewMultiTCPMuxDefault(muxes ...TCPMux) *MultiTCPMuxDefault {
|
||||
return &MultiTCPMuxDefault{
|
||||
muxes: muxes,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConnByUfrag returns a PacketConn given the connection's ufrag, network and local address
|
||||
// creates the connection if an existing one can't be found. This, unlike
|
||||
// GetAllConns, will only return a single PacketConn from the first mux that was
|
||||
// passed in to NewMultiTCPMuxDefault.
|
||||
func (m *MultiTCPMuxDefault) GetConnByUfrag(ufrag string, isIPv6 bool, local net.IP) (net.PacketConn, error) {
|
||||
// NOTE: We always use the first element here in order to maintain the
|
||||
// behavior of using an existing connection if one exists.
|
||||
if len(m.muxes) == 0 {
|
||||
return nil, errNoTCPMuxAvailable
|
||||
}
|
||||
return m.muxes[0].GetConnByUfrag(ufrag, isIPv6, local)
|
||||
}
|
||||
|
||||
// RemoveConnByUfrag stops and removes the muxed packet connection
|
||||
// from all underlying TCPMux instances.
|
||||
func (m *MultiTCPMuxDefault) RemoveConnByUfrag(ufrag string) {
|
||||
for _, mux := range m.muxes {
|
||||
mux.RemoveConnByUfrag(ufrag)
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllConns returns a PacketConn for each underlying TCPMux
|
||||
func (m *MultiTCPMuxDefault) GetAllConns(ufrag string, isIPv6 bool, local net.IP) ([]net.PacketConn, error) {
|
||||
if len(m.muxes) == 0 {
|
||||
// Make sure that we either return at least one connection or an error.
|
||||
return nil, errNoTCPMuxAvailable
|
||||
}
|
||||
var conns []net.PacketConn
|
||||
for _, mux := range m.muxes {
|
||||
conn, err := mux.GetConnByUfrag(ufrag, isIPv6, local)
|
||||
if err != nil {
|
||||
// For now, this implementation is all or none.
|
||||
return nil, err
|
||||
}
|
||||
if conn != nil {
|
||||
conns = append(conns, conn)
|
||||
}
|
||||
}
|
||||
return conns, nil
|
||||
}
|
||||
|
||||
// Close the multi mux, no further connections could be created
|
||||
func (m *MultiTCPMuxDefault) Close() error {
|
||||
var err error
|
||||
for _, mux := range m.muxes {
|
||||
if e := mux.Close(); e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
120
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_packet_conn.go
generated
vendored
120
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_packet_conn.go
generated
vendored
|
@ -1,15 +1,78 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/transport/v2/packetio"
|
||||
)
|
||||
|
||||
type bufferedConn struct {
|
||||
net.Conn
|
||||
buf *packetio.Buffer
|
||||
logger logging.LeveledLogger
|
||||
closed int32
|
||||
}
|
||||
|
||||
func newBufferedConn(conn net.Conn, bufSize int, logger logging.LeveledLogger) net.Conn {
|
||||
buf := packetio.NewBuffer()
|
||||
if bufSize > 0 {
|
||||
buf.SetLimitSize(bufSize)
|
||||
}
|
||||
|
||||
bc := &bufferedConn{
|
||||
Conn: conn,
|
||||
buf: buf,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
go bc.writeProcess()
|
||||
return bc
|
||||
}
|
||||
|
||||
func (bc *bufferedConn) Write(b []byte) (int, error) {
|
||||
n, err := bc.buf.Write(b)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (bc *bufferedConn) writeProcess() {
|
||||
pktBuf := make([]byte, receiveMTU)
|
||||
for atomic.LoadInt32(&bc.closed) == 0 {
|
||||
n, err := bc.buf.Read(pktBuf)
|
||||
if errors.Is(err, io.EOF) {
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
bc.logger.Warnf("read buffer error: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := bc.Conn.Write(pktBuf[:n]); err != nil {
|
||||
bc.logger.Warnf("write error: %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *bufferedConn) Close() error {
|
||||
atomic.StoreInt32(&bc.closed, 1)
|
||||
_ = bc.buf.Close()
|
||||
return bc.Conn.Close()
|
||||
}
|
||||
|
||||
type tcpPacketConn struct {
|
||||
params *tcpPacketParams
|
||||
|
||||
|
@ -31,9 +94,10 @@ type streamingPacket struct {
|
|||
}
|
||||
|
||||
type tcpPacketParams struct {
|
||||
ReadBuffer int
|
||||
LocalAddr net.Addr
|
||||
Logger logging.LeveledLogger
|
||||
ReadBuffer int
|
||||
LocalAddr net.Addr
|
||||
Logger logging.LeveledLogger
|
||||
WriteBuffer int
|
||||
}
|
||||
|
||||
func newTCPPacketConn(params tcpPacketParams) *tcpPacketConn {
|
||||
|
@ -50,7 +114,7 @@ func newTCPPacketConn(params tcpPacketParams) *tcpPacketConn {
|
|||
}
|
||||
|
||||
func (t *tcpPacketConn) AddConn(conn net.Conn, firstPacketData []byte) error {
|
||||
t.params.Logger.Infof("AddConn: %s %s", conn.RemoteAddr().Network(), conn.RemoteAddr())
|
||||
t.params.Logger.Infof("AddConn: %s remote %s to local %s", conn.RemoteAddr().Network(), conn.RemoteAddr(), conn.LocalAddr())
|
||||
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
@ -65,14 +129,25 @@ func (t *tcpPacketConn) AddConn(conn net.Conn, firstPacketData []byte) error {
|
|||
return fmt.Errorf("%w: %s", errConnectionAddrAlreadyExist, conn.RemoteAddr().String())
|
||||
}
|
||||
|
||||
if t.params.WriteBuffer > 0 {
|
||||
conn = newBufferedConn(conn, t.params.WriteBuffer, t.params.Logger)
|
||||
}
|
||||
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()
|
||||
if firstPacketData != nil {
|
||||
select {
|
||||
case <-t.closedChan:
|
||||
// NOTE: recvChan can fill up and never drain in edge
|
||||
// cases while closing a connection, which can cause the
|
||||
// packetConn to never finish closing. Bail out early
|
||||
// here to prevent that.
|
||||
return
|
||||
case t.recvChan <- streamingPacket{firstPacketData, conn.RemoteAddr(), nil}:
|
||||
}
|
||||
}
|
||||
t.startReading(conn)
|
||||
}()
|
||||
|
||||
|
@ -84,9 +159,8 @@ func (t *tcpPacketConn) startReading(conn net.Conn) {
|
|||
|
||||
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.params.Logger.Infof("%v: %s", errReadingStreamingPacket, err)
|
||||
t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err})
|
||||
t.removeConn(conn)
|
||||
return
|
||||
|
@ -95,7 +169,6 @@ func (t *tcpPacketConn) startReading(conn net.Conn) {
|
|||
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})
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +199,7 @@ func (t *tcpPacketConn) isClosed() bool {
|
|||
}
|
||||
|
||||
// WriteTo is for passive and s-o candidates.
|
||||
func (t *tcpPacketConn) ReadFrom(b []byte) (n int, raddr net.Addr, err error) {
|
||||
func (t *tcpPacketConn) ReadFrom(b []byte) (n int, rAddr net.Addr, err error) {
|
||||
pkt, ok := <-t.recvChan
|
||||
|
||||
if !ok {
|
||||
|
@ -147,27 +220,18 @@ func (t *tcpPacketConn) ReadFrom(b []byte) (n int, raddr net.Addr, err error) {
|
|||
}
|
||||
|
||||
// WriteTo is for active and s-o candidates.
|
||||
func (t *tcpPacketConn) WriteTo(buf []byte, raddr net.Addr) (n int, err error) {
|
||||
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()]
|
||||
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)
|
||||
t.params.Logger.Tracef("%w %s", errWriting, rAddr)
|
||||
return n, err
|
||||
}
|
||||
|
||||
|
@ -177,7 +241,7 @@ func (t *tcpPacketConn) WriteTo(buf []byte, raddr net.Addr) (n int, err error) {
|
|||
func (t *tcpPacketConn) closeAndLogError(closer io.Closer) {
|
||||
err := closer.Close()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnf("%w: %s", errClosingConnection, err)
|
||||
t.params.Logger.Warnf("%v: %s", errClosingConnection, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,15 +283,15 @@ func (t *tcpPacketConn) LocalAddr() net.Addr {
|
|||
return t.params.LocalAddr
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) SetDeadline(tm time.Time) error {
|
||||
func (t *tcpPacketConn) SetDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) SetReadDeadline(tm time.Time) error {
|
||||
func (t *tcpPacketConn) SetReadDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpPacketConn) SetWriteDeadline(tm time.Time) error {
|
||||
func (t *tcpPacketConn) SetWriteDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcptype.go
generated
vendored
5
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcptype.go
generated
vendored
|
@ -1,9 +1,12 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import "strings"
|
||||
|
||||
// TCPType is the type of ICE TCP candidate as described in
|
||||
// ttps://tools.ietf.org/html/rfc6544#section-4.5
|
||||
// https://tools.ietf.org/html/rfc6544#section-4.5
|
||||
type TCPType int
|
||||
|
||||
const (
|
||||
|
|
79
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/test_utils.go
generated
vendored
Normal file
79
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/test_utils.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build !js
|
||||
// +build !js
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newHostRemote(t *testing.T) *CandidateHost {
|
||||
remoteHostConfig := &CandidateHostConfig{
|
||||
Network: "udp",
|
||||
Address: "1.2.3.5",
|
||||
Port: 12350,
|
||||
Component: 1,
|
||||
}
|
||||
hostRemote, err := NewCandidateHost(remoteHostConfig)
|
||||
require.NoError(t, err)
|
||||
return hostRemote
|
||||
}
|
||||
|
||||
func newPrflxRemote(t *testing.T) *CandidatePeerReflexive {
|
||||
prflxConfig := &CandidatePeerReflexiveConfig{
|
||||
Network: "udp",
|
||||
Address: "10.10.10.2",
|
||||
Port: 19217,
|
||||
Component: 1,
|
||||
RelAddr: "4.3.2.1",
|
||||
RelPort: 43211,
|
||||
}
|
||||
prflxRemote, err := NewCandidatePeerReflexive(prflxConfig)
|
||||
require.NoError(t, err)
|
||||
return prflxRemote
|
||||
}
|
||||
|
||||
func newSrflxRemote(t *testing.T) *CandidateServerReflexive {
|
||||
srflxConfig := &CandidateServerReflexiveConfig{
|
||||
Network: "udp",
|
||||
Address: "10.10.10.2",
|
||||
Port: 19218,
|
||||
Component: 1,
|
||||
RelAddr: "4.3.2.1",
|
||||
RelPort: 43212,
|
||||
}
|
||||
srflxRemote, err := NewCandidateServerReflexive(srflxConfig)
|
||||
require.NoError(t, err)
|
||||
return srflxRemote
|
||||
}
|
||||
|
||||
func newRelayRemote(t *testing.T) *CandidateRelay {
|
||||
relayConfig := &CandidateRelayConfig{
|
||||
Network: "udp",
|
||||
Address: "1.2.3.4",
|
||||
Port: 12340,
|
||||
Component: 1,
|
||||
RelAddr: "4.3.2.1",
|
||||
RelPort: 43210,
|
||||
}
|
||||
relayRemote, err := NewCandidateRelay(relayConfig)
|
||||
require.NoError(t, err)
|
||||
return relayRemote
|
||||
}
|
||||
|
||||
func newHostLocal(t *testing.T) *CandidateHost {
|
||||
localHostConfig := &CandidateHostConfig{
|
||||
Network: "udp",
|
||||
Address: "192.168.1.1",
|
||||
Port: 19216,
|
||||
Component: 1,
|
||||
}
|
||||
hostLocal, err := NewCandidateHost(localHostConfig)
|
||||
require.NoError(t, err)
|
||||
return hostLocal
|
||||
}
|
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/transport.go
generated
vendored
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/transport.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
|
@ -44,12 +47,12 @@ func (a *Agent) connect(ctx context.Context, isControlling bool, remoteUfrag, re
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = a.startConnectivityChecks(isControlling, remoteUfrag, remotePwd)
|
||||
err = a.startConnectivityChecks(isControlling, remoteUfrag, remotePwd) //nolint:contextcheck
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// block until pair selected
|
||||
// Block until pair selected
|
||||
select {
|
||||
case <-a.done:
|
||||
return nil, a.getErr()
|
||||
|
@ -70,7 +73,7 @@ func (c *Conn) Read(p []byte) (int, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
n, err := c.agent.buffer.Read(p)
|
||||
n, err := c.agent.buf.Read(p)
|
||||
atomic.AddUint64(&c.bytesReceived, uint64(n))
|
||||
return n, err
|
||||
}
|
||||
|
@ -116,7 +119,7 @@ func (c *Conn) LocalAddr() net.Addr {
|
|||
return nil
|
||||
}
|
||||
|
||||
return pair.local.addr()
|
||||
return pair.Local.addr()
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote address of the current selected pair or nil if there is none.
|
||||
|
@ -126,20 +129,20 @@ func (c *Conn) RemoteAddr() net.Addr {
|
|||
return nil
|
||||
}
|
||||
|
||||
return pair.remote.addr()
|
||||
return pair.Remote.addr()
|
||||
}
|
||||
|
||||
// SetDeadline is a stub
|
||||
func (c *Conn) SetDeadline(t time.Time) error {
|
||||
func (c *Conn) SetDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetReadDeadline is a stub
|
||||
func (c *Conn) SetReadDeadline(t time.Time) error {
|
||||
func (c *Conn) SetReadDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWriteDeadline is a stub
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
func (c *Conn) SetWriteDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
|
363
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux.go
generated
vendored
Normal file
363
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux.go
generated
vendored
Normal file
|
@ -0,0 +1,363 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
"github.com/pion/transport/v2"
|
||||
"github.com/pion/transport/v2/stdnet"
|
||||
)
|
||||
|
||||
// UDPMux allows multiple connections to go over a single UDP port
|
||||
type UDPMux interface {
|
||||
io.Closer
|
||||
GetConn(ufrag string, addr net.Addr) (net.PacketConn, error)
|
||||
RemoveConnByUfrag(ufrag string)
|
||||
GetListenAddresses() []net.Addr
|
||||
}
|
||||
|
||||
// UDPMuxDefault is an implementation of the interface
|
||||
type UDPMuxDefault struct {
|
||||
params UDPMuxParams
|
||||
|
||||
closedChan chan struct{}
|
||||
closeOnce sync.Once
|
||||
|
||||
// connsIPv4 and connsIPv6 are maps of all udpMuxedConn indexed by ufrag|network|candidateType
|
||||
connsIPv4, connsIPv6 map[string]*udpMuxedConn
|
||||
|
||||
addressMapMu sync.RWMutex
|
||||
addressMap map[string]*udpMuxedConn
|
||||
|
||||
// Buffer pool to recycle buffers for net.UDPAddr encodes/decodes
|
||||
pool *sync.Pool
|
||||
|
||||
mu sync.Mutex
|
||||
|
||||
// For UDP connection listen at unspecified address
|
||||
localAddrsForUnspecified []net.Addr
|
||||
}
|
||||
|
||||
const maxAddrSize = 512
|
||||
|
||||
// UDPMuxParams are parameters for UDPMux.
|
||||
type UDPMuxParams struct {
|
||||
Logger logging.LeveledLogger
|
||||
UDPConn net.PacketConn
|
||||
|
||||
// Required for gathering local addresses
|
||||
// in case a un UDPConn is passed which does not
|
||||
// bind to a specific local address.
|
||||
Net transport.Net
|
||||
}
|
||||
|
||||
// NewUDPMuxDefault creates an implementation of UDPMux
|
||||
func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault {
|
||||
if params.Logger == nil {
|
||||
params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice")
|
||||
}
|
||||
|
||||
var localAddrsForUnspecified []net.Addr
|
||||
if addr, ok := params.UDPConn.LocalAddr().(*net.UDPAddr); !ok {
|
||||
params.Logger.Errorf("LocalAddr is not a net.UDPAddr, got %T", params.UDPConn.LocalAddr())
|
||||
} else if ok && addr.IP.IsUnspecified() {
|
||||
// For unspecified addresses, the correct behavior is to return errListenUnspecified, but
|
||||
// it will break the applications that are already using unspecified UDP connection
|
||||
// with UDPMuxDefault, so print a warn log and create a local address list for mux.
|
||||
params.Logger.Warn("UDPMuxDefault should not listening on unspecified address, use NewMultiUDPMuxFromPort instead")
|
||||
var networks []NetworkType
|
||||
switch {
|
||||
case addr.IP.To4() != nil:
|
||||
networks = []NetworkType{NetworkTypeUDP4}
|
||||
|
||||
case addr.IP.To16() != nil:
|
||||
networks = []NetworkType{NetworkTypeUDP4, NetworkTypeUDP6}
|
||||
|
||||
default:
|
||||
params.Logger.Errorf("LocalAddr expected IPV4 or IPV6, got %T", params.UDPConn.LocalAddr())
|
||||
}
|
||||
if len(networks) > 0 {
|
||||
if params.Net == nil {
|
||||
var err error
|
||||
if params.Net, err = stdnet.NewNet(); err != nil {
|
||||
params.Logger.Errorf("failed to get create network: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
ips, err := localInterfaces(params.Net, nil, nil, networks, true)
|
||||
if err == nil {
|
||||
for _, ip := range ips {
|
||||
localAddrsForUnspecified = append(localAddrsForUnspecified, &net.UDPAddr{IP: ip, Port: addr.Port})
|
||||
}
|
||||
} else {
|
||||
params.Logger.Errorf("failed to get local interfaces for unspecified addr: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m := &UDPMuxDefault{
|
||||
addressMap: map[string]*udpMuxedConn{},
|
||||
params: params,
|
||||
connsIPv4: make(map[string]*udpMuxedConn),
|
||||
connsIPv6: make(map[string]*udpMuxedConn),
|
||||
closedChan: make(chan struct{}, 1),
|
||||
pool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
// Big enough buffer to fit both packet and address
|
||||
return newBufferHolder(receiveMTU + maxAddrSize)
|
||||
},
|
||||
},
|
||||
localAddrsForUnspecified: localAddrsForUnspecified,
|
||||
}
|
||||
|
||||
go m.connWorker()
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// LocalAddr returns the listening address of this UDPMuxDefault
|
||||
func (m *UDPMuxDefault) LocalAddr() net.Addr {
|
||||
return m.params.UDPConn.LocalAddr()
|
||||
}
|
||||
|
||||
// GetListenAddresses returns the list of addresses that this mux is listening on
|
||||
func (m *UDPMuxDefault) GetListenAddresses() []net.Addr {
|
||||
if len(m.localAddrsForUnspecified) > 0 {
|
||||
return m.localAddrsForUnspecified
|
||||
}
|
||||
|
||||
return []net.Addr{m.LocalAddr()}
|
||||
}
|
||||
|
||||
// GetConn returns a PacketConn given the connection's ufrag and network address
|
||||
// creates the connection if an existing one can't be found
|
||||
func (m *UDPMuxDefault) GetConn(ufrag string, addr net.Addr) (net.PacketConn, error) {
|
||||
// don't check addr for mux using unspecified address
|
||||
if len(m.localAddrsForUnspecified) == 0 && m.params.UDPConn.LocalAddr().String() != addr.String() {
|
||||
return nil, errInvalidAddress
|
||||
}
|
||||
|
||||
var isIPv6 bool
|
||||
if udpAddr, _ := addr.(*net.UDPAddr); udpAddr != nil && udpAddr.IP.To4() == nil {
|
||||
isIPv6 = true
|
||||
}
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if m.IsClosed() {
|
||||
return nil, io.ErrClosedPipe
|
||||
}
|
||||
|
||||
if conn, ok := m.getConn(ufrag, isIPv6); ok {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
c := m.createMuxedConn(ufrag)
|
||||
go func() {
|
||||
<-c.CloseChannel()
|
||||
m.RemoveConnByUfrag(ufrag)
|
||||
}()
|
||||
|
||||
if isIPv6 {
|
||||
m.connsIPv6[ufrag] = c
|
||||
} else {
|
||||
m.connsIPv4[ufrag] = c
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// RemoveConnByUfrag stops and removes the muxed packet connection
|
||||
func (m *UDPMuxDefault) RemoveConnByUfrag(ufrag string) {
|
||||
removedConns := make([]*udpMuxedConn, 0, 2)
|
||||
|
||||
// Keep lock section small to avoid deadlock with conn lock
|
||||
m.mu.Lock()
|
||||
if c, ok := m.connsIPv4[ufrag]; ok {
|
||||
delete(m.connsIPv4, ufrag)
|
||||
removedConns = append(removedConns, c)
|
||||
}
|
||||
if c, ok := m.connsIPv6[ufrag]; ok {
|
||||
delete(m.connsIPv6, ufrag)
|
||||
removedConns = append(removedConns, c)
|
||||
}
|
||||
m.mu.Unlock()
|
||||
|
||||
if len(removedConns) == 0 {
|
||||
// No need to lock if no connection was found
|
||||
return
|
||||
}
|
||||
|
||||
m.addressMapMu.Lock()
|
||||
defer m.addressMapMu.Unlock()
|
||||
|
||||
for _, c := range removedConns {
|
||||
addresses := c.getAddresses()
|
||||
for _, addr := range addresses {
|
||||
delete(m.addressMap, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsClosed returns true if the mux had been closed
|
||||
func (m *UDPMuxDefault) IsClosed() bool {
|
||||
select {
|
||||
case <-m.closedChan:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Close the mux, no further connections could be created
|
||||
func (m *UDPMuxDefault) Close() error {
|
||||
var err error
|
||||
m.closeOnce.Do(func() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
for _, c := range m.connsIPv4 {
|
||||
_ = c.Close()
|
||||
}
|
||||
for _, c := range m.connsIPv6 {
|
||||
_ = c.Close()
|
||||
}
|
||||
|
||||
m.connsIPv4 = make(map[string]*udpMuxedConn)
|
||||
m.connsIPv6 = make(map[string]*udpMuxedConn)
|
||||
|
||||
close(m.closedChan)
|
||||
|
||||
_ = m.params.UDPConn.Close()
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *UDPMuxDefault) writeTo(buf []byte, rAddr net.Addr) (n int, err error) {
|
||||
return m.params.UDPConn.WriteTo(buf, rAddr)
|
||||
}
|
||||
|
||||
func (m *UDPMuxDefault) registerConnForAddress(conn *udpMuxedConn, addr string) {
|
||||
if m.IsClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
m.addressMapMu.Lock()
|
||||
defer m.addressMapMu.Unlock()
|
||||
|
||||
existing, ok := m.addressMap[addr]
|
||||
if ok {
|
||||
existing.removeAddress(addr)
|
||||
}
|
||||
m.addressMap[addr] = conn
|
||||
|
||||
m.params.Logger.Debugf("Registered %s for %s", addr, conn.params.Key)
|
||||
}
|
||||
|
||||
func (m *UDPMuxDefault) createMuxedConn(key string) *udpMuxedConn {
|
||||
c := newUDPMuxedConn(&udpMuxedConnParams{
|
||||
Mux: m,
|
||||
Key: key,
|
||||
AddrPool: m.pool,
|
||||
LocalAddr: m.LocalAddr(),
|
||||
Logger: m.params.Logger,
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (m *UDPMuxDefault) connWorker() {
|
||||
logger := m.params.Logger
|
||||
|
||||
defer func() {
|
||||
_ = m.Close()
|
||||
}()
|
||||
|
||||
buf := make([]byte, receiveMTU)
|
||||
for {
|
||||
n, addr, err := m.params.UDPConn.ReadFrom(buf)
|
||||
if m.IsClosed() {
|
||||
return
|
||||
} else if err != nil {
|
||||
if os.IsTimeout(err) {
|
||||
continue
|
||||
} else if !errors.Is(err, io.EOF) {
|
||||
logger.Errorf("could not read udp packet: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
udpAddr, ok := addr.(*net.UDPAddr)
|
||||
if !ok {
|
||||
logger.Errorf("underlying PacketConn did not return a UDPAddr")
|
||||
return
|
||||
}
|
||||
|
||||
// If we have already seen this address dispatch to the appropriate destination
|
||||
m.addressMapMu.Lock()
|
||||
destinationConn := m.addressMap[addr.String()]
|
||||
m.addressMapMu.Unlock()
|
||||
|
||||
// If we haven't seen this address before but is a STUN packet lookup by ufrag
|
||||
if destinationConn == nil && stun.IsMessage(buf[:n]) {
|
||||
msg := &stun.Message{
|
||||
Raw: append([]byte{}, buf[:n]...),
|
||||
}
|
||||
|
||||
if err = msg.Decode(); err != nil {
|
||||
m.params.Logger.Warnf("Failed to handle decode ICE from %s: %v", addr.String(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
attr, stunAttrErr := msg.Get(stun.AttrUsername)
|
||||
if stunAttrErr != nil {
|
||||
m.params.Logger.Warnf("No Username attribute in STUN message from %s", addr.String())
|
||||
continue
|
||||
}
|
||||
|
||||
ufrag := strings.Split(string(attr), ":")[0]
|
||||
isIPv6 := udpAddr.IP.To4() == nil
|
||||
|
||||
m.mu.Lock()
|
||||
destinationConn, _ = m.getConn(ufrag, isIPv6)
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
if destinationConn == nil {
|
||||
m.params.Logger.Tracef("dropping packet from %s, addr: %s", udpAddr.String(), addr.String())
|
||||
continue
|
||||
}
|
||||
|
||||
if err = destinationConn.writePacket(buf[:n], udpAddr); err != nil {
|
||||
m.params.Logger.Errorf("could not write packet: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UDPMuxDefault) getConn(ufrag string, isIPv6 bool) (val *udpMuxedConn, ok bool) {
|
||||
if isIPv6 {
|
||||
val, ok = m.connsIPv6[ufrag]
|
||||
} else {
|
||||
val, ok = m.connsIPv4[ufrag]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type bufferHolder struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func newBufferHolder(size int) *bufferHolder {
|
||||
return &bufferHolder{
|
||||
buf: make([]byte, size),
|
||||
}
|
||||
}
|
228
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_multi.go
generated
vendored
Normal file
228
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_multi.go
generated
vendored
Normal file
|
@ -0,0 +1,228 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/transport/v2"
|
||||
"github.com/pion/transport/v2/stdnet"
|
||||
)
|
||||
|
||||
// MultiUDPMuxDefault implements both UDPMux and AllConnsGetter,
|
||||
// allowing users to pass multiple UDPMux instances to the ICE agent
|
||||
// configuration.
|
||||
type MultiUDPMuxDefault struct {
|
||||
muxes []UDPMux
|
||||
localAddrToMux map[string]UDPMux
|
||||
}
|
||||
|
||||
// NewMultiUDPMuxDefault creates an instance of MultiUDPMuxDefault that
|
||||
// uses the provided UDPMux instances.
|
||||
func NewMultiUDPMuxDefault(muxes ...UDPMux) *MultiUDPMuxDefault {
|
||||
addrToMux := make(map[string]UDPMux)
|
||||
for _, mux := range muxes {
|
||||
for _, addr := range mux.GetListenAddresses() {
|
||||
addrToMux[addr.String()] = mux
|
||||
}
|
||||
}
|
||||
return &MultiUDPMuxDefault{
|
||||
muxes: muxes,
|
||||
localAddrToMux: addrToMux,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConn returns a PacketConn given the connection's ufrag and network
|
||||
// creates the connection if an existing one can't be found.
|
||||
func (m *MultiUDPMuxDefault) GetConn(ufrag string, addr net.Addr) (net.PacketConn, error) {
|
||||
mux, ok := m.localAddrToMux[addr.String()]
|
||||
if !ok {
|
||||
return nil, errNoUDPMuxAvailable
|
||||
}
|
||||
return mux.GetConn(ufrag, addr)
|
||||
}
|
||||
|
||||
// RemoveConnByUfrag stops and removes the muxed packet connection
|
||||
// from all underlying UDPMux instances.
|
||||
func (m *MultiUDPMuxDefault) RemoveConnByUfrag(ufrag string) {
|
||||
for _, mux := range m.muxes {
|
||||
mux.RemoveConnByUfrag(ufrag)
|
||||
}
|
||||
}
|
||||
|
||||
// Close the multi mux, no further connections could be created
|
||||
func (m *MultiUDPMuxDefault) Close() error {
|
||||
var err error
|
||||
for _, mux := range m.muxes {
|
||||
if e := mux.Close(); e != nil {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetListenAddresses returns the list of addresses that this mux is listening on
|
||||
func (m *MultiUDPMuxDefault) GetListenAddresses() []net.Addr {
|
||||
addrs := make([]net.Addr, 0, len(m.localAddrToMux))
|
||||
for _, mux := range m.muxes {
|
||||
addrs = append(addrs, mux.GetListenAddresses()...)
|
||||
}
|
||||
return addrs
|
||||
}
|
||||
|
||||
// NewMultiUDPMuxFromPort creates an instance of MultiUDPMuxDefault that
|
||||
// listen all interfaces on the provided port.
|
||||
func NewMultiUDPMuxFromPort(port int, opts ...UDPMuxFromPortOption) (*MultiUDPMuxDefault, error) {
|
||||
params := multiUDPMuxFromPortParam{
|
||||
networks: []NetworkType{NetworkTypeUDP4, NetworkTypeUDP6},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.apply(¶ms)
|
||||
}
|
||||
|
||||
if params.net == nil {
|
||||
var err error
|
||||
if params.net, err = stdnet.NewNet(); err != nil {
|
||||
return nil, fmt.Errorf("failed to get create network: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ips, err := localInterfaces(params.net, params.ifFilter, params.ipFilter, params.networks, params.includeLoopback)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conns := make([]net.PacketConn, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
conn, listenErr := params.net.ListenUDP("udp", &net.UDPAddr{IP: ip, Port: port})
|
||||
if listenErr != nil {
|
||||
err = listenErr
|
||||
break
|
||||
}
|
||||
if params.readBufferSize > 0 {
|
||||
_ = conn.SetReadBuffer(params.readBufferSize)
|
||||
}
|
||||
if params.writeBufferSize > 0 {
|
||||
_ = conn.SetWriteBuffer(params.writeBufferSize)
|
||||
}
|
||||
conns = append(conns, conn)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
for _, conn := range conns {
|
||||
_ = conn.Close()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
muxes := make([]UDPMux, 0, len(conns))
|
||||
for _, conn := range conns {
|
||||
mux := NewUDPMuxDefault(UDPMuxParams{
|
||||
Logger: params.logger,
|
||||
UDPConn: conn,
|
||||
Net: params.net,
|
||||
})
|
||||
muxes = append(muxes, mux)
|
||||
}
|
||||
|
||||
return NewMultiUDPMuxDefault(muxes...), nil
|
||||
}
|
||||
|
||||
// UDPMuxFromPortOption provide options for NewMultiUDPMuxFromPort
|
||||
type UDPMuxFromPortOption interface {
|
||||
apply(*multiUDPMuxFromPortParam)
|
||||
}
|
||||
|
||||
type multiUDPMuxFromPortParam struct {
|
||||
ifFilter func(string) bool
|
||||
ipFilter func(ip net.IP) bool
|
||||
networks []NetworkType
|
||||
readBufferSize int
|
||||
writeBufferSize int
|
||||
logger logging.LeveledLogger
|
||||
includeLoopback bool
|
||||
net transport.Net
|
||||
}
|
||||
|
||||
type udpMuxFromPortOption struct {
|
||||
f func(*multiUDPMuxFromPortParam)
|
||||
}
|
||||
|
||||
func (o *udpMuxFromPortOption) apply(p *multiUDPMuxFromPortParam) {
|
||||
o.f(p)
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithInterfaceFilter set the filter to filter out interfaces that should not be used
|
||||
func UDPMuxFromPortWithInterfaceFilter(f func(string) bool) UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.ifFilter = f
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithIPFilter set the filter to filter out IP addresses that should not be used
|
||||
func UDPMuxFromPortWithIPFilter(f func(ip net.IP) bool) UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.ipFilter = f
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithNetworks set the networks that should be used. default is both IPv4 and IPv6
|
||||
func UDPMuxFromPortWithNetworks(networks ...NetworkType) UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.networks = networks
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithReadBufferSize set the UDP connection read buffer size
|
||||
func UDPMuxFromPortWithReadBufferSize(size int) UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.readBufferSize = size
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithWriteBufferSize set the UDP connection write buffer size
|
||||
func UDPMuxFromPortWithWriteBufferSize(size int) UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.writeBufferSize = size
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithLogger set the logger for the created UDPMux
|
||||
func UDPMuxFromPortWithLogger(logger logging.LeveledLogger) UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.logger = logger
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithLoopback set loopback interface should be included
|
||||
func UDPMuxFromPortWithLoopback() UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.includeLoopback = true
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UDPMuxFromPortWithNet sets the network transport to use.
|
||||
func UDPMuxFromPortWithNet(n transport.Net) UDPMuxFromPortOption {
|
||||
return &udpMuxFromPortOption{
|
||||
f: func(p *multiUDPMuxFromPortParam) {
|
||||
p.net = n
|
||||
},
|
||||
}
|
||||
}
|
271
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_universal.go
generated
vendored
Normal file
271
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_universal.go
generated
vendored
Normal file
|
@ -0,0 +1,271 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun"
|
||||
"github.com/pion/transport/v2"
|
||||
)
|
||||
|
||||
// UniversalUDPMux allows multiple connections to go over a single UDP port for
|
||||
// host, server reflexive and relayed candidates.
|
||||
// Actual connection muxing is happening in the UDPMux.
|
||||
type UniversalUDPMux interface {
|
||||
UDPMux
|
||||
GetXORMappedAddr(stunAddr net.Addr, deadline time.Duration) (*stun.XORMappedAddress, error)
|
||||
GetRelayedAddr(turnAddr net.Addr, deadline time.Duration) (*net.Addr, error)
|
||||
GetConnForURL(ufrag string, url string, addr net.Addr) (net.PacketConn, error)
|
||||
}
|
||||
|
||||
// UniversalUDPMuxDefault handles STUN and TURN servers packets by wrapping the original UDPConn overriding ReadFrom.
|
||||
// It the passes packets to the UDPMux that does the actual connection muxing.
|
||||
type UniversalUDPMuxDefault struct {
|
||||
*UDPMuxDefault
|
||||
params UniversalUDPMuxParams
|
||||
|
||||
// Since we have a shared socket, for srflx candidates it makes sense to have a shared mapped address across all the agents
|
||||
// stun.XORMappedAddress indexed by the STUN server addr
|
||||
xorMappedMap map[string]*xorMapped
|
||||
}
|
||||
|
||||
// UniversalUDPMuxParams are parameters for UniversalUDPMux server reflexive.
|
||||
type UniversalUDPMuxParams struct {
|
||||
Logger logging.LeveledLogger
|
||||
UDPConn net.PacketConn
|
||||
XORMappedAddrCacheTTL time.Duration
|
||||
Net transport.Net
|
||||
}
|
||||
|
||||
// NewUniversalUDPMuxDefault creates an implementation of UniversalUDPMux embedding UDPMux
|
||||
func NewUniversalUDPMuxDefault(params UniversalUDPMuxParams) *UniversalUDPMuxDefault {
|
||||
if params.Logger == nil {
|
||||
params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice")
|
||||
}
|
||||
if params.XORMappedAddrCacheTTL == 0 {
|
||||
params.XORMappedAddrCacheTTL = time.Second * 25
|
||||
}
|
||||
|
||||
m := &UniversalUDPMuxDefault{
|
||||
params: params,
|
||||
xorMappedMap: make(map[string]*xorMapped),
|
||||
}
|
||||
|
||||
// Wrap UDP connection, process server reflexive messages
|
||||
// before they are passed to the UDPMux connection handler (connWorker)
|
||||
m.params.UDPConn = &udpConn{
|
||||
PacketConn: params.UDPConn,
|
||||
mux: m,
|
||||
logger: params.Logger,
|
||||
}
|
||||
|
||||
// Embed UDPMux
|
||||
udpMuxParams := UDPMuxParams{
|
||||
Logger: params.Logger,
|
||||
UDPConn: m.params.UDPConn,
|
||||
Net: m.params.Net,
|
||||
}
|
||||
m.UDPMuxDefault = NewUDPMuxDefault(udpMuxParams)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// udpConn is a wrapper around UDPMux conn that overrides ReadFrom and handles STUN/TURN packets
|
||||
type udpConn struct {
|
||||
net.PacketConn
|
||||
mux *UniversalUDPMuxDefault
|
||||
logger logging.LeveledLogger
|
||||
}
|
||||
|
||||
// GetRelayedAddr creates relayed connection to the given TURN service and returns the relayed addr.
|
||||
// Not implemented yet.
|
||||
func (m *UniversalUDPMuxDefault) GetRelayedAddr(net.Addr, time.Duration) (*net.Addr, error) {
|
||||
return nil, errNotImplemented
|
||||
}
|
||||
|
||||
// GetConnForURL add uniques to the muxed connection by concatenating ufrag and URL (e.g. STUN URL) to be able to support multiple STUN/TURN servers
|
||||
// and return a unique connection per server.
|
||||
func (m *UniversalUDPMuxDefault) GetConnForURL(ufrag string, url string, addr net.Addr) (net.PacketConn, error) {
|
||||
return m.UDPMuxDefault.GetConn(fmt.Sprintf("%s%s", ufrag, url), addr)
|
||||
}
|
||||
|
||||
// ReadFrom is called by UDPMux connWorker and handles packets coming from the STUN server discovering a mapped address.
|
||||
// It passes processed packets further to the UDPMux (maybe this is not really necessary).
|
||||
func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
n, addr, err = c.PacketConn.ReadFrom(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if stun.IsMessage(p[:n]) {
|
||||
msg := &stun.Message{
|
||||
Raw: append([]byte{}, p[:n]...),
|
||||
}
|
||||
|
||||
if err = msg.Decode(); err != nil {
|
||||
c.logger.Warnf("Failed to handle decode ICE from %s: %v", addr.String(), err)
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
udpAddr, ok := addr.(*net.UDPAddr)
|
||||
if !ok {
|
||||
// Message about this err will be logged in the UDPMux
|
||||
return
|
||||
}
|
||||
|
||||
if c.mux.isXORMappedResponse(msg, udpAddr.String()) {
|
||||
err = c.mux.handleXORMappedResponse(udpAddr, msg)
|
||||
if err != nil {
|
||||
c.logger.Debugf("%w: %v", errGetXorMappedAddrResponse, err)
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
return n, addr, err
|
||||
}
|
||||
|
||||
// isXORMappedResponse indicates whether the message is a XORMappedAddress and is coming from the known STUN server.
|
||||
func (m *UniversalUDPMuxDefault) isXORMappedResponse(msg *stun.Message, stunAddr string) bool {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
// Check first if it is a STUN server address because remote peer can also send similar messages but as a BindingSuccess
|
||||
_, ok := m.xorMappedMap[stunAddr]
|
||||
_, err := msg.Get(stun.AttrXORMappedAddress)
|
||||
return err == nil && ok
|
||||
}
|
||||
|
||||
// handleXORMappedResponse parses response from the STUN server, extracts XORMappedAddress attribute
|
||||
// and set the mapped address for the server
|
||||
func (m *UniversalUDPMuxDefault) handleXORMappedResponse(stunAddr *net.UDPAddr, msg *stun.Message) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
mappedAddr, ok := m.xorMappedMap[stunAddr.String()]
|
||||
if !ok {
|
||||
return errNoXorAddrMapping
|
||||
}
|
||||
|
||||
var addr stun.XORMappedAddress
|
||||
if err := addr.GetFrom(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.xorMappedMap[stunAddr.String()] = mappedAddr
|
||||
mappedAddr.SetAddr(&addr)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetXORMappedAddr returns *stun.XORMappedAddress if already present for a given STUN server.
|
||||
// Makes a STUN binding request to discover mapped address otherwise.
|
||||
// Blocks until the stun.XORMappedAddress has been discovered or deadline.
|
||||
// Method is safe for concurrent use.
|
||||
func (m *UniversalUDPMuxDefault) GetXORMappedAddr(serverAddr net.Addr, deadline time.Duration) (*stun.XORMappedAddress, error) {
|
||||
m.mu.Lock()
|
||||
mappedAddr, ok := m.xorMappedMap[serverAddr.String()]
|
||||
// If we already have a mapping for this STUN server (address already received)
|
||||
// and if it is not too old we return it without making a new request to STUN server
|
||||
if ok {
|
||||
if mappedAddr.expired() {
|
||||
mappedAddr.closeWaiters()
|
||||
delete(m.xorMappedMap, serverAddr.String())
|
||||
ok = false
|
||||
} else if mappedAddr.pending() {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
m.mu.Unlock()
|
||||
if ok {
|
||||
return mappedAddr.addr, nil
|
||||
}
|
||||
|
||||
// Otherwise, make a STUN request to discover the address
|
||||
// or wait for already sent request to complete
|
||||
waitAddrReceived, err := m.sendSTUN(serverAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %s", errSendSTUNPacket, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
// Block until response was handled by the connWorker routine and XORMappedAddress was updated
|
||||
select {
|
||||
case <-waitAddrReceived:
|
||||
// When channel closed, addr was obtained
|
||||
m.mu.Lock()
|
||||
mappedAddr := *m.xorMappedMap[serverAddr.String()]
|
||||
m.mu.Unlock()
|
||||
if mappedAddr.addr == nil {
|
||||
return nil, errNoXorAddrMapping
|
||||
}
|
||||
return mappedAddr.addr, nil
|
||||
case <-time.After(deadline):
|
||||
return nil, errXORMappedAddrTimeout
|
||||
}
|
||||
}
|
||||
|
||||
// sendSTUN sends a STUN request via UDP conn.
|
||||
//
|
||||
// The returned channel is closed when the STUN response has been received.
|
||||
// Method is safe for concurrent use.
|
||||
func (m *UniversalUDPMuxDefault) sendSTUN(serverAddr net.Addr) (chan struct{}, error) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
// If record present in the map, we already sent a STUN request,
|
||||
// just wait when waitAddrReceived will be closed
|
||||
addrMap, ok := m.xorMappedMap[serverAddr.String()]
|
||||
if !ok {
|
||||
addrMap = &xorMapped{
|
||||
expiresAt: time.Now().Add(m.params.XORMappedAddrCacheTTL),
|
||||
waitAddrReceived: make(chan struct{}),
|
||||
}
|
||||
m.xorMappedMap[serverAddr.String()] = addrMap
|
||||
}
|
||||
|
||||
req, err := stun.Build(stun.BindingRequest, stun.TransactionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = m.params.UDPConn.WriteTo(req.Raw, serverAddr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return addrMap.waitAddrReceived, nil
|
||||
}
|
||||
|
||||
type xorMapped struct {
|
||||
addr *stun.XORMappedAddress
|
||||
waitAddrReceived chan struct{}
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
func (a *xorMapped) closeWaiters() {
|
||||
select {
|
||||
case <-a.waitAddrReceived:
|
||||
// Notify was close, ok, that means we received duplicate response just exit
|
||||
break
|
||||
default:
|
||||
// Notify tha twe have a new addr
|
||||
close(a.waitAddrReceived)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *xorMapped) pending() bool {
|
||||
return a.addr == nil
|
||||
}
|
||||
|
||||
func (a *xorMapped) expired() bool {
|
||||
return a.expiresAt.Before(time.Now())
|
||||
}
|
||||
|
||||
func (a *xorMapped) SetAddr(addr *stun.XORMappedAddress) {
|
||||
a.addr = addr
|
||||
a.closeWaiters()
|
||||
}
|
246
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_muxed_conn.go
generated
vendored
Normal file
246
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_muxed_conn.go
generated
vendored
Normal file
|
@ -0,0 +1,246 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/transport/v2/packetio"
|
||||
)
|
||||
|
||||
type udpMuxedConnParams struct {
|
||||
Mux *UDPMuxDefault
|
||||
AddrPool *sync.Pool
|
||||
Key string
|
||||
LocalAddr net.Addr
|
||||
Logger logging.LeveledLogger
|
||||
}
|
||||
|
||||
// udpMuxedConn represents a logical packet conn for a single remote as identified by ufrag
|
||||
type udpMuxedConn struct {
|
||||
params *udpMuxedConnParams
|
||||
// Remote addresses that we have sent to on this conn
|
||||
addresses []string
|
||||
|
||||
// Channel holding incoming packets
|
||||
buf *packetio.Buffer
|
||||
closedChan chan struct{}
|
||||
closeOnce sync.Once
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func newUDPMuxedConn(params *udpMuxedConnParams) *udpMuxedConn {
|
||||
p := &udpMuxedConn{
|
||||
params: params,
|
||||
buf: packetio.NewBuffer(),
|
||||
closedChan: make(chan struct{}),
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) ReadFrom(b []byte) (n int, rAddr net.Addr, err error) {
|
||||
buf := c.params.AddrPool.Get().(*bufferHolder) //nolint:forcetypeassert
|
||||
defer c.params.AddrPool.Put(buf)
|
||||
|
||||
// Read address
|
||||
total, err := c.buf.Read(buf.buf)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
dataLen := int(binary.LittleEndian.Uint16(buf.buf[:2]))
|
||||
if dataLen > total || dataLen > len(b) {
|
||||
return 0, nil, io.ErrShortBuffer
|
||||
}
|
||||
|
||||
// Read data and then address
|
||||
offset := 2
|
||||
copy(b, buf.buf[offset:offset+dataLen])
|
||||
offset += dataLen
|
||||
|
||||
// Read address len & decode address
|
||||
addrLen := int(binary.LittleEndian.Uint16(buf.buf[offset : offset+2]))
|
||||
offset += 2
|
||||
|
||||
if rAddr, err = decodeUDPAddr(buf.buf[offset : offset+addrLen]); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return dataLen, rAddr, nil
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) WriteTo(buf []byte, rAddr net.Addr) (n int, err error) {
|
||||
if c.isClosed() {
|
||||
return 0, io.ErrClosedPipe
|
||||
}
|
||||
// Each time we write to a new address, we'll register it with the mux
|
||||
addr := rAddr.String()
|
||||
if !c.containsAddress(addr) {
|
||||
c.addAddress(addr)
|
||||
}
|
||||
|
||||
return c.params.Mux.writeTo(buf, rAddr)
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) LocalAddr() net.Addr {
|
||||
return c.params.LocalAddr
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) SetDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) SetReadDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) SetWriteDeadline(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) CloseChannel() <-chan struct{} {
|
||||
return c.closedChan
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) Close() error {
|
||||
var err error
|
||||
c.closeOnce.Do(func() {
|
||||
err = c.buf.Close()
|
||||
close(c.closedChan)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) isClosed() bool {
|
||||
select {
|
||||
case <-c.closedChan:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) getAddresses() []string {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
addresses := make([]string, len(c.addresses))
|
||||
copy(addresses, c.addresses)
|
||||
return addresses
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) addAddress(addr string) {
|
||||
c.mu.Lock()
|
||||
c.addresses = append(c.addresses, addr)
|
||||
c.mu.Unlock()
|
||||
|
||||
// Map it on mux
|
||||
c.params.Mux.registerConnForAddress(c, addr)
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) removeAddress(addr string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
newAddresses := make([]string, 0, len(c.addresses))
|
||||
for _, a := range c.addresses {
|
||||
if a != addr {
|
||||
newAddresses = append(newAddresses, a)
|
||||
}
|
||||
}
|
||||
|
||||
c.addresses = newAddresses
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) containsAddress(addr string) bool {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
for _, a := range c.addresses {
|
||||
if addr == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *udpMuxedConn) writePacket(data []byte, addr *net.UDPAddr) error {
|
||||
// Write two packets, address and data
|
||||
buf := c.params.AddrPool.Get().(*bufferHolder) //nolint:forcetypeassert
|
||||
defer c.params.AddrPool.Put(buf)
|
||||
|
||||
// Format of buffer | data len | data bytes | addr len | addr bytes |
|
||||
if len(buf.buf) < len(data)+maxAddrSize {
|
||||
return io.ErrShortBuffer
|
||||
}
|
||||
// Data length
|
||||
binary.LittleEndian.PutUint16(buf.buf, uint16(len(data)))
|
||||
offset := 2
|
||||
|
||||
// Data
|
||||
copy(buf.buf[offset:], data)
|
||||
offset += len(data)
|
||||
|
||||
// Write address first, leaving room for its length
|
||||
n, err := encodeUDPAddr(addr, buf.buf[offset+2:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
total := offset + n + 2
|
||||
|
||||
// Address len
|
||||
binary.LittleEndian.PutUint16(buf.buf[offset:], uint16(n))
|
||||
|
||||
if _, err := c.buf.Write(buf.buf[:total]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeUDPAddr(addr *net.UDPAddr, buf []byte) (int, error) {
|
||||
ipData, err := addr.IP.MarshalText()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
total := 2 + len(ipData) + 2 + len(addr.Zone)
|
||||
if total > len(buf) {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint16(buf, uint16(len(ipData)))
|
||||
offset := 2
|
||||
n := copy(buf[offset:], ipData)
|
||||
offset += n
|
||||
binary.LittleEndian.PutUint16(buf[offset:], uint16(addr.Port))
|
||||
offset += 2
|
||||
copy(buf[offset:], addr.Zone)
|
||||
return total, nil
|
||||
}
|
||||
|
||||
func decodeUDPAddr(buf []byte) (*net.UDPAddr, error) {
|
||||
addr := net.UDPAddr{}
|
||||
|
||||
offset := 0
|
||||
ipLen := int(binary.LittleEndian.Uint16(buf[:2]))
|
||||
offset += 2
|
||||
// Basic bounds checking
|
||||
if ipLen+offset > len(buf) {
|
||||
return nil, io.ErrShortBuffer
|
||||
}
|
||||
if err := addr.IP.UnmarshalText(buf[offset : offset+ipLen]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset += ipLen
|
||||
addr.Port = int(binary.LittleEndian.Uint16(buf[offset : offset+2]))
|
||||
offset += 2
|
||||
zone := make([]byte, len(buf[offset:]))
|
||||
copy(zone, buf[offset:])
|
||||
addr.Zone = string(zone)
|
||||
|
||||
return &addr, nil
|
||||
}
|
255
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/url.go
generated
vendored
255
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/url.go
generated
vendored
|
@ -1,225 +1,82 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
import "github.com/pion/stun"
|
||||
|
||||
type (
|
||||
// URL represents a STUN (rfc7064) or TURN (rfc7065) URI
|
||||
//
|
||||
// Deprecated: Please use pion/stun.URI
|
||||
URL = stun.URI
|
||||
|
||||
// ProtoType indicates the transport protocol type that is used in the ice.URL
|
||||
// structure.
|
||||
//
|
||||
// Deprecated: TPlease use pion/stun.ProtoType
|
||||
ProtoType = stun.ProtoType
|
||||
|
||||
// SchemeType indicates the type of server used in the ice.URL structure.
|
||||
//
|
||||
// Deprecated: Please use pion/stun.SchemeType
|
||||
SchemeType = stun.SchemeType
|
||||
)
|
||||
|
||||
// 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
|
||||
//
|
||||
// Deprecated: Please use pion/stun.SchemeTypeSTUN
|
||||
SchemeTypeSTUN = stun.SchemeTypeSTUN
|
||||
|
||||
// SchemeTypeSTUNS indicates the URL represents a STUNS (secure) server.
|
||||
SchemeTypeSTUNS
|
||||
//
|
||||
// Deprecated: Please use pion/stun.SchemeTypeSTUNS
|
||||
SchemeTypeSTUNS = stun.SchemeTypeSTUNS
|
||||
|
||||
// SchemeTypeTURN indicates the URL represents a TURN server.
|
||||
SchemeTypeTURN
|
||||
//
|
||||
// Deprecated: Please use pion/stun.SchemeTypeTURN
|
||||
SchemeTypeTURN = stun.SchemeTypeTURN
|
||||
|
||||
// SchemeTypeTURNS indicates the URL represents a TURNS (secure) server.
|
||||
SchemeTypeTURNS
|
||||
//
|
||||
// Deprecated: Please use pion/stun.SchemeTypeTURNS
|
||||
SchemeTypeTURNS = stun.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
|
||||
//
|
||||
// Deprecated: Please use pion/stun.ProtoTypeUDP
|
||||
ProtoTypeUDP = stun.ProtoTypeUDP
|
||||
|
||||
// ProtoTypeTCP indicates the URL uses a TCP transport.
|
||||
ProtoTypeTCP
|
||||
//
|
||||
// Deprecated: Please use pion/stun.ProtoTypeTCP
|
||||
ProtoTypeTCP = stun.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
|
||||
}
|
||||
// Unknown represents and unknown ProtoType or SchemeType
|
||||
//
|
||||
// Deprecated: Please use pion/stun.SchemeTypeUnknown or pion/stun.ProtoTypeUnknown
|
||||
const Unknown = 0
|
||||
|
||||
// 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
|
||||
}
|
||||
//
|
||||
// Deprecated: Please use pion/stun.ParseURI
|
||||
var ParseURL = stun.ParseURI //nolint:gochecknoglobals
|
||||
|
||||
var u URL
|
||||
u.Scheme = NewSchemeType(rawParts.Scheme)
|
||||
if u.Scheme == SchemeType(Unknown) {
|
||||
return nil, ErrSchemeType
|
||||
}
|
||||
// NewSchemeType defines a procedure for creating a new SchemeType from a raw
|
||||
// string naming the scheme type.
|
||||
//
|
||||
// Deprecated: Please use pion/stun.NewSchemeType
|
||||
var NewSchemeType = stun.NewSchemeType //nolint:gochecknoglobals
|
||||
|
||||
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
|
||||
}
|
||||
// NewProtoType defines a procedure for creating a new ProtoType from a raw
|
||||
// string naming the transport protocol type.
|
||||
//
|
||||
// Deprecated: Please use pion/stun.NewProtoType
|
||||
var NewProtoType = stun.NewProtoType //nolint:gochecknoglobals
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/usecandidate.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/usecandidate.go
generated
vendored
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package ice
|
||||
|
||||
import "github.com/pion/stun"
|
||||
|
|
233
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/util.go
generated
vendored
233
trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/util.go
generated
vendored
|
@ -1,233 +0,0 @@
|
|||
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