mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
For regression test, add srs-bench to 3rdparty
This commit is contained in:
parent
de87dd427d
commit
876210f6c9
1158 changed files with 256967 additions and 3 deletions
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.gitignore
generated
vendored
Normal file
24
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
### JetBrains IDE ###
|
||||
#####################
|
||||
.idea/
|
||||
|
||||
### Emacs Temporary Files ###
|
||||
#############################
|
||||
*~
|
||||
|
||||
### Folders ###
|
||||
###############
|
||||
bin/
|
||||
vendor/
|
||||
node_modules/
|
||||
|
||||
### Files ###
|
||||
#############
|
||||
*.ivf
|
||||
*.ogg
|
||||
tags
|
||||
cover.out
|
||||
*.sw[poe]
|
||||
*.wasm
|
||||
examples/sfu-ws/cert.pem
|
||||
examples/sfu-ws/key.pem
|
89
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.golangci.yml
generated
vendored
Normal file
89
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.golangci.yml
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: true
|
||||
misspell:
|
||||
locale: US
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
gomodguard:
|
||||
blocked:
|
||||
modules:
|
||||
- github.com/pkg/errors:
|
||||
recommendations:
|
||||
- errors
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers
|
||||
- bodyclose # checks whether HTTP response body is closed successfully
|
||||
- deadcode # Finds unused code
|
||||
- depguard # Go linter that checks if package imports are in a list of acceptable packages
|
||||
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
|
||||
- dupl # Tool for code clone detection
|
||||
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
|
||||
- exhaustive # check exhaustiveness of enum switch statements
|
||||
- exportloopref # checks for pointers to enclosing loop variables
|
||||
- gci # Gci control golang package import order and make it always deterministic.
|
||||
- gochecknoglobals # Checks that no globals are present in Go code
|
||||
- gochecknoinits # Checks that no init functions are present in Go code
|
||||
- gocognit # Computes and checks the cognitive complexity of functions
|
||||
- goconst # Finds repeated strings that could be replaced by a constant
|
||||
- gocritic # The most opinionated Go source code linter
|
||||
- godox # Tool for detection of FIXME, TODO and other comment keywords
|
||||
- goerr113 # Golang linter to check the errors handling expressions
|
||||
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
|
||||
- gofumpt # Gofumpt checks whether code was gofumpt-ed.
|
||||
- goheader # Checks is file header matches to pattern
|
||||
- goimports # Goimports does everything that gofmt does. Additionally it checks unused imports
|
||||
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
||||
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations.
|
||||
- goprintffuncname # Checks that printf-like functions are named with `f` at the end
|
||||
- gosec # Inspects source code for security problems
|
||||
- gosimple # Linter for Go source code that specializes in simplifying a code
|
||||
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||
- ineffassign # Detects when assignments to existing variables are not used
|
||||
- misspell # Finds commonly misspelled English words in comments
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||
- noctx # noctx finds sending http request without context.Context
|
||||
- scopelint # Scopelint checks for unpinned variables in go programs
|
||||
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
|
||||
- structcheck # Finds unused struct fields
|
||||
- stylecheck # Stylecheck is a replacement for golint
|
||||
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code
|
||||
- unconvert # Remove unnecessary type conversions
|
||||
- unparam # Reports unused function parameters
|
||||
- unused # Checks Go code for unused constants, variables, functions and types
|
||||
- varcheck # Finds unused global variables and constants
|
||||
- whitespace # Tool for detection of leading and trailing whitespace
|
||||
disable:
|
||||
- funlen # Tool for detection of long functions
|
||||
- gocyclo # Computes and checks the cyclomatic complexity of functions
|
||||
- godot # Check if comments end in a period
|
||||
- gomnd # An analyzer to detect magic numbers.
|
||||
- lll # Reports long lines
|
||||
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted
|
||||
- nestif # Reports deeply nested if statements
|
||||
- nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity
|
||||
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||
- prealloc # Finds slice declarations that could potentially be preallocated
|
||||
- rowserrcheck # checks whether Err of rows is checked successfully
|
||||
- sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed.
|
||||
- testpackage # linter that makes you use a separate _test package
|
||||
- wsl # Whitespace Linter - Forces you to use empty lines!
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
exclude-rules:
|
||||
# Allow complex tests, better to be self contained
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
# Allow complex main function in examples
|
||||
- path: examples
|
||||
text: "of func `main` is high"
|
||||
linters:
|
||||
- gocognit
|
||||
|
||||
run:
|
||||
skip-dirs-use-default: false
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/DESIGN.md
generated
vendored
Normal file
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/DESIGN.md
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<h1 align="center">
|
||||
Design
|
||||
</h1>
|
||||
|
||||
### Portable
|
||||
Pion SRTP is written in Go and extremely portable. Anywhere Golang runs, Pion SRTP 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.
|
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/LICENSE
generated
vendored
Normal file
21
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/README.md
generated
vendored
Normal file
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/README.md
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
<h1 align="center">
|
||||
<br>
|
||||
Pion SRTP
|
||||
<br>
|
||||
</h1>
|
||||
<h4 align="center">A Go implementation of SRTP</h4>
|
||||
<p align="center">
|
||||
<a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-srtp-gray.svg?longCache=true&colorB=brightgreen" alt="Pion SRTP"></a>
|
||||
<a href="https://sourcegraph.com/github.com/pion/srtp?badge"><img src="https://sourcegraph.com/github.com/pion/srtp/-/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/srtp"><img src="https://travis-ci.org/pion/srtp.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/srtp"><img src="https://godoc.org/github.com/pion/srtp?status.svg" alt="GoDoc"></a>
|
||||
<a href="https://codecov.io/gh/pion/srtp"><img src="https://codecov.io/gh/pion/srtp/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/srtp"><img src="https://goreportcard.com/badge/github.com/pion/srtp" alt="Go Report Card"></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
||||
</p>
|
||||
<br>
|
||||
|
||||
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).
|
||||
|
||||
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:
|
||||
|
||||
* [Sean DuBois](https://github.com/Sean-Der) - *Original Author*
|
||||
* [Michiel De Backker](https://github.com/backkem) - *io.Writer interfaces*
|
||||
* [Tobias Fridén](https://github.com/tobiasfriden) *SRTP authentication verification*
|
||||
* [chenkaiC4](https://github.com/chenkaiC4) - *Fix GolangCI Linter*
|
||||
* [Luke Curley](https://github.com/kixelated) - *Performance*
|
||||
* [Chris Hiszpanski](https://github.com/thinkski) - *Fix out-of-bounds access*
|
||||
* [Yutaka Takeda](https://github.com/enobufs) - *Fix log messages*
|
||||
* [Max Hawkins](https://github.com/maxhawkins)
|
||||
* [Woodrow Douglass](https://github.com/wdouglass)
|
||||
* [Hugo Arregui](https://github.com/hugoArregui)
|
||||
* [Atsushi Watanabe](https://github.com/at-wat)
|
||||
* [Novel Corpse](https://github.com/NovelCorpse)
|
||||
* [Jerko Steiner](https://github.com/jeremija)
|
||||
* [Juliusz Chroboczek](https://github.com/jech)
|
||||
* [Mission Liao](https://github.com/mission-liao)
|
||||
* [Orlando](https://github.com/OrlandoCo)
|
||||
* [Tarrence van As](https://github.com/tarrencev)
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/codecov.yml
generated
vendored
Normal file
20
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/codecov.yml
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# DO NOT EDIT THIS FILE
|
||||
#
|
||||
# It is automatically copied from https://github.com/pion/.goassets repository.
|
||||
#
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
# Allow decreasing 2% of total coverage to avoid noise.
|
||||
threshold: 2%
|
||||
patch:
|
||||
default:
|
||||
target: 70%
|
||||
only_pulls: true
|
||||
|
||||
ignore:
|
||||
- "examples/*"
|
||||
- "examples/**/*"
|
196
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/context.go
generated
vendored
Normal file
196
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/context.go
generated
vendored
Normal file
|
@ -0,0 +1,196 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pion/transport/replaydetector"
|
||||
)
|
||||
|
||||
const (
|
||||
labelSRTPEncryption = 0x00
|
||||
labelSRTPAuthenticationTag = 0x01
|
||||
labelSRTPSalt = 0x02
|
||||
|
||||
labelSRTCPEncryption = 0x03
|
||||
labelSRTCPAuthenticationTag = 0x04
|
||||
labelSRTCPSalt = 0x05
|
||||
|
||||
maxROCDisorder = 100
|
||||
maxSequenceNumber = 65535
|
||||
|
||||
srtcpIndexSize = 4
|
||||
)
|
||||
|
||||
// Encrypt/Decrypt state for a single SRTP SSRC
|
||||
type srtpSSRCState struct {
|
||||
ssrc uint32
|
||||
rolloverCounter uint32
|
||||
rolloverHasProcessed bool
|
||||
lastSequenceNumber uint16
|
||||
replayDetector replaydetector.ReplayDetector
|
||||
}
|
||||
|
||||
// Encrypt/Decrypt state for a single SRTCP SSRC
|
||||
type srtcpSSRCState struct {
|
||||
srtcpIndex uint32
|
||||
ssrc uint32
|
||||
replayDetector replaydetector.ReplayDetector
|
||||
}
|
||||
|
||||
// Context represents a SRTP cryptographic context.
|
||||
// Context can only be used for one-way operations.
|
||||
// it must either used ONLY for encryption or ONLY for decryption.
|
||||
type Context struct {
|
||||
cipher srtpCipher
|
||||
|
||||
srtpSSRCStates map[uint32]*srtpSSRCState
|
||||
srtcpSSRCStates map[uint32]*srtcpSSRCState
|
||||
|
||||
newSRTCPReplayDetector func() replaydetector.ReplayDetector
|
||||
newSRTPReplayDetector func() replaydetector.ReplayDetector
|
||||
}
|
||||
|
||||
// CreateContext creates a new SRTP Context.
|
||||
//
|
||||
// CreateContext receives variable number of ContextOption-s.
|
||||
// Passing multiple options which set the same parameter let the last one valid.
|
||||
// Following example create SRTP Context with replay protection with window size of 256.
|
||||
//
|
||||
// decCtx, err := srtp.CreateContext(key, salt, profile, srtp.SRTPReplayProtection(256))
|
||||
//
|
||||
func CreateContext(masterKey, masterSalt []byte, profile ProtectionProfile, opts ...ContextOption) (c *Context, err error) {
|
||||
keyLen, err := profile.keyLen()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
saltLen, err := profile.saltLen()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if masterKeyLen := len(masterKey); masterKeyLen != keyLen {
|
||||
return c, fmt.Errorf("%w expected(%d) actual(%d)", errShortSrtpMasterKey, masterKey, keyLen)
|
||||
} else if masterSaltLen := len(masterSalt); masterSaltLen != saltLen {
|
||||
return c, fmt.Errorf("%w expected(%d) actual(%d)", errShortSrtpMasterSalt, saltLen, masterSaltLen)
|
||||
}
|
||||
|
||||
c = &Context{
|
||||
srtpSSRCStates: map[uint32]*srtpSSRCState{},
|
||||
srtcpSSRCStates: map[uint32]*srtcpSSRCState{},
|
||||
}
|
||||
|
||||
switch profile {
|
||||
case ProtectionProfileAeadAes128Gcm:
|
||||
c.cipher, err = newSrtpCipherAeadAesGcm(masterKey, masterSalt)
|
||||
case ProtectionProfileAes128CmHmacSha1_80:
|
||||
c.cipher, err = newSrtpCipherAesCmHmacSha1(masterKey, masterSalt)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, profile)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, o := range append(
|
||||
[]ContextOption{ // Default options
|
||||
SRTPNoReplayProtection(),
|
||||
SRTCPNoReplayProtection(),
|
||||
},
|
||||
opts..., // User specified options
|
||||
) {
|
||||
if errOpt := o(c); errOpt != nil {
|
||||
return nil, errOpt
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc3550#appendix-A.1
|
||||
func (s *srtpSSRCState) nextRolloverCount(sequenceNumber uint16) (uint32, func()) {
|
||||
roc := s.rolloverCounter
|
||||
|
||||
switch {
|
||||
case !s.rolloverHasProcessed:
|
||||
case sequenceNumber == 0: // We exactly hit the rollover count
|
||||
// Only update rolloverCounter if lastSequenceNumber is greater then maxROCDisorder
|
||||
// otherwise we already incremented for disorder
|
||||
if s.lastSequenceNumber > maxROCDisorder {
|
||||
roc++
|
||||
}
|
||||
case s.lastSequenceNumber < maxROCDisorder &&
|
||||
sequenceNumber > (maxSequenceNumber-maxROCDisorder):
|
||||
// Our last sequence number incremented because we crossed 0, but then our current number was within maxROCDisorder of the max
|
||||
// So we fell behind, drop to account for jitter
|
||||
roc--
|
||||
case sequenceNumber < maxROCDisorder &&
|
||||
s.lastSequenceNumber > (maxSequenceNumber-maxROCDisorder):
|
||||
// our current is within a maxROCDisorder of 0
|
||||
// and our last sequence number was a high sequence number, increment to account for jitter
|
||||
roc++
|
||||
}
|
||||
return roc, func() {
|
||||
s.rolloverHasProcessed = true
|
||||
s.lastSequenceNumber = sequenceNumber
|
||||
s.rolloverCounter = roc
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) getSRTPSSRCState(ssrc uint32) *srtpSSRCState {
|
||||
s, ok := c.srtpSSRCStates[ssrc]
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
|
||||
s = &srtpSSRCState{
|
||||
ssrc: ssrc,
|
||||
replayDetector: c.newSRTPReplayDetector(),
|
||||
}
|
||||
c.srtpSSRCStates[ssrc] = s
|
||||
return s
|
||||
}
|
||||
|
||||
func (c *Context) getSRTCPSSRCState(ssrc uint32) *srtcpSSRCState {
|
||||
s, ok := c.srtcpSSRCStates[ssrc]
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
|
||||
s = &srtcpSSRCState{
|
||||
ssrc: ssrc,
|
||||
replayDetector: c.newSRTCPReplayDetector(),
|
||||
}
|
||||
c.srtcpSSRCStates[ssrc] = s
|
||||
return s
|
||||
}
|
||||
|
||||
// ROC returns SRTP rollover counter value of specified SSRC.
|
||||
func (c *Context) ROC(ssrc uint32) (uint32, bool) {
|
||||
s, ok := c.srtpSSRCStates[ssrc]
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return s.rolloverCounter, true
|
||||
}
|
||||
|
||||
// SetROC sets SRTP rollover counter value of specified SSRC.
|
||||
func (c *Context) SetROC(ssrc uint32, roc uint32) {
|
||||
s := c.getSRTPSSRCState(ssrc)
|
||||
s.rolloverCounter = roc
|
||||
}
|
||||
|
||||
// Index returns SRTCP index value of specified SSRC.
|
||||
func (c *Context) Index(ssrc uint32) (uint32, bool) {
|
||||
s, ok := c.srtcpSSRCStates[ssrc]
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return s.srtcpIndex, true
|
||||
}
|
||||
|
||||
// SetIndex sets SRTCP index value of specified SSRC.
|
||||
func (c *Context) SetIndex(ssrc uint32, index uint32) {
|
||||
s := c.getSRTCPSSRCState(ssrc)
|
||||
s.srtcpIndex = index % (maxSRTCPIndex + 1)
|
||||
}
|
40
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/errors.go
generated
vendored
Normal file
40
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
errDuplicated = errors.New("duplicated packet")
|
||||
errShortSrtpMasterKey = errors.New("SRTP master key is not long enough")
|
||||
errShortSrtpMasterSalt = errors.New("SRTP master salt is not long enough")
|
||||
errNoSuchSRTPProfile = errors.New("no such SRTP Profile")
|
||||
errNonZeroKDRNotSupported = errors.New("indexOverKdr > 0 is not supported yet")
|
||||
errExporterWrongLabel = errors.New("exporter called with wrong label")
|
||||
errNoConfig = errors.New("no config provided")
|
||||
errNoConn = errors.New("no conn provided")
|
||||
errFailedToVerifyAuthTag = errors.New("failed to verify auth tag")
|
||||
errTooShortRTCP = errors.New("packet is too short to be rtcp packet")
|
||||
errPayloadDiffers = errors.New("payload differs")
|
||||
errStartedChannelUsedIncorrectly = errors.New("started channel used incorrectly, should only be closed")
|
||||
|
||||
errStreamNotInited = errors.New("stream has not been inited, unable to close")
|
||||
errStreamAlreadyClosed = errors.New("stream is already closed")
|
||||
errStreamAlreadyInited = errors.New("stream is already inited")
|
||||
errFailedTypeAssertion = errors.New("failed to cast child")
|
||||
)
|
||||
|
||||
type errorDuplicated struct {
|
||||
Proto string // srtp or srtcp
|
||||
SSRC uint32
|
||||
Index uint32 // sequence number or index
|
||||
}
|
||||
|
||||
func (e *errorDuplicated) Error() string {
|
||||
return fmt.Sprintf("%s ssrc=%d index=%d: %v", e.Proto, e.SSRC, e.Index, errDuplicated)
|
||||
}
|
||||
|
||||
func (e *errorDuplicated) Unwrap() error {
|
||||
return errDuplicated
|
||||
}
|
11
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/go.mod
generated
vendored
Normal file
11
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
module github.com/pion/srtp/v2
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/pion/logging v0.2.2
|
||||
github.com/pion/rtcp v1.2.6
|
||||
github.com/pion/rtp v1.6.2
|
||||
github.com/pion/transport v0.12.2
|
||||
github.com/stretchr/testify v1.6.1
|
||||
)
|
32
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/go.sum
generated
vendored
Normal file
32
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
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/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/rtcp v1.2.6 h1:1zvwBbyd0TeEuuWftrd/4d++m+/kZSeiguxU61LFWpo=
|
||||
github.com/pion/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0=
|
||||
github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U=
|
||||
github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||
github.com/pion/transport v0.12.2 h1:WYEjhloRHt1R86LhUKjC5y+P52Y11/QqEUalvtzVoys=
|
||||
github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
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-20201201195509-5d6afe98e0b7 h1:3uJsdck53FDIpWwLeAXlia9p4C8j0BO2xZrqzKpL0D8=
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
63
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/key_derivation.go
generated
vendored
Normal file
63
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/key_derivation.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
func aesCmKeyDerivation(label byte, masterKey, masterSalt []byte, indexOverKdr int, outLen int) ([]byte, error) {
|
||||
if indexOverKdr != 0 {
|
||||
// 24-bit "index DIV kdr" must be xored to prf input.
|
||||
return nil, errNonZeroKDRNotSupported
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc3711#appendix-B.3
|
||||
// The input block for AES-CM is generated by exclusive-oring the master salt with the
|
||||
// concatenation of the encryption key label 0x00 with (index DIV kdr),
|
||||
// - index is 'rollover count' and DIV is 'divided by'
|
||||
|
||||
nMasterKey := len(masterKey)
|
||||
nMasterSalt := len(masterSalt)
|
||||
|
||||
prfIn := make([]byte, nMasterKey)
|
||||
copy(prfIn[:nMasterSalt], masterSalt)
|
||||
|
||||
prfIn[7] ^= label
|
||||
|
||||
// The resulting value is then AES encrypted using the master key to get the cipher key.
|
||||
block, err := aes.NewCipher(masterKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make([]byte, ((outLen+nMasterKey)/nMasterKey)*nMasterKey)
|
||||
var i uint16
|
||||
for n := 0; n < outLen; n += nMasterKey {
|
||||
binary.BigEndian.PutUint16(prfIn[nMasterKey-2:], i)
|
||||
block.Encrypt(out[n:n+nMasterKey], prfIn)
|
||||
i++
|
||||
}
|
||||
return out[:outLen], nil
|
||||
}
|
||||
|
||||
// Generate IV https://tools.ietf.org/html/rfc3711#section-4.1.1
|
||||
// where the 128-bit integer value IV SHALL be defined by the SSRC, the
|
||||
// SRTP packet index i, and the SRTP session salting key k_s, as below.
|
||||
// - ROC = a 32-bit unsigned rollover counter (ROC), which records how many
|
||||
// - times the 16-bit RTP sequence number has been reset to zero after
|
||||
// - passing through 65,535
|
||||
// i = 2^16 * ROC + SEQ
|
||||
// IV = (salt*2 ^ 16) | (ssrc*2 ^ 64) | (i*2 ^ 16)
|
||||
func generateCounter(sequenceNumber uint16, rolloverCounter uint32, ssrc uint32, sessionSalt []byte) []byte {
|
||||
counter := make([]byte, 16)
|
||||
|
||||
binary.BigEndian.PutUint32(counter[4:], ssrc)
|
||||
binary.BigEndian.PutUint32(counter[8:], rolloverCounter)
|
||||
binary.BigEndian.PutUint32(counter[12:], uint32(sequenceNumber)<<16)
|
||||
|
||||
for i := range sessionSalt {
|
||||
counter[i] ^= sessionSalt[i]
|
||||
}
|
||||
|
||||
return counter
|
||||
}
|
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/keying.go
generated
vendored
Normal file
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/keying.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
package srtp
|
||||
|
||||
const labelExtractorDtlsSrtp = "EXTRACTOR-dtls_srtp"
|
||||
|
||||
// KeyingMaterialExporter allows package SRTP to extract keying material
|
||||
type KeyingMaterialExporter interface {
|
||||
ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error)
|
||||
}
|
||||
|
||||
// ExtractSessionKeysFromDTLS allows setting the Config SessionKeys by
|
||||
// extracting them from DTLS. This behavior is defined in RFC5764:
|
||||
// https://tools.ietf.org/html/rfc5764
|
||||
func (c *Config) ExtractSessionKeysFromDTLS(exporter KeyingMaterialExporter, isClient bool) error {
|
||||
keyLen, err := c.Profile.keyLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
saltLen, err := c.Profile.saltLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyingMaterial, err := exporter.ExportKeyingMaterial(labelExtractorDtlsSrtp, nil, (keyLen*2)+(saltLen*2))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
offset := 0
|
||||
clientWriteKey := append([]byte{}, keyingMaterial[offset:offset+keyLen]...)
|
||||
offset += keyLen
|
||||
|
||||
serverWriteKey := append([]byte{}, keyingMaterial[offset:offset+keyLen]...)
|
||||
offset += keyLen
|
||||
|
||||
clientWriteKey = append(clientWriteKey, keyingMaterial[offset:offset+saltLen]...)
|
||||
offset += saltLen
|
||||
|
||||
serverWriteKey = append(serverWriteKey, keyingMaterial[offset:offset+saltLen]...)
|
||||
|
||||
if isClient {
|
||||
c.Keys.LocalMasterKey = clientWriteKey[0:keyLen]
|
||||
c.Keys.LocalMasterSalt = clientWriteKey[keyLen:]
|
||||
c.Keys.RemoteMasterKey = serverWriteKey[0:keyLen]
|
||||
c.Keys.RemoteMasterSalt = serverWriteKey[keyLen:]
|
||||
return nil
|
||||
}
|
||||
|
||||
c.Keys.LocalMasterKey = serverWriteKey[0:keyLen]
|
||||
c.Keys.LocalMasterSalt = serverWriteKey[keyLen:]
|
||||
c.Keys.RemoteMasterKey = clientWriteKey[0:keyLen]
|
||||
c.Keys.RemoteMasterSalt = clientWriteKey[keyLen:]
|
||||
return nil
|
||||
}
|
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/option.go
generated
vendored
Normal file
54
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/option.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"github.com/pion/transport/replaydetector"
|
||||
)
|
||||
|
||||
// ContextOption represents option of Context using the functional options pattern.
|
||||
type ContextOption func(*Context) error
|
||||
|
||||
// SRTPReplayProtection sets SRTP replay protection window size.
|
||||
func SRTPReplayProtection(windowSize uint) ContextOption { // nolint:golint
|
||||
return func(c *Context) error {
|
||||
c.newSRTPReplayDetector = func() replaydetector.ReplayDetector {
|
||||
return replaydetector.WithWrap(windowSize, maxSequenceNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SRTCPReplayProtection sets SRTCP replay protection window size.
|
||||
func SRTCPReplayProtection(windowSize uint) ContextOption {
|
||||
return func(c *Context) error {
|
||||
c.newSRTCPReplayDetector = func() replaydetector.ReplayDetector {
|
||||
return replaydetector.WithWrap(windowSize, maxSRTCPIndex)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SRTPNoReplayProtection disables SRTP replay protection.
|
||||
func SRTPNoReplayProtection() ContextOption { // nolint:golint
|
||||
return func(c *Context) error {
|
||||
c.newSRTPReplayDetector = func() replaydetector.ReplayDetector {
|
||||
return &nopReplayDetector{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SRTCPNoReplayProtection disables SRTCP replay protection.
|
||||
func SRTCPNoReplayProtection() ContextOption {
|
||||
return func(c *Context) error {
|
||||
c.newSRTCPReplayDetector = func() replaydetector.ReplayDetector {
|
||||
return &nopReplayDetector{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type nopReplayDetector struct{}
|
||||
|
||||
func (s *nopReplayDetector) Check(uint64) (func(), bool) {
|
||||
return func() {}, true
|
||||
}
|
56
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/protection_profile.go
generated
vendored
Normal file
56
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/protection_profile.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
package srtp
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ProtectionProfile specifies Cipher and AuthTag details, similar to TLS cipher suite
|
||||
type ProtectionProfile uint16
|
||||
|
||||
// Supported protection profiles
|
||||
const (
|
||||
ProtectionProfileAes128CmHmacSha1_80 ProtectionProfile = 0x0001
|
||||
ProtectionProfileAeadAes128Gcm ProtectionProfile = 0x0007
|
||||
)
|
||||
|
||||
func (p ProtectionProfile) keyLen() (int, error) {
|
||||
switch p {
|
||||
case ProtectionProfileAes128CmHmacSha1_80:
|
||||
fallthrough
|
||||
case ProtectionProfileAeadAes128Gcm:
|
||||
return 16, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p)
|
||||
}
|
||||
}
|
||||
|
||||
func (p ProtectionProfile) saltLen() (int, error) {
|
||||
switch p {
|
||||
case ProtectionProfileAes128CmHmacSha1_80:
|
||||
return 14, nil
|
||||
case ProtectionProfileAeadAes128Gcm:
|
||||
return 12, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p)
|
||||
}
|
||||
}
|
||||
|
||||
func (p ProtectionProfile) authTagLen() (int, error) {
|
||||
switch p {
|
||||
case ProtectionProfileAes128CmHmacSha1_80:
|
||||
return (&srtpCipherAesCmHmacSha1{}).authTagLen(), nil
|
||||
case ProtectionProfileAeadAes128Gcm:
|
||||
return (&srtpCipherAeadAesGcm{}).authTagLen(), nil
|
||||
default:
|
||||
return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p)
|
||||
}
|
||||
}
|
||||
|
||||
func (p ProtectionProfile) authKeyLen() (int, error) {
|
||||
switch p {
|
||||
case ProtectionProfileAes128CmHmacSha1_80:
|
||||
return 20, nil
|
||||
case ProtectionProfileAeadAes128Gcm:
|
||||
return 0, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p)
|
||||
}
|
||||
}
|
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/renovate.json
generated
vendored
Normal file
15
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/renovate.json
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
],
|
||||
"commitBody": "Generated by renovateBot",
|
||||
"packageRules": [
|
||||
{
|
||||
"packagePatterns": ["^golang.org/x/"],
|
||||
"schedule": ["on the first day of the month"]
|
||||
}
|
||||
]
|
||||
}
|
150
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session.go
generated
vendored
Normal file
150
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session.go
generated
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/transport/packetio"
|
||||
)
|
||||
|
||||
type streamSession interface {
|
||||
Close() error
|
||||
write([]byte) (int, error)
|
||||
decrypt([]byte) error
|
||||
}
|
||||
|
||||
type session struct {
|
||||
localContextMutex sync.Mutex
|
||||
localContext, remoteContext *Context
|
||||
localOptions, remoteOptions []ContextOption
|
||||
|
||||
newStream chan readStream
|
||||
|
||||
started chan interface{}
|
||||
closed chan interface{}
|
||||
|
||||
readStreamsClosed bool
|
||||
readStreams map[uint32]readStream
|
||||
readStreamsLock sync.Mutex
|
||||
|
||||
log logging.LeveledLogger
|
||||
bufferFactory func(packetType packetio.BufferPacketType, ssrc uint32) io.ReadWriteCloser
|
||||
|
||||
nextConn net.Conn
|
||||
}
|
||||
|
||||
// Config is used to configure a session.
|
||||
// You can provide either a KeyingMaterialExporter to export keys
|
||||
// or directly pass the keys themselves.
|
||||
// After a Config is passed to a session it must not be modified.
|
||||
type Config struct {
|
||||
Keys SessionKeys
|
||||
Profile ProtectionProfile
|
||||
BufferFactory func(packetType packetio.BufferPacketType, ssrc uint32) io.ReadWriteCloser
|
||||
LoggerFactory logging.LoggerFactory
|
||||
|
||||
// List of local/remote context options.
|
||||
// ReplayProtection is enabled on remote context by default.
|
||||
// Default replay protection window size is 64.
|
||||
LocalOptions, RemoteOptions []ContextOption
|
||||
}
|
||||
|
||||
// SessionKeys bundles the keys required to setup an SRTP session
|
||||
type SessionKeys struct {
|
||||
LocalMasterKey []byte
|
||||
LocalMasterSalt []byte
|
||||
RemoteMasterKey []byte
|
||||
RemoteMasterSalt []byte
|
||||
}
|
||||
|
||||
func (s *session) getOrCreateReadStream(ssrc uint32, child streamSession, proto func() readStream) (readStream, bool) {
|
||||
s.readStreamsLock.Lock()
|
||||
defer s.readStreamsLock.Unlock()
|
||||
|
||||
if s.readStreamsClosed {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
r, ok := s.readStreams[ssrc]
|
||||
if ok {
|
||||
return r, false
|
||||
}
|
||||
|
||||
// Create the readStream.
|
||||
r = proto()
|
||||
|
||||
if err := r.init(child, ssrc); err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
s.readStreams[ssrc] = r
|
||||
return r, true
|
||||
}
|
||||
|
||||
func (s *session) removeReadStream(ssrc uint32) {
|
||||
s.readStreamsLock.Lock()
|
||||
defer s.readStreamsLock.Unlock()
|
||||
|
||||
if s.readStreamsClosed {
|
||||
return
|
||||
}
|
||||
|
||||
delete(s.readStreams, ssrc)
|
||||
}
|
||||
|
||||
func (s *session) close() error {
|
||||
if s.nextConn == nil {
|
||||
return nil
|
||||
} else if err := s.nextConn.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
<-s.closed
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) start(localMasterKey, localMasterSalt, remoteMasterKey, remoteMasterSalt []byte, profile ProtectionProfile, child streamSession) error {
|
||||
var err error
|
||||
s.localContext, err = CreateContext(localMasterKey, localMasterSalt, profile, s.localOptions...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.remoteContext, err = CreateContext(remoteMasterKey, remoteMasterSalt, profile, s.remoteOptions...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
close(s.newStream)
|
||||
|
||||
s.readStreamsLock.Lock()
|
||||
s.readStreamsClosed = true
|
||||
s.readStreamsLock.Unlock()
|
||||
close(s.closed)
|
||||
}()
|
||||
|
||||
b := make([]byte, 8192)
|
||||
for {
|
||||
var i int
|
||||
i, err = s.nextConn.Read(b)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
s.log.Error(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err = child.decrypt(b[:i]); err != nil {
|
||||
s.log.Info(err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
close(s.started)
|
||||
|
||||
return nil
|
||||
}
|
180
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtcp.go
generated
vendored
Normal file
180
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtcp.go
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/rtcp"
|
||||
)
|
||||
|
||||
const defaultSessionSRTCPReplayProtectionWindow = 64
|
||||
|
||||
// SessionSRTCP implements io.ReadWriteCloser and provides a bi-directional SRTCP session
|
||||
// SRTCP itself does not have a design like this, but it is common in most applications
|
||||
// for local/remote to each have their own keying material. This provides those patterns
|
||||
// instead of making everyone re-implement
|
||||
type SessionSRTCP struct {
|
||||
session
|
||||
writeStream *WriteStreamSRTCP
|
||||
}
|
||||
|
||||
// NewSessionSRTCP creates a SRTCP session using conn as the underlying transport.
|
||||
func NewSessionSRTCP(conn net.Conn, config *Config) (*SessionSRTCP, error) { //nolint:dupl
|
||||
if config == nil {
|
||||
return nil, errNoConfig
|
||||
} else if conn == nil {
|
||||
return nil, errNoConn
|
||||
}
|
||||
|
||||
loggerFactory := config.LoggerFactory
|
||||
if loggerFactory == nil {
|
||||
loggerFactory = logging.NewDefaultLoggerFactory()
|
||||
}
|
||||
|
||||
localOpts := append(
|
||||
[]ContextOption{},
|
||||
config.LocalOptions...,
|
||||
)
|
||||
remoteOpts := append(
|
||||
[]ContextOption{
|
||||
// Default options
|
||||
SRTCPReplayProtection(defaultSessionSRTCPReplayProtectionWindow),
|
||||
},
|
||||
config.RemoteOptions...,
|
||||
)
|
||||
|
||||
s := &SessionSRTCP{
|
||||
session: session{
|
||||
nextConn: conn,
|
||||
localOptions: localOpts,
|
||||
remoteOptions: remoteOpts,
|
||||
readStreams: map[uint32]readStream{},
|
||||
newStream: make(chan readStream),
|
||||
started: make(chan interface{}),
|
||||
closed: make(chan interface{}),
|
||||
bufferFactory: config.BufferFactory,
|
||||
log: loggerFactory.NewLogger("srtp"),
|
||||
},
|
||||
}
|
||||
s.writeStream = &WriteStreamSRTCP{s}
|
||||
|
||||
err := s.session.start(
|
||||
config.Keys.LocalMasterKey, config.Keys.LocalMasterSalt,
|
||||
config.Keys.RemoteMasterKey, config.Keys.RemoteMasterSalt,
|
||||
config.Profile,
|
||||
s,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// OpenWriteStream returns the global write stream for the Session
|
||||
func (s *SessionSRTCP) OpenWriteStream() (*WriteStreamSRTCP, error) {
|
||||
return s.writeStream, nil
|
||||
}
|
||||
|
||||
// OpenReadStream opens a read stream for the given SSRC, it can be used
|
||||
// if you want a certain SSRC, but don't want to wait for AcceptStream
|
||||
func (s *SessionSRTCP) OpenReadStream(ssrc uint32) (*ReadStreamSRTCP, error) {
|
||||
r, _ := s.session.getOrCreateReadStream(ssrc, s, newReadStreamSRTCP)
|
||||
|
||||
if readStream, ok := r.(*ReadStreamSRTCP); ok {
|
||||
return readStream, nil
|
||||
}
|
||||
return nil, errFailedTypeAssertion
|
||||
}
|
||||
|
||||
// AcceptStream returns a stream to handle RTCP for a single SSRC
|
||||
func (s *SessionSRTCP) AcceptStream() (*ReadStreamSRTCP, uint32, error) {
|
||||
stream, ok := <-s.newStream
|
||||
if !ok {
|
||||
return nil, 0, errStreamAlreadyClosed
|
||||
}
|
||||
|
||||
readStream, ok := stream.(*ReadStreamSRTCP)
|
||||
if !ok {
|
||||
return nil, 0, errFailedTypeAssertion
|
||||
}
|
||||
|
||||
return readStream, stream.GetSSRC(), nil
|
||||
}
|
||||
|
||||
// Close ends the session
|
||||
func (s *SessionSRTCP) Close() error {
|
||||
return s.session.close()
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
func (s *SessionSRTCP) write(buf []byte) (int, error) {
|
||||
if _, ok := <-s.session.started; ok {
|
||||
return 0, errStartedChannelUsedIncorrectly
|
||||
}
|
||||
|
||||
s.session.localContextMutex.Lock()
|
||||
encrypted, err := s.localContext.EncryptRTCP(nil, buf, nil)
|
||||
s.session.localContextMutex.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return s.session.nextConn.Write(encrypted)
|
||||
}
|
||||
|
||||
func (s *SessionSRTCP) setWriteDeadline(t time.Time) error {
|
||||
return s.session.nextConn.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
// create a list of Destination SSRCs
|
||||
// that's a superset of all Destinations in the slice.
|
||||
func destinationSSRC(pkts []rtcp.Packet) []uint32 {
|
||||
ssrcSet := make(map[uint32]struct{})
|
||||
for _, p := range pkts {
|
||||
for _, ssrc := range p.DestinationSSRC() {
|
||||
ssrcSet[ssrc] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
out := make([]uint32, 0, len(ssrcSet))
|
||||
for ssrc := range ssrcSet {
|
||||
out = append(out, ssrc)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *SessionSRTCP) decrypt(buf []byte) error {
|
||||
decrypted, err := s.remoteContext.DecryptRTCP(buf, buf, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pkt, err := rtcp.Unmarshal(decrypted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ssrc := range destinationSSRC(pkt) {
|
||||
r, isNew := s.session.getOrCreateReadStream(ssrc, s, newReadStreamSRTCP)
|
||||
if r == nil {
|
||||
return nil // Session has been closed
|
||||
} else if isNew {
|
||||
s.session.newStream <- r // Notify AcceptStream
|
||||
}
|
||||
|
||||
readStream, ok := r.(*ReadStreamSRTCP)
|
||||
if !ok {
|
||||
return errFailedTypeAssertion
|
||||
}
|
||||
|
||||
_, err = readStream.write(decrypted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
171
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtp.go
generated
vendored
Normal file
171
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtp.go
generated
vendored
Normal file
|
@ -0,0 +1,171 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
const defaultSessionSRTPReplayProtectionWindow = 64
|
||||
|
||||
// SessionSRTP implements io.ReadWriteCloser and provides a bi-directional SRTP session
|
||||
// SRTP itself does not have a design like this, but it is common in most applications
|
||||
// for local/remote to each have their own keying material. This provides those patterns
|
||||
// instead of making everyone re-implement
|
||||
type SessionSRTP struct {
|
||||
session
|
||||
writeStream *WriteStreamSRTP
|
||||
}
|
||||
|
||||
// NewSessionSRTP creates a SRTP session using conn as the underlying transport.
|
||||
func NewSessionSRTP(conn net.Conn, config *Config) (*SessionSRTP, error) { //nolint:dupl
|
||||
if config == nil {
|
||||
return nil, errNoConfig
|
||||
} else if conn == nil {
|
||||
return nil, errNoConn
|
||||
}
|
||||
|
||||
loggerFactory := config.LoggerFactory
|
||||
if loggerFactory == nil {
|
||||
loggerFactory = logging.NewDefaultLoggerFactory()
|
||||
}
|
||||
|
||||
localOpts := append(
|
||||
[]ContextOption{},
|
||||
config.LocalOptions...,
|
||||
)
|
||||
remoteOpts := append(
|
||||
[]ContextOption{
|
||||
// Default options
|
||||
SRTPReplayProtection(defaultSessionSRTPReplayProtectionWindow),
|
||||
},
|
||||
config.RemoteOptions...,
|
||||
)
|
||||
|
||||
s := &SessionSRTP{
|
||||
session: session{
|
||||
nextConn: conn,
|
||||
localOptions: localOpts,
|
||||
remoteOptions: remoteOpts,
|
||||
readStreams: map[uint32]readStream{},
|
||||
newStream: make(chan readStream),
|
||||
started: make(chan interface{}),
|
||||
closed: make(chan interface{}),
|
||||
bufferFactory: config.BufferFactory,
|
||||
log: loggerFactory.NewLogger("srtp"),
|
||||
},
|
||||
}
|
||||
s.writeStream = &WriteStreamSRTP{s}
|
||||
|
||||
err := s.session.start(
|
||||
config.Keys.LocalMasterKey, config.Keys.LocalMasterSalt,
|
||||
config.Keys.RemoteMasterKey, config.Keys.RemoteMasterSalt,
|
||||
config.Profile,
|
||||
s,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// OpenWriteStream returns the global write stream for the Session
|
||||
func (s *SessionSRTP) OpenWriteStream() (*WriteStreamSRTP, error) {
|
||||
return s.writeStream, nil
|
||||
}
|
||||
|
||||
// OpenReadStream opens a read stream for the given SSRC, it can be used
|
||||
// if you want a certain SSRC, but don't want to wait for AcceptStream
|
||||
func (s *SessionSRTP) OpenReadStream(ssrc uint32) (*ReadStreamSRTP, error) {
|
||||
r, _ := s.session.getOrCreateReadStream(ssrc, s, newReadStreamSRTP)
|
||||
|
||||
if readStream, ok := r.(*ReadStreamSRTP); ok {
|
||||
return readStream, nil
|
||||
}
|
||||
|
||||
return nil, errFailedTypeAssertion
|
||||
}
|
||||
|
||||
// AcceptStream returns a stream to handle RTCP for a single SSRC
|
||||
func (s *SessionSRTP) AcceptStream() (*ReadStreamSRTP, uint32, error) {
|
||||
stream, ok := <-s.newStream
|
||||
if !ok {
|
||||
return nil, 0, errStreamAlreadyClosed
|
||||
}
|
||||
|
||||
readStream, ok := stream.(*ReadStreamSRTP)
|
||||
if !ok {
|
||||
return nil, 0, errFailedTypeAssertion
|
||||
}
|
||||
|
||||
return readStream, stream.GetSSRC(), nil
|
||||
}
|
||||
|
||||
// Close ends the session
|
||||
func (s *SessionSRTP) Close() error {
|
||||
return s.session.close()
|
||||
}
|
||||
|
||||
func (s *SessionSRTP) write(b []byte) (int, error) {
|
||||
packet := &rtp.Packet{}
|
||||
|
||||
err := packet.Unmarshal(b)
|
||||
if err != nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return s.writeRTP(&packet.Header, packet.Payload)
|
||||
}
|
||||
|
||||
func (s *SessionSRTP) writeRTP(header *rtp.Header, payload []byte) (int, error) {
|
||||
if _, ok := <-s.session.started; ok {
|
||||
return 0, errStartedChannelUsedIncorrectly
|
||||
}
|
||||
|
||||
s.session.localContextMutex.Lock()
|
||||
encrypted, err := s.localContext.encryptRTP(nil, header, payload)
|
||||
s.session.localContextMutex.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return s.session.nextConn.Write(encrypted)
|
||||
}
|
||||
|
||||
func (s *SessionSRTP) setWriteDeadline(t time.Time) error {
|
||||
return s.session.nextConn.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
func (s *SessionSRTP) decrypt(buf []byte) error {
|
||||
h := &rtp.Header{}
|
||||
if err := h.Unmarshal(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, isNew := s.session.getOrCreateReadStream(h.SSRC, s, newReadStreamSRTP)
|
||||
if r == nil {
|
||||
return nil // Session has been closed
|
||||
} else if isNew {
|
||||
s.session.newStream <- r // Notify AcceptStream
|
||||
}
|
||||
|
||||
readStream, ok := r.(*ReadStreamSRTP)
|
||||
if !ok {
|
||||
return errFailedTypeAssertion
|
||||
}
|
||||
|
||||
decrypted, err := s.remoteContext.decryptRTP(buf, buf, h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = readStream.write(decrypted)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
77
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtcp.go
generated
vendored
Normal file
77
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtcp.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/pion/rtcp"
|
||||
)
|
||||
|
||||
const maxSRTCPIndex = 0x7FFFFFFF
|
||||
|
||||
func (c *Context) decryptRTCP(dst, encrypted []byte) ([]byte, error) {
|
||||
out := allocateIfMismatch(dst, encrypted)
|
||||
tailOffset := len(encrypted) - (c.cipher.authTagLen() + srtcpIndexSize)
|
||||
|
||||
if tailOffset < 0 {
|
||||
return nil, fmt.Errorf("%w: %d", errTooShortRTCP, len(encrypted))
|
||||
} else if isEncrypted := encrypted[tailOffset] >> 7; isEncrypted == 0 {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
index := c.cipher.getRTCPIndex(encrypted)
|
||||
ssrc := binary.BigEndian.Uint32(encrypted[4:])
|
||||
|
||||
s := c.getSRTCPSSRCState(ssrc)
|
||||
markAsValid, ok := s.replayDetector.Check(uint64(index))
|
||||
if !ok {
|
||||
return nil, &errorDuplicated{Proto: "srtcp", SSRC: ssrc, Index: index}
|
||||
}
|
||||
|
||||
out, err := c.cipher.decryptRTCP(out, encrypted, index, ssrc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
markAsValid()
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DecryptRTCP decrypts a buffer that contains a RTCP packet
|
||||
func (c *Context) DecryptRTCP(dst, encrypted []byte, header *rtcp.Header) ([]byte, error) {
|
||||
if header == nil {
|
||||
header = &rtcp.Header{}
|
||||
}
|
||||
|
||||
if err := header.Unmarshal(encrypted); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.decryptRTCP(dst, encrypted)
|
||||
}
|
||||
|
||||
func (c *Context) encryptRTCP(dst, decrypted []byte) ([]byte, error) {
|
||||
ssrc := binary.BigEndian.Uint32(decrypted[4:])
|
||||
s := c.getSRTCPSSRCState(ssrc)
|
||||
|
||||
// We roll over early because MSB is used for marking as encrypted
|
||||
s.srtcpIndex++
|
||||
if s.srtcpIndex > maxSRTCPIndex {
|
||||
s.srtcpIndex = 0
|
||||
}
|
||||
|
||||
return c.cipher.encryptRTCP(dst, decrypted, s.srtcpIndex, ssrc)
|
||||
}
|
||||
|
||||
// EncryptRTCP Encrypts a RTCP packet
|
||||
func (c *Context) EncryptRTCP(dst, decrypted []byte, header *rtcp.Header) ([]byte, error) {
|
||||
if header == nil {
|
||||
header = &rtcp.Header{}
|
||||
}
|
||||
|
||||
if err := header.Unmarshal(decrypted); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.encryptRTCP(dst, decrypted)
|
||||
}
|
68
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp.go
generated
vendored
Normal file
68
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Package srtp implements Secure Real-time Transport Protocol
|
||||
package srtp
|
||||
|
||||
import (
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
func (c *Context) decryptRTP(dst, ciphertext []byte, header *rtp.Header) ([]byte, error) {
|
||||
s := c.getSRTPSSRCState(header.SSRC)
|
||||
|
||||
markAsValid, ok := s.replayDetector.Check(uint64(header.SequenceNumber))
|
||||
if !ok {
|
||||
return nil, &errorDuplicated{
|
||||
Proto: "srtp", SSRC: header.SSRC, Index: uint32(header.SequenceNumber),
|
||||
}
|
||||
}
|
||||
|
||||
dst = growBufferSize(dst, len(ciphertext)-c.cipher.authTagLen())
|
||||
roc, updateROC := s.nextRolloverCount(header.SequenceNumber)
|
||||
|
||||
dst, err := c.cipher.decryptRTP(dst, ciphertext, header, roc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
markAsValid()
|
||||
updateROC()
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// DecryptRTP decrypts a RTP packet with an encrypted payload
|
||||
func (c *Context) DecryptRTP(dst, encrypted []byte, header *rtp.Header) ([]byte, error) {
|
||||
if header == nil {
|
||||
header = &rtp.Header{}
|
||||
}
|
||||
|
||||
if err := header.Unmarshal(encrypted); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.decryptRTP(dst, encrypted, header)
|
||||
}
|
||||
|
||||
// EncryptRTP marshals and encrypts an RTP packet, writing to the dst buffer provided.
|
||||
// If the dst buffer does not have the capacity to hold `len(plaintext) + 10` bytes, a new one will be allocated and returned.
|
||||
// If a rtp.Header is provided, it will be Unmarshaled using the plaintext.
|
||||
func (c *Context) EncryptRTP(dst []byte, plaintext []byte, header *rtp.Header) ([]byte, error) {
|
||||
if header == nil {
|
||||
header = &rtp.Header{}
|
||||
}
|
||||
|
||||
if err := header.Unmarshal(plaintext); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.encryptRTP(dst, header, plaintext[header.PayloadOffset:])
|
||||
}
|
||||
|
||||
// encryptRTP marshals and encrypts an RTP packet, writing to the dst buffer provided.
|
||||
// If the dst buffer does not have the capacity, a new one will be allocated and returned.
|
||||
// Similar to above but faster because it can avoid unmarshaling the header and marshaling the payload.
|
||||
func (c *Context) encryptRTP(dst []byte, header *rtp.Header, payload []byte) (ciphertext []byte, err error) {
|
||||
s := c.getSRTPSSRCState(header.SSRC)
|
||||
roc, updateROC := s.nextRolloverCount(header.SequenceNumber)
|
||||
updateROC()
|
||||
|
||||
return c.cipher.encryptRTP(dst, header, payload, roc)
|
||||
}
|
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher.go
generated
vendored
Normal file
16
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher.go
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
package srtp
|
||||
|
||||
import "github.com/pion/rtp"
|
||||
|
||||
// cipher represents a implementation of one
|
||||
// of the SRTP Specific ciphers
|
||||
type srtpCipher interface {
|
||||
authTagLen() int
|
||||
getRTCPIndex([]byte) uint32
|
||||
|
||||
encryptRTP([]byte, *rtp.Header, []byte, uint32) ([]byte, error)
|
||||
encryptRTCP([]byte, []byte, uint32, uint32) ([]byte, error)
|
||||
|
||||
decryptRTP([]byte, []byte, *rtp.Header, uint32) ([]byte, error)
|
||||
decryptRTCP([]byte, []byte, uint32, uint32) ([]byte, error)
|
||||
}
|
172
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aead_aes_gcm.go
generated
vendored
Normal file
172
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aead_aes_gcm.go
generated
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
const (
|
||||
rtcpEncryptionFlag = 0x80
|
||||
)
|
||||
|
||||
type srtpCipherAeadAesGcm struct {
|
||||
srtpCipher, srtcpCipher cipher.AEAD
|
||||
|
||||
srtpSessionSalt, srtcpSessionSalt []byte
|
||||
}
|
||||
|
||||
func newSrtpCipherAeadAesGcm(masterKey, masterSalt []byte) (*srtpCipherAeadAesGcm, error) {
|
||||
s := &srtpCipherAeadAesGcm{}
|
||||
|
||||
srtpSessionKey, err := aesCmKeyDerivation(labelSRTPEncryption, masterKey, masterSalt, 0, len(masterKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srtpBlock, err := aes.NewCipher(srtpSessionKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.srtpCipher, err = cipher.NewGCM(srtpBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srtcpSessionKey, err := aesCmKeyDerivation(labelSRTCPEncryption, masterKey, masterSalt, 0, len(masterKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srtcpBlock, err := aes.NewCipher(srtcpSessionKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.srtcpCipher, err = cipher.NewGCM(srtcpBlock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.srtpSessionSalt, err = aesCmKeyDerivation(labelSRTPSalt, masterKey, masterSalt, 0, len(masterSalt)); err != nil {
|
||||
return nil, err
|
||||
} else if s.srtcpSessionSalt, err = aesCmKeyDerivation(labelSRTCPSalt, masterKey, masterSalt, 0, len(masterSalt)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAeadAesGcm) authTagLen() int {
|
||||
return 16
|
||||
}
|
||||
|
||||
func (s *srtpCipherAeadAesGcm) encryptRTP(dst []byte, header *rtp.Header, payload []byte, roc uint32) (ciphertext []byte, err error) {
|
||||
hdr, err := header.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iv := s.rtpInitializationVector(header, roc)
|
||||
out := s.srtpCipher.Seal(nil, iv, payload, hdr)
|
||||
return append(hdr, out...), nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAeadAesGcm) decryptRTP(dst, ciphertext []byte, header *rtp.Header, roc uint32) ([]byte, error) {
|
||||
iv := s.rtpInitializationVector(header, roc)
|
||||
|
||||
out, err := s.srtpCipher.Open(nil, iv, ciphertext[header.PayloadOffset:], ciphertext[:header.PayloadOffset])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(make([]byte, header.PayloadOffset), out...)
|
||||
copy(out, ciphertext[:header.PayloadOffset])
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAeadAesGcm) encryptRTCP(dst, decrypted []byte, srtcpIndex uint32, ssrc uint32) ([]byte, error) {
|
||||
iv := s.rtcpInitializationVector(srtcpIndex, ssrc)
|
||||
aad := s.rtcpAdditionalAuthenticatedData(decrypted, srtcpIndex)
|
||||
|
||||
out := s.srtcpCipher.Seal(nil, iv, decrypted[8:], aad)
|
||||
|
||||
out = append(make([]byte, 8), out...)
|
||||
copy(out, decrypted[:8])
|
||||
out = append(out, aad[8:]...)
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAeadAesGcm) decryptRTCP(out, encrypted []byte, srtcpIndex, ssrc uint32) ([]byte, error) {
|
||||
iv := s.rtcpInitializationVector(srtcpIndex, ssrc)
|
||||
aad := s.rtcpAdditionalAuthenticatedData(encrypted, srtcpIndex)
|
||||
|
||||
decrypted, err := s.srtcpCipher.Open(nil, iv, encrypted[8:len(encrypted)-srtcpIndexSize], aad)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decrypted = append(encrypted[:8], decrypted...)
|
||||
return decrypted, nil
|
||||
}
|
||||
|
||||
// The 12-octet IV used by AES-GCM SRTP is formed by first concatenating
|
||||
// 2 octets of zeroes, the 4-octet SSRC, the 4-octet rollover counter
|
||||
// (ROC), and the 2-octet sequence number (SEQ). The resulting 12-octet
|
||||
// value is then XORed to the 12-octet salt to form the 12-octet IV.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7714#section-8.1
|
||||
func (s *srtpCipherAeadAesGcm) rtpInitializationVector(header *rtp.Header, roc uint32) []byte {
|
||||
iv := make([]byte, 12)
|
||||
binary.BigEndian.PutUint32(iv[2:], header.SSRC)
|
||||
binary.BigEndian.PutUint32(iv[6:], roc)
|
||||
binary.BigEndian.PutUint16(iv[10:], header.SequenceNumber)
|
||||
|
||||
for i := range iv {
|
||||
iv[i] ^= s.srtpSessionSalt[i]
|
||||
}
|
||||
return iv
|
||||
}
|
||||
|
||||
// The 12-octet IV used by AES-GCM SRTCP is formed by first
|
||||
// concatenating 2 octets of zeroes, the 4-octet SSRC identifier,
|
||||
// 2 octets of zeroes, a single "0" bit, and the 31-bit SRTCP index.
|
||||
// The resulting 12-octet value is then XORed to the 12-octet salt to
|
||||
// form the 12-octet IV.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7714#section-9.1
|
||||
func (s *srtpCipherAeadAesGcm) rtcpInitializationVector(srtcpIndex uint32, ssrc uint32) []byte {
|
||||
iv := make([]byte, 12)
|
||||
|
||||
binary.BigEndian.PutUint32(iv[2:], ssrc)
|
||||
binary.BigEndian.PutUint32(iv[8:], srtcpIndex)
|
||||
|
||||
for i := range iv {
|
||||
iv[i] ^= s.srtcpSessionSalt[i]
|
||||
}
|
||||
return iv
|
||||
}
|
||||
|
||||
// In an SRTCP packet, a 1-bit Encryption flag is prepended to the
|
||||
// 31-bit SRTCP index to form a 32-bit value we shall call the
|
||||
// "ESRTCP word"
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7714#section-17
|
||||
func (s *srtpCipherAeadAesGcm) rtcpAdditionalAuthenticatedData(rtcpPacket []byte, srtcpIndex uint32) []byte {
|
||||
aad := make([]byte, 12)
|
||||
|
||||
copy(aad, rtcpPacket[:8])
|
||||
binary.BigEndian.PutUint32(aad[8:], srtcpIndex)
|
||||
aad[8] |= rtcpEncryptionFlag
|
||||
|
||||
return aad
|
||||
}
|
||||
|
||||
func (s *srtpCipherAeadAesGcm) getRTCPIndex(in []byte) uint32 {
|
||||
return binary.BigEndian.Uint32(in[len(in)-4:]) &^ (rtcpEncryptionFlag << 24)
|
||||
}
|
224
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aes_cm_hmac_sha1.go
generated
vendored
Normal file
224
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aes_cm_hmac_sha1.go
generated
vendored
Normal file
|
@ -0,0 +1,224 @@
|
|||
package srtp
|
||||
|
||||
import ( //nolint:gci
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1" //nolint:gosec
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
)
|
||||
|
||||
type srtpCipherAesCmHmacSha1 struct {
|
||||
srtpSessionSalt []byte
|
||||
srtpSessionAuth hash.Hash
|
||||
srtpBlock cipher.Block
|
||||
|
||||
srtcpSessionSalt []byte
|
||||
srtcpSessionAuth hash.Hash
|
||||
srtcpBlock cipher.Block
|
||||
}
|
||||
|
||||
func newSrtpCipherAesCmHmacSha1(masterKey, masterSalt []byte) (*srtpCipherAesCmHmacSha1, error) {
|
||||
s := &srtpCipherAesCmHmacSha1{}
|
||||
srtpSessionKey, err := aesCmKeyDerivation(labelSRTPEncryption, masterKey, masterSalt, 0, len(masterKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if s.srtpBlock, err = aes.NewCipher(srtpSessionKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srtcpSessionKey, err := aesCmKeyDerivation(labelSRTCPEncryption, masterKey, masterSalt, 0, len(masterKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if s.srtcpBlock, err = aes.NewCipher(srtcpSessionKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if s.srtpSessionSalt, err = aesCmKeyDerivation(labelSRTPSalt, masterKey, masterSalt, 0, len(masterSalt)); err != nil {
|
||||
return nil, err
|
||||
} else if s.srtcpSessionSalt, err = aesCmKeyDerivation(labelSRTCPSalt, masterKey, masterSalt, 0, len(masterSalt)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authKeyLen, err := ProtectionProfileAes128CmHmacSha1_80.authKeyLen()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srtpSessionAuthTag, err := aesCmKeyDerivation(labelSRTPAuthenticationTag, masterKey, masterSalt, 0, authKeyLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srtcpSessionAuthTag, err := aesCmKeyDerivation(labelSRTCPAuthenticationTag, masterKey, masterSalt, 0, authKeyLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.srtcpSessionAuth = hmac.New(sha1.New, srtcpSessionAuthTag)
|
||||
s.srtpSessionAuth = hmac.New(sha1.New, srtpSessionAuthTag)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) authTagLen() int {
|
||||
return 10
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) encryptRTP(dst []byte, header *rtp.Header, payload []byte, roc uint32) (ciphertext []byte, err error) {
|
||||
// Grow the given buffer to fit the output.
|
||||
dst = growBufferSize(dst, header.MarshalSize()+len(payload)+s.authTagLen())
|
||||
|
||||
// Copy the header unencrypted.
|
||||
n, err := header.MarshalTo(dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Encrypt the payload
|
||||
counter := generateCounter(header.SequenceNumber, roc, header.SSRC, s.srtpSessionSalt)
|
||||
stream := cipher.NewCTR(s.srtpBlock, counter)
|
||||
stream.XORKeyStream(dst[n:], payload)
|
||||
n += len(payload)
|
||||
|
||||
// Generate the auth tag.
|
||||
authTag, err := s.generateSrtpAuthTag(dst[:n], roc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Write the auth tag to the dest.
|
||||
copy(dst[n:], authTag)
|
||||
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) decryptRTP(dst, ciphertext []byte, header *rtp.Header, roc uint32) ([]byte, error) {
|
||||
// Split the auth tag and the cipher text into two parts.
|
||||
actualTag := ciphertext[len(ciphertext)-s.authTagLen():]
|
||||
ciphertext = ciphertext[:len(ciphertext)-s.authTagLen()]
|
||||
|
||||
// Generate the auth tag we expect to see from the ciphertext.
|
||||
expectedTag, err := s.generateSrtpAuthTag(ciphertext, roc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// See if the auth tag actually matches.
|
||||
// We use a constant time comparison to prevent timing attacks.
|
||||
if subtle.ConstantTimeCompare(actualTag, expectedTag) != 1 {
|
||||
return nil, errFailedToVerifyAuthTag
|
||||
}
|
||||
|
||||
// Write the plaintext header to the destination buffer.
|
||||
copy(dst, ciphertext[:header.PayloadOffset])
|
||||
|
||||
// Decrypt the ciphertext for the payload.
|
||||
counter := generateCounter(header.SequenceNumber, roc, header.SSRC, s.srtpSessionSalt)
|
||||
stream := cipher.NewCTR(s.srtpBlock, counter)
|
||||
stream.XORKeyStream(dst[header.PayloadOffset:], ciphertext[header.PayloadOffset:])
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) encryptRTCP(dst, decrypted []byte, srtcpIndex uint32, ssrc uint32) ([]byte, error) {
|
||||
dst = allocateIfMismatch(dst, decrypted)
|
||||
|
||||
// Encrypt everything after header
|
||||
stream := cipher.NewCTR(s.srtcpBlock, generateCounter(uint16(srtcpIndex&0xffff), srtcpIndex>>16, ssrc, s.srtcpSessionSalt))
|
||||
stream.XORKeyStream(dst[8:], dst[8:])
|
||||
|
||||
// Add SRTCP Index and set Encryption bit
|
||||
dst = append(dst, make([]byte, 4)...)
|
||||
binary.BigEndian.PutUint32(dst[len(dst)-4:], srtcpIndex)
|
||||
dst[len(dst)-4] |= 0x80
|
||||
|
||||
authTag, err := s.generateSrtcpAuthTag(dst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(dst, authTag...), nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) decryptRTCP(out, encrypted []byte, index, ssrc uint32) ([]byte, error) {
|
||||
tailOffset := len(encrypted) - (s.authTagLen() + srtcpIndexSize)
|
||||
out = out[0:tailOffset]
|
||||
|
||||
expectedTag, err := s.generateSrtcpAuthTag(encrypted[:len(encrypted)-s.authTagLen()])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
actualTag := encrypted[len(encrypted)-s.authTagLen():]
|
||||
if subtle.ConstantTimeCompare(actualTag, expectedTag) != 1 {
|
||||
return nil, errFailedToVerifyAuthTag
|
||||
}
|
||||
|
||||
stream := cipher.NewCTR(s.srtcpBlock, generateCounter(uint16(index&0xffff), index>>16, ssrc, s.srtcpSessionSalt))
|
||||
stream.XORKeyStream(out[8:], out[8:])
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) generateSrtpAuthTag(buf []byte, roc uint32) ([]byte, error) {
|
||||
// https://tools.ietf.org/html/rfc3711#section-4.2
|
||||
// In the case of SRTP, M SHALL consist of the Authenticated
|
||||
// Portion of the packet (as specified in Figure 1) concatenated with
|
||||
// the ROC, M = Authenticated Portion || ROC;
|
||||
//
|
||||
// The pre-defined authentication transform for SRTP is HMAC-SHA1
|
||||
// [RFC2104]. With HMAC-SHA1, the SRTP_PREFIX_LENGTH (Figure 3) SHALL
|
||||
// be 0. For SRTP (respectively SRTCP), the HMAC SHALL be applied to
|
||||
// the session authentication key and M as specified above, i.e.,
|
||||
// HMAC(k_a, M). The HMAC output SHALL then be truncated to the n_tag
|
||||
// left-most bits.
|
||||
// - Authenticated portion of the packet is everything BEFORE MKI
|
||||
// - k_a is the session message authentication key
|
||||
// - n_tag is the bit-length of the output authentication tag
|
||||
s.srtpSessionAuth.Reset()
|
||||
|
||||
if _, err := s.srtpSessionAuth.Write(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// For SRTP only, we need to hash the rollover counter as well.
|
||||
rocRaw := [4]byte{}
|
||||
binary.BigEndian.PutUint32(rocRaw[:], roc)
|
||||
|
||||
_, err := s.srtpSessionAuth.Write(rocRaw[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Truncate the hash to the first 10 bytes.
|
||||
return s.srtpSessionAuth.Sum(nil)[0:s.authTagLen()], nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) generateSrtcpAuthTag(buf []byte) ([]byte, error) {
|
||||
// https://tools.ietf.org/html/rfc3711#section-4.2
|
||||
//
|
||||
// The pre-defined authentication transform for SRTP is HMAC-SHA1
|
||||
// [RFC2104]. With HMAC-SHA1, the SRTP_PREFIX_LENGTH (Figure 3) SHALL
|
||||
// be 0. For SRTP (respectively SRTCP), the HMAC SHALL be applied to
|
||||
// the session authentication key and M as specified above, i.e.,
|
||||
// HMAC(k_a, M). The HMAC output SHALL then be truncated to the n_tag
|
||||
// left-most bits.
|
||||
// - Authenticated portion of the packet is everything BEFORE MKI
|
||||
// - k_a is the session message authentication key
|
||||
// - n_tag is the bit-length of the output authentication tag
|
||||
s.srtcpSessionAuth.Reset()
|
||||
|
||||
if _, err := s.srtcpSessionAuth.Write(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.srtcpSessionAuth.Sum(nil)[0:s.authTagLen()], nil
|
||||
}
|
||||
|
||||
func (s *srtpCipherAesCmHmacSha1) getRTCPIndex(in []byte) uint32 {
|
||||
tailOffset := len(in) - (s.authTagLen() + srtcpIndexSize)
|
||||
srtcpIndexBuffer := in[tailOffset : tailOffset+srtcpIndexSize]
|
||||
return binary.BigEndian.Uint32(srtcpIndexBuffer) &^ (1 << 31)
|
||||
}
|
8
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream.go
generated
vendored
Normal file
8
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
package srtp
|
||||
|
||||
type readStream interface {
|
||||
init(child streamSession, ssrc uint32) error
|
||||
|
||||
Read(buf []byte) (int, error)
|
||||
GetSSRC() uint32
|
||||
}
|
152
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtcp.go
generated
vendored
Normal file
152
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtcp.go
generated
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/transport/packetio"
|
||||
)
|
||||
|
||||
// Limit the buffer size to 100KB
|
||||
const srtcpBufferSize = 100 * 1000
|
||||
|
||||
// ReadStreamSRTCP handles decryption for a single RTCP SSRC
|
||||
type ReadStreamSRTCP struct {
|
||||
mu sync.Mutex
|
||||
|
||||
isInited bool
|
||||
isClosed chan bool
|
||||
|
||||
session *SessionSRTCP
|
||||
ssrc uint32
|
||||
|
||||
buffer io.ReadWriteCloser
|
||||
}
|
||||
|
||||
func (r *ReadStreamSRTCP) write(buf []byte) (n int, err error) {
|
||||
n, err = r.buffer.Write(buf)
|
||||
|
||||
if errors.Is(err, packetio.ErrFull) {
|
||||
// Silently drop data when the buffer is full.
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Used by getOrCreateReadStream
|
||||
func newReadStreamSRTCP() readStream {
|
||||
return &ReadStreamSRTCP{}
|
||||
}
|
||||
|
||||
// ReadRTCP reads and decrypts full RTCP packet and its header from the nextConn
|
||||
func (r *ReadStreamSRTCP) ReadRTCP(buf []byte) (int, *rtcp.Header, error) {
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
header := &rtcp.Header{}
|
||||
err = header.Unmarshal(buf[:n])
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return n, header, nil
|
||||
}
|
||||
|
||||
// Read reads and decrypts full RTCP packet from the nextConn
|
||||
func (r *ReadStreamSRTCP) Read(buf []byte) (int, error) {
|
||||
return r.buffer.Read(buf)
|
||||
}
|
||||
|
||||
// SetReadDeadline sets the deadline for the Read operation.
|
||||
// Setting to zero means no deadline.
|
||||
func (r *ReadStreamSRTCP) SetReadDeadline(t time.Time) error {
|
||||
return r.buffer.(*packetio.Buffer).SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// Close removes the ReadStream from the session and cleans up any associated state
|
||||
func (r *ReadStreamSRTCP) Close() error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
if !r.isInited {
|
||||
return errStreamNotInited
|
||||
}
|
||||
|
||||
select {
|
||||
case <-r.isClosed:
|
||||
return errStreamAlreadyClosed
|
||||
default:
|
||||
err := r.buffer.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.session.removeReadStream(r.ssrc)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReadStreamSRTCP) init(child streamSession, ssrc uint32) error {
|
||||
sessionSRTCP, ok := child.(*SessionSRTCP)
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if !ok {
|
||||
return errFailedTypeAssertion
|
||||
} else if r.isInited {
|
||||
return errStreamAlreadyInited
|
||||
}
|
||||
|
||||
r.session = sessionSRTCP
|
||||
r.ssrc = ssrc
|
||||
r.isInited = true
|
||||
r.isClosed = make(chan bool)
|
||||
|
||||
if r.session.bufferFactory != nil {
|
||||
r.buffer = r.session.bufferFactory(packetio.RTCPBufferPacket, ssrc)
|
||||
} else {
|
||||
// Create a buffer and limit it to 100KB
|
||||
buff := packetio.NewBuffer()
|
||||
buff.SetLimitSize(srtcpBufferSize)
|
||||
r.buffer = buff
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSSRC returns the SSRC we are demuxing for
|
||||
func (r *ReadStreamSRTCP) GetSSRC() uint32 {
|
||||
return r.ssrc
|
||||
}
|
||||
|
||||
// WriteStreamSRTCP is stream for a single Session that is used to encrypt RTCP
|
||||
type WriteStreamSRTCP struct {
|
||||
session *SessionSRTCP
|
||||
}
|
||||
|
||||
// WriteRTCP encrypts a RTCP header and its payload to the nextConn
|
||||
func (w *WriteStreamSRTCP) WriteRTCP(header *rtcp.Header, payload []byte) (int, error) {
|
||||
headerRaw, err := header.Marshal()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return w.session.write(append(headerRaw, payload...))
|
||||
}
|
||||
|
||||
// Write encrypts and writes a full RTCP packets to the nextConn
|
||||
func (w *WriteStreamSRTCP) Write(b []byte) (int, error) {
|
||||
return w.session.write(b)
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets the deadline for the Write operation.
|
||||
// Setting to zero means no deadline.
|
||||
func (w *WriteStreamSRTCP) SetWriteDeadline(t time.Time) error {
|
||||
return w.session.setWriteDeadline(t)
|
||||
}
|
149
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtp.go
generated
vendored
Normal file
149
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtp.go
generated
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
package srtp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/transport/packetio"
|
||||
)
|
||||
|
||||
// Limit the buffer size to 1MB
|
||||
const srtpBufferSize = 1000 * 1000
|
||||
|
||||
// ReadStreamSRTP handles decryption for a single RTP SSRC
|
||||
type ReadStreamSRTP struct {
|
||||
mu sync.Mutex
|
||||
|
||||
isInited bool
|
||||
isClosed chan bool
|
||||
|
||||
session *SessionSRTP
|
||||
ssrc uint32
|
||||
|
||||
buffer io.ReadWriteCloser
|
||||
}
|
||||
|
||||
// Used by getOrCreateReadStream
|
||||
func newReadStreamSRTP() readStream {
|
||||
return &ReadStreamSRTP{}
|
||||
}
|
||||
|
||||
func (r *ReadStreamSRTP) init(child streamSession, ssrc uint32) error {
|
||||
sessionSRTP, ok := child.(*SessionSRTP)
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
if !ok {
|
||||
return errFailedTypeAssertion
|
||||
} else if r.isInited {
|
||||
return errStreamAlreadyInited
|
||||
}
|
||||
|
||||
r.session = sessionSRTP
|
||||
r.ssrc = ssrc
|
||||
r.isInited = true
|
||||
r.isClosed = make(chan bool)
|
||||
|
||||
// Create a buffer with a 1MB limit
|
||||
if r.session.bufferFactory != nil {
|
||||
r.buffer = r.session.bufferFactory(packetio.RTPBufferPacket, ssrc)
|
||||
} else {
|
||||
buff := packetio.NewBuffer()
|
||||
buff.SetLimitSize(srtpBufferSize)
|
||||
r.buffer = buff
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReadStreamSRTP) write(buf []byte) (n int, err error) {
|
||||
n, err = r.buffer.Write(buf)
|
||||
|
||||
if errors.Is(err, packetio.ErrFull) {
|
||||
// Silently drop data when the buffer is full.
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Read reads and decrypts full RTP packet from the nextConn
|
||||
func (r *ReadStreamSRTP) Read(buf []byte) (int, error) {
|
||||
return r.buffer.Read(buf)
|
||||
}
|
||||
|
||||
// ReadRTP reads and decrypts full RTP packet and its header from the nextConn
|
||||
func (r *ReadStreamSRTP) ReadRTP(buf []byte) (int, *rtp.Header, error) {
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
header := &rtp.Header{}
|
||||
|
||||
err = header.Unmarshal(buf[:n])
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return n, header, nil
|
||||
}
|
||||
|
||||
// SetReadDeadline sets the deadline for the Read operation.
|
||||
// Setting to zero means no deadline.
|
||||
func (r *ReadStreamSRTP) SetReadDeadline(t time.Time) error {
|
||||
return r.buffer.(*packetio.Buffer).SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// Close removes the ReadStream from the session and cleans up any associated state
|
||||
func (r *ReadStreamSRTP) Close() error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
if !r.isInited {
|
||||
return errStreamNotInited
|
||||
}
|
||||
|
||||
select {
|
||||
case <-r.isClosed:
|
||||
return errStreamAlreadyClosed
|
||||
default:
|
||||
err := r.buffer.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.session.removeReadStream(r.ssrc)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetSSRC returns the SSRC we are demuxing for
|
||||
func (r *ReadStreamSRTP) GetSSRC() uint32 {
|
||||
return r.ssrc
|
||||
}
|
||||
|
||||
// WriteStreamSRTP is stream for a single Session that is used to encrypt RTP
|
||||
type WriteStreamSRTP struct {
|
||||
session *SessionSRTP
|
||||
}
|
||||
|
||||
// WriteRTP encrypts a RTP packet and writes to the connection
|
||||
func (w *WriteStreamSRTP) WriteRTP(header *rtp.Header, payload []byte) (int, error) {
|
||||
return w.session.writeRTP(header, payload)
|
||||
}
|
||||
|
||||
// Write encrypts and writes a full RTP packets to the nextConn
|
||||
func (w *WriteStreamSRTP) Write(b []byte) (int, error) {
|
||||
return w.session.write(b)
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets the deadline for the Write operation.
|
||||
// Setting to zero means no deadline.
|
||||
func (w *WriteStreamSRTP) SetWriteDeadline(t time.Time) error {
|
||||
return w.session.setWriteDeadline(t)
|
||||
}
|
33
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/util.go
generated
vendored
Normal file
33
trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/util.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package srtp
|
||||
|
||||
import "bytes"
|
||||
|
||||
// Grow the buffer size to the given number of bytes.
|
||||
func growBufferSize(buf []byte, size int) []byte {
|
||||
if size <= cap(buf) {
|
||||
return buf[:size]
|
||||
}
|
||||
|
||||
buf2 := make([]byte, size)
|
||||
copy(buf2, buf)
|
||||
return buf2
|
||||
}
|
||||
|
||||
// Check if buffers match, if not allocate a new buffer and return it
|
||||
func allocateIfMismatch(dst, src []byte) []byte {
|
||||
if dst == nil {
|
||||
dst = make([]byte, len(src))
|
||||
copy(dst, src)
|
||||
} else if !bytes.Equal(dst, src) { // bytes.Equal returns on ref equality, no optimization needed
|
||||
extraNeeded := len(src) - len(dst)
|
||||
if extraNeeded > 0 {
|
||||
dst = append(dst, make([]byte, extraNeeded)...)
|
||||
} else if extraNeeded < 0 {
|
||||
dst = dst[:len(dst)+extraNeeded]
|
||||
}
|
||||
|
||||
copy(dst, src)
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue