57 lines
1.7 KiB
Go
57 lines
1.7 KiB
Go
package media
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/pion/rtp"
|
|
)
|
|
|
|
// PacketGuard is a thin policy adapter around Pion's RTP parser. It does not
|
|
// implement RTP/RTCP framing; the mature library owns wire parsing.
|
|
type PacketGuard struct {
|
|
MaxPacketBytes int
|
|
MaxPayloadBytes int
|
|
AllowedSSRC uint32
|
|
RequireSSRC bool
|
|
AllowedPayloadTypes map[uint8]struct{}
|
|
}
|
|
|
|
type Packet struct {
|
|
PayloadType uint8
|
|
SequenceNumber uint16
|
|
Timestamp uint32
|
|
SSRC uint32
|
|
Marker bool
|
|
Payload []byte
|
|
}
|
|
|
|
func (g PacketGuard) Parse(raw []byte) (Packet, error) {
|
|
if len(raw) == 0 {
|
|
return Packet{}, errors.New("empty RTP packet")
|
|
}
|
|
if g.MaxPacketBytes > 0 && len(raw) > g.MaxPacketBytes {
|
|
return Packet{}, fmt.Errorf("RTP packet exceeds limit: %d > %d", len(raw), g.MaxPacketBytes)
|
|
}
|
|
var parsed rtp.Packet
|
|
if err := parsed.Unmarshal(raw); err != nil {
|
|
return Packet{}, fmt.Errorf("parse RTP packet: %w", err)
|
|
}
|
|
if len(g.AllowedPayloadTypes) > 0 {
|
|
if _, ok := g.AllowedPayloadTypes[parsed.PayloadType]; !ok {
|
|
return Packet{}, fmt.Errorf("RTP payload type %d is not allowed", parsed.PayloadType)
|
|
}
|
|
}
|
|
if g.RequireSSRC && parsed.SSRC != g.AllowedSSRC {
|
|
return Packet{}, fmt.Errorf("RTP SSRC %d is not allowed", parsed.SSRC)
|
|
}
|
|
if g.MaxPayloadBytes > 0 && len(parsed.Payload) > g.MaxPayloadBytes {
|
|
return Packet{}, fmt.Errorf("RTP payload exceeds limit: %d > %d", len(parsed.Payload), g.MaxPayloadBytes)
|
|
}
|
|
return Packet{
|
|
PayloadType: parsed.PayloadType, SequenceNumber: parsed.SequenceNumber,
|
|
Timestamp: parsed.Timestamp, SSRC: parsed.SSRC, Marker: parsed.Marker,
|
|
Payload: append([]byte(nil), parsed.Payload...),
|
|
}, nil
|
|
}
|