1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00
srs/trunk/3rdparty/srs-bench/vendor/github.com/google/gopacket/parser.go
Winlin 73dd8af4c9
HLS: Ignore empty NALU to avoid error. v6.0.65 (#3750)
For the DJI M30, there is a bug where empty NALU packets with a size of
zero are causing issues with HLS streaming. This bug leads to random
unpublish events due to the SRS disconnecting the connection for the HLS
module when it fails to handle empty NALU packets.

To address this bug, we have patched the system to ignore any empty NALU
packets with a size of zero. Additionally, we have created a tool in the
srs-bench to replay pcapng files captured by tcpdump or Wireshark. We
have also added utest using mprotect and asan to detect any memory
corruption.

It is important to note that this bug has been fixed in versions 4.0.271
6477f31004 and 5.0.170
939f6b484b. This patch specifically
addresses the issue in SRS 6.0.

Please be aware that there is another commit related to this bug that
partially fixes the issue but still leaves a small problem for asan to
detect memory corruption. This commit,
577cd299e1, only ignores empty NALU
packets but still reads beyond the memory.

---------

Co-authored-by: chundonglinlin <chundonglinlin@163.com>
2023-08-02 22:49:49 +08:00

350 lines
12 KiB
Go

// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.
package gopacket
import (
"fmt"
)
// A container for single LayerType->DecodingLayer mapping.
type decodingLayerElem struct {
typ LayerType
dec DecodingLayer
}
// DecodingLayer is an interface for packet layers that can decode themselves.
//
// The important part of DecodingLayer is that they decode themselves in-place.
// Calling DecodeFromBytes on a DecodingLayer totally resets the entire layer to
// the new state defined by the data passed in. A returned error leaves the
// DecodingLayer in an unknown intermediate state, thus its fields should not be
// trusted.
//
// Because the DecodingLayer is resetting its own fields, a call to
// DecodeFromBytes should normally not require any memory allocation.
type DecodingLayer interface {
// DecodeFromBytes resets the internal state of this layer to the state
// defined by the passed-in bytes. Slices in the DecodingLayer may
// reference the passed-in data, so care should be taken to copy it
// first should later modification of data be required before the
// DecodingLayer is discarded.
DecodeFromBytes(data []byte, df DecodeFeedback) error
// CanDecode returns the set of LayerTypes this DecodingLayer can
// decode. For Layers that are also DecodingLayers, this will most
// often be that Layer's LayerType().
CanDecode() LayerClass
// NextLayerType returns the LayerType which should be used to decode
// the LayerPayload.
NextLayerType() LayerType
// LayerPayload is the set of bytes remaining to decode after a call to
// DecodeFromBytes.
LayerPayload() []byte
}
// DecodingLayerFunc decodes given packet and stores decoded LayerType
// values into specified slice. Returns either first encountered
// unsupported LayerType value or decoding error. In case of success,
// returns (LayerTypeZero, nil).
type DecodingLayerFunc func([]byte, *[]LayerType) (LayerType, error)
// DecodingLayerContainer stores all DecodingLayer-s and serves as a
// searching tool for DecodingLayerParser.
type DecodingLayerContainer interface {
// Put adds new DecodingLayer to container. The new instance of
// the same DecodingLayerContainer is returned so it may be
// implemented as a value receiver.
Put(DecodingLayer) DecodingLayerContainer
// Decoder returns DecodingLayer to decode given LayerType and
// true if it was found. If no decoder found, return false.
Decoder(LayerType) (DecodingLayer, bool)
// LayersDecoder returns DecodingLayerFunc which decodes given
// packet, starting with specified LayerType and DecodeFeedback.
LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc
}
// DecodingLayerSparse is a sparse array-based implementation of
// DecodingLayerContainer. Each DecodingLayer is addressed in an
// allocated slice by LayerType value itself. Though this is the
// fastest container it may be memory-consuming if used with big
// LayerType values.
type DecodingLayerSparse []DecodingLayer
// Put implements DecodingLayerContainer interface.
func (dl DecodingLayerSparse) Put(d DecodingLayer) DecodingLayerContainer {
maxLayerType := LayerType(len(dl) - 1)
for _, typ := range d.CanDecode().LayerTypes() {
if typ > maxLayerType {
maxLayerType = typ
}
}
if extra := maxLayerType - LayerType(len(dl)) + 1; extra > 0 {
dl = append(dl, make([]DecodingLayer, extra)...)
}
for _, typ := range d.CanDecode().LayerTypes() {
dl[typ] = d
}
return dl
}
// LayersDecoder implements DecodingLayerContainer interface.
func (dl DecodingLayerSparse) LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc {
return LayersDecoder(dl, first, df)
}
// Decoder implements DecodingLayerContainer interface.
func (dl DecodingLayerSparse) Decoder(typ LayerType) (DecodingLayer, bool) {
if int64(typ) < int64(len(dl)) {
decoder := dl[typ]
return decoder, decoder != nil
}
return nil, false
}
// DecodingLayerArray is an array-based implementation of
// DecodingLayerContainer. Each DecodingLayer is searched linearly in
// an allocated slice in one-by-one fashion.
type DecodingLayerArray []decodingLayerElem
// Put implements DecodingLayerContainer interface.
func (dl DecodingLayerArray) Put(d DecodingLayer) DecodingLayerContainer {
TYPES:
for _, typ := range d.CanDecode().LayerTypes() {
for i := range dl {
if dl[i].typ == typ {
dl[i].dec = d
continue TYPES
}
}
dl = append(dl, decodingLayerElem{typ, d})
}
return dl
}
// Decoder implements DecodingLayerContainer interface.
func (dl DecodingLayerArray) Decoder(typ LayerType) (DecodingLayer, bool) {
for i := range dl {
if dl[i].typ == typ {
return dl[i].dec, true
}
}
return nil, false
}
// LayersDecoder implements DecodingLayerContainer interface.
func (dl DecodingLayerArray) LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc {
return LayersDecoder(dl, first, df)
}
// DecodingLayerMap is an map-based implementation of
// DecodingLayerContainer. Each DecodingLayer is searched in a map
// hashed by LayerType value.
type DecodingLayerMap map[LayerType]DecodingLayer
// Put implements DecodingLayerContainer interface.
func (dl DecodingLayerMap) Put(d DecodingLayer) DecodingLayerContainer {
for _, typ := range d.CanDecode().LayerTypes() {
if dl == nil {
dl = make(map[LayerType]DecodingLayer)
}
dl[typ] = d
}
return dl
}
// Decoder implements DecodingLayerContainer interface.
func (dl DecodingLayerMap) Decoder(typ LayerType) (DecodingLayer, bool) {
d, ok := dl[typ]
return d, ok
}
// LayersDecoder implements DecodingLayerContainer interface.
func (dl DecodingLayerMap) LayersDecoder(first LayerType, df DecodeFeedback) DecodingLayerFunc {
return LayersDecoder(dl, first, df)
}
// Static code check.
var (
_ = []DecodingLayerContainer{
DecodingLayerSparse(nil),
DecodingLayerMap(nil),
DecodingLayerArray(nil),
}
)
// DecodingLayerParser parses a given set of layer types. See DecodeLayers for
// more information on how DecodingLayerParser should be used.
type DecodingLayerParser struct {
// DecodingLayerParserOptions is the set of options available to the
// user to define the parser's behavior.
DecodingLayerParserOptions
dlc DecodingLayerContainer
first LayerType
df DecodeFeedback
decodeFunc DecodingLayerFunc
// Truncated is set when a decode layer detects that the packet has been
// truncated.
Truncated bool
}
// AddDecodingLayer adds a decoding layer to the parser. This adds support for
// the decoding layer's CanDecode layers to the parser... should they be
// encountered, they'll be parsed.
func (l *DecodingLayerParser) AddDecodingLayer(d DecodingLayer) {
l.SetDecodingLayerContainer(l.dlc.Put(d))
}
// SetTruncated is used by DecodingLayers to set the Truncated boolean in the
// DecodingLayerParser. Users should simply read Truncated after calling
// DecodeLayers.
func (l *DecodingLayerParser) SetTruncated() {
l.Truncated = true
}
// NewDecodingLayerParser creates a new DecodingLayerParser and adds in all
// of the given DecodingLayers with AddDecodingLayer.
//
// Each call to DecodeLayers will attempt to decode the given bytes first by
// treating them as a 'first'-type layer, then by using NextLayerType on
// subsequently decoded layers to find the next relevant decoder. Should a
// deoder not be available for the layer type returned by NextLayerType,
// decoding will stop.
//
// NewDecodingLayerParser uses DecodingLayerMap container by
// default.
func NewDecodingLayerParser(first LayerType, decoders ...DecodingLayer) *DecodingLayerParser {
dlp := &DecodingLayerParser{first: first}
dlp.df = dlp // Cast this once to the interface
// default container
dlc := DecodingLayerContainer(DecodingLayerMap(make(map[LayerType]DecodingLayer)))
for _, d := range decoders {
dlc = dlc.Put(d)
}
dlp.SetDecodingLayerContainer(dlc)
return dlp
}
// SetDecodingLayerContainer specifies container with decoders. This
// call replaces all decoders already registered in given instance of
// DecodingLayerParser.
func (l *DecodingLayerParser) SetDecodingLayerContainer(dlc DecodingLayerContainer) {
l.dlc = dlc
l.decodeFunc = l.dlc.LayersDecoder(l.first, l.df)
}
// DecodeLayers decodes as many layers as possible from the given data. It
// initially treats the data as layer type 'typ', then uses NextLayerType on
// each subsequent decoded layer until it gets to a layer type it doesn't know
// how to parse.
//
// For each layer successfully decoded, DecodeLayers appends the layer type to
// the decoded slice. DecodeLayers truncates the 'decoded' slice initially, so
// there's no need to empty it yourself.
//
// This decoding method is about an order of magnitude faster than packet
// decoding, because it only decodes known layers that have already been
// allocated. This means it doesn't need to allocate each layer it returns...
// instead it overwrites the layers that already exist.
//
// Example usage:
// func main() {
// var eth layers.Ethernet
// var ip4 layers.IPv4
// var ip6 layers.IPv6
// var tcp layers.TCP
// var udp layers.UDP
// var payload gopacket.Payload
// parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &ip6, &tcp, &udp, &payload)
// var source gopacket.PacketDataSource = getMyDataSource()
// decodedLayers := make([]gopacket.LayerType, 0, 10)
// for {
// data, _, err := source.ReadPacketData()
// if err != nil {
// fmt.Println("Error reading packet data: ", err)
// continue
// }
// fmt.Println("Decoding packet")
// err = parser.DecodeLayers(data, &decodedLayers)
// for _, typ := range decodedLayers {
// fmt.Println(" Successfully decoded layer type", typ)
// switch typ {
// case layers.LayerTypeEthernet:
// fmt.Println(" Eth ", eth.SrcMAC, eth.DstMAC)
// case layers.LayerTypeIPv4:
// fmt.Println(" IP4 ", ip4.SrcIP, ip4.DstIP)
// case layers.LayerTypeIPv6:
// fmt.Println(" IP6 ", ip6.SrcIP, ip6.DstIP)
// case layers.LayerTypeTCP:
// fmt.Println(" TCP ", tcp.SrcPort, tcp.DstPort)
// case layers.LayerTypeUDP:
// fmt.Println(" UDP ", udp.SrcPort, udp.DstPort)
// }
// }
// if decodedLayers.Truncated {
// fmt.Println(" Packet has been truncated")
// }
// if err != nil {
// fmt.Println(" Error encountered:", err)
// }
// }
// }
//
// If DecodeLayers is unable to decode the next layer type, it will return the
// error UnsupportedLayerType.
func (l *DecodingLayerParser) DecodeLayers(data []byte, decoded *[]LayerType) (err error) {
l.Truncated = false
if !l.IgnorePanic {
defer panicToError(&err)
}
typ, err := l.decodeFunc(data, decoded)
if typ != LayerTypeZero {
// no decoder
if l.IgnoreUnsupported {
return nil
}
return UnsupportedLayerType(typ)
}
return err
}
// UnsupportedLayerType is returned by DecodingLayerParser if DecodeLayers
// encounters a layer type that the DecodingLayerParser has no decoder for.
type UnsupportedLayerType LayerType
// Error implements the error interface, returning a string to say that the
// given layer type is unsupported.
func (e UnsupportedLayerType) Error() string {
return fmt.Sprintf("No decoder for layer type %v", LayerType(e))
}
func panicToError(e *error) {
if r := recover(); r != nil {
*e = fmt.Errorf("panic: %v", r)
}
}
// DecodingLayerParserOptions provides options to affect the behavior of a given
// DecodingLayerParser.
type DecodingLayerParserOptions struct {
// IgnorePanic determines whether a DecodingLayerParser should stop
// panics on its own (by returning them as an error from DecodeLayers)
// or should allow them to raise up the stack. Handling errors does add
// latency to the process of decoding layers, but is much safer for
// callers. IgnorePanic defaults to false, thus if the caller does
// nothing decode panics will be returned as errors.
IgnorePanic bool
// IgnoreUnsupported will stop parsing and return a nil error when it
// encounters a layer it doesn't have a parser for, instead of returning an
// UnsupportedLayerType error. If this is true, it's up to the caller to make
// sure that all expected layers have been parsed (by checking the decoded
// slice).
IgnoreUnsupported bool
}