From 32c281d2dcab5369b647c201fba9a5c968e95486 Mon Sep 17 00:00:00 2001 From: scruzin Date: Sat, 12 Jan 2019 18:43:51 +1030 Subject: [PATCH] Added type-specific wrappers for amf.Object.GetProperty, namely GetNumber, GetString and GetObject. --- rtmp/amf/amf.go | 44 ++++++++++++++++++++++++++++++++++++++------ rtmp/amf/amf_test.go | 24 ++++++++++++------------ rtmp/rtmp.go | 21 ++++++++------------- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/rtmp/amf/amf.go b/rtmp/amf/amf.go index 0112eec4..1ee86a66 100644 --- a/rtmp/amf/amf.go +++ b/rtmp/amf/amf.go @@ -473,19 +473,51 @@ func Decode(obj *Object, buf []byte, decodeName bool) (int, error) { return sz - len(buf), nil } -// GetProp returns an object's property, either by its index when idx is non-negative, or by its name otherwise. -// If the requested property is not found an ErrPropertyNotFound error is returned. -func (obj *Object) GetProp(name string, idx int) (*Property, error) { +// GetProperty returns a property, either by its index when idx is non-negative, or by its name otherwise. +// If the requested property is not found or the type does not match, an ErrPropertyNotFound error is returned. +func (obj *Object) GetProperty(name string, idx int, typ uint8) (*Property, error) { + var prop *Property if idx >= 0 { if idx < len(obj.Properties) { - return &obj.Properties[idx], nil + prop = &obj.Properties[idx] } } else { for i, p := range obj.Properties { if p.Name == name { - return &obj.Properties[i], nil + prop = &obj.Properties[i] + break } } } - return nil, ErrPropertyNotFound + if prop == nil || prop.Type != typ { + return nil, ErrPropertyNotFound + } + return prop, nil +} + +// GetNumber is a wrapper for GetProperty that returns a Number property's value, if any. +func (obj *Object) GetNumber(name string, idx int) (float64, error) { + prop, err := obj.GetProperty(name, idx, typeNumber) + if err != nil { + return 0, err + } + return prop.Number, nil +} + +// GetString is a wrapper for GetProperty that returns a String property's value, if any. +func (obj *Object) GetString(name string, idx int) (string, error) { + prop, err := obj.GetProperty(name, idx, typeString) + if err != nil { + return "", err + } + return prop.String, nil +} + +// GetObject is a wrapper for GetProperty that returns an Object property's value, if any. +func (obj *Object) GetObject(name string, idx int) (*Object, error) { + prop, err := obj.GetProperty(name, idx, TypeObject) + if err != nil { + return nil, err + } + return &prop.Object, nil } diff --git a/rtmp/amf/amf_test.go b/rtmp/amf/amf_test.go index 4c7e7f92..ef676e7e 100644 --- a/rtmp/amf/amf_test.go +++ b/rtmp/amf/amf_test.go @@ -232,32 +232,32 @@ func TestObject(t *testing.T) { } // Find some properties that exist. - prop, err := obj2.GetProp("", 2) + prop, err := obj2.GetProperty("", 2, typeString) if err != nil { - t.Errorf("GetProp(2) failed") + t.Errorf("GetProperty(2) failed") } if prop.String != "foo" { - t.Errorf("GetProp(2) returned wrong Property") + t.Errorf("GetProperty(2) returned wrong Property") } - prop, err = obj2.GetProp("", 3) + prop, err = obj2.GetProperty("", 3, typeNumber) if err != nil { - t.Errorf("GetProp(1) failed") + t.Errorf("GetProperty(1) failed") } if prop.Number != 1 { - t.Errorf("GetProp(1) returned wrong Property") + t.Errorf("GetProperty(1) returned wrong Property") } - prop, err = obj2.GetProp("", 9) + prop, err = obj2.GetProperty("", 9, typeBoolean) if err != nil { - t.Errorf("GetProp(9) failed") + t.Errorf("GetProperty(9) failed") return } - if prop.Type != typeBoolean && prop.Number != 1 { - t.Errorf("GetProp(9) returned wrong Property") + if prop.Number != 1 { + t.Errorf("GetProperty(9) returned wrong Property") } // Try to find one that doesn't exist. - prop, err = obj2.GetProp("", 10) + prop, err = obj2.GetProperty("", 10, TypeObject) if err != ErrPropertyNotFound { - t.Errorf("GetProp(10) failed") + t.Errorf("GetProperty(10) failed") } } diff --git a/rtmp/rtmp.go b/rtmp/rtmp.go index f1ff5f3b..93d07328 100644 --- a/rtmp/rtmp.go +++ b/rtmp/rtmp.go @@ -686,16 +686,14 @@ func handleInvoke(s *Session, body []byte) error { return err } - prop, err := obj.GetProp("", 0) + meth, err := obj.GetString("", 0) if err != nil { return err } - meth := prop.String - prop, err = obj.GetProp("", 1) + txn, err := obj.GetNumber("", 1) if err != nil { return err } - txn := prop.Number s.log(DebugLevel, pkg+"invoking method "+meth) switch meth { @@ -736,15 +734,15 @@ func handleInvoke(s *Session, body []byte) error { } case avCreatestream: - prop, err = obj.GetProp("", 3) + n, err := obj.GetNumber("", 3) if err != nil { return err } - s.streamID = int32(prop.Number) + s.streamID = int32(n) if s.link.protocol&featureWrite == 0 { return errNotWritable } - err := sendPublish(s) + err = sendPublish(s) if err != nil { return err } @@ -777,21 +775,18 @@ func handleInvoke(s *Session, body []byte) error { s.log(FatalLevel, pkg+"unsupported method avClose") case avOnStatus: - prop, err = obj.GetProp("", 3) + obj2, err := obj.GetObject("", 3) if err != nil { return err } - obj2 := prop.Object - prop, err = obj2.GetProp(avCode, -1) + code, err := obj2.GetString(avCode, -1) if err != nil { return err } - code := prop.String - prop, err = obj2.GetProp(avLevel, -1) + level, err := obj2.GetString(avLevel, -1) if err != nil { return err } - level := prop.String s.log(DebugLevel, pkg+"onStatus", "code", code, "level", level) switch code {