148 lines
5.8 KiB
Go
148 lines
5.8 KiB
Go
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
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
|
|
)
|
|
|
|
func (c ChannelType) String() string {
|
|
switch c {
|
|
case ChannelTypeReliable:
|
|
case ChannelTypeReliableUnordered:
|
|
return "ReliableUnordered"
|
|
case ChannelTypePartialReliableRexmit:
|
|
return "PartialReliableRexmit"
|
|
case ChannelTypePartialReliableRexmitUnordered:
|
|
return "PartialReliableRexmitUnordered"
|
|
case ChannelTypePartialReliableTimed:
|
|
return "PartialReliableTimed"
|
|
case ChannelTypePartialReliableTimedUnordered:
|
|
return "PartialReliableTimedUnordered"
|
|
}
|
|
return "Unknown"
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
func (c channelOpen) String() string {
|
|
return fmt.Sprintf("Open ChannelType(%s) Priority(%v) ReliabilityParameter(%d) Label(%s) Protocol(%s)", c.ChannelType, c.Priority, c.ReliabilityParameter, string(c.Label), string(c.Protocol))
|
|
}
|