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 {
56 vppRequestHeaderSize = 10 // size of a VPP request header
57 vppReplyHeaderSize = 6 // size of a VPP reply header
58 vppEventHeaderSize = 6 // size of a VPP event header
59 vppOtherHeaderSize = 2 // size of the header of other VPP messages
62 // EncodeMsg encodes provided `Message` structure into its binary-encoded data representation.
63 func (*MsgCodec) EncodeMsg(msg api.Message, msgID uint16) ([]byte, error) {
65 return nil, errors.New("nil message passed in")
68 buf := new(bytes.Buffer)
70 // encode message header
71 var header interface{}
72 if msg.GetMessageType() == api.RequestMessage {
73 header = &VppRequestHeader{VlMsgID: msgID}
74 } else if msg.GetMessageType() == api.ReplyMessage {
75 header = &VppReplyHeader{VlMsgID: msgID}
76 } else if msg.GetMessageType() == api.EventMessage {
77 header = &VppEventHeader{VlMsgID: msgID}
79 header = &VppOtherHeader{VlMsgID: msgID}
81 err := struc.Pack(buf, header)
83 return nil, fmt.Errorf("unable to encode message: header: %v, error %v", header, err)
86 // encode message content
87 if reflect.Indirect(reflect.ValueOf(msg)).NumField() > 0 {
88 err := struc.Pack(buf, msg)
90 return nil, fmt.Errorf("unable to encode message: header %v, error %v", header, err)
94 return buf.Bytes(), nil
97 // DecodeMsg decodes binary-encoded data of a message into provided `Message` structure.
98 func (*MsgCodec) DecodeMsg(data []byte, msg api.Message) error {
100 return errors.New("nil message passed in")
103 buf := bytes.NewReader(data)
105 // check which header is expected
106 var header interface{}
107 if msg.GetMessageType() == api.RequestMessage {
108 header = &VppRequestHeader{}
109 } else if msg.GetMessageType() == api.ReplyMessage {
110 header = &VppReplyHeader{}
111 } else if msg.GetMessageType() == api.EventMessage {
112 header = &VppEventHeader{}
114 header = &VppOtherHeader{}
117 // decode message header
118 err := struc.Unpack(buf, header)
120 return fmt.Errorf("unable to decode message: data %v, error %v", data, err)
123 // get rid of the message header
124 if msg.GetMessageType() == api.RequestMessage {
125 buf = bytes.NewReader(data[vppRequestHeaderSize:])
126 } else if msg.GetMessageType() == api.ReplyMessage {
127 buf = bytes.NewReader(data[vppReplyHeaderSize:])
128 } else if msg.GetMessageType() == api.EventMessage {
129 buf = bytes.NewReader(data[vppEventHeaderSize:])
131 buf = bytes.NewReader(data[vppOtherHeaderSize:])
134 // decode message content
135 err = struc.Unpack(buf, msg)
137 return fmt.Errorf("unable to decode message: data %v, error %v", data, err)