1 // Copyright (c) 2017 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
23 "git.fd.io/govpp.git/api"
24 "github.com/lunixbochs/struc"
27 // MsgCodec provides encoding and decoding functionality of `api.Message` structs into/from
28 // binary format as accepted by VPP.
29 type MsgCodec struct{}
31 // VppRequestHeader struct contains header fields implemented by all VPP requests.
32 type VppRequestHeader struct {
38 // VppReplyHeader struct contains header fields implemented by all VPP replies.
39 type VppReplyHeader struct {
44 // VppEventHeader struct contains header fields implemented by all VPP events.
45 type VppEventHeader struct {
50 // VppOtherHeader struct contains header fields implemented by other VPP messages (not requests nor replies).
51 type VppOtherHeader struct {
55 // EncodeMsg encodes provided `Message` structure into its binary-encoded data representation.
56 func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) {
58 return nil, errors.New("nil message passed in")
61 // encode message header
62 var header interface{}
63 switch msg.GetMessageType() {
64 case api.RequestMessage:
65 header = &VppRequestHeader{VlMsgID: msgID}
66 case api.ReplyMessage:
67 header = &VppReplyHeader{VlMsgID: msgID}
68 case api.EventMessage:
69 header = &VppEventHeader{VlMsgID: msgID}
71 header = &VppOtherHeader{VlMsgID: msgID}
74 buf := new(bytes.Buffer)
76 // encode message header
77 if err := struc.Pack(buf, header); err != nil {
78 return nil, fmt.Errorf("unable to encode message header: %v, error %v", header, err)
81 // encode message content
82 if reflect.TypeOf(msg).Elem().NumField() > 0 {
83 if err := struc.Pack(buf, msg); err != nil {
84 return nil, fmt.Errorf("unable to encode message data: %v, error %v", header, err)
88 return buf.Bytes(), nil
91 // DecodeMsg decodes binary-encoded data of a message into provided `Message` structure.
92 func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) error {
94 return errors.New("nil message passed in")
97 // check which header is expected
98 var header interface{}
99 switch msg.GetMessageType() {
100 case api.RequestMessage:
101 header = new(VppRequestHeader)
102 case api.ReplyMessage:
103 header = new(VppReplyHeader)
104 case api.EventMessage:
105 header = new(VppEventHeader)
107 header = new(VppOtherHeader)
110 buf := bytes.NewReader(data)
112 // decode message header
113 if err := struc.Unpack(buf, header); err != nil {
114 return fmt.Errorf("unable to decode message header: %+v, error %v", data, err)
117 // decode message content
118 if err := struc.Unpack(buf, msg); err != nil {
119 return fmt.Errorf("unable to decode message data: %+v, error %v", data, err)
125 func (*MsgCodec) DecodeMsgContext(data []byte, msg api.Message) (uint32, error) {
127 return 0, errors.New("nil message passed in")
130 var getContext func() uint32
132 // check which header is expected
133 var header interface{}
134 switch msg.GetMessageType() {
135 case api.RequestMessage:
136 header = new(VppRequestHeader)
137 getContext = func() uint32 { return header.(*VppRequestHeader).Context }
138 case api.ReplyMessage:
139 header = new(VppReplyHeader)
140 getContext = func() uint32 { return header.(*VppReplyHeader).Context }
145 buf := bytes.NewReader(data)
147 // decode message header
148 if err := struc.Unpack(buf, header); err != nil {
149 return 0, fmt.Errorf("decoding message header failed: %v", err)
152 return getContext(), nil