mirror of https://bitbucket.org/ausocean/av.git
protocol/rtmp/amf/amf.go: improving error messaging
This commit is contained in:
parent
c4e4cc750f
commit
dd6adbf9d0
|
@ -43,6 +43,7 @@ package amf
|
|||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
|
@ -163,11 +164,7 @@ func EncodeInt32(buf []byte, val uint32) ([]byte, error) {
|
|||
// Strings less than 65536 in length are encoded as TypeString, while longer strings are ecodeded as typeLongString.
|
||||
func EncodeString(buf []byte, val string) ([]byte, error) {
|
||||
const typeSize = 1
|
||||
if len(val) < 65536 && len(val)+typeSize+binary.Size(int16(0)) > len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
if len(val)+typeSize+binary.Size(uint32(0)) > len(buf) {
|
||||
if len(val) < 65536 && len(val)+typeSize+binary.Size(int16(0)) > len(buf) || len(val)+typeSize+binary.Size(uint32(0)) > len(buf) {
|
||||
return nil, ErrShortBuffer
|
||||
}
|
||||
|
||||
|
@ -222,7 +219,11 @@ func EncodeNamedString(buf []byte, key, val string) ([]byte, error) {
|
|||
binary.BigEndian.PutUint16(buf[:2], uint16(len(key)))
|
||||
buf = buf[2:]
|
||||
copy(buf, key)
|
||||
return EncodeString(buf[len(key):], val)
|
||||
b, err := EncodeString(buf[len(key):], val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode string: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// EncodeNamedNumber encodes a named number, where key is the name and val is the number value.
|
||||
|
@ -233,7 +234,11 @@ func EncodeNamedNumber(buf []byte, key string, val float64) ([]byte, error) {
|
|||
binary.BigEndian.PutUint16(buf[:2], uint16(len(key)))
|
||||
buf = buf[2:]
|
||||
copy(buf, key)
|
||||
return EncodeNumber(buf[len(key):], val)
|
||||
b, err := EncodeNumber(buf[len(key):], val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode number: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// EncodeNamedNumber encodes a named boolean, where key is the name and val is the boolean value.
|
||||
|
@ -244,14 +249,18 @@ func EncodeNamedBoolean(buf []byte, key string, val bool) ([]byte, error) {
|
|||
binary.BigEndian.PutUint16(buf[:2], uint16(len(key)))
|
||||
buf = buf[2:]
|
||||
copy(buf, key)
|
||||
return EncodeBoolean(buf[len(key):], val)
|
||||
b, err := EncodeBoolean(buf[len(key):], val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode boolean: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// EncodeProperty encodes a property.
|
||||
func EncodeProperty(prop *Property, buf []byte) ([]byte, error) {
|
||||
if prop.Type != TypeNull && prop.Name != "" {
|
||||
if len(buf) < 2+len(prop.Name) {
|
||||
return nil, ErrShortBuffer
|
||||
return nil, fmt.Errorf("not type null, short buffer: %w", ErrShortBuffer)
|
||||
}
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(len(prop.Name)))
|
||||
buf = buf[2:]
|
||||
|
@ -261,23 +270,47 @@ func EncodeProperty(prop *Property, buf []byte) ([]byte, error) {
|
|||
|
||||
switch prop.Type {
|
||||
case typeNumber:
|
||||
return EncodeNumber(buf, prop.Number)
|
||||
b, err := EncodeNumber(buf, prop.Number)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode number: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
case typeBoolean:
|
||||
return EncodeBoolean(buf, prop.Number != 0)
|
||||
b, err := EncodeBoolean(buf, prop.Number != 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode boolean: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
case TypeString:
|
||||
return EncodeString(buf, prop.String)
|
||||
b, err := EncodeString(buf, prop.String)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode string: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
case TypeNull:
|
||||
if len(buf) < 2 {
|
||||
return nil, ErrShortBuffer
|
||||
return nil, fmt.Errorf("type null, short buffer: %w", ErrShortBuffer)
|
||||
}
|
||||
buf[0] = TypeNull
|
||||
buf = buf[1:]
|
||||
case TypeObject:
|
||||
return Encode(&prop.Object, buf)
|
||||
b, err := Encode(&prop.Object, buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
case typeEcmaArray:
|
||||
return EncodeEcmaArray(&prop.Object, buf)
|
||||
b, err := EncodeEcmaArray(&prop.Object, buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode ecma array: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
case typeStrictArray:
|
||||
return EncodeArray(&prop.Object, buf)
|
||||
b, err := EncodeArray(&prop.Object, buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode array: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
default:
|
||||
return nil, ErrInvalidType
|
||||
}
|
||||
|
@ -294,7 +327,7 @@ func DecodeProperty(prop *Property, buf []byte, decodeName bool) (int, error) {
|
|||
}
|
||||
n := DecodeInt16(buf[:2])
|
||||
if int(n) > len(buf)-2 {
|
||||
return 0, ErrShortBuffer
|
||||
return 0, fmt.Errorf("short buffer after decode of int 16: %w", ErrShortBuffer)
|
||||
}
|
||||
|
||||
prop.Name = DecodeString(buf)
|
||||
|
@ -309,14 +342,14 @@ func DecodeProperty(prop *Property, buf []byte, decodeName bool) (int, error) {
|
|||
switch prop.Type {
|
||||
case typeNumber:
|
||||
if len(buf) < 8 {
|
||||
return 0, ErrShortBuffer
|
||||
return 0, fmt.Errorf("type number short buffer: %w", ErrShortBuffer)
|
||||
}
|
||||
prop.Number = DecodeNumber(buf[:8])
|
||||
buf = buf[8:]
|
||||
|
||||
case typeBoolean:
|
||||
if len(buf) < 1 {
|
||||
return 0, ErrShortBuffer
|
||||
return 0, fmt.Errorf("type boolean short buffer: %w", ErrShortBuffer)
|
||||
}
|
||||
prop.Number = float64(buf[0])
|
||||
buf = buf[1:]
|
||||
|
@ -324,7 +357,7 @@ func DecodeProperty(prop *Property, buf []byte, decodeName bool) (int, error) {
|
|||
case TypeString:
|
||||
n := DecodeInt16(buf[:2])
|
||||
if len(buf) < int(n+2) {
|
||||
return 0, ErrShortBuffer
|
||||
return 0, fmt.Errorf("type string: %w", ErrShortBuffer)
|
||||
}
|
||||
prop.String = DecodeString(buf)
|
||||
buf = buf[2+n:]
|
||||
|
@ -332,7 +365,7 @@ func DecodeProperty(prop *Property, buf []byte, decodeName bool) (int, error) {
|
|||
case TypeObject:
|
||||
n, err := Decode(&prop.Object, buf, true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, fmt.Errorf("could not decode type object: %w", err)
|
||||
}
|
||||
buf = buf[n:]
|
||||
|
||||
|
@ -343,7 +376,7 @@ func DecodeProperty(prop *Property, buf []byte, decodeName bool) (int, error) {
|
|||
buf = buf[4:]
|
||||
n, err := Decode(&prop.Object, buf, true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, fmt.Errorf("could not decode type ecma array: %w", err)
|
||||
}
|
||||
buf = buf[n:]
|
||||
|
||||
|
@ -367,14 +400,19 @@ func Encode(obj *Object, buf []byte) ([]byte, error) {
|
|||
var err error
|
||||
buf, err = EncodeProperty(&obj.Properties[i], buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("could not encode property no. %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(buf) < 3 {
|
||||
return nil, ErrShortBuffer
|
||||
return nil, fmt.Errorf("short buffer after property encoding: %w", ErrShortBuffer)
|
||||
}
|
||||
return EncodeInt24(buf, TypeObjectEnd)
|
||||
|
||||
b, err := EncodeInt24(buf, TypeObjectEnd)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode int 24: %w", err)
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
// EncodeEcmaArray encodes an ECMA array.
|
||||
|
@ -392,14 +430,20 @@ func EncodeEcmaArray(obj *Object, buf []byte) ([]byte, error) {
|
|||
var err error
|
||||
buf, err = EncodeProperty(&obj.Properties[i], buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("could not encode property no. %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(buf) < 3 {
|
||||
return nil, ErrShortBuffer
|
||||
return nil, fmt.Errorf("short buffer after property encoding: %w", ErrShortBuffer)
|
||||
}
|
||||
return EncodeInt24(buf, TypeObjectEnd)
|
||||
|
||||
b, err := EncodeInt24(buf, TypeObjectEnd)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not encode int 24: %w", err)
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// EncodeArray encodes an array.
|
||||
|
@ -417,7 +461,7 @@ func EncodeArray(obj *Object, buf []byte) ([]byte, error) {
|
|||
var err error
|
||||
buf, err = EncodeProperty(&obj.Properties[i], buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("could not encode property no. %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,7 +481,7 @@ func Decode(obj *Object, buf []byte, decodeName bool) (int, error) {
|
|||
var prop Property
|
||||
n, err := DecodeProperty(&prop, buf, decodeName)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, fmt.Errorf("could not decode property: %w", err)
|
||||
}
|
||||
buf = buf[n:]
|
||||
obj.Properties = append(obj.Properties, prop)
|
||||
|
|
Loading…
Reference in New Issue