-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.go
More file actions
executable file
·119 lines (101 loc) · 4.06 KB
/
api.go
File metadata and controls
executable file
·119 lines (101 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Package api provides the abstract API for communication with VPP via govpp core using channels,
// without the need of importing the base govpp package.
package api
import (
"reflect"
)
// Message is an interface that is implemented by all VPP Binary API messages generated by the binapi_generator.
type Message interface {
// GetMessageName returns the original VPP name of the message, as defined in the VPP API.
GetMessageName() string
// GetCrcString returns the string with CRC checksum of the message definition (the string represents a hexadecimal number).
GetCrcString() string
}
// DataType is an interface that is implemented by all VPP Binary API data types by the binapi_generator.
type DataType interface {
// GetTypeName returns the original VPP name of the data type, as defined in the VPP API.
GetTypeName() string
// GetCrcString returns the string with CRC checksum of the data type definition (the string represents a hexadecimal number).
GetCrcString() string
}
// ChannelProvider is capable of providing API channels for communication with VPP.
type ChannelProvider interface {
NewApiChannel() Channel
}
// MessageDecoder provides functionality for decoding binary data to generated API messages.
type MessageDecoder interface {
DecodeMsg(data []byte, msg Message) error
}
// Channel is the main communication interface with VPP. It contains two go channels, one for sending the requests
// to VPP and one for receiving the replies from it. The user can access the channels directly, or use the helper methods.
type Channel struct {
ReqChan chan *VppRequest // channel for sending the requests to VPP, closing this channel releases all resources in the ChannelProvider
ReplyChan chan *VppReply // channel where VPP replies are delivered to
Decoder MessageDecoder // used to decode binary data to generated API messages
ID uint32 // unique identifier of the channel, TODO: will be removed
}
// VppRequest is a request that will be sent to VPP.
type VppRequest struct {
Message Message // binary API message to be send to VPP
Multipart bool // true if multipart reply is expected, false otherwise
}
// VppReply is a reply received from VPP.
type VppReply struct {
MessageId uint16 // ID of the message
Data []byte // encoded data with the message - MessageDecoder can be used for decoding
LastPart bool // in case of multipart replies, true if this is the last reply
Error error // in case of error, data is nil and this member contains error description
}
// Close closes the API channel and releases all resouces in the ChannelProvider.
func (ch *Channel) Close() {
close(ch.ReqChan)
}
// SendRequest sends a request to VPP.
func (ch *Channel) SendRequest(msg Message) error {
ch.ReqChan <- &VppRequest{
Message: msg,
}
return nil
}
// SendRequest sends a multipart request (request to which multiple responses are expected) to VPP.
func (ch *Channel) SendMultiRequest(msg Message) error {
ch.ReqChan <- &VppRequest{
Message: msg,
Multipart: true,
}
return nil
}
// ReceiveReply receives a reply from VPP (blocks until a reply is delivered from VPP).
func (ch *Channel) ReceiveReply(msg Message) (Message, error) {
// TODO: timeout
vppReply := <-ch.ReplyChan
if vppReply.Error != nil {
return nil, vppReply.Error
}
// TODO: check message ID before decoding
err := ch.Decoder.DecodeMsg(vppReply.Data, msg)
return msg, err
}
// ReceiveReply receives multiple replies from VPP (blocks until all replies are delivered from VPP).
func (ch *Channel) ReceiveMultiReply(expMsg interface{}) ([]Message, error) {
// TODO: expMsg will be a factory
// TODO: timeout
var err error
var messages []Message
for vppReply := range ch.ReplyChan {
if vppReply.Error != nil {
return nil, vppReply.Error
}
// TODO: check message ID before decoding
msg := reflect.New(reflect.TypeOf(expMsg)).Interface() // TODO: get rid of reflection
err = ch.Decoder.DecodeMsg(vppReply.Data, msg.(Message))
if err != nil {
return nil, err
}
messages = append(messages, msg.(Message))
if vppReply.LastPart {
break
}
}
return messages, err
}