|
|
@ -34,13 +34,13 @@ const (
|
|
|
|
Amf0TypeMarkerNull = uint8(0x05)
|
|
|
|
Amf0TypeMarkerNull = uint8(0x05)
|
|
|
|
Amf0TypeMarkerEcmaArray = uint8(0x08)
|
|
|
|
Amf0TypeMarkerEcmaArray = uint8(0x08)
|
|
|
|
Amf0TypeMarkerObjectEnd = uint8(0x09) // end for both Object and Array
|
|
|
|
Amf0TypeMarkerObjectEnd = uint8(0x09) // end for both Object and Array
|
|
|
|
|
|
|
|
Amf0TypeMarkerStrictArray = uint8(0x0a)
|
|
|
|
Amf0TypeMarkerLongString = uint8(0x0c)
|
|
|
|
Amf0TypeMarkerLongString = uint8(0x0c)
|
|
|
|
|
|
|
|
|
|
|
|
// 还没用到的类型
|
|
|
|
// 还没用到的类型
|
|
|
|
//Amf0TypeMarkerMovieclip = uint8(0x04)
|
|
|
|
//Amf0TypeMarkerMovieclip = uint8(0x04)
|
|
|
|
//Amf0TypeMarkerUndefined = uint8(0x06)
|
|
|
|
//Amf0TypeMarkerUndefined = uint8(0x06)
|
|
|
|
//Amf0TypeMarkerReference = uint8(0x07)
|
|
|
|
//Amf0TypeMarkerReference = uint8(0x07)
|
|
|
|
//Amf0TypeMarkerStrictArray = uint8(0x0a)
|
|
|
|
|
|
|
|
//Amf0TypeMarkerData = uint8(0x0b)
|
|
|
|
//Amf0TypeMarkerData = uint8(0x0b)
|
|
|
|
//Amf0TypeMarkerUnsupported = uint8(0x0d)
|
|
|
|
//Amf0TypeMarkerUnsupported = uint8(0x0d)
|
|
|
|
//Amf0TypeMarkerRecordset = uint8(0x0e)
|
|
|
|
//Amf0TypeMarkerRecordset = uint8(0x0e)
|
|
|
@ -58,7 +58,7 @@ var (
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
type ObjectPair struct {
|
|
|
|
type ObjectPair struct {
|
|
|
|
Key string
|
|
|
|
Key string // Amf0TypeMarkerStrictArray类型的数据,Key为""
|
|
|
|
Value interface{} // TODO(chef): [perf] 考虑换成泛型 202206
|
|
|
|
Value interface{} // TODO(chef): [perf] 考虑换成泛型 202206
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -291,67 +291,56 @@ func (amf0) ReadObject(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
return nil, 0, err
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index += l
|
|
|
|
index += l
|
|
|
|
if len(b)-index < 1 {
|
|
|
|
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
var readErr error
|
|
|
|
|
|
|
|
ops, index, readErr = Amf0.read(b, index, k, ops)
|
|
|
|
|
|
|
|
if readErr != nil {
|
|
|
|
|
|
|
|
return ops, index, readErr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vt := b[index]
|
|
|
|
|
|
|
|
switch vt {
|
|
|
|
|
|
|
|
case Amf0TypeMarkerNumber:
|
|
|
|
|
|
|
|
v, l, err := Amf0.ReadNumber(b[index:])
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
|
|
|
|
index += l
|
|
|
|
|
|
|
|
case Amf0TypeMarkerBoolean:
|
|
|
|
|
|
|
|
v, l, err := Amf0.ReadBoolean(b[index:])
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
|
|
|
|
index += l
|
|
|
|
// TODO chef: 实现WriteArray
|
|
|
|
case Amf0TypeMarkerString:
|
|
|
|
|
|
|
|
v, l, err := Amf0.ReadString(b[index:])
|
|
|
|
// ReadArray Amf0TypeMarkerEcmaArray
|
|
|
|
if err != nil {
|
|
|
|
func (amf0) ReadArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
return nil, 0, err
|
|
|
|
if len(b) < 5 {
|
|
|
|
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
if b[0] != Amf0TypeMarkerEcmaArray {
|
|
|
|
index += l
|
|
|
|
return nil, 0, base.NewErrAmfInvalidType(b[0])
|
|
|
|
case Amf0TypeMarkerObject:
|
|
|
|
|
|
|
|
v, l, err := Amf0.ReadObject(b[index:])
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, 0, err
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
count := int(bele.BeUint32(b[1:]))
|
|
|
|
index += l
|
|
|
|
|
|
|
|
case Amf0TypeMarkerNull:
|
|
|
|
index := 5
|
|
|
|
l, err := Amf0.ReadNull(b[index:])
|
|
|
|
var ops ObjectPairArray
|
|
|
|
|
|
|
|
for i := 0; i < count; i++ {
|
|
|
|
|
|
|
|
k, l, err := Amf0.ReadStringWithoutType(b[index:])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index += l
|
|
|
|
index += l
|
|
|
|
case Amf0TypeMarkerEcmaArray:
|
|
|
|
|
|
|
|
v, l, err := Amf0.ReadArray(b[index:])
|
|
|
|
var readErr error
|
|
|
|
if err != nil {
|
|
|
|
ops, index, readErr = Amf0.read(b, index, k, ops)
|
|
|
|
return nil, 0, err
|
|
|
|
if readErr != nil {
|
|
|
|
|
|
|
|
return ops, index, readErr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
|
|
|
|
index += l
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
Log.Panicf("unknown type. vt=%d, hex=%s", vt, hex.Dump(nazabytes.Prefix(b, 4096)))
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(b)-index >= 3 && bytes.Equal(b[index:index+3], Amf0TypeMarkerArrayEndBytes) {
|
|
|
|
|
|
|
|
index += 3
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
Log.Warn("amf ReadArray without suffix Amf0TypeMarkerObjectEndBytes.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ops, index, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO chef:
|
|
|
|
func (amf0) ReadStrictArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
// - 实现WriteArray
|
|
|
|
|
|
|
|
// - ReadArray和ReadObject有些代码重复
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (amf0) ReadArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
|
|
|
|
if len(b) < 5 {
|
|
|
|
if len(b) < 5 {
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if b[0] != Amf0TypeMarkerEcmaArray {
|
|
|
|
if b[0] != Amf0TypeMarkerStrictArray {
|
|
|
|
return nil, 0, base.NewErrAmfInvalidType(b[0])
|
|
|
|
return nil, 0, base.NewErrAmfInvalidType(b[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count := int(bele.BeUint32(b[1:]))
|
|
|
|
count := int(bele.BeUint32(b[1:]))
|
|
|
@ -359,18 +348,37 @@ func (amf0) ReadArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
index := 5
|
|
|
|
index := 5
|
|
|
|
var ops ObjectPairArray
|
|
|
|
var ops ObjectPairArray
|
|
|
|
for i := 0; i < count; i++ {
|
|
|
|
for i := 0; i < count; i++ {
|
|
|
|
k, l, err := Amf0.ReadStringWithoutType(b[index:])
|
|
|
|
var readErr error
|
|
|
|
if err != nil {
|
|
|
|
ops, index, readErr = Amf0.read(b, index, "", ops)
|
|
|
|
return nil, 0, err
|
|
|
|
if readErr != nil {
|
|
|
|
|
|
|
|
return ops, index, readErr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index += l
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ops, index, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (amf0) ReadObjectOrArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
|
|
|
|
if len(b) < 1 {
|
|
|
|
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch b[0] {
|
|
|
|
|
|
|
|
case Amf0TypeMarkerObject:
|
|
|
|
|
|
|
|
return Amf0.ReadObject(b)
|
|
|
|
|
|
|
|
case Amf0TypeMarkerEcmaArray:
|
|
|
|
|
|
|
|
return Amf0.ReadArray(b)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, 0, base.NewErrAmfInvalidType(b[0])
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (amf0) read(b []byte, index int, k string, ops ObjectPairArray) (ObjectPairArray, int, error) {
|
|
|
|
if len(b)-index < 1 {
|
|
|
|
if len(b)-index < 1 {
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vt := b[index]
|
|
|
|
vt := b[index]
|
|
|
|
switch vt {
|
|
|
|
switch vt {
|
|
|
|
case Amf0TypeMarkerString:
|
|
|
|
case Amf0TypeMarkerNumber:
|
|
|
|
v, l, err := Amf0.ReadString(b[index:])
|
|
|
|
v, l, err := Amf0.ReadNumber(b[index:])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -383,8 +391,8 @@ func (amf0) ReadArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
index += l
|
|
|
|
index += l
|
|
|
|
case Amf0TypeMarkerNumber:
|
|
|
|
case Amf0TypeMarkerString:
|
|
|
|
v, l, err := Amf0.ReadNumber(b[index:])
|
|
|
|
v, l, err := Amf0.ReadString(b[index:])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -396,28 +404,31 @@ func (amf0) ReadArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
return nil, 0, err
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index += l
|
|
|
|
index += l
|
|
|
|
default:
|
|
|
|
case Amf0TypeMarkerObject:
|
|
|
|
Log.Panicf("unknown type. vt=%d", vt)
|
|
|
|
v, l, err := Amf0.ReadObject(b[index:])
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
|
|
|
|
index += l
|
|
|
|
|
|
|
|
case Amf0TypeMarkerEcmaArray:
|
|
|
|
|
|
|
|
v, l, err := Amf0.ReadArray(b[index:])
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
if len(b)-index >= 3 && bytes.Equal(b[index:index+3], Amf0TypeMarkerArrayEndBytes) {
|
|
|
|
index += l
|
|
|
|
index += 3
|
|
|
|
case Amf0TypeMarkerStrictArray:
|
|
|
|
} else {
|
|
|
|
v, l, err := Amf0.ReadStrictArray(b[index:])
|
|
|
|
Log.Warn("amf ReadArray without suffix Amf0TypeMarkerObjectEndBytes.")
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ops, index, nil
|
|
|
|
ops = append(ops, ObjectPair{k, v})
|
|
|
|
|
|
|
|
index += l
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
Log.Errorf("unknown type. vt=%d, hex=%s", vt, hex.Dump(nazabytes.Prefix(b, 4096)))
|
|
|
|
|
|
|
|
return ops, index, base.NewErrAmfInvalidType(vt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (amf0) ReadObjectOrArray(b []byte) (ObjectPairArray, int, error) {
|
|
|
|
return ops, index, nil
|
|
|
|
if len(b) < 1 {
|
|
|
|
|
|
|
|
return nil, 0, nazaerrors.Wrap(base.ErrAmfTooShort)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch b[0] {
|
|
|
|
|
|
|
|
case Amf0TypeMarkerObject:
|
|
|
|
|
|
|
|
return Amf0.ReadObject(b)
|
|
|
|
|
|
|
|
case Amf0TypeMarkerEcmaArray:
|
|
|
|
|
|
|
|
return Amf0.ReadArray(b)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, 0, base.NewErrAmfInvalidType(b[0])
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|