24
vendor/github.com/pion/datachannel/.gitignore
generated
vendored
Normal file
24
vendor/github.com/pion/datachannel/.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
vendor/github.com/pion/datachannel/.golangci.yml
generated
vendored
Normal file
89
vendor/github.com/pion/datachannel/.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
|
||||
16
vendor/github.com/pion/datachannel/AUTHORS.txt
generated
vendored
Normal file
16
vendor/github.com/pion/datachannel/AUTHORS.txt
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# 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 `.github/generate-authors.sh` for the scripting
|
||||
Atsushi Watanabe <atsushi.w@ieee.org>
|
||||
backkem <mail@backkem.me>
|
||||
Benny Daon <benny@tuzig.com>
|
||||
Eric Daniels <eric@erdaniels.com>
|
||||
Hugo Arregui <hugo.arregui@gmail.com>
|
||||
Hugo Arregui <hugo@decentraland.org>
|
||||
John Bradley <jrb@turrettech.com>
|
||||
Norman Rasmussen <norman@rasmussen.co.za>
|
||||
Sean DuBois <seaduboi@amazon.com>
|
||||
Sean DuBois <sean@siobud.com>
|
||||
Yutaka Takeda <yt0916@gmail.com>
|
||||
20
vendor/github.com/pion/datachannel/DESIGN.md
generated
vendored
Normal file
20
vendor/github.com/pion/datachannel/DESIGN.md
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<h1 align="center">
|
||||
Design
|
||||
</h1>
|
||||
|
||||
### Portable
|
||||
Pion Data Channels is written in Go and extremely portable. Anywhere Golang runs, Pion Data Channels 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
vendor/github.com/pion/datachannel/LICENSE
generated
vendored
Normal file
21
vendor/github.com/pion/datachannel/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.
|
||||
37
vendor/github.com/pion/datachannel/README.md
generated
vendored
Normal file
37
vendor/github.com/pion/datachannel/README.md
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
Pion Data Channels
|
||||
<br>
|
||||
</h1>
|
||||
<h4 align="center">A Go implementation of WebRTC Data Channels</h4>
|
||||
<p align="center">
|
||||
<a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-datachannel-gray.svg?longCache=true&colorB=brightgreen" alt="Pion Data Channels"></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/datachannel"><img src="https://travis-ci.org/pion/datachannel.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://pkg.go.dev/github.com/pion/datachannel"><img src="https://godoc.org/github.com/pion/datachannel?status.svg" alt="GoDoc"></a>
|
||||
<a href="https://codecov.io/gh/pion/datachannel"><img src="https://codecov.io/gh/pion/datachannel/branch/master/graph/badge.svg" alt="Coverage Status"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/pion/datachannel"><img src="https://goreportcard.com/badge/github.com/pion/datachannel" 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).
|
||||
|
||||
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:
|
||||
|
||||
### License
|
||||
MIT License - see [LICENSE](LICENSE) for full text
|
||||
20
vendor/github.com/pion/datachannel/codecov.yml
generated
vendored
Normal file
20
vendor/github.com/pion/datachannel/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/**/*"
|
||||
391
vendor/github.com/pion/datachannel/datachannel.go
generated
vendored
Normal file
391
vendor/github.com/pion/datachannel/datachannel.go
generated
vendored
Normal file
@@ -0,0 +1,391 @@
|
||||
// Package datachannel implements WebRTC Data Channels
|
||||
package datachannel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/sctp"
|
||||
)
|
||||
|
||||
const receiveMTU = 8192
|
||||
|
||||
// Reader is an extended io.Reader
|
||||
// that also returns if the message is text.
|
||||
type Reader interface {
|
||||
ReadDataChannel([]byte) (int, bool, error)
|
||||
}
|
||||
|
||||
// Writer is an extended io.Writer
|
||||
// that also allows indicating if a message is text.
|
||||
type Writer interface {
|
||||
WriteDataChannel([]byte, bool) (int, error)
|
||||
}
|
||||
|
||||
// ReadWriteCloser is an extended io.ReadWriteCloser
|
||||
// that also implements our Reader and Writer.
|
||||
type ReadWriteCloser interface {
|
||||
io.Reader
|
||||
io.Writer
|
||||
Reader
|
||||
Writer
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// DataChannel represents a data channel
|
||||
type DataChannel struct {
|
||||
Config
|
||||
|
||||
// stats
|
||||
messagesSent uint32
|
||||
messagesReceived uint32
|
||||
bytesSent uint64
|
||||
bytesReceived uint64
|
||||
|
||||
mu sync.Mutex
|
||||
onOpenCompleteHandler func()
|
||||
openCompleteHandlerOnce sync.Once
|
||||
|
||||
stream *sctp.Stream
|
||||
log logging.LeveledLogger
|
||||
}
|
||||
|
||||
// Config is used to configure the data channel.
|
||||
type Config struct {
|
||||
ChannelType ChannelType
|
||||
Negotiated bool
|
||||
Priority uint16
|
||||
ReliabilityParameter uint32
|
||||
Label string
|
||||
Protocol string
|
||||
LoggerFactory logging.LoggerFactory
|
||||
}
|
||||
|
||||
func newDataChannel(stream *sctp.Stream, config *Config) (*DataChannel, error) {
|
||||
return &DataChannel{
|
||||
Config: *config,
|
||||
stream: stream,
|
||||
log: config.LoggerFactory.NewLogger("datachannel"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Dial opens a data channels over SCTP
|
||||
func Dial(a *sctp.Association, id uint16, config *Config) (*DataChannel, error) {
|
||||
stream, err := a.OpenStream(id, sctp.PayloadTypeWebRTCBinary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dc, err := Client(stream, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
// Client opens a data channel over an SCTP stream
|
||||
func Client(stream *sctp.Stream, config *Config) (*DataChannel, error) {
|
||||
msg := &channelOpen{
|
||||
ChannelType: config.ChannelType,
|
||||
Priority: config.Priority,
|
||||
ReliabilityParameter: config.ReliabilityParameter,
|
||||
|
||||
Label: []byte(config.Label),
|
||||
Protocol: []byte(config.Protocol),
|
||||
}
|
||||
|
||||
if !config.Negotiated {
|
||||
rawMsg, err := msg.Marshal()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal ChannelOpen %w", err)
|
||||
}
|
||||
|
||||
if _, err = stream.WriteSCTP(rawMsg, sctp.PayloadTypeWebRTCDCEP); err != nil {
|
||||
return nil, fmt.Errorf("failed to send ChannelOpen %w", err)
|
||||
}
|
||||
}
|
||||
return newDataChannel(stream, config)
|
||||
}
|
||||
|
||||
// Accept is used to accept incoming data channels over SCTP
|
||||
func Accept(a *sctp.Association, config *Config, existingChannels ...*DataChannel) (*DataChannel, error) {
|
||||
stream, err := a.AcceptStream()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, ch := range existingChannels {
|
||||
if ch.StreamIdentifier() == stream.StreamIdentifier() {
|
||||
ch.stream.SetDefaultPayloadType(sctp.PayloadTypeWebRTCBinary)
|
||||
return ch, nil
|
||||
}
|
||||
}
|
||||
|
||||
stream.SetDefaultPayloadType(sctp.PayloadTypeWebRTCBinary)
|
||||
|
||||
dc, err := Server(stream, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
// Server accepts a data channel over an SCTP stream
|
||||
func Server(stream *sctp.Stream, config *Config) (*DataChannel, error) {
|
||||
buffer := make([]byte, receiveMTU)
|
||||
n, ppi, err := stream.ReadSCTP(buffer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ppi != sctp.PayloadTypeWebRTCDCEP {
|
||||
return nil, fmt.Errorf("%w %s", ErrInvalidPayloadProtocolIdentifier, ppi)
|
||||
}
|
||||
|
||||
openMsg, err := parseExpectDataChannelOpen(buffer[:n])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse DataChannelOpen packet %w", err)
|
||||
}
|
||||
|
||||
config.ChannelType = openMsg.ChannelType
|
||||
config.Priority = openMsg.Priority
|
||||
config.ReliabilityParameter = openMsg.ReliabilityParameter
|
||||
config.Label = string(openMsg.Label)
|
||||
config.Protocol = string(openMsg.Protocol)
|
||||
|
||||
dataChannel, err := newDataChannel(stream, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = dataChannel.writeDataChannelAck()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = dataChannel.commitReliabilityParams()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dataChannel, nil
|
||||
}
|
||||
|
||||
// Read reads a packet of len(p) bytes as binary data
|
||||
func (c *DataChannel) Read(p []byte) (int, error) {
|
||||
n, _, err := c.ReadDataChannel(p)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// ReadDataChannel reads a packet of len(p) bytes
|
||||
func (c *DataChannel) ReadDataChannel(p []byte) (int, bool, error) {
|
||||
for {
|
||||
n, ppi, err := c.stream.ReadSCTP(p)
|
||||
if err == io.EOF {
|
||||
// When the peer sees that an incoming stream was
|
||||
// reset, it also resets its corresponding outgoing stream.
|
||||
if closeErr := c.stream.Close(); closeErr != nil {
|
||||
return 0, false, closeErr
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
if ppi == sctp.PayloadTypeWebRTCDCEP {
|
||||
if err = c.handleDCEP(p[:n]); err != nil {
|
||||
c.log.Errorf("Failed to handle DCEP: %s", err.Error())
|
||||
}
|
||||
continue
|
||||
} else if ppi == sctp.PayloadTypeWebRTCBinaryEmpty || ppi == sctp.PayloadTypeWebRTCStringEmpty {
|
||||
n = 0
|
||||
}
|
||||
|
||||
atomic.AddUint32(&c.messagesReceived, 1)
|
||||
atomic.AddUint64(&c.bytesReceived, uint64(n))
|
||||
|
||||
isString := ppi == sctp.PayloadTypeWebRTCString || ppi == sctp.PayloadTypeWebRTCStringEmpty
|
||||
return n, isString, err
|
||||
}
|
||||
}
|
||||
|
||||
// MessagesSent returns the number of messages sent
|
||||
func (c *DataChannel) MessagesSent() uint32 {
|
||||
return atomic.LoadUint32(&c.messagesSent)
|
||||
}
|
||||
|
||||
// MessagesReceived returns the number of messages received
|
||||
func (c *DataChannel) MessagesReceived() uint32 {
|
||||
return atomic.LoadUint32(&c.messagesReceived)
|
||||
}
|
||||
|
||||
// OnOpen sets an event handler which is invoked when
|
||||
// a DATA_CHANNEL_ACK message is received.
|
||||
// The handler is called only on thefor the channel opened
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-rtcweb-data-protocol-09#section-5.2
|
||||
func (c *DataChannel) OnOpen(f func()) {
|
||||
c.mu.Lock()
|
||||
c.openCompleteHandlerOnce = sync.Once{}
|
||||
c.onOpenCompleteHandler = f
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *DataChannel) onOpenComplete() {
|
||||
c.mu.Lock()
|
||||
hdlr := c.onOpenCompleteHandler
|
||||
c.mu.Unlock()
|
||||
|
||||
if hdlr != nil {
|
||||
go c.openCompleteHandlerOnce.Do(func() {
|
||||
hdlr()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// BytesSent returns the number of bytes sent
|
||||
func (c *DataChannel) BytesSent() uint64 {
|
||||
return atomic.LoadUint64(&c.bytesSent)
|
||||
}
|
||||
|
||||
// BytesReceived returns the number of bytes received
|
||||
func (c *DataChannel) BytesReceived() uint64 {
|
||||
return atomic.LoadUint64(&c.bytesReceived)
|
||||
}
|
||||
|
||||
// StreamIdentifier returns the Stream identifier associated to the stream.
|
||||
func (c *DataChannel) StreamIdentifier() uint16 {
|
||||
return c.stream.StreamIdentifier()
|
||||
}
|
||||
|
||||
func (c *DataChannel) handleDCEP(data []byte) error {
|
||||
msg, err := parse(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse DataChannel packet %w", err)
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case *channelAck:
|
||||
c.log.Debug("Received DATA_CHANNEL_ACK")
|
||||
if err = c.commitReliabilityParams(); err != nil {
|
||||
return err
|
||||
}
|
||||
c.onOpenComplete()
|
||||
default:
|
||||
return fmt.Errorf("%w %v", ErrInvalidMessageType, msg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write writes len(p) bytes from p as binary data
|
||||
func (c *DataChannel) Write(p []byte) (n int, err error) {
|
||||
return c.WriteDataChannel(p, false)
|
||||
}
|
||||
|
||||
// WriteDataChannel writes len(p) bytes from p
|
||||
func (c *DataChannel) WriteDataChannel(p []byte, isString bool) (n int, err error) {
|
||||
// https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-12#section-6.6
|
||||
// SCTP does not support the sending of empty user messages. Therefore,
|
||||
// if an empty message has to be sent, the appropriate PPID (WebRTC
|
||||
// String Empty or WebRTC Binary Empty) is used and the SCTP user
|
||||
// message of one zero byte is sent. When receiving an SCTP user
|
||||
// message with one of these PPIDs, the receiver MUST ignore the SCTP
|
||||
// user message and process it as an empty message.
|
||||
var ppi sctp.PayloadProtocolIdentifier
|
||||
switch {
|
||||
case !isString && len(p) > 0:
|
||||
ppi = sctp.PayloadTypeWebRTCBinary
|
||||
case !isString && len(p) == 0:
|
||||
ppi = sctp.PayloadTypeWebRTCBinaryEmpty
|
||||
case isString && len(p) > 0:
|
||||
ppi = sctp.PayloadTypeWebRTCString
|
||||
case isString && len(p) == 0:
|
||||
ppi = sctp.PayloadTypeWebRTCStringEmpty
|
||||
}
|
||||
|
||||
atomic.AddUint32(&c.messagesSent, 1)
|
||||
atomic.AddUint64(&c.bytesSent, uint64(len(p)))
|
||||
|
||||
if len(p) == 0 {
|
||||
_, err := c.stream.WriteSCTP([]byte{0}, ppi)
|
||||
return 0, err
|
||||
}
|
||||
return c.stream.WriteSCTP(p, ppi)
|
||||
}
|
||||
|
||||
func (c *DataChannel) writeDataChannelAck() error {
|
||||
ack := channelAck{}
|
||||
ackMsg, err := ack.Marshal()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal ChannelOpen ACK: %w", err)
|
||||
}
|
||||
|
||||
if _, err = c.stream.WriteSCTP(ackMsg, sctp.PayloadTypeWebRTCDCEP); err != nil {
|
||||
return fmt.Errorf("failed to send ChannelOpen ACK: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Close closes the DataChannel and the underlying SCTP stream.
|
||||
func (c *DataChannel) Close() error {
|
||||
// https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7
|
||||
// Closing of a data channel MUST be signaled by resetting the
|
||||
// corresponding outgoing streams [RFC6525]. This means that 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. Resetting a stream sets
|
||||
// the Stream Sequence Numbers (SSNs) of the stream back to 'zero' with
|
||||
// a corresponding notification to the application layer that the reset
|
||||
// has been performed. Streams are available for reuse after a reset
|
||||
// has been performed.
|
||||
return c.stream.Close()
|
||||
}
|
||||
|
||||
// BufferedAmount returns the number of bytes of data currently queued to be
|
||||
// sent over this stream.
|
||||
func (c *DataChannel) BufferedAmount() uint64 {
|
||||
return c.stream.BufferedAmount()
|
||||
}
|
||||
|
||||
// BufferedAmountLowThreshold returns the number of bytes of buffered outgoing
|
||||
// data that is considered "low." Defaults to 0.
|
||||
func (c *DataChannel) BufferedAmountLowThreshold() uint64 {
|
||||
return c.stream.BufferedAmountLowThreshold()
|
||||
}
|
||||
|
||||
// SetBufferedAmountLowThreshold is used to update the threshold.
|
||||
// See BufferedAmountLowThreshold().
|
||||
func (c *DataChannel) SetBufferedAmountLowThreshold(th uint64) {
|
||||
c.stream.SetBufferedAmountLowThreshold(th)
|
||||
}
|
||||
|
||||
// OnBufferedAmountLow sets the callback handler which would be called when the
|
||||
// number of bytes of outgoing data buffered is lower than the threshold.
|
||||
func (c *DataChannel) OnBufferedAmountLow(f func()) {
|
||||
c.stream.OnBufferedAmountLow(f)
|
||||
}
|
||||
|
||||
func (c *DataChannel) commitReliabilityParams() error {
|
||||
switch c.Config.ChannelType {
|
||||
case ChannelTypeReliable:
|
||||
c.stream.SetReliabilityParams(false, sctp.ReliabilityTypeReliable, c.Config.ReliabilityParameter)
|
||||
case ChannelTypeReliableUnordered:
|
||||
c.stream.SetReliabilityParams(true, sctp.ReliabilityTypeReliable, c.Config.ReliabilityParameter)
|
||||
case ChannelTypePartialReliableRexmit:
|
||||
c.stream.SetReliabilityParams(false, sctp.ReliabilityTypeRexmit, c.Config.ReliabilityParameter)
|
||||
case ChannelTypePartialReliableRexmitUnordered:
|
||||
c.stream.SetReliabilityParams(true, sctp.ReliabilityTypeRexmit, c.Config.ReliabilityParameter)
|
||||
case ChannelTypePartialReliableTimed:
|
||||
c.stream.SetReliabilityParams(false, sctp.ReliabilityTypeTimed, c.Config.ReliabilityParameter)
|
||||
case ChannelTypePartialReliableTimedUnordered:
|
||||
c.stream.SetReliabilityParams(true, sctp.ReliabilityTypeTimed, c.Config.ReliabilityParameter)
|
||||
default:
|
||||
return fmt.Errorf("%w %v", ErrInvalidChannelType, c.Config.ChannelType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
24
vendor/github.com/pion/datachannel/errors.go
generated
vendored
Normal file
24
vendor/github.com/pion/datachannel/errors.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package datachannel
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrDataChannelMessageTooShort means that the data isn't long enough to be a valid DataChannel message
|
||||
ErrDataChannelMessageTooShort = errors.New("DataChannel message is not long enough to determine type")
|
||||
|
||||
// ErrInvalidPayloadProtocolIdentifier means that we got a DataChannel messages with a Payload Protocol Identifier
|
||||
// we don't know how to handle
|
||||
ErrInvalidPayloadProtocolIdentifier = errors.New("DataChannel message Payload Protocol Identifier is value we can't handle")
|
||||
|
||||
// ErrInvalidChannelType means that the remote requested a channel type that we don't support
|
||||
ErrInvalidChannelType = errors.New("invalid Channel Type")
|
||||
|
||||
// ErrInvalidMessageType is returned when a DataChannel Message has a type we don't support
|
||||
ErrInvalidMessageType = errors.New("invalid Message Type")
|
||||
|
||||
// ErrExpectedAndActualLengthMismatch is when the declared length and actual length don't match
|
||||
ErrExpectedAndActualLengthMismatch = errors.New("expected and actual length do not match")
|
||||
|
||||
// ErrUnexpectedDataChannelType is when a message type does not match the expected type
|
||||
ErrUnexpectedDataChannelType = errors.New("expected and actual message type does not match")
|
||||
)
|
||||
73
vendor/github.com/pion/datachannel/message.go
generated
vendored
Normal file
73
vendor/github.com/pion/datachannel/message.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
package datachannel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// message is a parsed DataChannel message
|
||||
type message interface {
|
||||
Marshal() ([]byte, error)
|
||||
Unmarshal([]byte) error
|
||||
}
|
||||
|
||||
// messageType is the first byte in a DataChannel message that specifies type
|
||||
type messageType byte
|
||||
|
||||
// DataChannel Message Types
|
||||
const (
|
||||
dataChannelAck messageType = 0x02
|
||||
dataChannelOpen messageType = 0x03
|
||||
)
|
||||
|
||||
func (t messageType) String() string {
|
||||
switch t {
|
||||
case dataChannelAck:
|
||||
return "DataChannelAck"
|
||||
case dataChannelOpen:
|
||||
return "DataChannelOpen"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown MessageType: %d", t)
|
||||
}
|
||||
}
|
||||
|
||||
// parse accepts raw input and returns a DataChannel message
|
||||
func parse(raw []byte) (message, error) {
|
||||
if len(raw) == 0 {
|
||||
return nil, ErrDataChannelMessageTooShort
|
||||
}
|
||||
|
||||
var msg message
|
||||
switch messageType(raw[0]) {
|
||||
case dataChannelOpen:
|
||||
msg = &channelOpen{}
|
||||
case dataChannelAck:
|
||||
msg = &channelAck{}
|
||||
default:
|
||||
return nil, fmt.Errorf("%w %v", ErrInvalidMessageType, messageType(raw[0]))
|
||||
}
|
||||
|
||||
if err := msg.Unmarshal(raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// parseExpectDataChannelOpen parses a DataChannelOpen message
|
||||
// or throws an error
|
||||
func parseExpectDataChannelOpen(raw []byte) (*channelOpen, error) {
|
||||
if len(raw) == 0 {
|
||||
return nil, ErrDataChannelMessageTooShort
|
||||
}
|
||||
|
||||
if actualTyp := messageType(raw[0]); actualTyp != dataChannelOpen {
|
||||
return nil, fmt.Errorf("%w expected(%s) actual(%s)", ErrUnexpectedDataChannelType, actualTyp, dataChannelOpen)
|
||||
}
|
||||
|
||||
msg := &channelOpen{}
|
||||
if err := msg.Unmarshal(raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
22
vendor/github.com/pion/datachannel/message_channel_ack.go
generated
vendored
Normal file
22
vendor/github.com/pion/datachannel/message_channel_ack.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package datachannel
|
||||
|
||||
// channelAck is used to ACK a DataChannel open
|
||||
type channelAck struct{}
|
||||
|
||||
const (
|
||||
channelOpenAckLength = 4
|
||||
)
|
||||
|
||||
// Marshal returns raw bytes for the given message
|
||||
func (c *channelAck) Marshal() ([]byte, error) {
|
||||
raw := make([]byte, channelOpenAckLength)
|
||||
raw[0] = uint8(dataChannelAck)
|
||||
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the struct with the given raw data
|
||||
func (c *channelAck) Unmarshal(raw []byte) error {
|
||||
// Message type already checked in Parse and there is no further data
|
||||
return nil
|
||||
}
|
||||
122
vendor/github.com/pion/datachannel/message_channel_open.go
generated
vendored
Normal file
122
vendor/github.com/pion/datachannel/message_channel_open.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
package datachannel
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
channelOpen represents a DATA_CHANNEL_OPEN Message
|
||||
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Message Type | Channel Type | Priority |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Reliability Parameter |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Label Length | Protocol Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Label |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Protocol |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type channelOpen struct {
|
||||
ChannelType ChannelType
|
||||
Priority uint16
|
||||
ReliabilityParameter uint32
|
||||
|
||||
Label []byte
|
||||
Protocol []byte
|
||||
}
|
||||
|
||||
const (
|
||||
channelOpenHeaderLength = 12
|
||||
)
|
||||
|
||||
// ChannelType determines the reliability of the WebRTC DataChannel
|
||||
type ChannelType byte
|
||||
|
||||
// ChannelType enums
|
||||
const (
|
||||
// ChannelTypeReliable determines the Data Channel provides a
|
||||
// reliable in-order bi-directional communication.
|
||||
ChannelTypeReliable ChannelType = 0x00
|
||||
// ChannelTypeReliableUnordered determines the Data Channel
|
||||
// provides a reliable unordered bi-directional communication.
|
||||
ChannelTypeReliableUnordered ChannelType = 0x80
|
||||
// ChannelTypePartialReliableRexmit determines the Data Channel
|
||||
// provides a partially-reliable in-order bi-directional communication.
|
||||
// User messages will not be retransmitted more times than specified in the Reliability Parameter.
|
||||
ChannelTypePartialReliableRexmit ChannelType = 0x01
|
||||
// ChannelTypePartialReliableRexmitUnordered determines
|
||||
// the Data Channel provides a partial reliable unordered bi-directional communication.
|
||||
// User messages will not be retransmitted more times than specified in the Reliability Parameter.
|
||||
ChannelTypePartialReliableRexmitUnordered ChannelType = 0x81
|
||||
// ChannelTypePartialReliableTimed determines the Data Channel
|
||||
// provides a partial reliable in-order bi-directional communication.
|
||||
// User messages might not be transmitted or retransmitted after
|
||||
// a specified life-time given in milli- seconds in the Reliability Parameter.
|
||||
// This life-time starts when providing the user message to the protocol stack.
|
||||
ChannelTypePartialReliableTimed ChannelType = 0x02
|
||||
// The Data Channel provides a partial reliable unordered bi-directional
|
||||
// communication. User messages might not be transmitted or retransmitted
|
||||
// after a specified life-time given in milli- seconds in the Reliability Parameter.
|
||||
// This life-time starts when providing the user message to the protocol stack.
|
||||
ChannelTypePartialReliableTimedUnordered ChannelType = 0x82
|
||||
)
|
||||
|
||||
// ChannelPriority enums
|
||||
const (
|
||||
ChannelPriorityBelowNormal uint16 = 128
|
||||
ChannelPriorityNormal uint16 = 256
|
||||
ChannelPriorityHigh uint16 = 512
|
||||
ChannelPriorityExtraHigh uint16 = 1024
|
||||
)
|
||||
|
||||
// Marshal returns raw bytes for the given message
|
||||
func (c *channelOpen) Marshal() ([]byte, error) {
|
||||
labelLength := len(c.Label)
|
||||
protocolLength := len(c.Protocol)
|
||||
|
||||
totalLen := channelOpenHeaderLength + labelLength + protocolLength
|
||||
raw := make([]byte, totalLen)
|
||||
|
||||
raw[0] = uint8(dataChannelOpen)
|
||||
raw[1] = byte(c.ChannelType)
|
||||
binary.BigEndian.PutUint16(raw[2:], c.Priority)
|
||||
binary.BigEndian.PutUint32(raw[4:], c.ReliabilityParameter)
|
||||
binary.BigEndian.PutUint16(raw[8:], uint16(labelLength))
|
||||
binary.BigEndian.PutUint16(raw[10:], uint16(protocolLength))
|
||||
endLabel := channelOpenHeaderLength + labelLength
|
||||
copy(raw[channelOpenHeaderLength:endLabel], c.Label)
|
||||
copy(raw[endLabel:endLabel+protocolLength], c.Protocol)
|
||||
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// Unmarshal populates the struct with the given raw data
|
||||
func (c *channelOpen) Unmarshal(raw []byte) error {
|
||||
if len(raw) < channelOpenHeaderLength {
|
||||
return fmt.Errorf("%w expected(%d) actual(%d)", ErrExpectedAndActualLengthMismatch, channelOpenHeaderLength, len(raw))
|
||||
}
|
||||
c.ChannelType = ChannelType(raw[1])
|
||||
c.Priority = binary.BigEndian.Uint16(raw[2:])
|
||||
c.ReliabilityParameter = binary.BigEndian.Uint32(raw[4:])
|
||||
|
||||
labelLength := binary.BigEndian.Uint16(raw[8:])
|
||||
protocolLength := binary.BigEndian.Uint16(raw[10:])
|
||||
|
||||
if expectedLen := int(channelOpenHeaderLength + labelLength + protocolLength); len(raw) != expectedLen {
|
||||
return fmt.Errorf("%w expected(%d) actual(%d)", ErrExpectedAndActualLengthMismatch, expectedLen, len(raw))
|
||||
}
|
||||
|
||||
c.Label = raw[channelOpenHeaderLength : channelOpenHeaderLength+labelLength]
|
||||
c.Protocol = raw[channelOpenHeaderLength+labelLength : channelOpenHeaderLength+labelLength+protocolLength]
|
||||
return nil
|
||||
}
|
||||
26
vendor/github.com/pion/datachannel/renovate.json
generated
vendored
Normal file
26
vendor/github.com/pion/datachannel/renovate.json
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
],
|
||||
"commitBody": "Generated by renovateBot",
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
|
||||
"automerge": true
|
||||
},
|
||||
{
|
||||
"packagePatterns": ["^golang.org/x/"],
|
||||
"schedule": ["on the first day of the month"]
|
||||
}
|
||||
],
|
||||
"ignorePaths": [
|
||||
".github/workflows/generate-authors.yml",
|
||||
".github/workflows/lint.yaml",
|
||||
".github/workflows/renovate-go-mod-fix.yaml",
|
||||
".github/workflows/test.yaml",
|
||||
".github/workflows/tidy-check.yaml"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user