trex_rpc_cmd_api.h revision 5cfeb192
1/*
2 Itay Marom
3 Cisco Systems, Inc.
4*/
5
6/*
7Copyright (c) 2015-2015 Cisco Systems, Inc.
8
9Licensed under the Apache License, Version 2.0 (the "License");
10you may not use this file except in compliance with the License.
11You may obtain a copy of the License at
12
13    http://www.apache.org/licenses/LICENSE-2.0
14
15Unless required by applicable law or agreed to in writing, software
16distributed under the License is distributed on an "AS IS" BASIS,
17WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18See the License for the specific language governing permissions and
19limitations under the License.
20*/
21
22#ifndef __TREX_RPC_CMD_API_H__
23#define __TREX_RPC_CMD_API_H__
24
25#include <string>
26#include <vector>
27#include <json/json.h>
28#include <trex_rpc_exception_api.h>
29
30#include "trex_api_class.h"
31
32/**
33 * describe different types of rc for run()
34 */
35typedef enum trex_rpc_cmd_rc_ {
36    TREX_RPC_CMD_OK,
37    TREX_RPC_CMD_PARSE_ERR,
38    TREX_RPC_CMD_EXECUTE_ERR,
39    TREX_RPC_CMD_INTERNAL_ERR
40} trex_rpc_cmd_rc_e;
41
42/**
43 * simple exception for RPC command processing
44 *
45 * @author imarom (23-Aug-15)
46 */
47class TrexRpcCommandException : TrexRpcException {
48public:
49    TrexRpcCommandException(trex_rpc_cmd_rc_e rc) : m_rc(rc) {
50
51    }
52
53    trex_rpc_cmd_rc_e get_rc() {
54        return m_rc;
55
56    }
57
58protected:
59    trex_rpc_cmd_rc_e m_rc;
60};
61
62/**
63 * interface for RPC command
64 *
65 * @author imarom (13-Aug-15)
66 */
67class TrexRpcCommand {
68public:
69
70    /**
71     * method name and params
72     */
73    TrexRpcCommand(const std::string &method_name,
74                   int param_count,
75                   bool needs_ownership,
76                   APIClass::type_e type);
77
78    /**
79     * entry point for executing RPC command
80     *
81     */
82    trex_rpc_cmd_rc_e run(const Json::Value &params, Json::Value &result);
83
84    const std::string &get_name() {
85        return m_name;
86    }
87
88    /**
89     * on test we enable this override
90     *
91     *
92     * @param enable
93     */
94    static void test_set_override_ownership(bool enable) {
95        g_test_override_ownership = enable;
96    }
97
98    static void test_set_override_api(bool enable) {
99        g_test_override_api = enable;
100    }
101
102    virtual ~TrexRpcCommand() {}
103
104protected:
105    static const int PARAM_COUNT_IGNORE = -1;
106
107    /**
108     * different types of fields
109     */
110    enum field_type_e {
111        FIELD_TYPE_BYTE,
112        FIELD_TYPE_UINT16,
113        FIELD_TYPE_UINT32,
114        FIELD_TYPE_UINT64,
115        FIELD_TYPE_INT,
116        FIELD_TYPE_DOUBLE,
117        FIELD_TYPE_UDOUBLE,
118        FIELD_TYPE_BOOL,
119        FIELD_TYPE_STR,
120        FIELD_TYPE_OBJ,
121        FIELD_TYPE_ARRAY
122    };
123
124    /**
125     * implemented by the dervied class
126     *
127     */
128    virtual trex_rpc_cmd_rc_e _run(const Json::Value &params, Json::Value &result) = 0;
129
130    /**
131     * check param count
132     */
133    void check_param_count(const Json::Value &params, int expected, Json::Value &result);
134
135    /**
136     * verify API handler
137     *
138     */
139    void verify_api_handler(const Json::Value &params, Json::Value &result);
140
141    /**
142     * verify ownership
143     *
144     */
145    void verify_ownership(const Json::Value &params, Json::Value &result);
146
147
148    /**
149     * validate port id
150     *
151     */
152    void validate_port_id(uint8_t port_id, Json::Value &result);
153
154    /**
155     * parse functions
156     *
157     */
158    template<typename T> uint8_t parse_byte(const Json::Value &parent, const T &param, Json::Value &result) {
159        check_field_type(parent, param, FIELD_TYPE_BYTE, result);
160        return parent[param].asUInt();
161    }
162
163    template<typename T> uint16_t parse_uint16(const Json::Value &parent, const T &param, Json::Value &result) {
164        check_field_type(parent, param, FIELD_TYPE_UINT16, result);
165        return parent[param].asUInt();
166    }
167
168    template<typename T> uint32_t parse_uint32(const Json::Value &parent, const T &param, Json::Value &result) {
169        check_field_type(parent, param, FIELD_TYPE_UINT32, result);
170        return parent[param].asUInt();
171    }
172
173    template<typename T> uint64_t parse_uint64(const Json::Value &parent, const T &param, Json::Value &result) {
174        check_field_type(parent, param, FIELD_TYPE_UINT64, result);
175        return parent[param].asUInt64();
176    }
177
178    template<typename T> int parse_int(const Json::Value &parent, const T &param, Json::Value &result) {
179        check_field_type(parent, param, FIELD_TYPE_INT, result);
180        return parent[param].asInt();
181    }
182
183    template<typename T> double parse_double(const Json::Value &parent, const T &param, Json::Value &result) {
184        check_field_type(parent, param, FIELD_TYPE_DOUBLE, result);
185        return parent[param].asDouble();
186    }
187
188    template<typename T> double parse_udouble(const Json::Value &parent, const T &param, Json::Value &result) {
189        check_field_type(parent, param, FIELD_TYPE_UDOUBLE, result);
190        return parent[param].asDouble();
191    }
192
193    template<typename T> bool parse_bool(const Json::Value &parent, const T &param, Json::Value &result) {
194        check_field_type(parent, param, FIELD_TYPE_BOOL, result);
195        return parent[param].asBool();
196    }
197
198    template<typename T> const std::string  parse_string(const Json::Value &parent, const T &param, Json::Value &result) {
199        check_field_type(parent, param, FIELD_TYPE_STR, result);
200        return parent[param].asString();
201    }
202
203    template<typename T> const Json::Value & parse_object(const Json::Value &parent, const T &param, Json::Value &result) {
204        check_field_type(parent, param, FIELD_TYPE_OBJ, result);
205        return parent[param];
206    }
207
208    template<typename T> const Json::Value & parse_array(const Json::Value &parent, const T &param, Json::Value &result) {
209        check_field_type(parent, param, FIELD_TYPE_ARRAY, result);
210        return parent[param];
211    }
212
213
214    /**
215     * parse with defaults
216     */
217    template<typename T> uint8_t parse_byte(const Json::Value &parent, const T &param, Json::Value &result, uint8_t def) {
218        /* if not exists - default */
219        if (parent[param] == Json::Value::null) {
220            return def;
221        }
222        return parse_byte(parent, param, result);
223    }
224
225     template<typename T> uint16_t parse_uint16(const Json::Value &parent, const T &param, Json::Value &result, uint16_t def) {
226         /* if not exists - default */
227         if (parent[param] == Json::Value::null) {
228             return def;
229         }
230         return parse_uint16(parent, param, result);
231    }
232
233    template<typename T> uint32_t parse_uint32(const Json::Value &parent, const T &param, Json::Value &result, uint32_t def) {
234        /* if not exists - default */
235        if (parent[param] == Json::Value::null) {
236            return def;
237        }
238        return parse_uint32(parent, param, result);
239    }
240
241    template<typename T> uint64_t parse_uint64(const Json::Value &parent, const T &param, Json::Value &result, uint64_t def) {
242        /* if not exists - default */
243        if (parent[param] == Json::Value::null) {
244            return def;
245        }
246        return parse_uint64(parent, param, result);
247    }
248
249    template<typename T> int parse_int(const Json::Value &parent, const T &param, Json::Value &result, int def) {
250        /* if not exists - default */
251        if (parent[param] == Json::Value::null) {
252            return def;
253        }
254        return parse_int(parent, param, result);
255    }
256
257    template<typename T> double parse_double(const Json::Value &parent, const T &param, Json::Value &result, double def) {
258        /* if not exists - default */
259        if (parent[param] == Json::Value::null) {
260            return def;
261        }
262        return parse_double(parent, param, result);
263    }
264
265    template<typename T> double parse_udouble(const Json::Value &parent, const T &param, Json::Value &result, double def) {
266        /* if not exists - default */
267        if (parent[param] == Json::Value::null) {
268            if (def < 0) {
269                std::stringstream ss;
270                ss << "default value of '" << param << "' is negative (please report)";
271                generate_parse_err(result, ss.str());
272            } else {
273                return def;
274            }
275        }
276        return parse_udouble(parent, param, result);
277    }
278
279    template<typename T> bool parse_bool(const Json::Value &parent, const T &param, Json::Value &result, bool def) {
280        /* if not exists - default */
281        if (parent[param] == Json::Value::null) {
282            return def;
283        }
284        return parse_bool(parent, param, result);
285    }
286
287    template<typename T> const std::string  parse_string(const Json::Value &parent, const T &param, Json::Value &result, const std::string &def) {
288        /* if not exists - default */
289        if (parent[param] == Json::Value::null) {
290            return def;
291        }
292        return parse_string(parent, param, result);
293    }
294
295    template<typename T> const Json::Value & parse_object(const Json::Value &parent, const T &param, Json::Value &result, const Json::Value &def) {
296        /* if not exists - default */
297        if (parent[param] == Json::Value::null) {
298            return def;
299        }
300        return parse_object(parent, param, result);
301    }
302
303    template<typename T> const Json::Value & parse_array(const Json::Value &parent, const T &param, Json::Value &result, const Json::Value &def) {
304        /* if not exists - default */
305        if (parent[param] == Json::Value::null) {
306            return def;
307        }
308        return parse_array(parent, param, result);
309    }
310
311    /* shortcut for parsing port id */
312    uint8_t parse_port(const Json::Value &params, Json::Value &result);
313
314    /**
315     * parse a field from choices
316     *
317     */
318    template<typename T> T parse_choice(const Json::Value &params, const std::string &name, const std::initializer_list<T> choices, Json::Value &result) {
319        const Json::Value &field = params[name];
320
321        if (field == Json::Value::null) {
322            std::stringstream ss;
323            ss << "field '" << name << "' is missing";
324            generate_parse_err(result, ss.str());
325        }
326
327        for (auto x : choices) {
328            if (field == x) {
329                return (x);
330            }
331        }
332
333        std::stringstream ss;
334
335        ss << "field '" << name << "' can only be one of [";
336        for (auto x : choices) {
337            ss << "'" << x << "' ,";
338        }
339
340        std::string s = ss.str();
341        s.pop_back();
342        s.pop_back();
343        s += "]";
344        generate_parse_err(result, s);
345
346        /* dummy return value - does not matter, the above will throw exception */
347        return (*choices.begin());
348    }
349
350    /**
351     * check field type
352     *
353     */
354    void check_field_type(const Json::Value &parent, const std::string &name, field_type_e type, Json::Value &result);
355    void check_field_type(const Json::Value &parent, int index, field_type_e type, Json::Value &result);
356    void check_field_type_common(const Json::Value &field, const std::string &name, field_type_e type, Json::Value &result);
357
358    /**
359     * error generating functions
360     *
361     */
362    void generate_parse_err(Json::Value &result, const std::string &msg);
363
364
365    /**
366     * method execute error
367     *
368     */
369    void generate_execute_err(Json::Value &result, const std::string &msg);
370
371    /**
372     * internal error
373     *
374     */
375    void generate_internal_err(Json::Value &result, const std::string &msg);
376
377
378    /**
379     * translate enum to string
380     *
381     */
382    const char * type_to_str(field_type_e type);
383
384    /**
385     * translate JSON values to string
386     *
387     */
388    const char * json_type_to_name(const Json::Value &value);
389
390    /* RPC command name */
391    std::string        m_name;
392    int                m_param_count;
393    bool               m_needs_ownership;
394    std::string        m_api_handler;
395    APIClass::type_e   m_api_type;
396    static bool        g_test_override_ownership;
397    static bool        g_test_override_api;
398};
399
400#endif /* __TREX_RPC_CMD_API_H__ */
401
402