直播:后台 JWT 推流、前台画中画;WebRTC 服务与 Nginx WebSocket 代理
Made-with: Cursor
This commit is contained in:
100
server/vendor/github.com/pion/sctp/chunkheader.go
generated
vendored
Normal file
100
server/vendor/github.com/pion/sctp/chunkheader.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package sctp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
chunkHeader represents a SCTP Chunk header, defined in https://tools.ietf.org/html/rfc4960#section-3.2
|
||||
The figure below illustrates the field format for the chunks to be
|
||||
transmitted in the SCTP packet. Each chunk is formatted with a Chunk
|
||||
Type field, a chunk-specific Flag field, a Chunk Length field, and a
|
||||
Value field.
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk Type | Chunk Flags | Chunk Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| Chunk Value |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
type chunkHeader struct {
|
||||
typ chunkType
|
||||
flags byte
|
||||
raw []byte
|
||||
}
|
||||
|
||||
const (
|
||||
chunkHeaderSize = 4
|
||||
)
|
||||
|
||||
// SCTP chunk header errors
|
||||
var (
|
||||
ErrChunkHeaderTooSmall = errors.New("raw is too small for a SCTP chunk")
|
||||
ErrChunkHeaderNotEnoughSpace = errors.New("not enough data left in SCTP packet to satisfy requested length")
|
||||
ErrChunkHeaderPaddingNonZero = errors.New("chunk padding is non-zero at offset")
|
||||
)
|
||||
|
||||
func (c *chunkHeader) unmarshal(raw []byte) error {
|
||||
if len(raw) < chunkHeaderSize {
|
||||
return fmt.Errorf("%w: raw only %d bytes, %d is the minimum length", ErrChunkHeaderTooSmall, len(raw), chunkHeaderSize)
|
||||
}
|
||||
|
||||
c.typ = chunkType(raw[0])
|
||||
c.flags = raw[1]
|
||||
length := binary.BigEndian.Uint16(raw[2:])
|
||||
|
||||
// Length includes Chunk header
|
||||
valueLength := int(length - chunkHeaderSize)
|
||||
lengthAfterValue := len(raw) - (chunkHeaderSize + valueLength)
|
||||
|
||||
if lengthAfterValue < 0 {
|
||||
return fmt.Errorf("%w: remain %d req %d ", ErrChunkHeaderNotEnoughSpace, valueLength, len(raw)-chunkHeaderSize)
|
||||
} else if lengthAfterValue < 4 {
|
||||
// https://tools.ietf.org/html/rfc4960#section-3.2
|
||||
// The Chunk Length field does not count any chunk padding.
|
||||
// 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.
|
||||
for i := lengthAfterValue; i > 0; i-- {
|
||||
paddingOffset := chunkHeaderSize + valueLength + (i - 1)
|
||||
if raw[paddingOffset] != 0 {
|
||||
return fmt.Errorf("%w: %d ", ErrChunkHeaderPaddingNonZero, paddingOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.raw = raw[chunkHeaderSize : chunkHeaderSize+valueLength]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chunkHeader) marshal() ([]byte, error) {
|
||||
raw := make([]byte, 4+len(c.raw))
|
||||
|
||||
raw[0] = uint8(c.typ)
|
||||
raw[1] = c.flags
|
||||
binary.BigEndian.PutUint16(raw[2:], uint16(len(c.raw)+chunkHeaderSize))
|
||||
copy(raw[4:], c.raw)
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
func (c *chunkHeader) valueLength() int {
|
||||
return len(c.raw)
|
||||
}
|
||||
|
||||
// String makes chunkHeader printable
|
||||
func (c chunkHeader) String() string {
|
||||
return c.typ.String()
|
||||
}
|
||||
Reference in New Issue
Block a user