diff options
author | kali kaneko (leap communications) <kali@leap.se> | 2021-11-29 01:46:27 +0100 |
---|---|---|
committer | kali kaneko (leap communications) <kali@leap.se> | 2021-11-29 18:14:16 +0100 |
commit | 18f52af5be3a9a0c73811706108f790d65ee9c67 (patch) | |
tree | e13cbacb47d56919caa9c44a2b45dec1497a7860 /vendor/github.com/pion/rtcp/goodbye.go | |
parent | ebcef0d57b6ecb5a40c6579f6be07182dd3033ba (diff) |
[pkg] update vendor
Diffstat (limited to 'vendor/github.com/pion/rtcp/goodbye.go')
-rw-r--r-- | vendor/github.com/pion/rtcp/goodbye.go | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/vendor/github.com/pion/rtcp/goodbye.go b/vendor/github.com/pion/rtcp/goodbye.go new file mode 100644 index 0000000..b8718b3 --- /dev/null +++ b/vendor/github.com/pion/rtcp/goodbye.go @@ -0,0 +1,146 @@ +package rtcp + +import ( + "encoding/binary" +) + +// The Goodbye packet indicates that one or more sources are no longer active. +type Goodbye struct { + // The SSRC/CSRC identifiers that are no longer active + Sources []uint32 + // Optional text indicating the reason for leaving, e.g., "camera malfunction" or "RTP loop detected" + Reason string +} + +var _ Packet = (*Goodbye)(nil) // assert is a Packet + +// Marshal encodes the Goodbye packet in binary +func (g Goodbye) Marshal() ([]byte, error) { + /* + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |V=2|P| SC | PT=BYE=203 | length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SSRC/CSRC | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * : ... : + * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * (opt) | length | reason for leaving ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + rawPacket := make([]byte, g.len()) + packetBody := rawPacket[headerLength:] + + if len(g.Sources) > countMax { + return nil, errTooManySources + } + + for i, s := range g.Sources { + binary.BigEndian.PutUint32(packetBody[i*ssrcLength:], s) + } + + if g.Reason != "" { + reason := []byte(g.Reason) + + if len(reason) > sdesMaxOctetCount { + return nil, errReasonTooLong + } + + reasonOffset := len(g.Sources) * ssrcLength + packetBody[reasonOffset] = uint8(len(reason)) + copy(packetBody[reasonOffset+1:], reason) + } + + hData, err := g.Header().Marshal() + if err != nil { + return nil, err + } + copy(rawPacket, hData) + + return rawPacket, nil +} + +// Unmarshal decodes the Goodbye packet from binary +func (g *Goodbye) Unmarshal(rawPacket []byte) error { + /* + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |V=2|P| SC | PT=BYE=203 | length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SSRC/CSRC | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * : ... : + * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * (opt) | length | reason for leaving ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + var header Header + if err := header.Unmarshal(rawPacket); err != nil { + return err + } + + if header.Type != TypeGoodbye { + return errWrongType + } + + if getPadding(len(rawPacket)) != 0 { + return errPacketTooShort + } + + g.Sources = make([]uint32, header.Count) + + reasonOffset := int(headerLength + header.Count*ssrcLength) + if reasonOffset > len(rawPacket) { + return errPacketTooShort + } + + for i := 0; i < int(header.Count); i++ { + offset := headerLength + i*ssrcLength + + g.Sources[i] = binary.BigEndian.Uint32(rawPacket[offset:]) + } + + if reasonOffset < len(rawPacket) { + reasonLen := int(rawPacket[reasonOffset]) + reasonEnd := reasonOffset + 1 + reasonLen + + if reasonEnd > len(rawPacket) { + return errPacketTooShort + } + + g.Reason = string(rawPacket[reasonOffset+1 : reasonEnd]) + } + + return nil +} + +// Header returns the Header associated with this packet. +func (g *Goodbye) Header() Header { + return Header{ + Padding: false, + Count: uint8(len(g.Sources)), + Type: TypeGoodbye, + Length: uint16((g.len() / 4) - 1), + } +} + +func (g *Goodbye) len() int { + srcsLength := len(g.Sources) * ssrcLength + reasonLength := len(g.Reason) + 1 + + l := headerLength + srcsLength + reasonLength + + // align to 32-bit boundary + return l + getPadding(l) +} + +// DestinationSSRC returns an array of SSRC values that this packet refers to. +func (g *Goodbye) DestinationSSRC() []uint32 { + out := make([]uint32, len(g.Sources)) + copy(out, g.Sources) + return out +} |