-
Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathpacket.go
131 lines (109 loc) · 3.07 KB
/
packet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package rtcp
// Packet represents an RTCP packet, a protocol used for out-of-band statistics
// and control information for an RTP session.
type Packet interface {
// DestinationSSRC returns an array of SSRC values that this packet refers to.
DestinationSSRC() []uint32
Marshal() ([]byte, error)
Unmarshal(rawPacket []byte) error
MarshalSize() int
}
// Unmarshal takes an entire udp datagram (which may consist of multiple RTCP packets) and
// returns the unmarshaled packets it contains.
//
// If this is a reduced-size RTCP packet a feedback packet (Goodbye, SliceLossIndication, etc)
// will be returned. Otherwise, the underlying type of the returned packet will be
// CompoundPacket.
func Unmarshal(rawData []byte) ([]Packet, error) {
var packets []Packet
for len(rawData) != 0 {
p, processed, err := unmarshal(rawData)
if err != nil {
return nil, err
}
packets = append(packets, p)
rawData = rawData[processed:]
}
switch len(packets) {
// Empty packet
case 0:
return nil, errInvalidHeader
// Multiple Packets
default:
return packets, nil
}
}
// Marshal takes an array of Packets and serializes them to a single buffer.
func Marshal(packets []Packet) ([]byte, error) {
out := make([]byte, 0)
for _, p := range packets {
data, err := p.Marshal()
if err != nil {
return nil, err
}
out = append(out, data...)
}
return out, nil
}
// unmarshal is a factory which pulls the first RTCP packet from a bytestream,
// and returns it's parsed representation, and the amount of data that was processed.
//
//nolint:cyclop
func unmarshal(rawData []byte) (packet Packet, bytesprocessed int, err error) {
var header Header
err = header.Unmarshal(rawData)
if err != nil {
return nil, 0, err
}
bytesprocessed = int(header.Length+1) * 4
if bytesprocessed > len(rawData) {
return nil, 0, errPacketTooShort
}
inPacket := rawData[:bytesprocessed]
switch header.Type {
case TypeSenderReport:
packet = new(SenderReport)
case TypeReceiverReport:
packet = new(ReceiverReport)
case TypeSourceDescription:
packet = new(SourceDescription)
case TypeGoodbye:
packet = new(Goodbye)
case TypeTransportSpecificFeedback:
switch header.Count {
case FormatTLN:
packet = new(TransportLayerNack)
case FormatRRR:
packet = new(RapidResynchronizationRequest)
case FormatTCC:
packet = new(TransportLayerCC)
case FormatCCFB:
packet = new(CCFeedbackReport)
default:
packet = new(RawPacket)
}
case TypePayloadSpecificFeedback:
switch header.Count {
case FormatPLI:
packet = new(PictureLossIndication)
case FormatSLI:
packet = new(SliceLossIndication)
case FormatREMB:
packet = new(ReceiverEstimatedMaximumBitrate)
case FormatFIR:
packet = new(FullIntraRequest)
default:
packet = new(RawPacket)
}
case TypeExtendedReport:
packet = new(ExtendedReport)
case TypeApplicationDefined:
packet = new(ApplicationDefined)
default:
packet = new(RawPacket)
}
err = packet.Unmarshal(inPacket)
return packet, bytesprocessed, err
}