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
104cf14d68
commit
df854339ea
1383 changed files with 118469 additions and 41421 deletions
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.gitignore
generated
vendored
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.gitignore
generated
vendored
|
@ -1 +1,25 @@
|
|||
### JetBrains IDE ###
|
||||
#####################
|
||||
.idea/
|
||||
|
||||
### Emacs Temporary Files ###
|
||||
#############################
|
||||
*~
|
||||
|
||||
### Folders ###
|
||||
###############
|
||||
bin/
|
||||
vendor/
|
||||
node_modules/
|
||||
|
||||
### Files ###
|
||||
#############
|
||||
*.ivf
|
||||
*.ogg
|
||||
tags
|
||||
cover.out
|
||||
*.sw[poe]
|
||||
*.wasm
|
||||
examples/sfu-ws/cert.pem
|
||||
examples/sfu-ws/key.pem
|
||||
wasm_exec.js
|
||||
|
|
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.golangci.yml
generated
vendored
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.golangci.yml
generated
vendored
|
@ -5,18 +5,31 @@ linters-settings:
|
|||
locale: US
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
gomodguard:
|
||||
blocked:
|
||||
modules:
|
||||
- github.com/pkg/errors:
|
||||
recommendations:
|
||||
- errors
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
|
||||
- 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
|
||||
- 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
|
||||
|
@ -29,43 +42,64 @@ 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
|
||||
- forbidigo # Forbids identifiers
|
||||
- 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:
|
||||
exclude-use-default: false
|
||||
exclude-rules:
|
||||
# Allow complex tests, better to be self contained
|
||||
- path: _test\.go
|
||||
|
|
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.goreleaser.yml
generated
vendored
Normal file
2
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.goreleaser.yml
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
builds:
|
||||
- skip: true
|
33
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/AUTHORS.txt
generated
vendored
Normal file
33
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/AUTHORS.txt
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
# 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>
|
||||
Adrian Cable <adrian.cable@gmail.com>
|
||||
Atsushi Watanabe <atsushi.w@ieee.org>
|
||||
backkem <mail@backkem.me>
|
||||
Cecylia Bocovich <cohosh@torproject.org>
|
||||
chenkaiC4 <chenkaic4@gmail.com>
|
||||
Eric Daniels <eric@erdaniels.com>
|
||||
Hugo Arregui <hugo.arregui@gmail.com>
|
||||
Hugo Arregui <hugo@decentraland.org>
|
||||
Jerko Steiner <jerko.steiner@gmail.com>
|
||||
Jerry Tao <taojay315@gmail.com>
|
||||
John Bradley <jrb@turrettech.com>
|
||||
Konstantin Itskov <konstantin.itskov@kovits.com>
|
||||
Lukas Herman <lherman.cs@gmail.com>
|
||||
Luke Curley <lcurley@twitch.tv>
|
||||
Michael MacDonald <github@macdonald.cx>
|
||||
ronan <ronan.jezequel@gmail.com>
|
||||
Sam Lancia <sam@vaion.com>
|
||||
Sean DuBois <seaduboi@amazon.com>
|
||||
Sean DuBois <sean@siobud.com>
|
||||
Steffen Vogel <post@steffenvogel.de>
|
||||
Teddy <richardgeorgeoff@gmail.com>
|
||||
Will Forcey <wsforc3y@gmail.com>
|
||||
Yutaka Takeda <yt0916@gmail.com>
|
||||
ZHENK <chengzhenyang@gmail.com>
|
||||
|
||||
# List of contributors not appearing in Git history
|
||||
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/DESIGN.md
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/DESIGN.md
generated
vendored
|
@ -1,20 +0,0 @@
|
|||
<h1 align="center">
|
||||
Design
|
||||
</h1>
|
||||
|
||||
### Portable
|
||||
Pion SCTP is written in Go and extremely portable. Anywhere Golang runs, Pion SCTP should work as well! Instead of dealing with complicated
|
||||
cross-compiling of multiple libraries, you now can run anywhere with one `go build`
|
||||
|
||||
### Simple API
|
||||
The API is based on an io.ReadWriteCloser.
|
||||
|
||||
### Readable
|
||||
If code comes from an RFC we try to make sure everything is commented with a link to the spec.
|
||||
This makes learning and debugging easier, this library was written to also serve as a guide for others.
|
||||
|
||||
### Tested
|
||||
Every commit is tested via travis-ci Go provides fantastic facilities for testing, and more will be added as time goes on.
|
||||
|
||||
### Shared libraries
|
||||
Every pion product is built using shared libraries, allowing others to review and reuse our libraries.
|
32
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/README.md
generated
vendored
32
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/README.md
generated
vendored
|
@ -6,49 +6,29 @@
|
|||
<h4 align="center">A Go implementation of SCTP</h4>
|
||||
<p align="center">
|
||||
<a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-sctp-gray.svg?longCache=true&colorB=brightgreen" alt="Pion SCTP"></a>
|
||||
<!--<a href="https://sourcegraph.com/github.com/pion/webrtc?badge"><img src="https://sourcegraph.com/github.com/pion/webrtc/-/badge.svg" alt="Sourcegraph Widget"></a>-->
|
||||
<a href="https://pion.ly/slack"><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/sctp"><img src="https://travis-ci.org/pion/sctp.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/sctp"><img src="https://godoc.org/github.com/pion/sctp?status.svg" alt="GoDoc"></a>
|
||||
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/pion/sctp/test.yaml">
|
||||
<a href="https://pkg.go.dev/github.com/pion/sctp"><img src="https://pkg.go.dev/badge/github.com/pion/sctp.svg" alt="Go Reference"></a>
|
||||
<a href="https://codecov.io/gh/pion/sctp"><img src="https://codecov.io/gh/pion/sctp/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/sctp"><img src="https://goreportcard.com/badge/github.com/pion/sctp" alt="Go Report Card"></a>
|
||||
<!--<a href="https://www.codacy.com/app/Sean-Der/webrtc"><img src="https://api.codacy.com/project/badge/Grade/18f4aec384894e6aac0b94effe51961d" alt="Codacy Badge"></a>-->
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
||||
</p>
|
||||
<br>
|
||||
|
||||
See [DESIGN.md](DESIGN.md) for an overview of features and future goals.
|
||||
|
||||
### Roadmap
|
||||
The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones.
|
||||
|
||||
### Community
|
||||
Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion).
|
||||
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*
|
||||
* [Michiel De Backker](https://github.com/backkem) - *Public API, Initialization*
|
||||
* [Konstantin Itskov](https://github.com/trivigy) - *Fix documentation*
|
||||
* [chenkaiC4](https://github.com/chenkaiC4) - *Fix GolangCI Linter*
|
||||
* [Ronan J](https://github.com/ronanj) - *Fix PPID*
|
||||
* [Michael MacDonald](https://github.com/mjmac) - *Fix races*
|
||||
* [Yutaka Takeda](https://github.com/enobufs) - *PR-SCTP, Retransmissions, Congestion Control*
|
||||
* [Antoine Baché](https://github.com/Antonito) - *SCTP Profiling*
|
||||
* [Cecylia Bocovich](https://github.com/cohosh) - *Fix SCTP reads*
|
||||
* [Hugo Arregui](https://github.com/hugoArregui)
|
||||
* [Atsushi Watanabe](https://github.com/at-wat)
|
||||
* [Lukas Herman](https://github.com/lherman-cs)
|
||||
* [Luke Curley](https://github.com/kixelated) - *Performance*
|
||||
* [Aaron France](https://github.com/AeroNotix)
|
||||
* [ZHENK](https://github.com/scorpionknifes)
|
||||
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
|
||||
|
|
524
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association.go
generated
vendored
524
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association.go
generated
vendored
|
@ -2,6 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
|
@ -12,13 +14,33 @@ import (
|
|||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/randutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Use global random generator to properly seed by crypto grade random.
|
||||
var globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals
|
||||
|
||||
// Association errors
|
||||
var (
|
||||
globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals
|
||||
errChunk = errors.New("Abort chunk, with following errors")
|
||||
ErrChunk = errors.New("abort chunk, with following errors")
|
||||
ErrShutdownNonEstablished = errors.New("shutdown called in non-established state")
|
||||
ErrAssociationClosedBeforeConn = errors.New("association closed before connecting")
|
||||
ErrSilentlyDiscard = errors.New("silently discard")
|
||||
ErrInitNotStoredToSend = errors.New("the init not stored to send")
|
||||
ErrCookieEchoNotStoredToSend = errors.New("cookieEcho not stored to send")
|
||||
ErrSCTPPacketSourcePortZero = errors.New("sctp packet must not have a source port of 0")
|
||||
ErrSCTPPacketDestinationPortZero = errors.New("sctp packet must not have a destination port of 0")
|
||||
ErrInitChunkBundled = errors.New("init chunk must not be bundled with any other chunk")
|
||||
ErrInitChunkVerifyTagNotZero = errors.New("init chunk expects a verification tag of 0 on the packet when out-of-the-blue")
|
||||
ErrHandleInitState = errors.New("todo: handle Init when in state")
|
||||
ErrInitAckNoCookie = errors.New("no cookie in InitAck")
|
||||
ErrInflightQueueTSNPop = errors.New("unable to be popped from inflight queue TSN")
|
||||
ErrTSNRequestNotExist = errors.New("requested non-existent TSN")
|
||||
ErrResetPacketInStateNotExist = errors.New("sending reset packet in non-established state")
|
||||
ErrParamterType = errors.New("unexpected parameter type")
|
||||
ErrPayloadDataStateNotExist = errors.New("sending payload data in non-established state")
|
||||
ErrChunkTypeUnhandled = errors.New("unhandled chunk type")
|
||||
ErrHandshakeInitAck = errors.New("handshake failed (INIT ACK)")
|
||||
ErrHandshakeCookieEcho = errors.New("handshake failed (COOKIE ECHO)")
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -46,6 +68,7 @@ const (
|
|||
const (
|
||||
timerT1Init int = iota
|
||||
timerT1Cookie
|
||||
timerT2Shutdown
|
||||
timerT3RTX
|
||||
timerReconfig
|
||||
)
|
||||
|
@ -60,8 +83,8 @@ const (
|
|||
// ack transmission state
|
||||
const (
|
||||
ackStateIdle int = iota // ack timer is off
|
||||
ackStateImmediate // ack timer is on (ack is being delayed)
|
||||
ackStateDelay // will send ack immediately
|
||||
ackStateImmediate // will send ack immediately
|
||||
ackStateDelay // ack timer is on (ack is being delayed)
|
||||
)
|
||||
|
||||
// other constants
|
||||
|
@ -94,21 +117,17 @@ func getAssociationStateString(a uint32) string {
|
|||
|
||||
// Association represents an SCTP association
|
||||
// 13.2. Parameters Necessary per Association (i.e., the TCB)
|
||||
// Peer : Tag value to be sent in every packet and is received
|
||||
// Verification: in the INIT or INIT ACK chunk.
|
||||
// Tag :
|
||||
//
|
||||
// My : Tag expected in every inbound packet and sent in the
|
||||
// Verification: INIT or INIT ACK chunk.
|
||||
// Peer : Tag value to be sent in every packet and is received
|
||||
// Verification: in the INIT or INIT ACK chunk.
|
||||
// Tag :
|
||||
// State : A state variable indicating what state the association
|
||||
// : is in, i.e., COOKIE-WAIT, COOKIE-ECHOED, ESTABLISHED,
|
||||
// : SHUTDOWN-PENDING, SHUTDOWN-SENT, SHUTDOWN-RECEIVED,
|
||||
// : SHUTDOWN-ACK-SENT.
|
||||
//
|
||||
// Tag :
|
||||
// State : A state variable indicating what state the association
|
||||
// : is in, i.e., COOKIE-WAIT, COOKIE-ECHOED, ESTABLISHED,
|
||||
// : SHUTDOWN-PENDING, SHUTDOWN-SENT, SHUTDOWN-RECEIVED,
|
||||
// : SHUTDOWN-ACK-SENT.
|
||||
//
|
||||
// Note: No "CLOSED" state is illustrated since if a
|
||||
// association is "CLOSED" its TCB SHOULD be removed.
|
||||
// Note: No "CLOSED" state is illustrated since if a
|
||||
// association is "CLOSED" its TCB SHOULD be removed.
|
||||
type Association struct {
|
||||
bytesReceived uint64
|
||||
bytesSent uint64
|
||||
|
@ -127,6 +146,13 @@ type Association struct {
|
|||
willRetransmitFast bool
|
||||
willRetransmitReconfig bool
|
||||
|
||||
willSendShutdown bool
|
||||
willSendShutdownAck bool
|
||||
willSendShutdownComplete bool
|
||||
|
||||
willSendAbort bool
|
||||
willSendAbortCause errorCause
|
||||
|
||||
// Reconfig
|
||||
myNextRSN uint32
|
||||
reconfigs map[uint32]*chunkReconfig
|
||||
|
@ -143,7 +169,8 @@ type Association struct {
|
|||
pendingQueue *pendingQueue
|
||||
controlQueue *controlQueue
|
||||
mtu uint32
|
||||
maxPayloadSize uint32 // max DATA chunk payload size
|
||||
maxPayloadSize uint32 // max DATA chunk payload size
|
||||
srtt atomic.Value // type float64
|
||||
cumulativeTSNAckPoint uint32
|
||||
advancedPeerTSNAckPoint uint32
|
||||
useForwardTSN bool
|
||||
|
@ -159,12 +186,13 @@ type Association struct {
|
|||
fastRecoverExitPoint uint32
|
||||
|
||||
// RTX & Ack timer
|
||||
rtoMgr *rtoManager
|
||||
t1Init *rtxTimer
|
||||
t1Cookie *rtxTimer
|
||||
t3RTX *rtxTimer
|
||||
tReconfig *rtxTimer
|
||||
ackTimer *ackTimer
|
||||
rtoMgr *rtoManager
|
||||
t1Init *rtxTimer
|
||||
t1Cookie *rtxTimer
|
||||
t2Shutdown *rtxTimer
|
||||
t3RTX *rtxTimer
|
||||
tReconfig *rtxTimer
|
||||
ackTimer *ackTimer
|
||||
|
||||
// Chunks stored for retransmission
|
||||
storedInit *chunkInit
|
||||
|
@ -217,7 +245,7 @@ func Server(config Config) (*Association, error) {
|
|||
}
|
||||
return a, nil
|
||||
case <-a.readLoopCloseCh:
|
||||
return nil, errors.Errorf("association closed before connecting")
|
||||
return nil, ErrAssociationClosedBeforeConn
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +261,7 @@ func Client(config Config) (*Association, error) {
|
|||
}
|
||||
return a, nil
|
||||
case <-a.readLoopCloseCh:
|
||||
return nil, errors.Errorf("association closed before connecting")
|
||||
return nil, ErrAssociationClosedBeforeConn
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +309,7 @@ func createAssociation(config Config) *Association {
|
|||
handshakeCompletedCh: make(chan error),
|
||||
cumulativeTSNAckPoint: tsn - 1,
|
||||
advancedPeerTSNAckPoint: tsn - 1,
|
||||
silentError: errors.Errorf("silently discard"),
|
||||
silentError: ErrSilentlyDiscard,
|
||||
stats: &associationStats{},
|
||||
log: config.LoggerFactory.NewLogger("sctp"),
|
||||
}
|
||||
|
@ -296,10 +324,12 @@ func createAssociation(config Config) *Association {
|
|||
a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d inflight=%d (INI)",
|
||||
a.name, a.cwnd, a.ssthresh, a.inflightQueue.getNumBytes())
|
||||
|
||||
a.srtt.Store(float64(0))
|
||||
a.t1Init = newRTXTimer(timerT1Init, a, maxInitRetrans)
|
||||
a.t1Cookie = newRTXTimer(timerT1Cookie, a, maxInitRetrans)
|
||||
a.t3RTX = newRTXTimer(timerT3RTX, a, noMaxRetrans) // retransmit forever
|
||||
a.tReconfig = newRTXTimer(timerReconfig, a, noMaxRetrans) // retransmit forever
|
||||
a.t2Shutdown = newRTXTimer(timerT2Shutdown, a, noMaxRetrans) // retransmit forever
|
||||
a.t3RTX = newRTXTimer(timerT3RTX, a, noMaxRetrans) // retransmit forever
|
||||
a.tReconfig = newRTXTimer(timerReconfig, a, noMaxRetrans) // retransmit forever
|
||||
a.ackTimer = newAckTimer(a)
|
||||
|
||||
return a
|
||||
|
@ -336,7 +366,7 @@ func (a *Association) init(isClient bool) {
|
|||
func (a *Association) sendInit() error {
|
||||
a.log.Debugf("[%s] sending INIT", a.name)
|
||||
if a.storedInit == nil {
|
||||
return errors.Errorf("the init not stored to send")
|
||||
return ErrInitNotStoredToSend
|
||||
}
|
||||
|
||||
outbound := &packet{}
|
||||
|
@ -357,7 +387,7 @@ func (a *Association) sendInit() error {
|
|||
// caller must hold a.lock
|
||||
func (a *Association) sendCookieEcho() error {
|
||||
if a.storedCookieEcho == nil {
|
||||
return errors.Errorf("cookieEcho not stored to send")
|
||||
return ErrCookieEchoNotStoredToSend
|
||||
}
|
||||
|
||||
a.log.Debugf("[%s] sending COOKIE-ECHO", a.name)
|
||||
|
@ -374,10 +404,62 @@ func (a *Association) sendCookieEcho() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Shutdown initiates the shutdown sequence. The method blocks until the
|
||||
// shutdown sequence is completed and the connection is closed, or until the
|
||||
// passed context is done, in which case the context's error is returned.
|
||||
func (a *Association) Shutdown(ctx context.Context) error {
|
||||
a.log.Debugf("[%s] closing association..", a.name)
|
||||
|
||||
state := a.getState()
|
||||
|
||||
if state != established {
|
||||
return fmt.Errorf("%w: shutdown %s", ErrShutdownNonEstablished, a.name)
|
||||
}
|
||||
|
||||
// Attempt a graceful shutdown.
|
||||
a.setState(shutdownPending)
|
||||
|
||||
a.lock.Lock()
|
||||
|
||||
if a.inflightQueue.size() == 0 {
|
||||
// No more outstanding, send shutdown.
|
||||
a.willSendShutdown = true
|
||||
a.awakeWriteLoop()
|
||||
a.setState(shutdownSent)
|
||||
}
|
||||
|
||||
a.lock.Unlock()
|
||||
|
||||
select {
|
||||
case <-a.closeWriteLoopCh:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
// Close ends the SCTP Association and cleans up any state
|
||||
func (a *Association) Close() error {
|
||||
a.log.Debugf("[%s] closing association..", a.name)
|
||||
|
||||
err := a.close()
|
||||
|
||||
// Wait for readLoop to end
|
||||
<-a.readLoopCloseCh
|
||||
|
||||
a.log.Debugf("[%s] association closed", a.name)
|
||||
a.log.Debugf("[%s] stats nDATAs (in) : %d", a.name, a.stats.getNumDATAs())
|
||||
a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKs())
|
||||
a.log.Debugf("[%s] stats nT3Timeouts : %d", a.name, a.stats.getNumT3Timeouts())
|
||||
a.log.Debugf("[%s] stats nAckTimeouts: %d", a.name, a.stats.getNumAckTimeouts())
|
||||
a.log.Debugf("[%s] stats nFastRetrans: %d", a.name, a.stats.getNumFastRetrans())
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *Association) close() error {
|
||||
a.log.Debugf("[%s] closing association..", a.name)
|
||||
|
||||
a.setState(closed)
|
||||
|
||||
err := a.netConn.Close()
|
||||
|
@ -387,22 +469,34 @@ func (a *Association) Close() error {
|
|||
// awake writeLoop to exit
|
||||
a.closeWriteLoopOnce.Do(func() { close(a.closeWriteLoopCh) })
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Abort sends the abort packet with user initiated abort and immediately
|
||||
// closes the connection.
|
||||
func (a *Association) Abort(reason string) {
|
||||
a.log.Debugf("[%s] aborting association: %s", a.name, reason)
|
||||
|
||||
a.lock.Lock()
|
||||
|
||||
a.willSendAbort = true
|
||||
a.willSendAbortCause = &errorCauseUserInitiatedAbort{
|
||||
upperLayerAbortReason: []byte(reason),
|
||||
}
|
||||
|
||||
a.lock.Unlock()
|
||||
|
||||
a.awakeWriteLoop()
|
||||
|
||||
// Wait for readLoop to end
|
||||
<-a.readLoopCloseCh
|
||||
|
||||
a.log.Debugf("[%s] association closed", a.name)
|
||||
a.log.Debugf("[%s] stats nDATAs (in) : %d", a.name, a.stats.getNumDATAs())
|
||||
a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKs())
|
||||
a.log.Debugf("[%s] stats nT3Timeouts : %d", a.name, a.stats.getNumT3Timeouts())
|
||||
a.log.Debugf("[%s] stats nAckTimeouts: %d", a.name, a.stats.getNumAckTimeouts())
|
||||
a.log.Debugf("[%s] stats nFastRetrans: %d", a.name, a.stats.getNumFastRetrans())
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *Association) closeAllTimers() {
|
||||
// Close all retransmission & ack timers
|
||||
a.t1Init.close()
|
||||
a.t1Cookie.close()
|
||||
a.t2Shutdown.close()
|
||||
a.t3RTX.close()
|
||||
a.tReconfig.close()
|
||||
a.ackTimer.close()
|
||||
|
@ -422,6 +516,13 @@ func (a *Association) readLoop() {
|
|||
a.lock.Unlock()
|
||||
close(a.acceptCh)
|
||||
close(a.readLoopCloseCh)
|
||||
|
||||
a.log.Debugf("[%s] association closed", a.name)
|
||||
a.log.Debugf("[%s] stats nDATAs (in) : %d", a.name, a.stats.getNumDATAs())
|
||||
a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKs())
|
||||
a.log.Debugf("[%s] stats nT3Timeouts : %d", a.name, a.stats.getNumT3Timeouts())
|
||||
a.log.Debugf("[%s] stats nAckTimeouts: %d", a.name, a.stats.getNumAckTimeouts())
|
||||
a.log.Debugf("[%s] stats nFastRetrans: %d", a.name, a.stats.getNumFastRetrans())
|
||||
}()
|
||||
|
||||
a.log.Debugf("[%s] readLoop entered", a.name)
|
||||
|
@ -451,15 +552,16 @@ func (a *Association) readLoop() {
|
|||
|
||||
func (a *Association) writeLoop() {
|
||||
a.log.Debugf("[%s] writeLoop entered", a.name)
|
||||
defer a.log.Debugf("[%s] writeLoop exited", a.name)
|
||||
|
||||
loop:
|
||||
for {
|
||||
rawPackets := a.gatherOutbound()
|
||||
rawPackets, ok := a.gatherOutbound()
|
||||
|
||||
for _, raw := range rawPackets {
|
||||
_, err := a.netConn.Write(raw)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
if !errors.Is(err, io.EOF) {
|
||||
a.log.Warnf("[%s] failed to write packets on netConn: %v", a.name, err)
|
||||
}
|
||||
a.log.Debugf("[%s] writeLoop ended", a.name)
|
||||
|
@ -468,6 +570,14 @@ loop:
|
|||
atomic.AddUint64(&a.bytesSent, uint64(len(raw)))
|
||||
}
|
||||
|
||||
if !ok {
|
||||
if err := a.close(); err != nil {
|
||||
a.log.Warnf("[%s] failed to close association: %v", a.name, err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-a.awakeWriteLoopCh:
|
||||
case <-a.closeWriteLoopCh:
|
||||
|
@ -477,8 +587,6 @@ loop:
|
|||
|
||||
a.setState(closed)
|
||||
a.closeAllTimers()
|
||||
|
||||
a.log.Debugf("[%s] writeLoop exited", a.name)
|
||||
}
|
||||
|
||||
func (a *Association) awakeWriteLoop() {
|
||||
|
@ -526,7 +634,7 @@ func (a *Association) handleInbound(raw []byte) error {
|
|||
}
|
||||
|
||||
// The caller should hold the lock
|
||||
func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte) [][]byte {
|
||||
func (a *Association) gatherDataPacketsToRetransmit(rawPackets [][]byte) [][]byte {
|
||||
for _, p := range a.getDataPacketsToRetransmit() {
|
||||
raw, err := p.marshal()
|
||||
if err != nil {
|
||||
|
@ -536,6 +644,11 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte)
|
|||
rawPackets = append(rawPackets, raw)
|
||||
}
|
||||
|
||||
return rawPackets
|
||||
}
|
||||
|
||||
// The caller should hold the lock
|
||||
func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte) [][]byte {
|
||||
// Pop unsent data chunks from the pending queue to send as much as
|
||||
// cwnd and rwnd allow.
|
||||
chunks, sisToReset := a.popPendingDataChunksToSend()
|
||||
|
@ -599,7 +712,7 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte)
|
|||
}
|
||||
|
||||
// The caller should hold the lock
|
||||
func (a *Association) gatherOutboundFrastRetransmissionPackets(rawPackets [][]byte) [][]byte {
|
||||
func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byte) [][]byte {
|
||||
if a.willRetransmitFast {
|
||||
a.willRetransmitFast = false
|
||||
|
||||
|
@ -662,7 +775,7 @@ func (a *Association) gatherOutboundSackPackets(rawPackets [][]byte) [][]byte {
|
|||
if a.ackState == ackStateImmediate {
|
||||
a.ackState = ackStateIdle
|
||||
sack := a.createSelectiveAckChunk()
|
||||
a.log.Debugf("[%s] sending SACK: %s", a.name, sack.String())
|
||||
a.log.Debugf("[%s] sending SACK: %s", a.name, sack)
|
||||
raw, err := a.createPacket([]chunk{sack}).marshal()
|
||||
if err != nil {
|
||||
a.log.Warnf("[%s] failed to serialize a SACK packet", a.name)
|
||||
|
@ -692,11 +805,86 @@ func (a *Association) gatherOutboundForwardTSNPackets(rawPackets [][]byte) [][]b
|
|||
return rawPackets
|
||||
}
|
||||
|
||||
// gatherOutbound gathers outgoing packets
|
||||
func (a *Association) gatherOutbound() [][]byte {
|
||||
func (a *Association) gatherOutboundShutdownPackets(rawPackets [][]byte) ([][]byte, bool) {
|
||||
ok := true
|
||||
|
||||
switch {
|
||||
case a.willSendShutdown:
|
||||
a.willSendShutdown = false
|
||||
|
||||
shutdown := &chunkShutdown{
|
||||
cumulativeTSNAck: a.cumulativeTSNAckPoint,
|
||||
}
|
||||
|
||||
raw, err := a.createPacket([]chunk{shutdown}).marshal()
|
||||
if err != nil {
|
||||
a.log.Warnf("[%s] failed to serialize a Shutdown packet", a.name)
|
||||
} else {
|
||||
a.t2Shutdown.start(a.rtoMgr.getRTO())
|
||||
rawPackets = append(rawPackets, raw)
|
||||
}
|
||||
case a.willSendShutdownAck:
|
||||
a.willSendShutdownAck = false
|
||||
|
||||
shutdownAck := &chunkShutdownAck{}
|
||||
|
||||
raw, err := a.createPacket([]chunk{shutdownAck}).marshal()
|
||||
if err != nil {
|
||||
a.log.Warnf("[%s] failed to serialize a ShutdownAck packet", a.name)
|
||||
} else {
|
||||
a.t2Shutdown.start(a.rtoMgr.getRTO())
|
||||
rawPackets = append(rawPackets, raw)
|
||||
}
|
||||
case a.willSendShutdownComplete:
|
||||
a.willSendShutdownComplete = false
|
||||
|
||||
shutdownComplete := &chunkShutdownComplete{}
|
||||
|
||||
raw, err := a.createPacket([]chunk{shutdownComplete}).marshal()
|
||||
if err != nil {
|
||||
a.log.Warnf("[%s] failed to serialize a ShutdownComplete packet", a.name)
|
||||
} else {
|
||||
rawPackets = append(rawPackets, raw)
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
|
||||
return rawPackets, ok
|
||||
}
|
||||
|
||||
func (a *Association) gatherAbortPacket() ([]byte, error) {
|
||||
cause := a.willSendAbortCause
|
||||
|
||||
a.willSendAbort = false
|
||||
a.willSendAbortCause = nil
|
||||
|
||||
abort := &chunkAbort{}
|
||||
|
||||
if cause != nil {
|
||||
abort.errorCauses = []errorCause{cause}
|
||||
}
|
||||
|
||||
raw, err := a.createPacket([]chunk{abort}).marshal()
|
||||
|
||||
return raw, err
|
||||
}
|
||||
|
||||
// gatherOutbound gathers outgoing packets. The returned bool value set to
|
||||
// false means the association should be closed down after the final send.
|
||||
func (a *Association) gatherOutbound() ([][]byte, bool) {
|
||||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
|
||||
if a.willSendAbort {
|
||||
pkt, err := a.gatherAbortPacket()
|
||||
if err != nil {
|
||||
a.log.Warnf("[%s] failed to serialize an abort packet", a.name)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return [][]byte{pkt}, false
|
||||
}
|
||||
|
||||
rawPackets := [][]byte{}
|
||||
|
||||
if a.controlQueue.size() > 0 {
|
||||
|
@ -712,14 +900,25 @@ func (a *Association) gatherOutbound() [][]byte {
|
|||
|
||||
state := a.getState()
|
||||
|
||||
if state == established {
|
||||
ok := true
|
||||
|
||||
switch state {
|
||||
case established:
|
||||
rawPackets = a.gatherDataPacketsToRetransmit(rawPackets)
|
||||
rawPackets = a.gatherOutboundDataAndReconfigPackets(rawPackets)
|
||||
rawPackets = a.gatherOutboundFrastRetransmissionPackets(rawPackets)
|
||||
rawPackets = a.gatherOutboundFastRetransmissionPackets(rawPackets)
|
||||
rawPackets = a.gatherOutboundSackPackets(rawPackets)
|
||||
rawPackets = a.gatherOutboundForwardTSNPackets(rawPackets)
|
||||
case shutdownPending, shutdownSent, shutdownReceived:
|
||||
rawPackets = a.gatherDataPacketsToRetransmit(rawPackets)
|
||||
rawPackets = a.gatherOutboundFastRetransmissionPackets(rawPackets)
|
||||
rawPackets = a.gatherOutboundSackPackets(rawPackets)
|
||||
rawPackets, ok = a.gatherOutboundShutdownPackets(rawPackets)
|
||||
case shutdownAckSent:
|
||||
rawPackets, ok = a.gatherOutboundShutdownPackets(rawPackets)
|
||||
}
|
||||
|
||||
return rawPackets
|
||||
return rawPackets, ok
|
||||
}
|
||||
|
||||
func checkPacket(p *packet) error {
|
||||
|
@ -731,7 +930,7 @@ func checkPacket(p *packet) error {
|
|||
// identify the association to which this packet belongs. The port
|
||||
// number 0 MUST NOT be used.
|
||||
if p.sourcePort == 0 {
|
||||
return errors.Errorf("sctp packet must not have a source port of 0")
|
||||
return ErrSCTPPacketSourcePortZero
|
||||
}
|
||||
|
||||
// This is the SCTP port number to which this packet is destined.
|
||||
|
@ -739,7 +938,7 @@ func checkPacket(p *packet) error {
|
|||
// SCTP packet to the correct receiving endpoint/application. The
|
||||
// port number 0 MUST NOT be used.
|
||||
if p.destinationPort == 0 {
|
||||
return errors.Errorf("sctp packet must not have a destination port of 0")
|
||||
return ErrSCTPPacketDestinationPortZero
|
||||
}
|
||||
|
||||
// Check values on the packet that are specific to a particular chunk type
|
||||
|
@ -750,13 +949,13 @@ func checkPacket(p *packet) error {
|
|||
// They MUST be the only chunks present in the SCTP packets that carry
|
||||
// them.
|
||||
if len(p.chunks) != 1 {
|
||||
return errors.Errorf("init chunk must not be bundled with any other chunk")
|
||||
return ErrInitChunkBundled
|
||||
}
|
||||
|
||||
// A packet containing an INIT chunk MUST have a zero Verification
|
||||
// Tag.
|
||||
if p.verificationTag != 0 {
|
||||
return errors.Errorf("init chunk expects a verification tag of 0 on the packet when out-of-the-blue")
|
||||
return ErrInitChunkVerifyTagNotZero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -812,6 +1011,26 @@ func (a *Association) BytesReceived() uint64 {
|
|||
return atomic.LoadUint64(&a.bytesReceived)
|
||||
}
|
||||
|
||||
// MTU returns the association's current MTU
|
||||
func (a *Association) MTU() uint32 {
|
||||
return atomic.LoadUint32(&a.mtu)
|
||||
}
|
||||
|
||||
// CWND returns the association's current congestion window (cwnd)
|
||||
func (a *Association) CWND() uint32 {
|
||||
return atomic.LoadUint32(&a.cwnd)
|
||||
}
|
||||
|
||||
// RWND returns the association's current receiver window (rwnd)
|
||||
func (a *Association) RWND() uint32 {
|
||||
return atomic.LoadUint32(&a.rwnd)
|
||||
}
|
||||
|
||||
// SRTT returns the latest smoothed round-trip time (srrt)
|
||||
func (a *Association) SRTT() float64 {
|
||||
return a.srtt.Load().(float64) //nolint:forcetypeassert
|
||||
}
|
||||
|
||||
func setSupportedExtensions(init *chunkInitCommon) {
|
||||
// nolint:godox
|
||||
// TODO RFC5061 https://tools.ietf.org/html/rfc6525#section-5.2
|
||||
|
@ -838,7 +1057,7 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) {
|
|||
if state != closed && state != cookieWait && state != cookieEchoed {
|
||||
// 5.2.2. Unexpected INIT in States Other than CLOSED, COOKIE-ECHOED,
|
||||
// COOKIE-WAIT, and SHUTDOWN-ACK-SENT
|
||||
return nil, errors.Errorf("todo: handle Init when in state %s", getAssociationStateString(state))
|
||||
return nil, fmt.Errorf("%w: %s", ErrHandleInitState, getAssociationStateString(state))
|
||||
}
|
||||
|
||||
// Should we be setting any of these permanently until we've ACKed further?
|
||||
|
@ -859,14 +1078,14 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) {
|
|||
case *paramSupportedExtensions:
|
||||
for _, t := range v.ChunkTypes {
|
||||
if t == ctForwardTSN {
|
||||
a.log.Debugf("[%s] use ForwardTSN (on init)\n", a.name)
|
||||
a.log.Debugf("[%s] use ForwardTSN (on init)", a.name)
|
||||
a.useForwardTSN = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !a.useForwardTSN {
|
||||
a.log.Warnf("[%s] not using ForwardTSN (on init)\n", a.name)
|
||||
a.log.Warnf("[%s] not using ForwardTSN (on init)", a.name)
|
||||
}
|
||||
|
||||
outbound := &packet{}
|
||||
|
@ -944,17 +1163,17 @@ func (a *Association) handleInitAck(p *packet, i *chunkInitAck) error {
|
|||
case *paramSupportedExtensions:
|
||||
for _, t := range v.ChunkTypes {
|
||||
if t == ctForwardTSN {
|
||||
a.log.Debugf("[%s] use ForwardTSN (on initAck)\n", a.name)
|
||||
a.log.Debugf("[%s] use ForwardTSN (on initAck)", a.name)
|
||||
a.useForwardTSN = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !a.useForwardTSN {
|
||||
a.log.Warnf("[%s] not using ForwardTSN (on initAck)\n", a.name)
|
||||
a.log.Warnf("[%s] not using ForwardTSN (on initAck)", a.name)
|
||||
}
|
||||
if cookieParam == nil {
|
||||
return errors.Errorf("no cookie in InitAck")
|
||||
return ErrInitAckNoCookie
|
||||
}
|
||||
|
||||
a.storedCookieEcho = &chunkCookieEcho{}
|
||||
|
@ -996,6 +1215,11 @@ func (a *Association) handleHeartbeat(c *chunkHeartbeat) []*packet {
|
|||
func (a *Association) handleCookieEcho(c *chunkCookieEcho) []*packet {
|
||||
state := a.getState()
|
||||
a.log.Debugf("[%s] COOKIE-ECHO received in state '%s'", a.name, getAssociationStateString(state))
|
||||
|
||||
if a.myCookie == nil {
|
||||
a.log.Debugf("[%s] COOKIE-ECHO received before initialization", a.name)
|
||||
return nil
|
||||
}
|
||||
switch state {
|
||||
default:
|
||||
return nil
|
||||
|
@ -1054,7 +1278,7 @@ func (a *Association) handleData(d *chunkPayloadData) []*packet {
|
|||
|
||||
canPush := a.payloadQueue.canPush(d, a.peerLastTSN)
|
||||
if canPush {
|
||||
s := a.getOrCreateStream(d.streamIdentifier)
|
||||
s := a.getOrCreateStream(d.streamIdentifier, true, PayloadTypeUnknown)
|
||||
if s == nil {
|
||||
// silentely discard the data. (sender will retry on T3-rtx timeout)
|
||||
// see pion/sctp#30
|
||||
|
@ -1145,14 +1369,7 @@ func (a *Association) OpenStream(streamIdentifier uint16, defaultPayloadType Pay
|
|||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
|
||||
if _, ok := a.streams[streamIdentifier]; ok {
|
||||
return nil, errors.Errorf("there already exists a stream with identifier %d", streamIdentifier)
|
||||
}
|
||||
|
||||
s := a.createStream(streamIdentifier, false)
|
||||
s.setDefaultPayloadType(defaultPayloadType)
|
||||
|
||||
return s, nil
|
||||
return a.getOrCreateStream(streamIdentifier, false, defaultPayloadType), nil
|
||||
}
|
||||
|
||||
// AcceptStream accepts a stream
|
||||
|
@ -1195,12 +1412,17 @@ func (a *Association) createStream(streamIdentifier uint16, accept bool) *Stream
|
|||
}
|
||||
|
||||
// getOrCreateStream gets or creates a stream. The caller should hold the lock.
|
||||
func (a *Association) getOrCreateStream(streamIdentifier uint16) *Stream {
|
||||
func (a *Association) getOrCreateStream(streamIdentifier uint16, accept bool, defaultPayloadType PayloadProtocolIdentifier) *Stream {
|
||||
if s, ok := a.streams[streamIdentifier]; ok {
|
||||
s.SetDefaultPayloadType(defaultPayloadType)
|
||||
return s
|
||||
}
|
||||
|
||||
return a.createStream(streamIdentifier, true)
|
||||
s := a.createStream(streamIdentifier, accept)
|
||||
if s != nil {
|
||||
s.SetDefaultPayloadType(defaultPayloadType)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// The caller should hold the lock.
|
||||
|
@ -1213,7 +1435,7 @@ func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int,
|
|||
for i := a.cumulativeTSNAckPoint + 1; sna32LTE(i, d.cumulativeTSNAck); i++ {
|
||||
c, ok := a.inflightQueue.pop(i)
|
||||
if !ok {
|
||||
return nil, 0, errors.Errorf("tsn %v unable to be popped from inflight queue", i)
|
||||
return nil, 0, fmt.Errorf("%w: %v", ErrInflightQueueTSNPop, i)
|
||||
}
|
||||
|
||||
if !c.acked {
|
||||
|
@ -1249,6 +1471,7 @@ func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int,
|
|||
a.minTSN2MeasureRTT = a.myNextTSN
|
||||
rtt := time.Since(c.since).Seconds() * 1000.0
|
||||
srtt := a.rtoMgr.setNewRTT(rtt)
|
||||
a.srtt.Store(srtt)
|
||||
a.log.Tracef("[%s] SACK: measured-rtt=%f srtt=%f new-rto=%f",
|
||||
a.name, rtt, srtt, a.rtoMgr.getRTO())
|
||||
}
|
||||
|
@ -1268,7 +1491,7 @@ func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int,
|
|||
tsn := d.cumulativeTSNAck + uint32(i)
|
||||
c, ok := a.inflightQueue.get(tsn)
|
||||
if !ok {
|
||||
return nil, 0, errors.Errorf("requested non-existent TSN %v", tsn)
|
||||
return nil, 0, fmt.Errorf("%w: %v", ErrTSNRequestNotExist, tsn)
|
||||
}
|
||||
|
||||
if !c.acked {
|
||||
|
@ -1287,6 +1510,7 @@ func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int,
|
|||
a.minTSN2MeasureRTT = a.myNextTSN
|
||||
rtt := time.Since(c.since).Seconds() * 1000.0
|
||||
srtt := a.rtoMgr.setNewRTT(rtt)
|
||||
a.srtt.Store(srtt)
|
||||
a.log.Tracef("[%s] SACK: measured-rtt=%f srtt=%f new-rto=%f",
|
||||
a.name, rtt, srtt, a.rtoMgr.getRTO())
|
||||
}
|
||||
|
@ -1384,7 +1608,7 @@ func (a *Association) processFastRetransmission(cumTSNAckPoint, htna uint32, cum
|
|||
for tsn := cumTSNAckPoint + 1; sna32LT(tsn, maxTSN); tsn++ {
|
||||
c, ok := a.inflightQueue.get(tsn)
|
||||
if !ok {
|
||||
return errors.Errorf("requested non-existent TSN %v", tsn)
|
||||
return fmt.Errorf("%w: %v", ErrTSNRequestNotExist, tsn)
|
||||
}
|
||||
if !c.acked && !c.abandoned() && c.missIndicator < 3 {
|
||||
c.missIndicator++
|
||||
|
@ -1419,7 +1643,7 @@ func (a *Association) processFastRetransmission(cumTSNAckPoint, htna uint32, cum
|
|||
func (a *Association) handleSack(d *chunkSelectiveAck) error {
|
||||
a.log.Tracef("[%s] SACK: cumTSN=%d a_rwnd=%d", a.name, d.cumulativeTSNAck, d.advertisedReceiverWindowCredit)
|
||||
state := a.getState()
|
||||
if state != established {
|
||||
if state != established && state != shutdownPending && state != shutdownReceived {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1518,19 +1742,94 @@ func (a *Association) handleSack(d *chunkSelectiveAck) error {
|
|||
a.awakeWriteLoop()
|
||||
}
|
||||
|
||||
if a.inflightQueue.size() > 0 {
|
||||
a.postprocessSack(state, cumTSNAckPointAdvanced)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// The caller must hold the lock. This method was only added because the
|
||||
// linter was complaining about the "cognitive complexity" of handleSack.
|
||||
func (a *Association) postprocessSack(state uint32, shouldAwakeWriteLoop bool) {
|
||||
switch {
|
||||
case a.inflightQueue.size() > 0:
|
||||
// Start timer. (noop if already started)
|
||||
a.log.Tracef("[%s] T3-rtx timer start (pt3)", a.name)
|
||||
a.t3RTX.start(a.rtoMgr.getRTO())
|
||||
case state == shutdownPending:
|
||||
// No more outstanding, send shutdown.
|
||||
shouldAwakeWriteLoop = true
|
||||
a.willSendShutdown = true
|
||||
a.setState(shutdownSent)
|
||||
case state == shutdownReceived:
|
||||
// No more outstanding, send shutdown ack.
|
||||
shouldAwakeWriteLoop = true
|
||||
a.willSendShutdownAck = true
|
||||
a.setState(shutdownAckSent)
|
||||
}
|
||||
|
||||
if cumTSNAckPointAdvanced {
|
||||
if shouldAwakeWriteLoop {
|
||||
a.awakeWriteLoop()
|
||||
}
|
||||
}
|
||||
|
||||
// The caller should hold the lock.
|
||||
func (a *Association) handleShutdown(_ *chunkShutdown) {
|
||||
state := a.getState()
|
||||
|
||||
switch state {
|
||||
case established:
|
||||
if a.inflightQueue.size() > 0 {
|
||||
a.setState(shutdownReceived)
|
||||
} else {
|
||||
// No more outstanding, send shutdown ack.
|
||||
a.willSendShutdownAck = true
|
||||
a.setState(shutdownAckSent)
|
||||
|
||||
a.awakeWriteLoop()
|
||||
}
|
||||
|
||||
// a.cumulativeTSNAckPoint = c.cumulativeTSNAck
|
||||
case shutdownSent:
|
||||
a.willSendShutdownAck = true
|
||||
a.setState(shutdownAckSent)
|
||||
|
||||
a.awakeWriteLoop()
|
||||
}
|
||||
}
|
||||
|
||||
// The caller should hold the lock.
|
||||
func (a *Association) handleShutdownAck(_ *chunkShutdownAck) {
|
||||
state := a.getState()
|
||||
if state == shutdownSent || state == shutdownAckSent {
|
||||
a.t2Shutdown.stop()
|
||||
a.willSendShutdownComplete = true
|
||||
|
||||
a.awakeWriteLoop()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Association) handleShutdownComplete(_ *chunkShutdownComplete) error {
|
||||
state := a.getState()
|
||||
if state == shutdownAckSent {
|
||||
a.t2Shutdown.stop()
|
||||
|
||||
return a.close()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Association) handleAbort(c *chunkAbort) error {
|
||||
var errStr string
|
||||
for _, e := range c.errorCauses {
|
||||
errStr += fmt.Sprintf("(%s)", e)
|
||||
}
|
||||
|
||||
_ = a.close()
|
||||
|
||||
return fmt.Errorf("[%s] %w: %s", a.name, ErrChunk, errStr)
|
||||
}
|
||||
|
||||
// createForwardTSN generates ForwardTSN chunk.
|
||||
// This method will be be called if useForwardTSN is set to false.
|
||||
// The caller should hold the lock.
|
||||
|
@ -1633,7 +1932,7 @@ func (a *Association) handleForwardTSN(c *chunkForwardTSN) []*packet {
|
|||
// send a SACK to its peer (the sender of the FORWARD TSN) since such a
|
||||
// duplicate may indicate the previous SACK was lost in the network.
|
||||
|
||||
a.log.Tracef("[%s] should send ack? newCumTSN=%d peerLastTSN=%d\n",
|
||||
a.log.Tracef("[%s] should send ack? newCumTSN=%d peerLastTSN=%d",
|
||||
a.name, c.newCumulativeTSN, a.peerLastTSN)
|
||||
if sna32LTE(c.newCumulativeTSN, a.peerLastTSN) {
|
||||
a.log.Tracef("[%s] sending ack on Forward TSN", a.name)
|
||||
|
@ -1686,7 +1985,7 @@ func (a *Association) sendResetRequest(streamIdentifier uint16) error {
|
|||
|
||||
state := a.getState()
|
||||
if state != established {
|
||||
return errors.Errorf("sending reset packet in non-established state: state=%s",
|
||||
return fmt.Errorf("%w: state=%s", ErrResetPacketInStateNotExist,
|
||||
getAssociationStateString(state))
|
||||
}
|
||||
|
||||
|
@ -1708,21 +2007,23 @@ func (a *Association) sendResetRequest(streamIdentifier uint16) error {
|
|||
func (a *Association) handleReconfigParam(raw param) (*packet, error) {
|
||||
switch p := raw.(type) {
|
||||
case *paramOutgoingResetRequest:
|
||||
a.log.Tracef("[%s] handleReconfigParam (OutgoingResetRequest)", a.name)
|
||||
a.reconfigRequests[p.reconfigRequestSequenceNumber] = p
|
||||
resp := a.resetStreamsIfAny(p)
|
||||
if resp != nil {
|
||||
return resp, nil
|
||||
}
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
|
||||
case *paramReconfigResponse:
|
||||
a.log.Tracef("[%s] handleReconfigParam (ReconfigResponse)", a.name)
|
||||
delete(a.reconfigs, p.reconfigResponseSequenceNumber)
|
||||
if len(a.reconfigs) == 0 {
|
||||
a.tReconfig.stop()
|
||||
}
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil
|
||||
default:
|
||||
return nil, errors.Errorf("unexpected parameter type %T", p)
|
||||
return nil, fmt.Errorf("%w: %t", ErrParamterType, p)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1737,7 +2038,11 @@ func (a *Association) resetStreamsIfAny(p *paramOutgoingResetRequest) *packet {
|
|||
if !ok {
|
||||
continue
|
||||
}
|
||||
a.unregisterStream(s, io.EOF)
|
||||
a.lock.Unlock()
|
||||
s.onInboundStreamReset()
|
||||
a.lock.Lock()
|
||||
a.log.Debugf("[%s] deleting stream %d", a.name, id)
|
||||
delete(a.streams, s.streamIdentifier)
|
||||
}
|
||||
delete(a.reconfigRequests, p.reconfigRequestSequenceNumber)
|
||||
} else {
|
||||
|
@ -1777,7 +2082,6 @@ func (a *Association) movePendingDataChunkToInflightQueue(c *chunkPayloadData) {
|
|||
a.log.Tracef("[%s] sending ppi=%d tsn=%d ssn=%d sent=%d len=%d (%v,%v)",
|
||||
a.name, c.payloadType, c.tsn, c.streamSequenceNumber, c.nSent, len(c.userData), c.beginningFragment, c.endingFragment)
|
||||
|
||||
// Push it into the inflightQueue
|
||||
a.inflightQueue.pushNoCheck(c)
|
||||
}
|
||||
|
||||
|
@ -1880,7 +2184,7 @@ func (a *Association) sendPayloadData(chunks []*chunkPayloadData) error {
|
|||
|
||||
state := a.getState()
|
||||
if state != established {
|
||||
return errors.Errorf("sending payload data in non-established state: state=%s",
|
||||
return fmt.Errorf("%w: state=%s", ErrPayloadDataStateNotExist,
|
||||
getAssociationStateString(state))
|
||||
}
|
||||
|
||||
|
@ -2014,7 +2318,6 @@ func (a *Association) handleChunkEnd() {
|
|||
defer a.lock.Unlock()
|
||||
|
||||
if a.immediateAckTriggered {
|
||||
// Send SACK now!
|
||||
a.ackState = ackStateImmediate
|
||||
a.ackTimer.stop()
|
||||
a.awakeWriteLoop()
|
||||
|
@ -2037,6 +2340,8 @@ func (a *Association) handleChunk(p *packet, c chunk) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
isAbort := false
|
||||
|
||||
switch c := c.(type) {
|
||||
case *chunkInit:
|
||||
packets, err = a.handleInit(p, c)
|
||||
|
@ -2045,11 +2350,8 @@ func (a *Association) handleChunk(p *packet, c chunk) error {
|
|||
err = a.handleInitAck(p, c)
|
||||
|
||||
case *chunkAbort:
|
||||
var errStr string
|
||||
for _, e := range c.errorCauses {
|
||||
errStr += fmt.Sprintf("(%s)", e)
|
||||
}
|
||||
return fmt.Errorf("[%s] %w: %s", a.name, errChunk, errStr)
|
||||
isAbort = true
|
||||
err = a.handleAbort(c)
|
||||
|
||||
case *chunkError:
|
||||
var errStr string
|
||||
|
@ -2079,12 +2381,23 @@ func (a *Association) handleChunk(p *packet, c chunk) error {
|
|||
case *chunkForwardTSN:
|
||||
packets = a.handleForwardTSN(c)
|
||||
|
||||
case *chunkShutdown:
|
||||
a.handleShutdown(c)
|
||||
case *chunkShutdownAck:
|
||||
a.handleShutdownAck(c)
|
||||
case *chunkShutdownComplete:
|
||||
err = a.handleShutdownComplete(c)
|
||||
|
||||
default:
|
||||
err = errors.Errorf("unhandled chunk type")
|
||||
err = ErrChunkTypeUnhandled
|
||||
}
|
||||
|
||||
// Log and return, the only condition that is fatal is a ABORT chunk
|
||||
if err != nil {
|
||||
if isAbort {
|
||||
return err
|
||||
}
|
||||
|
||||
a.log.Errorf("Failed to handle chunk: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
@ -2117,6 +2430,20 @@ func (a *Association) onRetransmissionTimeout(id int, nRtos uint) {
|
|||
return
|
||||
}
|
||||
|
||||
if id == timerT2Shutdown {
|
||||
a.log.Debugf("[%s] retransmission of shutdown timeout (nRtos=%d): %v", a.name, nRtos)
|
||||
state := a.getState()
|
||||
|
||||
switch state {
|
||||
case shutdownSent:
|
||||
a.willSendShutdown = true
|
||||
a.awakeWriteLoop()
|
||||
case shutdownAckSent:
|
||||
a.willSendShutdownAck = true
|
||||
a.awakeWriteLoop()
|
||||
}
|
||||
}
|
||||
|
||||
if id == timerT3RTX {
|
||||
a.stats.incT3Timeouts()
|
||||
|
||||
|
@ -2190,13 +2517,18 @@ func (a *Association) onRetransmissionFailure(id int) {
|
|||
|
||||
if id == timerT1Init {
|
||||
a.log.Errorf("[%s] retransmission failure: T1-init", a.name)
|
||||
a.handshakeCompletedCh <- errors.Errorf("handshake failed (INIT ACK)")
|
||||
a.handshakeCompletedCh <- ErrHandshakeInitAck
|
||||
return
|
||||
}
|
||||
|
||||
if id == timerT1Cookie {
|
||||
a.log.Errorf("[%s] retransmission failure: T1-cookie", a.name)
|
||||
a.handshakeCompletedCh <- errors.Errorf("handshake failed (COOKIE ECHO)")
|
||||
a.handshakeCompletedCh <- ErrHandshakeCookieEcho
|
||||
return
|
||||
}
|
||||
|
||||
if id == timerT2Shutdown {
|
||||
a.log.Errorf("[%s] retransmission failure: T2-shutdown", a.name)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
31
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_abort.go
generated
vendored
31
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_abort.go
generated
vendored
|
@ -1,9 +1,8 @@
|
|||
package sctp // nolint:dupl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -17,28 +16,34 @@ SHUTDOWN COMPLETE) MAY be bundled with an ABORT, but they MUST be
|
|||
placed before the ABORT in the SCTP packet or they will be ignored by
|
||||
the receiver.
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 6 |Reserved |T| Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| zero or more Error Causes |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 6 |Reserved |T| Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| zero or more Error Causes |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkAbort struct {
|
||||
chunkHeader
|
||||
errorCauses []errorCause
|
||||
}
|
||||
|
||||
// Abort chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotAbort = errors.New("ChunkType is not of type ABORT")
|
||||
ErrBuildAbortChunkFailed = errors.New("failed build Abort Chunk")
|
||||
)
|
||||
|
||||
func (a *chunkAbort) unmarshal(raw []byte) error {
|
||||
if err := a.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.typ != ctAbort {
|
||||
return errors.Errorf("ChunkType is not of type ABORT, actually is %s", a.typ.String())
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotAbort, a.typ.String())
|
||||
}
|
||||
|
||||
offset := chunkHeaderSize
|
||||
|
@ -49,7 +54,7 @@ func (a *chunkAbort) unmarshal(raw []byte) error {
|
|||
|
||||
e, err := buildErrorCause(raw[offset:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed build Abort Chunk")
|
||||
return fmt.Errorf("%w: %v", ErrBuildAbortChunkFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
offset += int(e.length())
|
||||
|
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_ack.go
generated
vendored
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_ack.go
generated
vendored
|
@ -1,29 +1,35 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
chunkCookieAck represents an SCTP Chunk of type chunkCookieAck
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 11 |Chunk Flags | Length = 4 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 11 |Chunk Flags | Length = 4 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkCookieAck struct {
|
||||
chunkHeader
|
||||
}
|
||||
|
||||
// Cookie ack chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotCookieAck = errors.New("ChunkType is not of type COOKIEACK")
|
||||
)
|
||||
|
||||
func (c *chunkCookieAck) unmarshal(raw []byte) error {
|
||||
if err := c.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.typ != ctCookieAck {
|
||||
return errors.Errorf("ChunkType is not of type COOKIEACK, actually is %s", c.typ.String())
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotCookieAck, c.typ.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
27
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_echo.go
generated
vendored
27
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_echo.go
generated
vendored
|
@ -1,34 +1,39 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
CookieEcho represents an SCTP Chunk of type CookieEcho
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 10 |Chunk Flags | Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Cookie |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 10 |Chunk Flags | Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Cookie |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkCookieEcho struct {
|
||||
chunkHeader
|
||||
cookie []byte
|
||||
}
|
||||
|
||||
// Cookie echo chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotCookieEcho = errors.New("ChunkType is not of type COOKIEECHO")
|
||||
)
|
||||
|
||||
func (c *chunkCookieEcho) unmarshal(raw []byte) error {
|
||||
if err := c.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.typ != ctCookieEcho {
|
||||
return errors.Errorf("ChunkType is not of type COOKIEECHO, actually is %s", c.typ.String())
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotCookieEcho, c.typ.String())
|
||||
}
|
||||
c.cookie = c.raw
|
||||
|
||||
|
|
53
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_error.go
generated
vendored
53
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_error.go
generated
vendored
|
@ -1,51 +1,56 @@
|
|||
package sctp // nolint:dupl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
Operation Error (ERROR) (9)
|
||||
Operation Error (ERROR) (9)
|
||||
|
||||
An endpoint sends this chunk to its peer endpoint to notify it of
|
||||
certain error conditions. It contains one or more error causes. An
|
||||
Operation Error is not considered fatal in and of itself, but may be
|
||||
used with an ERROR chunk to report a fatal condition. It has the
|
||||
following parameters:
|
||||
An endpoint sends this chunk to its peer endpoint to notify it of
|
||||
certain error conditions. It contains one or more error causes. An
|
||||
Operation Error is not considered fatal in and of itself, but may be
|
||||
used with an ERROR chunk to report a fatal condition. It has the
|
||||
following parameters:
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 9 | Chunk Flags | Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
\ \
|
||||
/ one or more Error Causes /
|
||||
\ \
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 9 | Chunk Flags | Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
\ \
|
||||
/ one or more Error Causes /
|
||||
\ \
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Chunk Flags: 8 bits
|
||||
Chunk Flags: 8 bits
|
||||
|
||||
Set to 0 on transmit and ignored on receipt.
|
||||
Set to 0 on transmit and ignored on receipt.
|
||||
|
||||
Length: 16 bits (unsigned integer)
|
||||
Length: 16 bits (unsigned integer)
|
||||
|
||||
Set to the size of the chunk in bytes, including the chunk header
|
||||
and all the Error Cause fields present.
|
||||
Set to the size of the chunk in bytes, including the chunk header
|
||||
and all the Error Cause fields present.
|
||||
*/
|
||||
type chunkError struct {
|
||||
chunkHeader
|
||||
errorCauses []errorCause
|
||||
}
|
||||
|
||||
// Error chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotCtError = errors.New("ChunkType is not of type ctError")
|
||||
ErrBuildErrorChunkFailed = errors.New("failed build Error Chunk")
|
||||
)
|
||||
|
||||
func (a *chunkError) unmarshal(raw []byte) error {
|
||||
if err := a.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.typ != ctError {
|
||||
return errors.Errorf("ChunkType is not of type ctError, actually is %s", a.typ.String())
|
||||
return fmt.Errorf("%w, actually is %s", ErrChunkTypeNotCtError, a.typ.String())
|
||||
}
|
||||
|
||||
offset := chunkHeaderSize
|
||||
|
@ -56,7 +61,7 @@ func (a *chunkError) unmarshal(raw []byte) error {
|
|||
|
||||
e, err := buildErrorCause(raw[offset:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed build Error Chunk")
|
||||
return fmt.Errorf("%w: %v", ErrBuildErrorChunkFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
offset += int(e.length())
|
||||
|
|
17
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_forward_tsn.go
generated
vendored
17
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_forward_tsn.go
generated
vendored
|
@ -2,9 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// This chunk shall be used by the data sender to inform the data
|
||||
|
@ -44,7 +43,11 @@ const (
|
|||
forwardTSNStreamLength = 4
|
||||
)
|
||||
|
||||
var errMarshalStreamFailed = errors.New("failed to marshal stream")
|
||||
// Forward TSN chunk errors
|
||||
var (
|
||||
ErrMarshalStreamFailed = errors.New("failed to marshal stream")
|
||||
ErrChunkTooShort = errors.New("chunk too short")
|
||||
)
|
||||
|
||||
func (c *chunkForwardTSN) unmarshal(raw []byte) error {
|
||||
if err := c.chunkHeader.unmarshal(raw); err != nil {
|
||||
|
@ -52,7 +55,7 @@ func (c *chunkForwardTSN) unmarshal(raw []byte) error {
|
|||
}
|
||||
|
||||
if len(c.raw) < newCumulativeTSNLength {
|
||||
return errors.New("chunk to short")
|
||||
return ErrChunkTooShort
|
||||
}
|
||||
|
||||
c.newCumulativeTSN = binary.BigEndian.Uint32(c.raw[0:])
|
||||
|
@ -63,7 +66,7 @@ func (c *chunkForwardTSN) unmarshal(raw []byte) error {
|
|||
s := chunkForwardTSNStream{}
|
||||
|
||||
if err := s.unmarshal(c.raw[offset:]); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal stream: %w", err)
|
||||
return fmt.Errorf("%w: %v", ErrMarshalStreamFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
c.streams = append(c.streams, s)
|
||||
|
@ -82,7 +85,7 @@ func (c *chunkForwardTSN) marshal() ([]byte, error) {
|
|||
for _, s := range c.streams {
|
||||
b, err := s.marshal()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", errMarshalStreamFailed, err)
|
||||
return nil, fmt.Errorf("%w: %v", ErrMarshalStreamFailed, err) //nolint:errorlint
|
||||
}
|
||||
out = append(out, b...)
|
||||
}
|
||||
|
@ -127,7 +130,7 @@ func (s *chunkForwardTSNStream) length() int {
|
|||
|
||||
func (s *chunkForwardTSNStream) unmarshal(raw []byte) error {
|
||||
if len(raw) < forwardTSNStreamLength {
|
||||
return errors.New("stream to short")
|
||||
return ErrChunkTooShort
|
||||
}
|
||||
s.identifier = binary.BigEndian.Uint16(raw[0:])
|
||||
s.sequence = binary.BigEndian.Uint16(raw[2:])
|
||||
|
|
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat.go
generated
vendored
44
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat.go
generated
vendored
|
@ -1,7 +1,8 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -14,16 +15,15 @@ the present association.
|
|||
The parameter field contains the Heartbeat Information, which is a
|
||||
variable-length opaque data structure understood only by the sender.
|
||||
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 4 | Chunk Flags | Heartbeat Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Heartbeat Information TLV (Variable-Length) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 4 | Chunk Flags | Heartbeat Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Heartbeat Information TLV (Variable-Length) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Defined as a variable-length parameter using the format described
|
||||
in Section 3.2.1, i.e.:
|
||||
|
@ -31,35 +31,43 @@ in Section 3.2.1, i.e.:
|
|||
Variable Parameters Status Type Value
|
||||
-------------------------------------------------------------
|
||||
heartbeat Info Mandatory 1
|
||||
|
||||
*/
|
||||
type chunkHeartbeat struct {
|
||||
chunkHeader
|
||||
params []param
|
||||
}
|
||||
|
||||
// Heartbeat chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotHeartbeat = errors.New("ChunkType is not of type HEARTBEAT")
|
||||
ErrHeartbeatNotLongEnoughInfo = errors.New("heartbeat is not long enough to contain Heartbeat Info")
|
||||
ErrParseParamTypeFailed = errors.New("failed to parse param type")
|
||||
ErrHeartbeatParam = errors.New("heartbeat should only have HEARTBEAT param")
|
||||
ErrHeartbeatChunkUnmarshal = errors.New("failed unmarshalling param in Heartbeat Chunk")
|
||||
)
|
||||
|
||||
func (h *chunkHeartbeat) unmarshal(raw []byte) error {
|
||||
if err := h.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
} else if h.typ != ctHeartbeat {
|
||||
return errors.Errorf("ChunkType is not of type HEARTBEAT, actually is %s", h.typ.String())
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotHeartbeat, h.typ.String())
|
||||
}
|
||||
|
||||
if len(raw) <= chunkHeaderSize {
|
||||
return errors.Errorf("Heartbeat is not long enough to contain Heartbeat Info %d", len(raw))
|
||||
return fmt.Errorf("%w: %d", ErrHeartbeatNotLongEnoughInfo, len(raw))
|
||||
}
|
||||
|
||||
pType, err := parseParamType(raw[chunkHeaderSize:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse param type")
|
||||
return fmt.Errorf("%w: %v", ErrParseParamTypeFailed, err) //nolint:errorlint
|
||||
}
|
||||
if pType != heartbeatInfo {
|
||||
return errors.Errorf("Heartbeat should only have HEARTBEAT param, instead have %s", pType.String())
|
||||
return fmt.Errorf("%w: instead have %s", ErrHeartbeatParam, pType.String())
|
||||
}
|
||||
|
||||
p, err := buildParam(pType, raw[chunkHeaderSize:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed unmarshalling param in Heartbeat Chunk")
|
||||
return fmt.Errorf("%w: %v", ErrHeartbeatChunkUnmarshal, err) //nolint:errorlint
|
||||
}
|
||||
h.params = append(h.params, p)
|
||||
|
||||
|
@ -67,7 +75,7 @@ func (h *chunkHeartbeat) unmarshal(raw []byte) error {
|
|||
}
|
||||
|
||||
func (h *chunkHeartbeat) Marshal() ([]byte, error) {
|
||||
return nil, errors.Errorf("Unimplemented")
|
||||
return nil, ErrUnimplemented
|
||||
}
|
||||
|
||||
func (h *chunkHeartbeat) check() (abort bool, err error) {
|
||||
|
|
41
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat_ack.go
generated
vendored
41
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat_ack.go
generated
vendored
|
@ -1,7 +1,8 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -14,16 +15,15 @@ HEARTBEAT chunk to which this ack is responding.
|
|||
|
||||
The parameter field contains a variable-length opaque data structure.
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 5 | Chunk Flags | Heartbeat Ack Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Heartbeat Information TLV (Variable-Length) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 5 | Chunk Flags | Heartbeat Ack Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Heartbeat Information TLV (Variable-Length) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Defined as a variable-length parameter using the format described
|
||||
in Section 3.2.1, i.e.:
|
||||
|
@ -31,34 +31,41 @@ in Section 3.2.1, i.e.:
|
|||
Variable Parameters Status Type Value
|
||||
-------------------------------------------------------------
|
||||
Heartbeat Info Mandatory 1
|
||||
|
||||
*/
|
||||
type chunkHeartbeatAck struct {
|
||||
chunkHeader
|
||||
params []param
|
||||
}
|
||||
|
||||
func (h *chunkHeartbeatAck) unmarshal(raw []byte) error {
|
||||
return errors.Errorf("Unimplemented")
|
||||
// Heartbeat ack chunk errors
|
||||
var (
|
||||
ErrUnimplemented = errors.New("unimplemented")
|
||||
ErrHeartbeatAckParams = errors.New("heartbeat Ack must have one param")
|
||||
ErrHeartbeatAckNotHeartbeatInfo = errors.New("heartbeat Ack must have one param, and it should be a HeartbeatInfo")
|
||||
ErrHeartbeatAckMarshalParam = errors.New("unable to marshal parameter for Heartbeat Ack")
|
||||
)
|
||||
|
||||
func (h *chunkHeartbeatAck) unmarshal([]byte) error {
|
||||
return ErrUnimplemented
|
||||
}
|
||||
|
||||
func (h *chunkHeartbeatAck) marshal() ([]byte, error) {
|
||||
if len(h.params) != 1 {
|
||||
return nil, errors.Errorf("Heartbeat Ack must have one param")
|
||||
return nil, ErrHeartbeatAckParams
|
||||
}
|
||||
|
||||
switch h.params[0].(type) {
|
||||
case *paramHeartbeatInfo:
|
||||
// ParamHeartbeatInfo is valid
|
||||
default:
|
||||
return nil, errors.Errorf("Heartbeat Ack must have one param, and it should be a HeartbeatInfo")
|
||||
return nil, ErrHeartbeatAckNotHeartbeatInfo
|
||||
}
|
||||
|
||||
out := make([]byte, 0)
|
||||
for idx, p := range h.params {
|
||||
pp, err := p.marshal()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to marshal parameter for Heartbeat Ack")
|
||||
return nil, fmt.Errorf("%w: %v", ErrHeartbeatAckMarshalParam, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
out = append(out, pp...)
|
||||
|
|
50
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init.go
generated
vendored
50
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init.go
generated
vendored
|
@ -1,9 +1,8 @@
|
|||
package sctp // nolint:dupl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -11,40 +10,53 @@ Init represents an SCTP Chunk of type INIT
|
|||
|
||||
See chunkInitCommon for the fixed headers
|
||||
|
||||
Variable Parameters Status Type Value
|
||||
-------------------------------------------------------------
|
||||
IPv4 IP (Note 1) Optional 5
|
||||
IPv6 IP (Note 1) Optional 6
|
||||
Cookie Preservative Optional 9
|
||||
Reserved for ECN Capable (Note 2) Optional 32768 (0x8000)
|
||||
Host Name IP (Note 3) Optional 11
|
||||
Supported IP Types (Note 4) Optional 12
|
||||
Variable Parameters Status Type Value
|
||||
-------------------------------------------------------------
|
||||
IPv4 IP (Note 1) Optional 5
|
||||
IPv6 IP (Note 1) Optional 6
|
||||
Cookie Preservative Optional 9
|
||||
Reserved for ECN Capable (Note 2) Optional 32768 (0x8000)
|
||||
Host Name IP (Note 3) Optional 11
|
||||
Supported IP Types (Note 4) Optional 12
|
||||
*/
|
||||
type chunkInit struct {
|
||||
chunkHeader
|
||||
chunkInitCommon
|
||||
}
|
||||
|
||||
// Init chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotTypeInit = errors.New("ChunkType is not of type INIT")
|
||||
ErrChunkValueNotLongEnough = errors.New("chunk Value isn't long enough for mandatory parameters exp")
|
||||
ErrChunkTypeInitFlagZero = errors.New("ChunkType of type INIT flags must be all 0")
|
||||
ErrChunkTypeInitUnmarshalFailed = errors.New("failed to unmarshal INIT body")
|
||||
ErrChunkTypeInitMarshalFailed = errors.New("failed marshaling INIT common data")
|
||||
ErrChunkTypeInitInitateTagZero = errors.New("ChunkType of type INIT ACK InitiateTag must not be 0")
|
||||
ErrInitInboundStreamRequestZero = errors.New("INIT ACK inbound stream request must be > 0")
|
||||
ErrInitOutboundStreamRequestZero = errors.New("INIT ACK outbound stream request must be > 0")
|
||||
ErrInitAdvertisedReceiver1500 = errors.New("INIT ACK Advertised Receiver Window Credit (a_rwnd) must be >= 1500")
|
||||
)
|
||||
|
||||
func (i *chunkInit) unmarshal(raw []byte) error {
|
||||
if err := i.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i.typ != ctInit {
|
||||
return errors.Errorf("ChunkType is not of type INIT, actually is %s", i.typ.String())
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotTypeInit, i.typ.String())
|
||||
} else if len(i.raw) < initChunkMinLength {
|
||||
return errors.Errorf("Chunk Value isn't long enough for mandatory parameters exp: %d actual: %d", initChunkMinLength, len(i.raw))
|
||||
return fmt.Errorf("%w: %d actual: %d", ErrChunkValueNotLongEnough, initChunkMinLength, len(i.raw))
|
||||
}
|
||||
|
||||
// The Chunk Flags field in INIT is reserved, and all bits in it should
|
||||
// be set to 0 by the sender and ignored by the receiver. The sequence
|
||||
// of parameters within an INIT can be processed in any order.
|
||||
if i.flags != 0 {
|
||||
return errors.New("ChunkType of type INIT flags must be all 0")
|
||||
return ErrChunkTypeInitFlagZero
|
||||
}
|
||||
|
||||
if err := i.chunkInitCommon.unmarshal(i.raw); err != nil {
|
||||
return errors.Wrap(err, "Failed to unmarshal INIT body")
|
||||
return fmt.Errorf("%w: %v", ErrChunkTypeInitUnmarshalFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -53,7 +65,7 @@ func (i *chunkInit) unmarshal(raw []byte) error {
|
|||
func (i *chunkInit) marshal() ([]byte, error) {
|
||||
initShared, err := i.chunkInitCommon.marshal()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed marshaling INIT common data")
|
||||
return nil, fmt.Errorf("%w: %v", ErrChunkTypeInitMarshalFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
i.chunkHeader.typ = ctInit
|
||||
|
@ -75,7 +87,7 @@ func (i *chunkInit) check() (abort bool, err error) {
|
|||
// association by transmitting an ABORT.
|
||||
if i.initiateTag == 0 {
|
||||
abort = true
|
||||
return abort, errors.New("ChunkType of type INIT InitiateTag must not be 0")
|
||||
return abort, ErrChunkTypeInitInitateTagZero
|
||||
}
|
||||
|
||||
// Defines the maximum number of streams the sender of this INIT
|
||||
|
@ -90,7 +102,7 @@ func (i *chunkInit) check() (abort bool, err error) {
|
|||
// the association.
|
||||
if i.numInboundStreams == 0 {
|
||||
abort = true
|
||||
return abort, errors.New("INIT inbound stream request must be > 0")
|
||||
return abort, ErrInitInboundStreamRequestZero
|
||||
}
|
||||
|
||||
// Defines the number of outbound streams the sender of this INIT
|
||||
|
@ -102,7 +114,7 @@ func (i *chunkInit) check() (abort bool, err error) {
|
|||
|
||||
if i.numOutboundStreams == 0 {
|
||||
abort = true
|
||||
return abort, errors.New("INIT outbound stream request must be > 0")
|
||||
return abort, ErrInitOutboundStreamRequestZero
|
||||
}
|
||||
|
||||
// An SCTP receiver MUST be able to receive a minimum of 1500 bytes in
|
||||
|
@ -111,7 +123,7 @@ func (i *chunkInit) check() (abort bool, err error) {
|
|||
// ACK.
|
||||
if i.advertisedReceiverWindowCredit < 1500 {
|
||||
abort = true
|
||||
return abort, errors.New("INIT Advertised Receiver Window Credit (a_rwnd) must be >= 1500")
|
||||
return abort, ErrInitAdvertisedReceiver1500
|
||||
}
|
||||
|
||||
return false, nil
|
||||
|
|
51
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_ack.go
generated
vendored
51
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_ack.go
generated
vendored
|
@ -1,9 +1,8 @@
|
|||
package sctp // nolint:dupl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -11,41 +10,53 @@ chunkInitAck represents an SCTP Chunk of type INIT ACK
|
|||
|
||||
See chunkInitCommon for the fixed headers
|
||||
|
||||
Variable Parameters Status Type Value
|
||||
-------------------------------------------------------------
|
||||
State Cookie Mandatory 7
|
||||
IPv4 IP (Note 1) Optional 5
|
||||
IPv6 IP (Note 1) Optional 6
|
||||
Unrecognized Parameter Optional 8
|
||||
Reserved for ECN Capable (Note 2) Optional 32768 (0x8000)
|
||||
Host Name IP (Note 3) Optional 11<Paste>
|
||||
|
||||
Variable Parameters Status Type Value
|
||||
-------------------------------------------------------------
|
||||
State Cookie Mandatory 7
|
||||
IPv4 IP (Note 1) Optional 5
|
||||
IPv6 IP (Note 1) Optional 6
|
||||
Unrecognized Parameter Optional 8
|
||||
Reserved for ECN Capable (Note 2) Optional 32768 (0x8000)
|
||||
Host Name IP (Note 3) Optional 11<Paste>
|
||||
*/
|
||||
type chunkInitAck struct {
|
||||
chunkHeader
|
||||
chunkInitCommon
|
||||
}
|
||||
|
||||
// Init ack chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotInitAck = errors.New("ChunkType is not of type INIT ACK")
|
||||
ErrChunkNotLongEnoughForParams = errors.New("chunk Value isn't long enough for mandatory parameters exp")
|
||||
ErrChunkTypeInitAckFlagZero = errors.New("ChunkType of type INIT ACK flags must be all 0")
|
||||
ErrInitAckUnmarshalFailed = errors.New("failed to unmarshal INIT body")
|
||||
ErrInitCommonDataMarshalFailed = errors.New("failed marshaling INIT common data")
|
||||
ErrChunkTypeInitAckInitateTagZero = errors.New("ChunkType of type INIT ACK InitiateTag must not be 0")
|
||||
ErrInitAckInboundStreamRequestZero = errors.New("INIT ACK inbound stream request must be > 0")
|
||||
ErrInitAckOutboundStreamRequestZero = errors.New("INIT ACK outbound stream request must be > 0")
|
||||
ErrInitAckAdvertisedReceiver1500 = errors.New("INIT ACK Advertised Receiver Window Credit (a_rwnd) must be >= 1500")
|
||||
)
|
||||
|
||||
func (i *chunkInitAck) unmarshal(raw []byte) error {
|
||||
if err := i.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i.typ != ctInitAck {
|
||||
return errors.Errorf("ChunkType is not of type INIT ACK, actually is %s", i.typ.String())
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotInitAck, i.typ.String())
|
||||
} else if len(i.raw) < initChunkMinLength {
|
||||
return errors.Errorf("Chunk Value isn't long enough for mandatory parameters exp: %d actual: %d", initChunkMinLength, len(i.raw))
|
||||
return fmt.Errorf("%w: %d actual: %d", ErrChunkNotLongEnoughForParams, initChunkMinLength, len(i.raw))
|
||||
}
|
||||
|
||||
// The Chunk Flags field in INIT is reserved, and all bits in it should
|
||||
// be set to 0 by the sender and ignored by the receiver. The sequence
|
||||
// of parameters within an INIT can be processed in any order.
|
||||
if i.flags != 0 {
|
||||
return errors.New("ChunkType of type INIT ACK flags must be all 0")
|
||||
return ErrChunkTypeInitAckFlagZero
|
||||
}
|
||||
|
||||
if err := i.chunkInitCommon.unmarshal(i.raw); err != nil {
|
||||
return errors.Wrap(err, "Failed to unmarshal INIT body")
|
||||
return fmt.Errorf("%w: %v", ErrInitAckUnmarshalFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -54,7 +65,7 @@ func (i *chunkInitAck) unmarshal(raw []byte) error {
|
|||
func (i *chunkInitAck) marshal() ([]byte, error) {
|
||||
initShared, err := i.chunkInitCommon.marshal()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed marshaling INIT common data")
|
||||
return nil, fmt.Errorf("%w: %v", ErrInitCommonDataMarshalFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
i.chunkHeader.typ = ctInitAck
|
||||
|
@ -77,7 +88,7 @@ func (i *chunkInitAck) check() (abort bool, err error) {
|
|||
// purpose.
|
||||
if i.initiateTag == 0 {
|
||||
abort = true
|
||||
return abort, errors.New("ChunkType of type INIT ACK InitiateTag must not be 0")
|
||||
return abort, ErrChunkTypeInitAckInitateTagZero
|
||||
}
|
||||
|
||||
// Defines the maximum number of streams the sender of this INIT ACK
|
||||
|
@ -92,7 +103,7 @@ func (i *chunkInitAck) check() (abort bool, err error) {
|
|||
// destroy the association discarding its TCB.
|
||||
if i.numInboundStreams == 0 {
|
||||
abort = true
|
||||
return abort, errors.New("INIT ACK inbound stream request must be > 0")
|
||||
return abort, ErrInitAckInboundStreamRequestZero
|
||||
}
|
||||
|
||||
// Defines the number of outbound streams the sender of this INIT ACK
|
||||
|
@ -105,7 +116,7 @@ func (i *chunkInitAck) check() (abort bool, err error) {
|
|||
|
||||
if i.numOutboundStreams == 0 {
|
||||
abort = true
|
||||
return abort, errors.New("INIT ACK outbound stream request must be > 0")
|
||||
return abort, ErrInitAckOutboundStreamRequestZero
|
||||
}
|
||||
|
||||
// An SCTP receiver MUST be able to receive a minimum of 1500 bytes in
|
||||
|
@ -114,7 +125,7 @@ func (i *chunkInitAck) check() (abort bool, err error) {
|
|||
// ACK.
|
||||
if i.advertisedReceiverWindowCredit < 1500 {
|
||||
abort = true
|
||||
return abort, errors.New("INIT ACK Advertised Receiver Window Credit (a_rwnd) must be >= 1500")
|
||||
return abort, ErrInitAckAdvertisedReceiver1500
|
||||
}
|
||||
|
||||
return false, nil
|
||||
|
|
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_common.go
generated
vendored
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_common.go
generated
vendored
|
@ -2,9 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -54,6 +53,13 @@ const (
|
|||
initOptionalVarHeaderLength = 4
|
||||
)
|
||||
|
||||
// Init chunk errors
|
||||
var (
|
||||
ErrInitChunkParseParamTypeFailed = errors.New("failed to parse param type")
|
||||
ErrInitChunkUnmarshalParam = errors.New("failed unmarshalling param in Init Chunk")
|
||||
ErrInitAckMarshalParam = errors.New("unable to marshal parameter for INIT/INITACK")
|
||||
)
|
||||
|
||||
func (i *chunkInitCommon) unmarshal(raw []byte) error {
|
||||
i.initiateTag = binary.BigEndian.Uint32(raw[0:])
|
||||
i.advertisedReceiverWindowCredit = binary.BigEndian.Uint32(raw[4:])
|
||||
|
@ -84,11 +90,11 @@ func (i *chunkInitCommon) unmarshal(raw []byte) error {
|
|||
if remaining > initOptionalVarHeaderLength {
|
||||
pType, err := parseParamType(raw[offset:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse param type")
|
||||
return fmt.Errorf("%w: %v", ErrInitChunkParseParamTypeFailed, err) //nolint:errorlint
|
||||
}
|
||||
p, err := buildParam(pType, raw[offset:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed unmarshalling param in Init Chunk")
|
||||
return fmt.Errorf("%w: %v", ErrInitChunkUnmarshalParam, err) //nolint:errorlint
|
||||
}
|
||||
i.params = append(i.params, p)
|
||||
padding := getPadding(p.length())
|
||||
|
@ -112,7 +118,7 @@ func (i *chunkInitCommon) marshal() ([]byte, error) {
|
|||
for idx, p := range i.params {
|
||||
pp, err := p.marshal()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to marshal parameter for INIT/INITACK")
|
||||
return nil, fmt.Errorf("%w: %v", ErrInitAckMarshalParam, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
out = append(out, pp...)
|
||||
|
|
66
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_payload_data.go
generated
vendored
66
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_payload_data.go
generated
vendored
|
@ -2,6 +2,7 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
@ -9,38 +10,38 @@ import (
|
|||
/*
|
||||
chunkPayloadData represents an SCTP Chunk of type DATA
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 0 | Reserved|U|B|E| Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| TSN |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Stream Identifier S | Stream Sequence Number n |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Payload Protocol Identifier |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| User Data (seq n of Stream S) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 0 | Reserved|U|B|E| Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| TSN |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Stream Identifier S | Stream Sequence Number n |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Payload Protocol Identifier |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| User Data (seq n of Stream S) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
An unfragmented user message shall have both the B and E bits set to
|
||||
'1'. Setting both B and E bits to '0' indicates a middle fragment of
|
||||
a multi-fragment user message, as summarized in the following table:
|
||||
B E Description
|
||||
============================================================
|
||||
| 1 0 | First piece of a fragmented user message |
|
||||
+----------------------------------------------------------+
|
||||
| 0 0 | Middle piece of a fragmented user message |
|
||||
+----------------------------------------------------------+
|
||||
| 0 1 | Last piece of a fragmented user message |
|
||||
+----------------------------------------------------------+
|
||||
| 1 1 | Unfragmented message |
|
||||
============================================================
|
||||
| Table 1: Fragment Description Flags |
|
||||
============================================================
|
||||
|
||||
B E Description
|
||||
============================================================
|
||||
| 1 0 | First piece of a fragmented user message |
|
||||
+----------------------------------------------------------+
|
||||
| 0 0 | Middle piece of a fragmented user message |
|
||||
+----------------------------------------------------------+
|
||||
| 0 1 | Last piece of a fragmented user message |
|
||||
+----------------------------------------------------------+
|
||||
| 1 1 | Unfragmented message |
|
||||
============================================================
|
||||
| Table 1: Fragment Description Flags |
|
||||
============================================================
|
||||
*/
|
||||
type chunkPayloadData struct {
|
||||
chunkHeader
|
||||
|
@ -88,6 +89,7 @@ type PayloadProtocolIdentifier uint32
|
|||
// PayloadProtocolIdentifier enums
|
||||
// https://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml#sctp-parameters-25
|
||||
const (
|
||||
PayloadTypeUnknown PayloadProtocolIdentifier = 0
|
||||
PayloadTypeWebRTCDCEP PayloadProtocolIdentifier = 50
|
||||
PayloadTypeWebRTCString PayloadProtocolIdentifier = 51
|
||||
PayloadTypeWebRTCBinary PayloadProtocolIdentifier = 53
|
||||
|
@ -95,6 +97,11 @@ const (
|
|||
PayloadTypeWebRTCBinaryEmpty PayloadProtocolIdentifier = 57
|
||||
)
|
||||
|
||||
// Data chunk errors
|
||||
var (
|
||||
ErrChunkPayloadSmall = errors.New("packet is smaller than the header size")
|
||||
)
|
||||
|
||||
func (p PayloadProtocolIdentifier) String() string {
|
||||
switch p {
|
||||
case PayloadTypeWebRTCDCEP:
|
||||
|
@ -122,6 +129,9 @@ func (p *chunkPayloadData) unmarshal(raw []byte) error {
|
|||
p.beginningFragment = p.flags&payloadDataBeginingFragmentBitmask != 0
|
||||
p.endingFragment = p.flags&payloadDataEndingFragmentBitmask != 0
|
||||
|
||||
if len(raw) < payloadDataHeaderSize {
|
||||
return ErrChunkPayloadSmall
|
||||
}
|
||||
p.tsn = binary.BigEndian.Uint32(p.raw[0:])
|
||||
p.streamIdentifier = binary.BigEndian.Uint16(p.raw[4:])
|
||||
p.streamSequenceNumber = binary.BigEndian.Uint16(p.raw[6:])
|
||||
|
|
18
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_reconfig.go
generated
vendored
18
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_reconfig.go
generated
vendored
|
@ -1,9 +1,8 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// https://tools.ietf.org/html/rfc6525#section-3.1
|
||||
|
@ -29,13 +28,20 @@ type chunkReconfig struct {
|
|||
paramB param
|
||||
}
|
||||
|
||||
// Reconfigure chunk errors
|
||||
var (
|
||||
ErrChunkParseParamTypeFailed = errors.New("failed to parse param type")
|
||||
ErrChunkMarshalParamAReconfigFailed = errors.New("unable to marshal parameter A for reconfig")
|
||||
ErrChunkMarshalParamBReconfigFailed = errors.New("unable to marshal parameter B for reconfig")
|
||||
)
|
||||
|
||||
func (c *chunkReconfig) unmarshal(raw []byte) error {
|
||||
if err := c.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
pType, err := parseParamType(c.raw)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse param type")
|
||||
return fmt.Errorf("%w: %v", ErrChunkParseParamTypeFailed, err) //nolint:errorlint
|
||||
}
|
||||
a, err := buildParam(pType, c.raw)
|
||||
if err != nil {
|
||||
|
@ -48,7 +54,7 @@ func (c *chunkReconfig) unmarshal(raw []byte) error {
|
|||
if len(c.raw) > offset {
|
||||
pType, err := parseParamType(c.raw[offset:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse param type")
|
||||
return fmt.Errorf("%w: %v", ErrChunkParseParamTypeFailed, err) //nolint:errorlint
|
||||
}
|
||||
b, err := buildParam(pType, c.raw[offset:])
|
||||
if err != nil {
|
||||
|
@ -63,7 +69,7 @@ func (c *chunkReconfig) unmarshal(raw []byte) error {
|
|||
func (c *chunkReconfig) marshal() ([]byte, error) {
|
||||
out, err := c.paramA.marshal()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to marshal parameter A for reconfig")
|
||||
return nil, fmt.Errorf("%w: %v", ErrChunkMarshalParamAReconfigFailed, err) //nolint:errorlint
|
||||
}
|
||||
if c.paramB != nil {
|
||||
// Pad param A
|
||||
|
@ -71,7 +77,7 @@ func (c *chunkReconfig) marshal() ([]byte, error) {
|
|||
|
||||
outB, err := c.paramB.marshal()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unable to marshal parameter B for reconfig")
|
||||
return nil, fmt.Errorf("%w: %v", ErrChunkMarshalParamBReconfigFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
out = append(out, outB...)
|
||||
|
|
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_selective_ack.go
generated
vendored
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_selective_ack.go
generated
vendored
|
@ -2,9 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -47,6 +46,13 @@ type gapAckBlock struct {
|
|||
end uint16
|
||||
}
|
||||
|
||||
// Selective ack chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotSack = errors.New("ChunkType is not of type SACK")
|
||||
ErrSackSizeNotLargeEnoughInfo = errors.New("SACK Chunk size is not large enough to contain header")
|
||||
ErrSackSizeNotMatchPredicted = errors.New("SACK Chunk size does not match predicted amount from header values")
|
||||
)
|
||||
|
||||
// String makes gapAckBlock printable
|
||||
func (g gapAckBlock) String() string {
|
||||
return fmt.Sprintf("%d - %d", g.start, g.end)
|
||||
|
@ -70,11 +76,11 @@ func (s *chunkSelectiveAck) unmarshal(raw []byte) error {
|
|||
}
|
||||
|
||||
if s.typ != ctSack {
|
||||
return errors.Errorf("ChunkType is not of type SACK, actually is %s", s.typ.String())
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotSack, s.typ.String())
|
||||
}
|
||||
|
||||
if len(s.raw) < selectiveAckHeaderSize {
|
||||
return errors.Errorf("SACK Chunk size is not large enough to contain header (%v remaining, needs %v bytes)",
|
||||
return fmt.Errorf("%w: %v remaining, needs %v bytes", ErrSackSizeNotLargeEnoughInfo,
|
||||
len(s.raw), selectiveAckHeaderSize)
|
||||
}
|
||||
|
||||
|
@ -84,7 +90,7 @@ func (s *chunkSelectiveAck) unmarshal(raw []byte) error {
|
|||
s.duplicateTSN = make([]uint32, binary.BigEndian.Uint16(s.raw[10:]))
|
||||
|
||||
if len(s.raw) != selectiveAckHeaderSize+(4*len(s.gapAckBlocks)+(4*len(s.duplicateTSN))) {
|
||||
return errors.Errorf("SACK Chunk size does not match predicted amount from header values")
|
||||
return ErrSackSizeNotMatchPredicted
|
||||
}
|
||||
|
||||
offset := selectiveAckHeaderSize
|
||||
|
|
69
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown.go
generated
vendored
Normal file
69
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
chunkShutdown represents an SCTP Chunk of type chunkShutdown
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 7 | Chunk Flags | Length = 8 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Cumulative TSN Ack |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkShutdown struct {
|
||||
chunkHeader
|
||||
cumulativeTSNAck uint32
|
||||
}
|
||||
|
||||
const (
|
||||
cumulativeTSNAckLength = 4
|
||||
)
|
||||
|
||||
// Shutdown chunk errors
|
||||
var (
|
||||
ErrInvalidChunkSize = errors.New("invalid chunk size")
|
||||
ErrChunkTypeNotShutdown = errors.New("ChunkType is not of type SHUTDOWN")
|
||||
)
|
||||
|
||||
func (c *chunkShutdown) unmarshal(raw []byte) error {
|
||||
if err := c.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.typ != ctShutdown {
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotShutdown, c.typ.String())
|
||||
}
|
||||
|
||||
if len(c.raw) != cumulativeTSNAckLength {
|
||||
return ErrInvalidChunkSize
|
||||
}
|
||||
|
||||
c.cumulativeTSNAck = binary.BigEndian.Uint32(c.raw[0:])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chunkShutdown) marshal() ([]byte, error) {
|
||||
out := make([]byte, cumulativeTSNAckLength)
|
||||
binary.BigEndian.PutUint32(out[0:], c.cumulativeTSNAck)
|
||||
|
||||
c.typ = ctShutdown
|
||||
c.raw = out
|
||||
return c.chunkHeader.marshal()
|
||||
}
|
||||
|
||||
func (c *chunkShutdown) check() (abort bool, err error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// String makes chunkShutdown printable
|
||||
func (c *chunkShutdown) String() string {
|
||||
return c.chunkHeader.String()
|
||||
}
|
50
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_ack.go
generated
vendored
Normal file
50
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_ack.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
chunkShutdownAck represents an SCTP Chunk of type chunkShutdownAck
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 8 | Chunk Flags | Length = 4 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkShutdownAck struct {
|
||||
chunkHeader
|
||||
}
|
||||
|
||||
// Shutdown ack chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotShutdownAck = errors.New("ChunkType is not of type SHUTDOWN-ACK")
|
||||
)
|
||||
|
||||
func (c *chunkShutdownAck) unmarshal(raw []byte) error {
|
||||
if err := c.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.typ != ctShutdownAck {
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotShutdownAck, c.typ.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chunkShutdownAck) marshal() ([]byte, error) {
|
||||
c.typ = ctShutdownAck
|
||||
return c.chunkHeader.marshal()
|
||||
}
|
||||
|
||||
func (c *chunkShutdownAck) check() (abort bool, err error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// String makes chunkShutdownAck printable
|
||||
func (c *chunkShutdownAck) String() string {
|
||||
return c.chunkHeader.String()
|
||||
}
|
50
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_complete.go
generated
vendored
Normal file
50
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_complete.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
chunkShutdownComplete represents an SCTP Chunk of type chunkShutdownComplete
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 14 |Reserved |T| Length = 4 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkShutdownComplete struct {
|
||||
chunkHeader
|
||||
}
|
||||
|
||||
// Shutdown complete chunk errors
|
||||
var (
|
||||
ErrChunkTypeNotShutdownComplete = errors.New("ChunkType is not of type SHUTDOWN-COMPLETE")
|
||||
)
|
||||
|
||||
func (c *chunkShutdownComplete) unmarshal(raw []byte) error {
|
||||
if err := c.chunkHeader.unmarshal(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.typ != ctShutdownComplete {
|
||||
return fmt.Errorf("%w: actually is %s", ErrChunkTypeNotShutdownComplete, c.typ.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chunkShutdownComplete) marshal() ([]byte, error) {
|
||||
c.typ = ctShutdownComplete
|
||||
return c.chunkHeader.marshal()
|
||||
}
|
||||
|
||||
func (c *chunkShutdownComplete) check() (abort bool, err error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// String makes chunkShutdownComplete printable
|
||||
func (c *chunkShutdownComplete) String() string {
|
||||
return c.chunkHeader.String()
|
||||
}
|
35
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunkheader.go
generated
vendored
35
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunkheader.go
generated
vendored
|
@ -2,8 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -13,15 +13,15 @@ transmitted in the SCTP packet. Each chunk is formatted with a Chunk
|
|||
Type field, a chunk-specific Flag field, a Chunk Length field, and a
|
||||
Value field.
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk Type | Chunk Flags | Chunk Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Chunk Value |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk Type | Chunk Flags | Chunk Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Chunk Value |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkHeader struct {
|
||||
typ chunkType
|
||||
|
@ -33,9 +33,16 @@ const (
|
|||
chunkHeaderSize = 4
|
||||
)
|
||||
|
||||
// SCTP chunk header errors
|
||||
var (
|
||||
ErrChunkHeaderTooSmall = errors.New("raw is too small for a SCTP chunk")
|
||||
ErrChunkHeaderNotEnoughSpace = errors.New("not enough data left in SCTP packet to satisfy requested length")
|
||||
ErrChunkHeaderPaddingNonZero = errors.New("chunk padding is non-zero at offset")
|
||||
)
|
||||
|
||||
func (c *chunkHeader) unmarshal(raw []byte) error {
|
||||
if len(raw) < chunkHeaderSize {
|
||||
return errors.Errorf("raw only %d bytes, %d is the minimum length for a SCTP chunk", len(raw), chunkHeaderSize)
|
||||
return fmt.Errorf("%w: raw only %d bytes, %d is the minimum length", ErrChunkHeaderTooSmall, len(raw), chunkHeaderSize)
|
||||
}
|
||||
|
||||
c.typ = chunkType(raw[0])
|
||||
|
@ -47,7 +54,7 @@ func (c *chunkHeader) unmarshal(raw []byte) error {
|
|||
lengthAfterValue := len(raw) - (chunkHeaderSize + valueLength)
|
||||
|
||||
if lengthAfterValue < 0 {
|
||||
return errors.Errorf("Not enough data left in SCTP packet to satisfy requested length remain %d req %d ", valueLength, len(raw)-chunkHeaderSize)
|
||||
return fmt.Errorf("%w: remain %d req %d ", ErrChunkHeaderNotEnoughSpace, valueLength, len(raw)-chunkHeaderSize)
|
||||
} else if lengthAfterValue < 4 {
|
||||
// https://tools.ietf.org/html/rfc4960#section-3.2
|
||||
// The Chunk Length field does not count any chunk padding.
|
||||
|
@ -61,7 +68,7 @@ func (c *chunkHeader) unmarshal(raw []byte) error {
|
|||
for i := lengthAfterValue; i > 0; i-- {
|
||||
paddingOffset := chunkHeaderSize + valueLength + (i - 1)
|
||||
if raw[paddingOffset] != 0 {
|
||||
return errors.Errorf("Chunk padding is non-zero at offset %d ", paddingOffset)
|
||||
return fmt.Errorf("%w: %d ", ErrChunkHeaderPaddingNonZero, paddingOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause.go
generated
vendored
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause.go
generated
vendored
|
@ -2,9 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// errorCauseCode is a cause code that appears in either a ERROR or ABORT chunk
|
||||
|
@ -19,6 +18,11 @@ type errorCause interface {
|
|||
errorCauseCode() errorCauseCode
|
||||
}
|
||||
|
||||
// Error and abort chunk errors
|
||||
var (
|
||||
ErrBuildErrorCaseHandle = errors.New("BuildErrorCause does not handle")
|
||||
)
|
||||
|
||||
// buildErrorCause delegates the building of a error cause from raw bytes to the correct structure
|
||||
func buildErrorCause(raw []byte) (errorCause, error) {
|
||||
var e errorCause
|
||||
|
@ -31,13 +35,16 @@ func buildErrorCause(raw []byte) (errorCause, error) {
|
|||
e = &errorCauseUnrecognizedChunkType{}
|
||||
case protocolViolation:
|
||||
e = &errorCauseProtocolViolation{}
|
||||
case userInitiatedAbort:
|
||||
e = &errorCauseUserInitiatedAbort{}
|
||||
default:
|
||||
return nil, errors.Errorf("BuildErrorCause does not handle %s", c.String())
|
||||
return nil, fmt.Errorf("%w: %s", ErrBuildErrorCaseHandle, c.String())
|
||||
}
|
||||
|
||||
if err := e.unmarshal(raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
|
|
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_protocol_violation.go
generated
vendored
38
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_protocol_violation.go
generated
vendored
|
@ -1,33 +1,37 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
/*
|
||||
This error cause MAY be included in ABORT chunks that are sent
|
||||
because an SCTP endpoint detects a protocol violation of the peer
|
||||
that is not covered by the error causes described in Section 3.3.10.1
|
||||
to Section 3.3.10.12. An implementation MAY provide additional
|
||||
information specifying what kind of protocol violation has been
|
||||
detected.
|
||||
This error cause MAY be included in ABORT chunks that are sent
|
||||
because an SCTP endpoint detects a protocol violation of the peer
|
||||
that is not covered by the error causes described in Section 3.3.10.1
|
||||
to Section 3.3.10.12. An implementation MAY provide additional
|
||||
information specifying what kind of protocol violation has been
|
||||
detected.
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Cause Code=13 | Cause Length=Variable |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
/ Additional Information /
|
||||
\ \
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Cause Code=13 | Cause Length=Variable |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
/ Additional Information /
|
||||
\ \
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type errorCauseProtocolViolation struct {
|
||||
errorCauseHeader
|
||||
additionalInformation []byte
|
||||
}
|
||||
|
||||
// Abort chunk errors
|
||||
var (
|
||||
ErrProtocolViolationUnmarshal = errors.New("unable to unmarshal Protocol Violation error")
|
||||
)
|
||||
|
||||
func (e *errorCauseProtocolViolation) marshal() ([]byte, error) {
|
||||
e.raw = e.additionalInformation
|
||||
return e.errorCauseHeader.marshal()
|
||||
|
@ -36,7 +40,7 @@ func (e *errorCauseProtocolViolation) marshal() ([]byte, error) {
|
|||
func (e *errorCauseProtocolViolation) unmarshal(raw []byte) error {
|
||||
err := e.errorCauseHeader.unmarshal(raw)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Unable to unmarshal Protocol Violation error")
|
||||
return fmt.Errorf("%w: %v", ErrProtocolViolationUnmarshal, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
e.additionalInformation = e.raw
|
||||
|
|
46
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_user_initiated_abort.go
generated
vendored
Normal file
46
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_user_initiated_abort.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
This error cause MAY be included in ABORT chunks that are sent
|
||||
because of an upper-layer request. The upper layer can specify an
|
||||
Upper Layer Abort Reason that is transported by SCTP transparently
|
||||
and MAY be delivered to the upper-layer protocol at the peer.
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Cause Code=12 | Cause Length=Variable |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
/ Upper Layer Abort Reason /
|
||||
\ \
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type errorCauseUserInitiatedAbort struct {
|
||||
errorCauseHeader
|
||||
upperLayerAbortReason []byte
|
||||
}
|
||||
|
||||
func (e *errorCauseUserInitiatedAbort) marshal() ([]byte, error) {
|
||||
e.code = userInitiatedAbort
|
||||
e.errorCauseHeader.raw = e.upperLayerAbortReason
|
||||
return e.errorCauseHeader.marshal()
|
||||
}
|
||||
|
||||
func (e *errorCauseUserInitiatedAbort) unmarshal(raw []byte) error {
|
||||
err := e.errorCauseHeader.unmarshal(raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.upperLayerAbortReason = e.errorCauseHeader.raw
|
||||
return nil
|
||||
}
|
||||
|
||||
// String makes errorCauseUserInitiatedAbort printable
|
||||
func (e *errorCauseUserInitiatedAbort) String() string {
|
||||
return fmt.Sprintf("%s: %s", e.errorCauseHeader.String(), e.upperLayerAbortReason)
|
||||
}
|
14
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/go.mod
generated
vendored
14
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/go.mod
generated
vendored
|
@ -1,14 +0,0 @@
|
|||
module github.com/pion/sctp
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/pion/logging v0.2.2
|
||||
github.com/pion/randutil v0.1.0
|
||||
github.com/pion/transport v0.10.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/stretchr/testify v1.6.1
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
)
|
||||
|
||||
go 1.13
|
36
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/go.sum
generated
vendored
36
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/go.sum
generated
vendored
|
@ -1,36 +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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
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/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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.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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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=
|
74
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/packet.go
generated
vendored
74
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/packet.go
generated
vendored
|
@ -2,10 +2,9 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Create the crc32 table we'll use for the checksum
|
||||
|
@ -20,34 +19,29 @@ Packet represents an SCTP packet, defined in https://tools.ietf.org/html/rfc4960
|
|||
An SCTP packet is composed of a common header and chunks. A chunk
|
||||
contains either control information or user data.
|
||||
|
||||
SCTP Packet Format
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Common Header |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk #1 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk #n |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
SCTP Packet Format
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Common Header |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk #1 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk #n |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
|
||||
SCTP Common Header Format
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Source Value Number | Destination Value Number |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Verification Tag |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
|
||||
SCTP Common Header Format
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Source Value Number | Destination Value Number |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Verification Tag |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Checksum |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type packet struct {
|
||||
sourcePort uint16
|
||||
|
@ -60,9 +54,17 @@ const (
|
|||
packetHeaderSize = 12
|
||||
)
|
||||
|
||||
// SCTP packet errors
|
||||
var (
|
||||
ErrPacketRawTooSmall = errors.New("raw is smaller than the minimum length for a SCTP packet")
|
||||
ErrParseSCTPChunkNotEnoughData = errors.New("unable to parse SCTP chunk, not enough data for complete header")
|
||||
ErrUnmarshalUnknownChunkType = errors.New("failed to unmarshal, contains unknown chunk type")
|
||||
ErrChecksumMismatch = errors.New("checksum mismatch theirs")
|
||||
)
|
||||
|
||||
func (p *packet) unmarshal(raw []byte) error {
|
||||
if len(raw) < packetHeaderSize {
|
||||
return errors.Errorf("raw only %d bytes, %d is the minimum length for a SCTP packet", len(raw), packetHeaderSize)
|
||||
return fmt.Errorf("%w: raw only %d bytes, %d is the minimum length", ErrPacketRawTooSmall, len(raw), packetHeaderSize)
|
||||
}
|
||||
|
||||
p.sourcePort = binary.BigEndian.Uint16(raw[0:])
|
||||
|
@ -75,7 +77,7 @@ func (p *packet) unmarshal(raw []byte) error {
|
|||
if offset == len(raw) {
|
||||
break
|
||||
} else if offset+chunkHeaderSize > len(raw) {
|
||||
return errors.Errorf("Unable to parse SCTP chunk, not enough data for complete header: offset %d remaining %d", offset, len(raw))
|
||||
return fmt.Errorf("%w: offset %d remaining %d", ErrParseSCTPChunkNotEnoughData, offset, len(raw))
|
||||
}
|
||||
|
||||
var c chunk
|
||||
|
@ -102,8 +104,14 @@ func (p *packet) unmarshal(raw []byte) error {
|
|||
c = &chunkForwardTSN{}
|
||||
case ctError:
|
||||
c = &chunkError{}
|
||||
case ctShutdown:
|
||||
c = &chunkShutdown{}
|
||||
case ctShutdownAck:
|
||||
c = &chunkShutdownAck{}
|
||||
case ctShutdownComplete:
|
||||
c = &chunkShutdownComplete{}
|
||||
default:
|
||||
return errors.Errorf("Failed to unmarshal, contains unknown chunk type %s", chunkType(raw[offset]).String())
|
||||
return fmt.Errorf("%w: %s", ErrUnmarshalUnknownChunkType, chunkType(raw[offset]).String())
|
||||
}
|
||||
|
||||
if err := c.unmarshal(raw[offset:]); err != nil {
|
||||
|
@ -117,7 +125,7 @@ func (p *packet) unmarshal(raw []byte) error {
|
|||
theirChecksum := binary.LittleEndian.Uint32(raw[8:])
|
||||
ourChecksum := generatePacketChecksum(raw)
|
||||
if theirChecksum != ourChecksum {
|
||||
return errors.Errorf("Checksum mismatch theirs: %d ours: %d", theirChecksum, ourChecksum)
|
||||
return fmt.Errorf("%w: %d ours: %d", ErrChecksumMismatch, theirChecksum, ourChecksum)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
10
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param.go
generated
vendored
10
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param.go
generated
vendored
|
@ -1,7 +1,8 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type param interface {
|
||||
|
@ -9,12 +10,17 @@ type param interface {
|
|||
length() int
|
||||
}
|
||||
|
||||
// ErrParamTypeUnhandled is returned if unknown parameter type is specified.
|
||||
var ErrParamTypeUnhandled = errors.New("unhandled ParamType")
|
||||
|
||||
func buildParam(t paramType, rawParam []byte) (param, error) {
|
||||
switch t {
|
||||
case forwardTSNSupp:
|
||||
return (¶mForwardTSNSupported{}).unmarshal(rawParam)
|
||||
case supportedExt:
|
||||
return (¶mSupportedExtensions{}).unmarshal(rawParam)
|
||||
case ecnCapable:
|
||||
return (¶mECNCapable{}).unmarshal(rawParam)
|
||||
case random:
|
||||
return (¶mRandom{}).unmarshal(rawParam)
|
||||
case reqHMACAlgo:
|
||||
|
@ -30,6 +36,6 @@ func buildParam(t paramType, rawParam []byte) (param, error) {
|
|||
case reconfigResp:
|
||||
return (¶mReconfigResponse{}).unmarshal(rawParam)
|
||||
default:
|
||||
return nil, errors.Errorf("Unhandled ParamType %v", t)
|
||||
return nil, fmt.Errorf("%w: %v", ErrParamTypeUnhandled, t)
|
||||
}
|
||||
}
|
||||
|
|
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_ecn_capable.go
generated
vendored
Normal file
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_ecn_capable.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
package sctp
|
||||
|
||||
type paramECNCapable struct {
|
||||
paramHeader
|
||||
}
|
||||
|
||||
func (r *paramECNCapable) marshal() ([]byte, error) {
|
||||
r.typ = ecnCapable
|
||||
r.raw = []byte{}
|
||||
return r.paramHeader.marshal()
|
||||
}
|
||||
|
||||
func (r *paramECNCapable) unmarshal(raw []byte) (param, error) {
|
||||
err := r.paramHeader.unmarshal(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
7
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_outgoing_reset_request.go
generated
vendored
7
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_outgoing_reset_request.go
generated
vendored
|
@ -52,7 +52,10 @@ type paramOutgoingResetRequest struct {
|
|||
streamIdentifiers []uint16
|
||||
}
|
||||
|
||||
var errSSNResetRequestParamTooShort = errors.New("outgoing SSN reset request parameter too short")
|
||||
// Outgoing reset request parameter errors
|
||||
var (
|
||||
ErrSSNResetRequestParamTooShort = errors.New("outgoing SSN reset request parameter too short")
|
||||
)
|
||||
|
||||
func (r *paramOutgoingResetRequest) marshal() ([]byte, error) {
|
||||
r.typ = outSSNResetReq
|
||||
|
@ -72,7 +75,7 @@ func (r *paramOutgoingResetRequest) unmarshal(raw []byte) (param, error) {
|
|||
return nil, err
|
||||
}
|
||||
if len(r.raw) < paramOutgoingResetRequestStreamIdentifiersOffset {
|
||||
return nil, errSSNResetRequestParamTooShort
|
||||
return nil, ErrSSNResetRequestParamTooShort
|
||||
}
|
||||
r.reconfigRequestSequenceNumber = binary.BigEndian.Uint32(r.raw)
|
||||
r.reconfigResponseSequenceNumber = binary.BigEndian.Uint32(r.raw[4:])
|
||||
|
|
7
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_reconfig_response.go
generated
vendored
7
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_reconfig_response.go
generated
vendored
|
@ -45,7 +45,10 @@ const (
|
|||
reconfigResultInProgress reconfigResult = 6
|
||||
)
|
||||
|
||||
var errReconfigRespParamTooShort = errors.New("reconfig response parameter too short")
|
||||
// Reconfiguration response errors
|
||||
var (
|
||||
ErrReconfigRespParamTooShort = errors.New("reconfig response parameter too short")
|
||||
)
|
||||
|
||||
func (t reconfigResult) String() string {
|
||||
switch t {
|
||||
|
@ -83,7 +86,7 @@ func (r *paramReconfigResponse) unmarshal(raw []byte) (param, error) {
|
|||
return nil, err
|
||||
}
|
||||
if len(r.raw) < 8 {
|
||||
return nil, errReconfigRespParamTooShort
|
||||
return nil, ErrReconfigRespParamTooShort
|
||||
}
|
||||
r.reconfigResponseSequenceNumber = binary.BigEndian.Uint32(r.raw)
|
||||
r.result = reconfigResult(binary.BigEndian.Uint32(r.raw[4:]))
|
||||
|
|
|
@ -2,9 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type hmacAlgorithm uint16
|
||||
|
@ -16,6 +15,9 @@ const (
|
|||
hmacSHA256 hmacAlgorithm = 3
|
||||
)
|
||||
|
||||
// ErrInvalidAlgorithmType is returned if unknown auth algorithm is specified.
|
||||
var ErrInvalidAlgorithmType = errors.New("invalid algorithm type")
|
||||
|
||||
func (c hmacAlgorithm) String() string {
|
||||
switch c {
|
||||
case hmacResv1:
|
||||
|
@ -63,7 +65,7 @@ func (r *paramRequestedHMACAlgorithm) unmarshal(raw []byte) (param, error) {
|
|||
case hmacSHA256:
|
||||
r.availableAlgorithms = append(r.availableAlgorithms, a)
|
||||
default:
|
||||
return nil, errors.Errorf("Invalid algorithm type '%v'", a)
|
||||
return nil, fmt.Errorf("%w: %v", ErrInvalidAlgorithmType, a)
|
||||
}
|
||||
|
||||
i += 2
|
||||
|
|
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramheader.go
generated
vendored
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramheader.go
generated
vendored
|
@ -3,9 +3,8 @@ package sctp
|
|||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type paramHeader struct {
|
||||
|
@ -18,6 +17,14 @@ const (
|
|||
paramHeaderLength = 4
|
||||
)
|
||||
|
||||
// Parameter header parse errors
|
||||
var (
|
||||
ErrParamHeaderTooShort = errors.New("param header too short")
|
||||
ErrParamHeaderSelfReportedLengthShorter = errors.New("param self reported length is shorter than header length")
|
||||
ErrParamHeaderSelfReportedLengthLonger = errors.New("param self reported length is longer than header length")
|
||||
ErrParamHeaderParseFailed = errors.New("failed to parse param type")
|
||||
)
|
||||
|
||||
func (p *paramHeader) marshal() ([]byte, error) {
|
||||
paramLengthPlusHeader := paramHeaderLength + len(p.raw)
|
||||
|
||||
|
@ -31,20 +38,20 @@ func (p *paramHeader) marshal() ([]byte, error) {
|
|||
|
||||
func (p *paramHeader) unmarshal(raw []byte) error {
|
||||
if len(raw) < paramHeaderLength {
|
||||
return errors.New("param header too short")
|
||||
return ErrParamHeaderTooShort
|
||||
}
|
||||
|
||||
paramLengthPlusHeader := binary.BigEndian.Uint16(raw[2:])
|
||||
if int(paramLengthPlusHeader) < paramHeaderLength {
|
||||
return errors.Errorf("param self reported length (%d) smaller than header length (%d)", int(paramLengthPlusHeader), paramHeaderLength)
|
||||
return fmt.Errorf("%w: param self reported length (%d) shorter than header length (%d)", ErrParamHeaderSelfReportedLengthShorter, int(paramLengthPlusHeader), paramHeaderLength)
|
||||
}
|
||||
if len(raw) < int(paramLengthPlusHeader) {
|
||||
return errors.Errorf("param length (%d) shorter than its self reported length (%d)", len(raw), int(paramLengthPlusHeader))
|
||||
return fmt.Errorf("%w: param length (%d) shorter than its self reported length (%d)", ErrParamHeaderSelfReportedLengthLonger, len(raw), int(paramLengthPlusHeader))
|
||||
}
|
||||
|
||||
typ, err := parseParamType(raw[0:])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse param type")
|
||||
return fmt.Errorf("%w: %v", ErrParamHeaderParseFailed, err) //nolint:errorlint
|
||||
}
|
||||
p.typ = typ
|
||||
p.raw = raw[paramHeaderLength:paramLengthPlusHeader]
|
||||
|
|
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramtype.go
generated
vendored
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramtype.go
generated
vendored
|
@ -2,9 +2,8 @@ package sctp
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// paramType represents a SCTP INIT/INITACK parameter
|
||||
|
@ -25,6 +24,7 @@ const (
|
|||
reconfigResp paramType = 16 // Re-configuration Response Parameter [RFC6525]
|
||||
addOutStreamsReq paramType = 17 // Add Outgoing Streams Request Parameter [RFC6525]
|
||||
addIncStreamsReq paramType = 18 // Add Incoming Streams Request Parameter [RFC6525]
|
||||
ecnCapable paramType = 32768 // ECN Capable (0x8000) [RFC2960]
|
||||
random paramType = 32770 // Random (0x8002) [RFC4805]
|
||||
chunkList paramType = 32771 // Chunk List (0x8003) [RFC4895]
|
||||
reqHMACAlgo paramType = 32772 // Requested HMAC Algorithm Parameter (0x8004) [RFC4895]
|
||||
|
@ -39,9 +39,14 @@ const (
|
|||
adaptLayerInd paramType = 49158 // Adaptation Layer Indication (0xC006) [RFC5061]
|
||||
)
|
||||
|
||||
// Parameter packet errors
|
||||
var (
|
||||
ErrParamPacketTooShort = errors.New("packet to short")
|
||||
)
|
||||
|
||||
func parseParamType(raw []byte) (paramType, error) {
|
||||
if len(raw) < 2 {
|
||||
return paramType(0), errors.New("packet to short")
|
||||
return paramType(0), ErrParamPacketTooShort
|
||||
}
|
||||
return paramType(binary.BigEndian.Uint16(raw)), nil
|
||||
}
|
||||
|
@ -76,6 +81,8 @@ func (p paramType) String() string {
|
|||
return "Add Outgoing Streams Request Parameter"
|
||||
case addIncStreamsReq:
|
||||
return "Add Incoming Streams Request Parameter"
|
||||
case ecnCapable:
|
||||
return "ECN Capable"
|
||||
case random:
|
||||
return "Random"
|
||||
case chunkList:
|
||||
|
|
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/pending_queue.go
generated
vendored
19
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/pending_queue.go
generated
vendored
|
@ -1,7 +1,7 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// pendingBaseQueue
|
||||
|
@ -48,10 +48,11 @@ type pendingQueue struct {
|
|||
unorderedIsSelected bool
|
||||
}
|
||||
|
||||
// Pending queue errors
|
||||
var (
|
||||
errUnexpectedChuckPoppedUnordered = errors.New("unexpected chunk popped (unordered)")
|
||||
errUnexpectedChuckPoppedOrdered = errors.New("unexpected chunk popped (ordered)")
|
||||
errUnexpectedQState = errors.New("unexpected q state (should've been selected)")
|
||||
ErrUnexpectedChuckPoppedUnordered = errors.New("unexpected chunk popped (unordered)")
|
||||
ErrUnexpectedChuckPoppedOrdered = errors.New("unexpected chunk popped (ordered)")
|
||||
ErrUnexpectedQState = errors.New("unexpected q state (should've been selected)")
|
||||
)
|
||||
|
||||
func newPendingQueue() *pendingQueue {
|
||||
|
@ -90,12 +91,12 @@ func (q *pendingQueue) pop(c *chunkPayloadData) error {
|
|||
if q.unorderedIsSelected {
|
||||
popped = q.unorderedQueue.pop()
|
||||
if popped != c {
|
||||
return errUnexpectedChuckPoppedUnordered
|
||||
return ErrUnexpectedChuckPoppedUnordered
|
||||
}
|
||||
} else {
|
||||
popped = q.orderedQueue.pop()
|
||||
if popped != c {
|
||||
return errUnexpectedChuckPoppedOrdered
|
||||
return ErrUnexpectedChuckPoppedOrdered
|
||||
}
|
||||
}
|
||||
if popped.endingFragment {
|
||||
|
@ -103,12 +104,12 @@ func (q *pendingQueue) pop(c *chunkPayloadData) error {
|
|||
}
|
||||
} else {
|
||||
if !c.beginningFragment {
|
||||
return errUnexpectedQState
|
||||
return ErrUnexpectedQState
|
||||
}
|
||||
if c.unordered {
|
||||
popped := q.unorderedQueue.pop()
|
||||
if popped != c {
|
||||
return errUnexpectedChuckPoppedUnordered
|
||||
return ErrUnexpectedChuckPoppedUnordered
|
||||
}
|
||||
if !popped.endingFragment {
|
||||
q.selected = true
|
||||
|
@ -117,7 +118,7 @@ func (q *pendingQueue) pop(c *chunkPayloadData) error {
|
|||
} else {
|
||||
popped := q.orderedQueue.pop()
|
||||
if popped != c {
|
||||
return errUnexpectedChuckPoppedOrdered
|
||||
return ErrUnexpectedChuckPoppedOrdered
|
||||
}
|
||||
if !popped.endingFragment {
|
||||
q.selected = true
|
||||
|
|
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/reassembly_queue.go
generated
vendored
3
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/reassembly_queue.go
generated
vendored
|
@ -1,11 +1,10 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func sortChunksByTSN(a []*chunkPayloadData) {
|
||||
|
|
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/renovate.json
generated
vendored
13
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/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"
|
||||
]
|
||||
}
|
||||
|
|
179
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/stream.go
generated
vendored
179
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/stream.go
generated
vendored
|
@ -1,12 +1,16 @@
|
|||
package sctp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -18,6 +22,36 @@ const (
|
|||
ReliabilityTypeTimed byte = 2
|
||||
)
|
||||
|
||||
// StreamState is an enum for SCTP Stream state field
|
||||
// This field identifies the state of stream.
|
||||
type StreamState int
|
||||
|
||||
// StreamState enums
|
||||
const (
|
||||
StreamStateOpen StreamState = iota // Stream object starts with StreamStateOpen
|
||||
StreamStateClosing // Outgoing stream is being reset
|
||||
StreamStateClosed // Stream has been closed
|
||||
)
|
||||
|
||||
func (ss StreamState) String() string {
|
||||
switch ss {
|
||||
case StreamStateOpen:
|
||||
return "open"
|
||||
case StreamStateClosing:
|
||||
return "closing"
|
||||
case StreamStateClosed:
|
||||
return "closed"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// SCTP stream errors
|
||||
var (
|
||||
ErrOutboundPacketTooLarge = errors.New("outbound packet larger than maximum message size")
|
||||
ErrStreamClosed = errors.New("stream closed")
|
||||
ErrReadDeadlineExceeded = fmt.Errorf("read deadline exceeded: %w", os.ErrDeadlineExceeded)
|
||||
)
|
||||
|
||||
// Stream represents an SCTP stream
|
||||
type Stream struct {
|
||||
association *Association
|
||||
|
@ -28,13 +62,14 @@ type Stream struct {
|
|||
sequenceNumber uint16
|
||||
readNotifier *sync.Cond
|
||||
readErr error
|
||||
writeErr error
|
||||
readTimeoutCancel chan struct{}
|
||||
unordered bool
|
||||
reliabilityType byte
|
||||
reliabilityValue uint32
|
||||
bufferedAmount uint64
|
||||
bufferedAmountLow uint64
|
||||
onBufferedAmountLow func()
|
||||
state StreamState
|
||||
log logging.LeveledLogger
|
||||
name string
|
||||
}
|
||||
|
@ -48,15 +83,7 @@ func (s *Stream) StreamIdentifier() uint16 {
|
|||
|
||||
// SetDefaultPayloadType sets the default payload type used by Write.
|
||||
func (s *Stream) SetDefaultPayloadType(defaultPayloadType PayloadProtocolIdentifier) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.setDefaultPayloadType(defaultPayloadType)
|
||||
}
|
||||
|
||||
// setDefaultPayloadType sets the defaultPayloadType. The caller should hold the lock.
|
||||
func (s *Stream) setDefaultPayloadType(defaultPayloadType PayloadProtocolIdentifier) {
|
||||
s.defaultPayloadType = defaultPayloadType
|
||||
atomic.StoreUint32((*uint32)(&s.defaultPayloadType), uint32(defaultPayloadType))
|
||||
}
|
||||
|
||||
// SetReliabilityParams sets reliability parameters for this stream.
|
||||
|
@ -93,6 +120,14 @@ func (s *Stream) ReadSCTP(p []byte) (int, PayloadProtocolIdentifier, error) {
|
|||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
defer func() {
|
||||
// close readTimeoutCancel if the current read timeout routine is no longer effective
|
||||
if s.readTimeoutCancel != nil && s.readErr != nil {
|
||||
close(s.readTimeoutCancel)
|
||||
s.readTimeoutCancel = nil
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
n, ppi, err := s.reassemblyQueue.read(p)
|
||||
if err == nil {
|
||||
|
@ -110,6 +145,47 @@ func (s *Stream) ReadSCTP(p []byte) (int, PayloadProtocolIdentifier, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// SetReadDeadline sets the read deadline in an identical way to net.Conn
|
||||
func (s *Stream) SetReadDeadline(deadline time.Time) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if s.readTimeoutCancel != nil {
|
||||
close(s.readTimeoutCancel)
|
||||
s.readTimeoutCancel = nil
|
||||
}
|
||||
|
||||
if s.readErr != nil {
|
||||
if !errors.Is(s.readErr, ErrReadDeadlineExceeded) {
|
||||
return nil
|
||||
}
|
||||
s.readErr = nil
|
||||
}
|
||||
|
||||
if !deadline.IsZero() {
|
||||
s.readTimeoutCancel = make(chan struct{})
|
||||
|
||||
go func(readTimeoutCancel chan struct{}) {
|
||||
t := time.NewTimer(time.Until(deadline))
|
||||
select {
|
||||
case <-readTimeoutCancel:
|
||||
t.Stop()
|
||||
return
|
||||
case <-t.C:
|
||||
s.lock.Lock()
|
||||
if s.readErr == nil {
|
||||
s.readErr = ErrReadDeadlineExceeded
|
||||
}
|
||||
s.readTimeoutCancel = nil
|
||||
s.lock.Unlock()
|
||||
|
||||
s.readNotifier.Signal()
|
||||
}
|
||||
}(s.readTimeoutCancel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Stream) handleData(pd *chunkPayloadData) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
@ -174,26 +250,28 @@ func (s *Stream) handleForwardTSNForUnordered(newCumulativeTSN uint32) {
|
|||
|
||||
// Write writes len(p) bytes from p with the default Payload Protocol Identifier
|
||||
func (s *Stream) Write(p []byte) (n int, err error) {
|
||||
return s.WriteSCTP(p, s.defaultPayloadType)
|
||||
ppi := PayloadProtocolIdentifier(atomic.LoadUint32((*uint32)(&s.defaultPayloadType)))
|
||||
return s.WriteSCTP(p, ppi)
|
||||
}
|
||||
|
||||
// WriteSCTP writes len(p) bytes from p to the DTLS connection
|
||||
func (s *Stream) WriteSCTP(p []byte, ppi PayloadProtocolIdentifier) (n int, err error) {
|
||||
func (s *Stream) WriteSCTP(p []byte, ppi PayloadProtocolIdentifier) (int, error) {
|
||||
maxMessageSize := s.association.MaxMessageSize()
|
||||
if len(p) > int(maxMessageSize) {
|
||||
return 0, errors.Errorf("Outbound packet larger than maximum message size %v", math.MaxUint16)
|
||||
return 0, fmt.Errorf("%w: %v", ErrOutboundPacketTooLarge, math.MaxUint16)
|
||||
}
|
||||
|
||||
s.lock.RLock()
|
||||
err = s.writeErr
|
||||
s.lock.RUnlock()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
if s.State() != StreamStateOpen {
|
||||
return 0, ErrStreamClosed
|
||||
}
|
||||
|
||||
chunks := s.packetize(p, ppi)
|
||||
|
||||
return len(p), s.association.sendPayloadData(chunks)
|
||||
n := len(p)
|
||||
err := s.association.sendPayloadData(chunks)
|
||||
if err != nil {
|
||||
return n, ErrStreamClosed
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (s *Stream) packetize(raw []byte, ppi PayloadProtocolIdentifier) []*chunkPayloadData {
|
||||
|
@ -257,26 +335,23 @@ func (s *Stream) packetize(raw []byte, ppi PayloadProtocolIdentifier) []*chunkPa
|
|||
// Close closes the write-direction of the stream.
|
||||
// Future calls to Write are not permitted after calling Close.
|
||||
func (s *Stream) Close() error {
|
||||
if sid, isOpen := func() (uint16, bool) {
|
||||
if sid, resetOutbound := func() (uint16, bool) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
isOpen := true
|
||||
if s.writeErr == nil {
|
||||
s.writeErr = errors.New("Stream closed")
|
||||
} else {
|
||||
isOpen = false
|
||||
}
|
||||
s.log.Debugf("[%s] Close: state=%s", s.name, s.state.String())
|
||||
|
||||
if s.readErr == nil {
|
||||
s.readErr = io.EOF
|
||||
} else {
|
||||
isOpen = false
|
||||
if s.state == StreamStateOpen {
|
||||
if s.readErr == nil {
|
||||
s.state = StreamStateClosing
|
||||
} else {
|
||||
s.state = StreamStateClosed
|
||||
}
|
||||
s.log.Debugf("[%s] state change: open => %s", s.name, s.state.String())
|
||||
return s.streamIdentifier, true
|
||||
}
|
||||
s.readNotifier.Broadcast() // broadcast regardless
|
||||
|
||||
return s.streamIdentifier, isOpen
|
||||
}(); isOpen {
|
||||
return s.streamIdentifier, false
|
||||
}(); resetOutbound {
|
||||
// Reset the outgoing stream
|
||||
// https://tools.ietf.org/html/rfc6525
|
||||
return s.association.sendResetRequest(sid)
|
||||
|
@ -355,3 +430,35 @@ func (s *Stream) getNumBytesInReassemblyQueue() int {
|
|||
// No lock is required as it reads the size with atomic load function.
|
||||
return s.reassemblyQueue.getNumBytes()
|
||||
}
|
||||
|
||||
func (s *Stream) onInboundStreamReset() {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
s.log.Debugf("[%s] onInboundStreamReset: state=%s", s.name, s.state.String())
|
||||
|
||||
// No more inbound data to read. Unblock the read with io.EOF.
|
||||
// This should cause DCEP layer (datachannel package) to call Close() which
|
||||
// will reset outgoing stream also.
|
||||
|
||||
// See RFC 8831 section 6.7:
|
||||
// if one side decides to close the data channel, it resets the corresponding
|
||||
// outgoing stream. When the peer sees that an incoming stream was
|
||||
// reset, it also resets its corresponding outgoing stream. Once this
|
||||
// is completed, the data channel is closed.
|
||||
|
||||
s.readErr = io.EOF
|
||||
s.readNotifier.Broadcast()
|
||||
|
||||
if s.state == StreamStateClosing {
|
||||
s.log.Debugf("[%s] state change: closing => closed", s.name)
|
||||
s.state = StreamStateClosed
|
||||
}
|
||||
}
|
||||
|
||||
// State return the stream state.
|
||||
func (s *Stream) State() StreamState {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
return s.state
|
||||
}
|
||||
|
|
4
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/util.go
generated
vendored
4
trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/util.go
generated
vendored
|
@ -4,8 +4,8 @@ const (
|
|||
paddingMultiple = 4
|
||||
)
|
||||
|
||||
func getPadding(len int) int {
|
||||
return (paddingMultiple - (len % paddingMultiple)) % paddingMultiple
|
||||
func getPadding(l int) int {
|
||||
return (paddingMultiple - (l % paddingMultiple)) % paddingMultiple
|
||||
}
|
||||
|
||||
func padByte(in []byte, cnt int) []byte {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue