add missing implementation for proxy
[govpp.git] / proxy / client.go
1 package proxy
2
3 import (
4         "fmt"
5         "log"
6         "net/rpc"
7         "reflect"
8         "time"
9
10         "git.fd.io/govpp.git/api"
11 )
12
13 type Client struct {
14         serverAddr string
15         rpc        *rpc.Client
16 }
17
18 // Connect dials remote proxy server on given address and
19 // returns new client if successful.
20 func Connect(addr string) (*Client, error) {
21         client, err := rpc.DialHTTP("tcp", addr)
22         if err != nil {
23                 return nil, fmt.Errorf("connection error:%v", err)
24         }
25         c := &Client{
26                 serverAddr: addr,
27                 rpc:        client,
28         }
29         return c, nil
30 }
31
32 // NewStatsClient returns new StatsClient which implements api.StatsProvider.
33 func (c *Client) NewStatsClient() (*StatsClient, error) {
34         stats := &StatsClient{
35                 rpc: c.rpc,
36         }
37         return stats, nil
38 }
39
40 // NewBinapiClient returns new BinapiClient which implements api.Channel.
41 func (c *Client) NewBinapiClient() (*BinapiClient, error) {
42         binapi := &BinapiClient{
43                 rpc: c.rpc,
44         }
45         return binapi, nil
46 }
47
48 type StatsClient struct {
49         rpc *rpc.Client
50 }
51
52 func (s *StatsClient) GetSystemStats(sysStats *api.SystemStats) error {
53         // we need to start with a clean, zeroed item before decoding
54         // 'cause if the new values are 'zero' for the type, they will be ignored
55         // by the decoder. (i.e the old values will be left unchanged).
56         req := StatsRequest{StatsType: "system"}
57         resp := StatsResponse{SysStats: new(api.SystemStats)}
58         if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
59                 return err
60         }
61         *sysStats = *resp.SysStats
62         return nil
63 }
64
65 func (s *StatsClient) GetNodeStats(nodeStats *api.NodeStats) error {
66         req := StatsRequest{StatsType: "node"}
67         resp := StatsResponse{NodeStats: new(api.NodeStats)}
68         if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
69                 return err
70         }
71         *nodeStats = *resp.NodeStats
72         return nil
73 }
74
75 func (s *StatsClient) GetInterfaceStats(ifaceStats *api.InterfaceStats) error {
76         req := StatsRequest{StatsType: "interface"}
77         resp := StatsResponse{IfaceStats: new(api.InterfaceStats)}
78         if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
79                 return err
80         }
81         *ifaceStats = *resp.IfaceStats
82         return nil
83 }
84
85 func (s *StatsClient) GetErrorStats(errStats *api.ErrorStats) error {
86         req := StatsRequest{StatsType: "error"}
87         resp := StatsResponse{ErrStats: new(api.ErrorStats)}
88         if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
89                 return err
90         }
91         *errStats = *resp.ErrStats
92         return nil
93 }
94
95 func (s *StatsClient) GetBufferStats(bufStats *api.BufferStats) error {
96         req := StatsRequest{StatsType: "buffer"}
97         resp := StatsResponse{BufStats: new(api.BufferStats)}
98         if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil {
99                 return err
100         }
101         *bufStats = *resp.BufStats
102         return nil
103 }
104
105 type BinapiClient struct {
106         rpc *rpc.Client
107 }
108
109 func (b *BinapiClient) SendRequest(msg api.Message) api.RequestCtx {
110         req := &requestCtx{
111                 rpc: b.rpc,
112                 req: msg,
113         }
114         log.Printf("SendRequest: %T %+v", msg, msg)
115         return req
116 }
117
118 type requestCtx struct {
119         rpc *rpc.Client
120         req api.Message
121 }
122
123 func (r *requestCtx) ReceiveReply(msg api.Message) error {
124         req := BinapiRequest{
125                 Msg:      r.req,
126                 ReplyMsg: msg,
127         }
128         resp := BinapiResponse{}
129
130         err := r.rpc.Call("BinapiRPC.Invoke", req, &resp)
131         if err != nil {
132                 return fmt.Errorf("RPC call failed: %v", err)
133         }
134
135         // we set the value of msg to the value from response
136         reflect.ValueOf(msg).Elem().Set(reflect.ValueOf(resp.Msg).Elem())
137
138         return nil
139 }
140
141 func (b *BinapiClient) SendMultiRequest(msg api.Message) api.MultiRequestCtx {
142         req := &multiRequestCtx{
143                 rpc: b.rpc,
144                 req: msg,
145         }
146         log.Printf("SendMultiRequest: %T %+v", msg, msg)
147         return req
148 }
149
150 type multiRequestCtx struct {
151         rpc *rpc.Client
152         req api.Message
153
154         index   int
155         replies []api.Message
156 }
157
158 func (r *multiRequestCtx) ReceiveReply(msg api.Message) (stop bool, err error) {
159         // we call Invoke only on first ReceiveReply
160         if r.index == 0 {
161                 req := BinapiRequest{
162                         Msg:      r.req,
163                         ReplyMsg: msg,
164                         IsMulti:  true,
165                 }
166                 resp := BinapiResponse{}
167
168                 err := r.rpc.Call("BinapiRPC.Invoke", req, &resp)
169                 if err != nil {
170                         return false, fmt.Errorf("RPC call failed: %v", err)
171                 }
172
173                 r.replies = resp.Msgs
174         }
175
176         if r.index >= len(r.replies) {
177                 return true, nil
178         }
179
180         // we set the value of msg to the value from response
181         reflect.ValueOf(msg).Elem().Set(reflect.ValueOf(r.replies[r.index]).Elem())
182         r.index++
183
184         return false, nil
185 }
186
187 func (b *BinapiClient) SubscribeNotification(notifChan chan api.Message, event api.Message) (api.SubscriptionCtx, error) {
188         panic("implement me")
189 }
190
191 func (b *BinapiClient) SetReplyTimeout(timeout time.Duration) {
192         req := BinapiTimeoutRequest{Timeout: timeout}
193         resp := BinapiTimeoutResponse{}
194         if err := b.rpc.Call("BinapiRPC.SetTimeout", req, &resp); err != nil {
195                 log.Println(err)
196         }
197 }
198
199 func (b *BinapiClient) CheckCompatiblity(msgs ...api.Message) error {
200         for _, msg := range msgs {
201                 req := BinapiCompatibilityRequest{
202                         MsgName: msg.GetMessageName(),
203                         Crc:     msg.GetCrcString(),
204                 }
205                 resp := BinapiCompatibilityResponse{}
206                 if err := b.rpc.Call("BinapiRPC.Compatibility", req, &resp); err != nil {
207                         return err
208                 }
209         }
210         return nil
211 }
212
213 func (b *BinapiClient) Close() {
214         b.rpc.Close()
215 }