直播:后台 JWT 推流、前台画中画;WebRTC 服务与 Nginx WebSocket 代理
Made-with: Cursor
This commit is contained in:
167
server/vendor/github.com/pion/sctp/chunk_init_common.go
generated
vendored
Normal file
167
server/vendor/github.com/pion/sctp/chunk_init_common.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package sctp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
chunkInitCommon represents an SCTP Chunk body of type INIT and INIT ACK
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Type = 1 | Chunk Flags | Chunk Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Initiate Tag |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Advertised Receiver Window Credit (a_rwnd) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Number of Outbound Streams | Number of Inbound Streams |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Initial TSN |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Optional/Variable-Length Parameters |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
The INIT chunk contains the following parameters. Unless otherwise
|
||||
noted, each parameter MUST only be included once in the INIT chunk.
|
||||
|
||||
Fixed Parameters Status
|
||||
----------------------------------------------
|
||||
Initiate Tag Mandatory
|
||||
Advertised Receiver Window Credit Mandatory
|
||||
Number of Outbound Streams Mandatory
|
||||
Number of Inbound Streams Mandatory
|
||||
Initial TSN Mandatory
|
||||
*/
|
||||
|
||||
type chunkInitCommon struct {
|
||||
initiateTag uint32
|
||||
advertisedReceiverWindowCredit uint32
|
||||
numOutboundStreams uint16
|
||||
numInboundStreams uint16
|
||||
initialTSN uint32
|
||||
params []param
|
||||
unrecognizedParams []paramHeader
|
||||
}
|
||||
|
||||
const (
|
||||
initChunkMinLength = 16
|
||||
initOptionalVarHeaderLength = 4
|
||||
)
|
||||
|
||||
// Init chunk errors
|
||||
var (
|
||||
ErrInitChunkParseParamTypeFailed = errors.New("failed to parse param type")
|
||||
ErrInitAckMarshalParam = errors.New("unable to marshal parameter for INIT/INITACK")
|
||||
)
|
||||
|
||||
func (i *chunkInitCommon) unmarshal(raw []byte) error {
|
||||
i.initiateTag = binary.BigEndian.Uint32(raw[0:])
|
||||
i.advertisedReceiverWindowCredit = binary.BigEndian.Uint32(raw[4:])
|
||||
i.numOutboundStreams = binary.BigEndian.Uint16(raw[8:])
|
||||
i.numInboundStreams = binary.BigEndian.Uint16(raw[10:])
|
||||
i.initialTSN = binary.BigEndian.Uint32(raw[12:])
|
||||
|
||||
// https://tools.ietf.org/html/rfc4960#section-3.2.1
|
||||
//
|
||||
// Chunk values of SCTP control chunks consist of a chunk-type-specific
|
||||
// header of required fields, followed by zero or more parameters. The
|
||||
// optional and variable-length parameters contained in a chunk are
|
||||
// defined in a Type-Length-Value format as shown below.
|
||||
//
|
||||
// 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
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Parameter Type | Parameter Length |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | |
|
||||
// | Parameter Value |
|
||||
// | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
offset := initChunkMinLength
|
||||
remaining := len(raw) - offset
|
||||
for remaining > 0 {
|
||||
if remaining > initOptionalVarHeaderLength {
|
||||
var pHeader paramHeader
|
||||
if err := pHeader.unmarshal(raw[offset:]); err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrInitChunkParseParamTypeFailed, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
p, err := buildParam(pHeader.typ, raw[offset:])
|
||||
if err != nil {
|
||||
i.unrecognizedParams = append(i.unrecognizedParams, pHeader)
|
||||
} else {
|
||||
i.params = append(i.params, p)
|
||||
}
|
||||
|
||||
padding := getPadding(pHeader.length())
|
||||
offset += pHeader.length() + padding
|
||||
remaining -= pHeader.length() + padding
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *chunkInitCommon) marshal() ([]byte, error) {
|
||||
out := make([]byte, initChunkMinLength)
|
||||
binary.BigEndian.PutUint32(out[0:], i.initiateTag)
|
||||
binary.BigEndian.PutUint32(out[4:], i.advertisedReceiverWindowCredit)
|
||||
binary.BigEndian.PutUint16(out[8:], i.numOutboundStreams)
|
||||
binary.BigEndian.PutUint16(out[10:], i.numInboundStreams)
|
||||
binary.BigEndian.PutUint32(out[12:], i.initialTSN)
|
||||
for idx, p := range i.params {
|
||||
pp, err := p.marshal()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrInitAckMarshalParam, err) //nolint:errorlint
|
||||
}
|
||||
|
||||
out = append(out, pp...)
|
||||
|
||||
// Chunks (including Type, Length, and Value fields) are padded out
|
||||
// by the sender with all zero bytes to be a multiple of 4 bytes
|
||||
// long. This padding MUST NOT be more than 3 bytes in total. The
|
||||
// Chunk Length value does not include terminating padding of the
|
||||
// chunk. *However, it does include padding of any variable-length
|
||||
// parameter except the last parameter in the chunk.* The receiver
|
||||
// MUST ignore the padding.
|
||||
if idx != len(i.params)-1 {
|
||||
out = padByte(out, getPadding(len(pp)))
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// String makes chunkInitCommon printable
|
||||
func (i chunkInitCommon) String() string {
|
||||
format := `initiateTag: %d
|
||||
advertisedReceiverWindowCredit: %d
|
||||
numOutboundStreams: %d
|
||||
numInboundStreams: %d
|
||||
initialTSN: %d`
|
||||
|
||||
res := fmt.Sprintf(format,
|
||||
i.initiateTag,
|
||||
i.advertisedReceiverWindowCredit,
|
||||
i.numOutboundStreams,
|
||||
i.numInboundStreams,
|
||||
i.initialTSN,
|
||||
)
|
||||
|
||||
for i, param := range i.params {
|
||||
res += fmt.Sprintf("Param %d:\n %s", i, param)
|
||||
}
|
||||
return res
|
||||
}
|
||||
Reference in New Issue
Block a user