1 #include "tr_mon_req.h"/*
2 * Copyright (c) 2018, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include "tr_mon_req.h"
41 // Monitoring request decoders
44 * Decode a single option
47 * { "type": "some_tpye" }
49 * @param opt_json JSON object reference
50 * @param dest allocated memory for the result
51 * @return TR_MON_SUCCESS on success, error on error
53 static TR_MON_RC tr_mon_decode_one_opt(json_t *opt_json, TR_MON_OPT *dest)
56 TR_MON_OPT_TYPE opt_type = OPT_TYPE_UNKNOWN;
58 if ( (opt_json == NULL) || (dest == NULL))
61 if (! json_is_object(opt_json))
62 return TR_MON_NOPARSE;
64 jstr = json_object_get(opt_json, "type");
65 if ( (jstr == NULL) || (! json_is_string(jstr)) )
66 return TR_MON_NOPARSE;
68 opt_type = opt_type_from_string(json_string_value(jstr));
69 if (opt_type == OPT_TYPE_UNKNOWN)
70 return TR_MON_NOPARSE;
72 dest->type = opt_type;
73 return TR_MON_SUCCESS;
77 * Decode options array
80 * [{option}, {option}, ...]
83 static TR_MON_RC tr_mon_options_decode(json_t *opts_json, TR_MON_REQ *req)
85 TR_MON_OPT opt; // not a pointer
89 if ( (opts_json == NULL) || (req == NULL))
92 if (! json_is_array(opts_json))
93 return TR_MON_NOPARSE;
95 n_opts = json_array_size(opts_json);
96 for (ii=0; ii < n_opts; ii++) {
97 if (tr_mon_decode_one_opt(json_array_get(opts_json, ii),
98 &opt) != TR_MON_SUCCESS) {
99 return TR_MON_NOPARSE;
101 tr_mon_req_add_option(req, opt.type);
103 return TR_MON_SUCCESS;
107 * Parse JSON for a request
109 static json_t *tr_mon_req_parse(const char *input)
111 json_t *parsed_json = NULL;
112 json_error_t json_error;
114 parsed_json = json_loads(input, JSON_REJECT_DUPLICATES, &json_error);
119 * Decode a JSON request
123 * "command": "some_command_name",
124 * "options": [{option1}, ...]
127 * (options are optional)
129 * Caller must free the return value with tr_mon_req_free().
131 * @param mem_ctx talloc context for the returned struct
132 * @param req_json reference to JSON request object
133 * @return decoded request struct or NULL on failure
135 TR_MON_REQ *tr_mon_req_decode(TALLOC_CTX *mem_ctx, const char *req_str)
137 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
138 TR_MON_REQ *req = NULL;
139 json_t *req_json = NULL;
141 json_t *opts_json = NULL;
142 TR_MON_CMD cmd = MON_CMD_UNKNOWN;
144 req_json = tr_mon_req_parse(req_str); // TODO: Check errors
146 if (! json_is_object(req_json))
149 // Get the command and verify that it is a string value
150 jval = json_object_get(req_json, "command");
151 if (! json_is_string(jval))
154 cmd = cmd_from_string(json_string_value(jval));
155 if (cmd == MON_CMD_UNKNOWN)
158 /* Command is good. Allocate the request in the tmp context */
159 req = tr_mon_req_new(tmp_ctx, cmd);
163 /* Parse options if we have any */
164 opts_json = json_object_get(req_json, "options");
166 if (tr_mon_options_decode(opts_json, req) != TR_MON_SUCCESS) {
167 req = NULL; // memory still in tmp_ctx, so it will be cleaned up
172 /* Success! Put the request in the caller's talloc context */
173 talloc_steal(mem_ctx, req);
176 talloc_free(tmp_ctx);
178 json_decref(req_json);