diff --git a/examples/rp-client.go b/examples/rp-client.go index 11dca9a..e396d8b 100644 --- a/examples/rp-client.go +++ b/examples/rp-client.go @@ -58,6 +58,7 @@ func ReadPropertyClientExample(cmd *cobra.Command, args []string) { replyRaw := make([]byte, 1024) sentRequests := 0 for { + listenConn.SetDeadline(time.Now().Add(5 * time.Second)) if _, err := listenConn.WriteTo(mReadProperty, remoteUDPAddr); err != nil { log.Fatalf("Failed to write the request: %s\n", err) } @@ -65,6 +66,9 @@ func ReadPropertyClientExample(cmd *cobra.Command, args []string) { log.Printf("sent: %x", mReadProperty) nBytes, remoteAddr, err := listenConn.ReadFrom(replyRaw) + if err != nil { + log.Fatalf("error reading incoming packet: %v\n", err) + } log.Printf("read %d bytes from %s: %x\n", nBytes, remoteAddr, replyRaw[:nBytes]) @@ -87,7 +91,7 @@ func ReadPropertyClientExample(cmd *cobra.Command, args []string) { } log.Printf( - "decoded CACK reply:\n\tObject Type: %d\n\tInstance Id: %d\n\tProperty Id: %d\n\tValue: %f\n", + "decoded CACK reply:\n\tObject Type: %d\n\tInstance Id: %d\n\tProperty Id: %d\n\tValue: %v\f", decodedCACK.ObjectType, decodedCACK.InstanceId, decodedCACK.PropertyId, decodedCACK.PresentValue, ) diff --git a/go.mod b/go.mod index 5c5387c..b231425 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.19 require ( github.com/google/go-cmp v0.5.0 + github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.7.0 ) diff --git a/go.sum b/go.sum index 946150b..b5dd525 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= diff --git a/objects/objects.go b/objects/objects.go index 60d00c4..ebd0589 100644 --- a/objects/objects.go +++ b/objects/objects.go @@ -1,6 +1,9 @@ package objects import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) @@ -33,14 +36,21 @@ const objLenMin int = 2 // UnmarshalBinary sets the values retrieved from byte sequence in a Object frame. func (o *Object) UnmarshalBinary(b []byte) error { if l := len(b); l < objLenMin { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal - binary %x - too short", b), + ) } + o.TagNumber = b[0] >> 4 o.TagClass = common.IntToBool(int(b[0]) & 0x8 >> 3) o.Length = b[0] & 0x7 if l := len(b); l < int(o.Length) { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal object - binary %x - marshal length too short", b), + ) } o.Data = b[1:o.Length] @@ -52,7 +62,7 @@ func (o *Object) UnmarshalBinary(b []byte) error { func (o *Object) MarshalBinary() ([]byte, error) { b := make([]byte, o.MarshalLen()) if err := o.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal object") } return b, nil @@ -61,7 +71,10 @@ func (o *Object) MarshalBinary() ([]byte, error) { // MarshalTo puts the byte sequence in the byte array given as b. func (o *Object) MarshalTo(b []byte) error { if len(b) < o.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal object - binary %x - marshal length too short", b), + ) } b[0] = o.TagNumber<<4 | uint8(common.BoolToInt(o.TagClass))<<3 | o.Length if o.Length > 0 { diff --git a/objects/oid.go b/objects/oid.go index 5301c14..9f6bdc4 100644 --- a/objects/oid.go +++ b/objects/oid.go @@ -3,6 +3,7 @@ package objects import ( "encoding/binary" + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) @@ -16,17 +17,17 @@ func DecObjectIdentifier(rawPayload APDUPayload) (ObjectIdentifier, error) { rawObject, ok := rawPayload.(*Object) if !ok { - return decObjectId, common.ErrWrongPayload + return decObjectId, errors.Wrap(common.ErrWrongPayload, "failed to decode ObjectID") } switch rawObject.TagClass { case true: if rawObject.Length != 4 { - return decObjectId, common.ErrWrongStructure + return decObjectId, errors.Wrap(common.ErrWrongStructure, "failed to decode ObjectID - wrong binary length") } case false: if rawObject.Length != 4 || rawObject.TagNumber != TagBACnetObjectIdentifier { - return decObjectId, common.ErrWrongStructure + return decObjectId, errors.Wrap(common.ErrWrongStructure, "failed to decode ObjectID - wrong tag number") } } diff --git a/objects/primitive.go b/objects/primitive.go index 4a9f737..5268507 100644 --- a/objects/primitive.go +++ b/objects/primitive.go @@ -2,19 +2,27 @@ package objects import ( "encoding/binary" + "fmt" "math" + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) func DecUnisgnedInteger(rawPayload APDUPayload) (uint32, error) { rawObject, ok := rawPayload.(*Object) if !ok { - return 0, common.ErrWrongPayload + return 0, errors.Wrap( + common.ErrWrongPayload, + fmt.Sprintf("failed to decode UnsignedInteger - %v", rawPayload), + ) } if rawObject.TagNumber != TagUnsignedInteger || rawObject.TagClass { - return 0, common.ErrWrongStructure + return 0, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode UnsignedInteger - wrong tag number - %v", rawObject.TagNumber), + ) } switch rawObject.Length { @@ -28,7 +36,10 @@ func DecUnisgnedInteger(rawPayload APDUPayload) (uint32, error) { return binary.BigEndian.Uint32(rawObject.Data), nil } - return 0, common.ErrNotImplemented + return 0, errors.Wrap( + common.ErrNotImplemented, + fmt.Sprintf("failed to decode UnsignedInteger - %v", rawObject.Data), + ) } func EncUnsignedInteger16(value uint16) *Object { @@ -48,11 +59,17 @@ func EncUnsignedInteger16(value uint16) *Object { func DecEnumerated(rawPayload APDUPayload) (uint32, error) { rawObject, ok := rawPayload.(*Object) if !ok { - return 0, common.ErrWrongPayload + return 0, errors.Wrap( + common.ErrWrongPayload, + fmt.Sprintf("failed to decode EnumObject - %v", rawPayload), + ) } if rawObject.TagNumber != TagEnumerated || rawObject.TagClass { - return 0, common.ErrWrongStructure + return 0, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode EnumObject - wrong tag number - %v", rawObject.TagNumber), + ) } switch rawObject.Length { @@ -66,7 +83,10 @@ func DecEnumerated(rawPayload APDUPayload) (uint32, error) { return binary.BigEndian.Uint32(rawObject.Data), nil } - return 0, common.ErrNotImplemented + return 0, errors.Wrap( + common.ErrNotImplemented, + fmt.Sprintf("failed to decode EnumObject - %v", rawObject.Data), + ) } func EncEnumerated(value uint8) *Object { @@ -86,11 +106,17 @@ func EncEnumerated(value uint8) *Object { func DecReal(rawPayload APDUPayload) (float32, error) { rawObject, ok := rawPayload.(*Object) if !ok { - return 0, common.ErrWrongPayload + return 0, errors.Wrap( + common.ErrWrongPayload, + fmt.Sprintf("failed to decode Real - %v", rawPayload), + ) } if rawObject.TagNumber != TagReal { - return 0, common.ErrWrongStructure + return 0, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode real - wrong tag number - %v", rawObject.TagNumber), + ) } return math.Float32frombits(binary.BigEndian.Uint32(rawObject.Data)), nil @@ -113,11 +139,17 @@ func EncReal(value float32) *Object { func DecNull(rawPayload APDUPayload) (bool, error) { rawObject, ok := rawPayload.(*Object) if !ok { - return false, common.ErrWrongPayload + return false, errors.Wrap( + common.ErrWrongPayload, + fmt.Sprintf("failed to decode Null - %v", rawPayload), + ) } if rawObject.TagNumber != TagReal { - return false, common.ErrWrongStructure + return false, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode Null - wrong tag number - %v", rawObject.TagNumber), + ) } return rawObject.TagNumber == TagNull && !rawObject.TagClass && rawObject.Length == 0, nil diff --git a/objects/priority.go b/objects/priority.go index 289e1e3..fda0f73 100644 --- a/objects/priority.go +++ b/objects/priority.go @@ -1,23 +1,34 @@ package objects import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) func DecPriority(rawPayload APDUPayload) (uint8, error) { rawObject, ok := rawPayload.(*Object) if !ok { - return 0, common.ErrWrongPayload + return 0, errors.Wrap( + common.ErrWrongPayload, + fmt.Sprintf("failed to decode Priority Object - %v", rawPayload), + ) } switch rawObject.TagClass { case true: if rawObject.Length != 1 { - return 0, common.ErrWrongStructure + return 0, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode Priority Object - wrong binary length - %x", rawObject.Data),) } case false: if rawObject.Length != 1 || !rawObject.TagClass { - return 0, common.ErrWrongStructure + return 0, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode Priority Object - wrong tag number - %v", rawObject.TagNumber), + ) } } diff --git a/objects/property.go b/objects/property.go index beca247..fd15e60 100644 --- a/objects/property.go +++ b/objects/property.go @@ -1,23 +1,35 @@ package objects import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) func DecPropertyIdentifier(rawPayload APDUPayload) (uint8, error) { rawObject, ok := rawPayload.(*Object) if !ok { - return 0, common.ErrWrongPayload + return 0, errors.Wrap( + common.ErrWrongPayload, + fmt.Sprintf("failed to decode PropertyID - %v", rawPayload), + ) } switch rawObject.TagClass { case true: if rawObject.Length != 1 { - return 0, common.ErrWrongStructure + return 0, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode PropertyID - wrong binary length - %x", rawObject.Data), + ) } case false: if rawObject.Length != 1 || !rawObject.TagClass { - return 0, common.ErrWrongStructure + return 0, errors.Wrap( + common.ErrWrongStructure, + fmt.Sprintf("failed to decode PropertyID - wrong tag number - %v", rawObject.TagNumber), + ) } } diff --git a/objects/tags.go b/objects/tags.go index de161c7..aebdf7c 100644 --- a/objects/tags.go +++ b/objects/tags.go @@ -1,6 +1,9 @@ package objects import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) @@ -20,14 +23,20 @@ func NewNamedTag(number uint8, class bool, name uint8) *NamedTag { func (n *NamedTag) UnmarshalBinary(b []byte) error { if l := len(b); l < objLenMin { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal NamedTag - binary too short - %x", b), + ) } n.TagNumber = b[0] >> 4 n.TagClass = common.IntToBool(int(b[0]) & 0x8 >> 3) n.Name = b[0] & 0x7 if l := len(b); l < 1 { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal NamedTag - missing data - %v", n), + ) } return nil @@ -36,7 +45,7 @@ func (n *NamedTag) UnmarshalBinary(b []byte) error { func (n *NamedTag) MarshalBinary() ([]byte, error) { b := make([]byte, n.MarshalLen()) if err := n.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary") } return b, nil @@ -44,7 +53,7 @@ func (n *NamedTag) MarshalBinary() ([]byte, error) { func (n *NamedTag) MarshalTo(b []byte) error { if len(b) < n.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap(common.ErrTooShortToMarshalBinary, "failed to marshall NamedTag - marshal length too short") } b[0] = n.TagNumber<<4 | uint8(common.BoolToInt(n.TagClass))<<3 | n.Name @@ -58,7 +67,7 @@ func (n *NamedTag) MarshalLen() int { func DecOpeningTab(rawPayload APDUPayload) (bool, error) { rawTag, ok := rawPayload.(*NamedTag) if !ok { - return false, common.ErrWrongPayload + return false, errors.Wrap(common.ErrWrongPayload, "failed to decode OpeningTab") } return rawTag.Name == 0x6 && rawTag.TagClass, nil } @@ -76,7 +85,7 @@ func EncOpeningTag(tagN uint8) *NamedTag { func DecClosingTab(rawPayload APDUPayload) (bool, error) { rawTag, ok := rawPayload.(*NamedTag) if !ok { - return false, common.ErrWrongPayload + return false, errors.Wrap(common.ErrWrongPayload, "failed to decode ClosingTab") } return rawTag.Name == 0x7 && rawTag.TagClass, nil } diff --git a/parsing.go b/parsing.go index 33f4c38..ada6cab 100644 --- a/parsing.go +++ b/parsing.go @@ -1,6 +1,9 @@ package bacnet import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/plumbing" "github.com/ulbios/bacnet/services" @@ -15,7 +18,10 @@ func combine(t, s uint8) uint16 { // Parse decodes the given bytes. func Parse(b []byte) (plumbing.BACnet, error) { if len(b) < bacnetLenMin { - return nil, common.ErrTooShortToParse + return nil, errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("Parsing length %d", len(b)), + ) } var bvlc plumbing.BVLC @@ -25,12 +31,12 @@ func Parse(b []byte) (plumbing.BACnet, error) { offset := 0 if err := bvlc.UnmarshalBinary(b); err != nil { - return nil, err + return nil, errors.Wrap(err, fmt.Sprintf("Parsing BVLC %x", b)) } offset += bvlc.MarshalLen() if err := npdu.UnmarshalBinary(b[offset:]); err != nil { - return nil, err + return nil, errors.Wrap(err, fmt.Sprintf("Parsing NPDU %x", b[offset:])) } offset += npdu.MarshalLen() @@ -60,11 +66,17 @@ func Parse(b []byte) (plumbing.BACnet, error) { case combine(plumbing.Error<<4, 0): bacnet = services.NewError(&bvlc, &npdu) default: - return nil, common.ErrNotImplemented + return nil, errors.Wrap( + common.ErrNotImplemented, + fmt.Sprintf("Parsing service: %x", c), + ) } if err := bacnet.UnmarshalBinary(b); err != nil { - return nil, err + return nil, errors.Wrap( + err, + fmt.Sprintf("Parsing BACnet %x", b[offset:]), + ) } return bacnet, nil diff --git a/plumbing/apdu.go b/plumbing/apdu.go index ac05171..add4a94 100644 --- a/plumbing/apdu.go +++ b/plumbing/apdu.go @@ -1,6 +1,9 @@ package plumbing import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/objects" ) @@ -28,14 +31,16 @@ func NewAPDU(t, s uint8, objs []objects.APDUPayload) *APDU { // UnmarshalBinary sets the values retrieved from byte sequence in a APDU frame. func (a *APDU) UnmarshalBinary(b []byte) error { if l := len(b); l < a.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal APDU %v - marshal length too short", a.Type), + ) } a.Type = b[0] >> 4 a.Flags = b[0] & 0x7 var offset int = 1 - switch a.Type { case UnConfirmedReq: a.Service = b[offset] @@ -134,7 +139,10 @@ func (a *APDU) UnmarshalBinary(b []byte) error { // MarshalTo puts the byte sequence in the byte array given as b. func (a *APDU) MarshalTo(b []byte) error { if len(b) < a.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal APDU %v - marshal length too short", a.Type), + ) } var offset int = 0 @@ -149,14 +157,17 @@ func (a *APDU) MarshalTo(b []byte) error { for _, o := range a.Objects { ob, err := o.MarshalBinary() if err != nil { - return err + return errors.Wrap(err, "failed to marshal UnconfirmedReq") } copy(b[offset:offset+o.MarshalLen()], ob) offset += int(o.MarshalLen()) if offset > a.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal UnconfirmedReq %v - marshal length too short", a.Type), + ) } } } @@ -169,14 +180,17 @@ func (a *APDU) MarshalTo(b []byte) error { for _, o := range a.Objects { ob, err := o.MarshalBinary() if err != nil { - return err + return errors.Wrap(err, "failed to marshal CACK/SACK/ERROR") } copy(b[offset:offset+o.MarshalLen()], ob) offset += o.MarshalLen() if offset > a.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal CACK/SACK/ERROR %x - binary overflow", b), + ) } } } @@ -191,14 +205,17 @@ func (a *APDU) MarshalTo(b []byte) error { for _, o := range a.Objects { ob, err := o.MarshalBinary() if err != nil { - return err + return errors.Wrap(err, "failed to marshal ConfirmedReq") } copy(b[offset:offset+o.MarshalLen()], ob) offset += o.MarshalLen() if offset > a.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal ConfirmedReq %v - binary overflow", a.Type), + ) } } } diff --git a/plumbing/bvlc.go b/plumbing/bvlc.go index 8d4829c..f537d38 100644 --- a/plumbing/bvlc.go +++ b/plumbing/bvlc.go @@ -2,7 +2,9 @@ package plumbing import ( "encoding/binary" + "fmt" + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) @@ -34,7 +36,10 @@ func NewBVLC(f uint8) *BVLC { // UnmarshalBinary sets the values retrieved from byte sequence in a BVLC frame. func (bvlc *BVLC) UnmarshalBinary(b []byte) error { if l := len(b); l < bvlc.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal BVLC %v - binary too short", bvlc.Function), + ) } bvlc.Type = b[0] bvlc.Function = b[1] @@ -47,7 +52,7 @@ func (bvlc *BVLC) UnmarshalBinary(b []byte) error { func (bvlc *BVLC) MarshalBinary() ([]byte, error) { b := make([]byte, bvlc.MarshalLen()) if err := bvlc.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary") } return b, nil @@ -63,7 +68,10 @@ func (bvlc *BVLC) MarshalLen() int { // MarshalTo puts the byte sequence in the byte array given as b. func (bvlc *BVLC) MarshalTo(b []byte) error { if len(b) < bvlc.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal BVLC %v - marshal length too short", bvlc.Function), + ) } b[0] = byte(bvlc.Type) b[1] = byte(bvlc.Function) diff --git a/plumbing/npdu.go b/plumbing/npdu.go index 0d9bc6f..7059c10 100644 --- a/plumbing/npdu.go +++ b/plumbing/npdu.go @@ -2,7 +2,9 @@ package plumbing import ( "encoding/binary" + "fmt" + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" ) @@ -35,7 +37,10 @@ func (n *NPDU) SetControlFlags(nsduContain bool, dstSpecifier bool, srcSpecifier // UnmarshalBinary sets the values retrieved from byte sequence in a NPDU frame. func (n *NPDU) UnmarshalBinary(b []byte) error { if l := len(b); l < n.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal NPDU %v - marshal length too short", n), + ) } n.Version = b[0] n.Control = b[1] @@ -51,7 +56,10 @@ func (n *NPDU) UnmarshalBinary(b []byte) error { // MarshalTo puts the byte sequence in the byte array given as b. func (n *NPDU) MarshalTo(b []byte) error { if len(b) < n.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshall NPDU %v - marshal length too short", n), + ) } b[0] = n.Version b[1] = n.Control diff --git a/services/cack.go b/services/cack.go index d1919b0..fc8e29c 100644 --- a/services/cack.go +++ b/services/cack.go @@ -1,6 +1,9 @@ package services import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/objects" "github.com/ulbios/bacnet/plumbing" @@ -22,13 +25,11 @@ type ComplexACKDec struct { func ComplexACKObjects(objectType uint16, instN uint32, propertyId uint8, value float32) []objects.APDUPayload { objs := make([]objects.APDUPayload, 5) - objs[0] = objects.EncObjectIdentifier(true, 0, objectType, instN) objs[1] = objects.EncPropertyIdentifier(true, 1, propertyId) objs[2] = objects.EncOpeningTag(3) objs[3] = objects.EncReal(value) objs[4] = objects.EncClosingTag(3) - return objs } @@ -41,28 +42,39 @@ func NewComplexACK(bvlc *plumbing.BVLC, npdu *plumbing.NPDU) *ComplexACK { objects.ObjectTypeAnalogOutput, 1, objects.PropertyIdPresentValue, 0)), } c.SetLength() - return c } func (c *ComplexACK) UnmarshalBinary(b []byte) error { if l := len(b); l < c.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal CACK %v - marshal length too short", c), + ) } var offset int = 0 if err := c.BVLC.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling CACK %v", c), + ) } offset += c.BVLC.MarshalLen() if err := c.NPDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling CACK %v", c), + ) } offset += c.NPDU.MarshalLen() if err := c.APDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling CACK %v", c), + ) } return nil @@ -71,28 +83,31 @@ func (c *ComplexACK) UnmarshalBinary(b []byte) error { func (c *ComplexACK) MarshalBinary() ([]byte, error) { b := make([]byte, c.MarshalLen()) if err := c.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary - marshal length too short") } return b, nil } func (c *ComplexACK) MarshalTo(b []byte) error { if len(b) < c.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal CACK %x - marshal length too short", b), + ) } var offset = 0 if err := c.BVLC.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling CACK") } offset += c.BVLC.MarshalLen() if err := c.NPDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling CACK") } offset += c.NPDU.MarshalLen() if err := c.APDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling CACK") } return nil @@ -114,7 +129,10 @@ func (c *ComplexACK) Decode() (ComplexACKDec, error) { decCACK := ComplexACKDec{} if len(c.APDU.Objects) != 3 { - return decCACK, common.ErrWrongObjectCount + return decCACK, errors.Wrap( + common.ErrWrongObjectCount, + fmt.Sprintf("failed to decode CACK - objects count: %d", len(c.APDU.Objects)), + ) } for i, obj := range c.APDU.Objects { @@ -122,20 +140,20 @@ func (c *ComplexACK) Decode() (ComplexACKDec, error) { case 0: objId, err := objects.DecObjectIdentifier(obj) if err != nil { - return decCACK, err + return decCACK, errors.Wrap(err, "decoding CACK") } decCACK.ObjectType = objId.ObjectType decCACK.InstanceId = objId.InstanceNumber case 1: propId, err := objects.DecPropertyIdentifier(obj) if err != nil { - return decCACK, err + return decCACK, errors.Wrap(err, "decoding CACK") } decCACK.PropertyId = propId case 2: value, err := objects.DecReal(obj) if err != nil { - return decCACK, err + return decCACK, errors.Wrap(err, "decoding CACK") } decCACK.PresentValue = value } diff --git a/services/err.go b/services/err.go index f5d4383..959c4db 100644 --- a/services/err.go +++ b/services/err.go @@ -1,6 +1,9 @@ package services import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/objects" "github.com/ulbios/bacnet/plumbing" @@ -44,22 +47,34 @@ func NewError(bvlc *plumbing.BVLC, npdu *plumbing.NPDU) *Error { // UnmarshalBinary sets the values retrieved from byte sequence in a UnconfirmedIAm frame. func (e *Error) UnmarshalBinary(b []byte) error { if l := len(b); l < e.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal Error %v - marshal length too short", e), + ) } var offset int = 0 if err := e.BVLC.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling Error %v", e), + ) } offset += e.BVLC.MarshalLen() if err := e.NPDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling Error %v", e), + ) } offset += e.NPDU.MarshalLen() if err := e.APDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling Error %v", e), + ) } return nil @@ -69,7 +84,7 @@ func (e *Error) UnmarshalBinary(b []byte) error { func (e *Error) MarshalBinary() ([]byte, error) { b := make([]byte, e.MarshalLen()) if err := e.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary - marshal length too short") } return b, nil } @@ -77,21 +92,24 @@ func (e *Error) MarshalBinary() ([]byte, error) { // MarshalTo puts the byte sequence in the byte array given as b. func (e *Error) MarshalTo(b []byte) error { if len(b) < e.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal Error %x - marshal length too short", b), + ) } var offset = 0 if err := e.BVLC.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling Error") } offset += e.BVLC.MarshalLen() if err := e.NPDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling Error") } offset += e.NPDU.MarshalLen() if err := e.APDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling Error") } return nil @@ -115,7 +133,10 @@ func (e *Error) Decode() (ErrorDec, error) { decErr := ErrorDec{} if len(e.APDU.Objects) != 2 { - return decErr, common.ErrWrongObjectCount + return decErr, errors.Wrap( + common.ErrWrongObjectCount, + fmt.Sprintf("failed to decode Error - object count: %d", len(e.APDU.Objects)), + ) } for i, obj := range e.APDU.Objects { @@ -123,13 +144,13 @@ func (e *Error) Decode() (ErrorDec, error) { case 0: errClass, err := objects.DecEnumerated(obj) if err != nil { - return decErr, err + return decErr, errors.Wrap(err, "failed to decode Enumerated Object") } decErr.ErrorClass = uint8(errClass) case 1: errCode, err := objects.DecEnumerated(obj) if err != nil { - return decErr, err + return decErr, errors.Wrap(err, "failed to decode Enumerated Object") } decErr.ErrorCode = uint8(errCode) } diff --git a/services/iam.go b/services/iam.go index dc8910b..1f2d148 100644 --- a/services/iam.go +++ b/services/iam.go @@ -1,6 +1,9 @@ package services import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/objects" "github.com/ulbios/bacnet/plumbing" @@ -48,22 +51,34 @@ func NewUnconfirmedIAm(bvlc *plumbing.BVLC, npdu *plumbing.NPDU) *UnconfirmedIAm // UnmarshalBinary sets the values retrieved from byte sequence in a UnconfirmedIAm frame. func (u *UnconfirmedIAm) UnmarshalBinary(b []byte) error { if l := len(b); l < u.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal UnconfirmedIAm %x - marshal length too short", b), + ) } var offset int = 0 if err := u.BVLC.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling UnconfirmedIAm %v", u), + ) } offset += u.BVLC.MarshalLen() if err := u.NPDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling UnconfirmedIAm %v", u), + ) } offset += u.NPDU.MarshalLen() if err := u.APDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling UnconfirmedIAm %v", u), + ) } return nil @@ -73,7 +88,7 @@ func (u *UnconfirmedIAm) UnmarshalBinary(b []byte) error { func (u *UnconfirmedIAm) MarshalBinary() ([]byte, error) { b := make([]byte, u.MarshalLen()) if err := u.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary - marshal length too short") } return b, nil } @@ -81,21 +96,24 @@ func (u *UnconfirmedIAm) MarshalBinary() ([]byte, error) { // MarshalTo puts the byte sequence in the byte array given as b. func (u *UnconfirmedIAm) MarshalTo(b []byte) error { if len(b) < u.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal UnconfirmedIAm %x - marshal length too short", b), + ) } var offset = 0 if err := u.BVLC.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling UnconfirmedIAm") } offset += u.BVLC.MarshalLen() if err := u.NPDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling UnconfirmedIAm") } offset += u.NPDU.MarshalLen() if err := u.APDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling UnconfirmedIAm") } return nil @@ -119,7 +137,10 @@ func (u *UnconfirmedIAm) Decode() (UnconfirmedIAmDec, error) { decIAm := UnconfirmedIAmDec{} if len(u.APDU.Objects) != 4 { - return decIAm, common.ErrWrongObjectCount + return decIAm, errors.Wrap( + common.ErrWrongObjectCount, + fmt.Sprintf("failed to decode UnconfirmedIAm %d - wrong object count", len(u.APDU.Objects)), + ) } for i, obj := range u.APDU.Objects { @@ -127,25 +148,25 @@ func (u *UnconfirmedIAm) Decode() (UnconfirmedIAmDec, error) { case 0: objId, err := objects.DecObjectIdentifier(obj) if err != nil { - return decIAm, err + return decIAm, errors.Wrap(err, "decoding UnconfirmedIAm") } decIAm.DeviceId = objId.InstanceNumber case 1: maxLen, err := objects.DecUnisgnedInteger(obj) if err != nil { - return decIAm, err + return decIAm, errors.Wrap(err, "decoding UnconfirmedIAm") } decIAm.MaxAPDULength = uint16(maxLen) case 2: segSupport, err := objects.DecEnumerated(obj) if err != nil { - return decIAm, err + return decIAm, errors.Wrap(err, "decoding UnconfirmedIAm") } decIAm.SegmentationSupported = uint8(segSupport) case 3: vendorId, err := objects.DecUnisgnedInteger(obj) if err != nil { - return decIAm, err + return decIAm, errors.Wrap(err, "decoding UnconfirmedIAm") } decIAm.VendorId = uint16(vendorId) } diff --git a/services/rp.go b/services/rp.go index b6eb281..b348b63 100644 --- a/services/rp.go +++ b/services/rp.go @@ -1,6 +1,9 @@ package services import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/objects" "github.com/ulbios/bacnet/plumbing" @@ -43,22 +46,34 @@ func NewConfirmedReadProperty(bvlc *plumbing.BVLC, npdu *plumbing.NPDU) *Confirm func (c *ConfirmedReadProperty) UnmarshalBinary(b []byte) error { if l := len(b); l < c.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal ConfirmedRP %v - marshal length too short", c), + ) } var offset int = 0 if err := c.BVLC.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling ConfirmedRP %v", c), + ) } offset += c.BVLC.MarshalLen() if err := c.NPDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling ConfirmedRP %v", c), + ) } offset += c.NPDU.MarshalLen() if err := c.APDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling ConfirmedRP %v", c), + ) } return nil @@ -67,28 +82,31 @@ func (c *ConfirmedReadProperty) UnmarshalBinary(b []byte) error { func (c *ConfirmedReadProperty) MarshalBinary() ([]byte, error) { b := make([]byte, c.MarshalLen()) if err := c.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary - marshal length too short") } return b, nil } func (c *ConfirmedReadProperty) MarshalTo(b []byte) error { if len(b) < c.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal ConfirmedRP %x - marshal length too short", b), + ) } var offset = 0 if err := c.BVLC.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "failed to marshal ConfirmedRP") } offset += c.BVLC.MarshalLen() if err := c.NPDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "failed to marshal ConfirmedRP") } offset += c.NPDU.MarshalLen() if err := c.APDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "failed to marshal ConfirmedRP") } return nil @@ -110,7 +128,10 @@ func (c *ConfirmedReadProperty) Decode() (ConfirmedReadPropertyDec, error) { decCRP := ConfirmedReadPropertyDec{} if len(c.APDU.Objects) != 2 { - return decCRP, common.ErrWrongObjectCount + return decCRP, errors.Wrap( + common.ErrWrongObjectCount, + fmt.Sprintf("failed to decode ConfirmedRP - object count %d", len(c.APDU.Objects)), + ) } for i, obj := range c.APDU.Objects { @@ -118,14 +139,14 @@ func (c *ConfirmedReadProperty) Decode() (ConfirmedReadPropertyDec, error) { case 0: objId, err := objects.DecObjectIdentifier(obj) if err != nil { - return decCRP, err + return decCRP, errors.Wrap(err, "decoding ConfirmedRP") } decCRP.ObjectType = objId.ObjectType decCRP.InstanceId = objId.InstanceNumber case 1: propId, err := objects.DecPropertyIdentifier(obj) if err != nil { - return decCRP, err + return decCRP, errors.Wrap(err, "decoding ConfirmedRP") } decCRP.PropertyId = propId } diff --git a/services/sack.go b/services/sack.go index 28160c2..79d2f26 100644 --- a/services/sack.go +++ b/services/sack.go @@ -1,6 +1,9 @@ package services import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/plumbing" ) @@ -26,22 +29,34 @@ func NewSimpleACK(bvlc *plumbing.BVLC, npdu *plumbing.NPDU) *SimpleACK { func (s *SimpleACK) UnmarshalBinary(b []byte) error { if l := len(b); l < s.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal SACK %v - marshal length too short", s), + ) } var offset int = 0 if err := s.BVLC.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling SACK %v", s), + ) } offset += s.BVLC.MarshalLen() if err := s.NPDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling SACK %v", s), + ) } offset += s.NPDU.MarshalLen() if err := s.APDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling SACK %v", s), + ) } return nil @@ -50,28 +65,31 @@ func (s *SimpleACK) UnmarshalBinary(b []byte) error { func (s *SimpleACK) MarshalBinary() ([]byte, error) { b := make([]byte, s.MarshalLen()) if err := s.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary - marshal length too short") } return b, nil } func (s *SimpleACK) MarshalTo(b []byte) error { if len(b) < s.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal SACK %x - marshal length too short", b), + ) } var offset = 0 if err := s.BVLC.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling SACK") } offset += s.BVLC.MarshalLen() if err := s.NPDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling SACK") } offset += s.NPDU.MarshalLen() if err := s.APDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling SACK") } return nil diff --git a/services/whois.go b/services/whois.go index f70988b..8b69b18 100644 --- a/services/whois.go +++ b/services/whois.go @@ -1,6 +1,9 @@ package services import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/plumbing" ) @@ -26,22 +29,34 @@ func NewUnconfirmedWhoIs(bvlc *plumbing.BVLC, npdu *plumbing.NPDU) *UnconfirmedW // UnmarshalBinary sets the values retrieved from byte sequence in a UnconfirmedWhoIs frame. func (u *UnconfirmedWhoIs) UnmarshalBinary(b []byte) error { if l := len(b); l < u.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal UnconfirmedWhoIs %v - marshal length too short", u), + ) } var offset int = 0 if err := u.BVLC.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling UnconfirmedWhoIs %v", u), + ) } offset += u.BVLC.MarshalLen() if err := u.NPDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling UnconfirmedWhoIs %v", u), + ) } offset += u.NPDU.MarshalLen() if err := u.APDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling UnconfirmedWhoIs %v", u), + ) } return nil @@ -51,7 +66,7 @@ func (u *UnconfirmedWhoIs) UnmarshalBinary(b []byte) error { func (u *UnconfirmedWhoIs) MarshalBinary() ([]byte, error) { b := make([]byte, u.MarshalLen()) if err := u.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary - marshal length too short") } return b, nil } @@ -59,21 +74,24 @@ func (u *UnconfirmedWhoIs) MarshalBinary() ([]byte, error) { // MarshalTo puts the byte sequence in the byte array given as b. func (u *UnconfirmedWhoIs) MarshalTo(b []byte) error { if len(b) < u.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal UnconfirmedWhoIs %x - marshal length too short", b), + ) } var offset = 0 if err := u.BVLC.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling UnconfirmedWhoIs") } offset += u.BVLC.MarshalLen() if err := u.NPDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling UnconfirmedWhoIs") } offset += u.NPDU.MarshalLen() if err := u.APDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "marshalling UnconfirmedWhoIs") } return nil diff --git a/services/wp.go b/services/wp.go index 33a6c37..022fef6 100644 --- a/services/wp.go +++ b/services/wp.go @@ -1,6 +1,9 @@ package services import ( + "fmt" + + "github.com/pkg/errors" "github.com/ulbios/bacnet/common" "github.com/ulbios/bacnet/objects" "github.com/ulbios/bacnet/plumbing" @@ -48,22 +51,34 @@ func NewConfirmedWriteProperty(bvlc *plumbing.BVLC, npdu *plumbing.NPDU) *Confir func (c *ConfirmedWriteProperty) UnmarshalBinary(b []byte) error { if l := len(b); l < c.MarshalLen() { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("failed to unmarshal ConfirmedWP %v - marshal length too short", c), + ) } var offset int = 0 if err := c.BVLC.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling ConfirmedWP %v", c), + ) } offset += c.BVLC.MarshalLen() if err := c.NPDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling ConfirmedWP %v", c), + ) } offset += c.NPDU.MarshalLen() if err := c.APDU.UnmarshalBinary(b[offset:]); err != nil { - return common.ErrTooShortToParse + return errors.Wrap( + common.ErrTooShortToParse, + fmt.Sprintf("unmarshalling ConfirmedWP %v", c), + ) } return nil @@ -72,28 +87,31 @@ func (c *ConfirmedWriteProperty) UnmarshalBinary(b []byte) error { func (c *ConfirmedWriteProperty) MarshalBinary() ([]byte, error) { b := make([]byte, c.MarshalLen()) if err := c.MarshalTo(b); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to marshal binary - marshal length too short") } return b, nil } func (c *ConfirmedWriteProperty) MarshalTo(b []byte) error { if len(b) < c.MarshalLen() { - return common.ErrTooShortToMarshalBinary + return errors.Wrap( + common.ErrTooShortToMarshalBinary, + fmt.Sprintf("failed to marshal ConfirmedWP %x - marshal length too short", b), + ) } var offset = 0 if err := c.BVLC.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "failed to marshal ConfirmedWP") } offset += c.BVLC.MarshalLen() if err := c.NPDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "failed to marshal ConfirmedWP") } offset += c.NPDU.MarshalLen() if err := c.APDU.MarshalTo(b[offset:]); err != nil { - return err + return errors.Wrap(err, "failed to marshal ConfirmedWP") } return nil @@ -115,7 +133,10 @@ func (c *ConfirmedWriteProperty) Decode() (ConfirmedWritePropertyDec, error) { decCWP := ConfirmedWritePropertyDec{} if len(c.APDU.Objects) != 5 { - return decCWP, common.ErrWrongObjectCount + return decCWP, errors.Wrap( + common.ErrWrongObjectCount, + fmt.Sprintf("failed to decode ConfirmedWP - object count %d", len(c.APDU.Objects)), + ) } for i, obj := range c.APDU.Objects { @@ -123,26 +144,26 @@ func (c *ConfirmedWriteProperty) Decode() (ConfirmedWritePropertyDec, error) { case 0: objId, err := objects.DecObjectIdentifier(obj) if err != nil { - return decCWP, err + return decCWP, errors.Wrap(err, "decoding ConfirmedWP") } decCWP.ObjectType = objId.ObjectType decCWP.InstanceId = objId.InstanceNumber case 1: propId, err := objects.DecPropertyIdentifier(obj) if err != nil { - return decCWP, err + return decCWP, errors.Wrap(err, "decoding ConfirmedWP") } decCWP.PropertyId = propId case 2: value, err := objects.DecReal(obj) if err != nil { - return decCWP, err + return decCWP, errors.Wrap(err, "decoding ConfirmedWP") } decCWP.Value = value case 4: priority, err := objects.DecPriority(obj) if err != nil { - return decCWP, err + return decCWP, errors.Wrap(err, "decoding ConfirmedWP") } decCWP.Priority = priority }