Optimize socketclient adapter and add various code improvements
[govpp.git] / codec / msg_codec.go
index 572e672..3f60cae 100644 (file)
@@ -20,8 +20,9 @@ import (
        "fmt"
        "reflect"
 
-       "git.fd.io/govpp.git/api"
        "github.com/lunixbochs/struc"
+
+       "git.fd.io/govpp.git/api"
 )
 
 // MsgCodec provides encoding and decoding functionality of `api.Message` structs into/from
@@ -53,13 +54,25 @@ type VppOtherHeader struct {
 }
 
 // EncodeMsg encodes provided `Message` structure into its binary-encoded data representation.
-func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) {
+func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) (data []byte, err error) {
        if msg == nil {
                return nil, errors.New("nil message passed in")
        }
 
-       // encode message header
+       // try to recover panic which might possibly occur in struc.Pack call
+       defer func() {
+               if r := recover(); r != nil {
+                       var ok bool
+                       if err, ok = r.(error); !ok {
+                               err = fmt.Errorf("%v", r)
+                       }
+                       err = fmt.Errorf("panic occurred during encoding message %s: %v", msg.GetMessageName(), err)
+               }
+       }()
+
        var header interface{}
+
+       // encode message header
        switch msg.GetMessageType() {
        case api.RequestMessage:
                header = &VppRequestHeader{VlMsgID: msgID}
@@ -75,13 +88,13 @@ func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) {
 
        // encode message header
        if err := struc.Pack(buf, header); err != nil {
-               return nil, fmt.Errorf("unable to encode message header: %v, error %v", header, err)
+               return nil, fmt.Errorf("failed to encode message header: %+v, error: %v", header, err)
        }
 
        // encode message content
        if reflect.TypeOf(msg).Elem().NumField() > 0 {
                if err := struc.Pack(buf, msg); err != nil {
-                       return nil, fmt.Errorf("unable to encode message data: %v, error %v", header, err)
+                       return nil, fmt.Errorf("failed to encode message data: %+v, error: %v", data, err)
                }
        }
 
@@ -89,13 +102,25 @@ func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) {
 }
 
 // DecodeMsg decodes binary-encoded data of a message into provided `Message` structure.
-func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) error {
+func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) (err error) {
        if msg == nil {
                return errors.New("nil message passed in")
        }
 
-       // check which header is expected
+       // try to recover panic which might possibly occur
+       defer func() {
+               if r := recover(); r != nil {
+                       var ok bool
+                       if err, ok = r.(error); !ok {
+                               err = fmt.Errorf("%v", r)
+                       }
+                       err = fmt.Errorf("panic occurred during decoding message %s: %v", msg.GetMessageName(), err)
+               }
+       }()
+
        var header interface{}
+
+       // check which header is expected
        switch msg.GetMessageType() {
        case api.RequestMessage:
                header = new(VppRequestHeader)
@@ -110,13 +135,13 @@ func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) error {
        buf := bytes.NewReader(data)
 
        // decode message header
-       if err := struc.Unpack(buf, header); err != nil {
-               return fmt.Errorf("unable to decode message header: %+v, error %v", data, err)
+       if err = struc.Unpack(buf, header); err != nil {
+               return fmt.Errorf("failed to decode message header: %+v, error: %v", header, err)
        }
 
        // decode message content
        if err := struc.Unpack(buf, msg); err != nil {
-               return fmt.Errorf("unable to decode message data: %+v, error %v", data, err)
+               return fmt.Errorf("failed to decode message data: %+v, error: %v", data, err)
        }
 
        return nil
@@ -127,17 +152,19 @@ func (*MsgCodec) DecodeMsgContext(data []byte, msg api.Message) (uint32, error)
                return 0, errors.New("nil message passed in")
        }
 
+       var header interface{}
        var getContext func() uint32
 
        // check which header is expected
-       var header interface{}
        switch msg.GetMessageType() {
        case api.RequestMessage:
                header = new(VppRequestHeader)
                getContext = func() uint32 { return header.(*VppRequestHeader).Context }
+
        case api.ReplyMessage:
                header = new(VppReplyHeader)
                getContext = func() uint32 { return header.(*VppReplyHeader).Context }
+
        default:
                return 0, nil
        }