1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "jsonrpc_internal.h" 35 36 struct jsonrpc_request { 37 const struct spdk_json_val *version; 38 const struct spdk_json_val *method; 39 const struct spdk_json_val *params; 40 const struct spdk_json_val *id; 41 }; 42 43 static int 44 capture_val(const struct spdk_json_val *val, void *out) 45 { 46 const struct spdk_json_val **vptr = out; 47 48 *vptr = val; 49 return 0; 50 } 51 52 static const struct spdk_json_object_decoder jsonrpc_request_decoders[] = { 53 {"jsonrpc", offsetof(struct jsonrpc_request, version), capture_val}, 54 {"method", offsetof(struct jsonrpc_request, method), capture_val}, 55 {"params", offsetof(struct jsonrpc_request, params), capture_val, true}, 56 {"id", offsetof(struct jsonrpc_request, id), capture_val, true}, 57 }; 58 59 static void 60 parse_single_request(struct spdk_jsonrpc_server_conn *conn, struct spdk_json_val *values) 61 { 62 bool invalid = false; 63 struct jsonrpc_request req = {}; 64 65 if (spdk_json_decode_object(values, jsonrpc_request_decoders, 66 sizeof(jsonrpc_request_decoders) / sizeof(*jsonrpc_request_decoders), 67 &req)) { 68 invalid = true; 69 goto done; 70 } 71 72 if (!req.version || req.version->type != SPDK_JSON_VAL_STRING || 73 !spdk_json_strequal(req.version, "2.0")) { 74 invalid = true; 75 } 76 77 if (!req.method || req.method->type != SPDK_JSON_VAL_STRING) { 78 req.method = NULL; 79 invalid = true; 80 } 81 82 if (req.id) { 83 if (req.id->type != SPDK_JSON_VAL_STRING && 84 req.id->type != SPDK_JSON_VAL_NUMBER && 85 req.id->type != SPDK_JSON_VAL_NULL) { 86 req.id = NULL; 87 invalid = true; 88 } 89 } 90 91 if (req.params) { 92 if (req.params->type != SPDK_JSON_VAL_ARRAY_BEGIN && 93 req.params->type != SPDK_JSON_VAL_OBJECT_BEGIN) { 94 req.params = NULL; 95 invalid = true; 96 } 97 } 98 99 done: 100 if (invalid) { 101 spdk_jsonrpc_server_handle_error(conn, SPDK_JSONRPC_ERROR_INVALID_REQUEST, req.method, req.params, 102 req.id); 103 } else { 104 spdk_jsonrpc_server_handle_request(conn, req.method, req.params, req.id); 105 } 106 } 107 108 static void 109 parse_batch_request(struct spdk_jsonrpc_server_conn *conn, struct spdk_json_val *values) 110 { 111 size_t num_values, i; 112 113 assert(values[0].type == SPDK_JSON_VAL_ARRAY_BEGIN); 114 num_values = values[0].len; 115 values++; 116 117 assert(conn->json_writer == NULL); 118 119 if (num_values == 0) { 120 SPDK_TRACELOG(SPDK_TRACE_RPC, "empty batch array not allowed"); 121 spdk_jsonrpc_server_handle_error(conn, SPDK_JSONRPC_ERROR_INVALID_REQUEST, NULL, NULL, NULL); 122 return; 123 } 124 125 i = 0; 126 while (i < num_values) { 127 struct spdk_json_val *v = &values[i]; 128 129 parse_single_request(conn, v); 130 i += spdk_json_val_len(v); 131 } 132 133 if (conn->json_writer) { 134 /* 135 * There was at least one response - finish the batch array. 136 */ 137 spdk_json_write_array_end(conn->json_writer); 138 spdk_json_write_end(conn->json_writer); 139 conn->json_writer = NULL; 140 } 141 } 142 143 int 144 spdk_jsonrpc_parse_request(struct spdk_jsonrpc_server_conn *conn, void *json, size_t size) 145 { 146 ssize_t rc; 147 void *end = NULL; 148 149 assert(conn->json_writer == NULL); 150 151 conn->batch = false; 152 153 /* Check to see if we have received a full JSON value. */ 154 rc = spdk_json_parse(json, size, NULL, 0, &end, 0); 155 if (rc == SPDK_JSON_PARSE_INCOMPLETE) { 156 return 0; 157 } else if (rc < 0 || rc > SPDK_JSONRPC_MAX_VALUES) { 158 SPDK_TRACELOG(SPDK_TRACE_RPC, "JSON parse error\n"); 159 spdk_jsonrpc_server_handle_error(conn, SPDK_JSONRPC_ERROR_PARSE_ERROR, NULL, NULL, NULL); 160 161 /* 162 * Can't recover from parse error (no guaranteed resync point in streaming JSON). 163 * Return an error to indicate that the connection should be closed. 164 */ 165 return -1; 166 } 167 168 /* Decode a second time now that there is a full JSON value available. */ 169 rc = spdk_json_parse(json, size, conn->values, SPDK_JSONRPC_MAX_VALUES, &end, 170 SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE); 171 if (rc < 0 || rc > SPDK_JSONRPC_MAX_VALUES) { 172 SPDK_TRACELOG(SPDK_TRACE_RPC, "JSON parse error on second pass\n"); 173 spdk_jsonrpc_server_handle_error(conn, SPDK_JSONRPC_ERROR_PARSE_ERROR, NULL, NULL, NULL); 174 return -1; 175 } 176 177 assert(end != NULL); 178 179 if (conn->values[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) { 180 parse_single_request(conn, conn->values); 181 } else if (conn->values[0].type == SPDK_JSON_VAL_ARRAY_BEGIN) { 182 conn->batch = true; 183 parse_batch_request(conn, conn->values); 184 } else { 185 SPDK_TRACELOG(SPDK_TRACE_RPC, "top-level JSON value was not array or object\n"); 186 spdk_jsonrpc_server_handle_error(conn, SPDK_JSONRPC_ERROR_INVALID_REQUEST, NULL, NULL, NULL); 187 } 188 189 return end - json; 190 } 191 192 static struct spdk_json_write_ctx * 193 begin_response(struct spdk_jsonrpc_server_conn *conn, const struct spdk_json_val *id) 194 { 195 struct spdk_json_write_ctx *w = conn->json_writer; 196 197 if (w == NULL) { 198 conn->json_writer = w = spdk_json_write_begin(spdk_jsonrpc_server_write_cb, conn, 0); 199 } 200 201 if (w == NULL) { 202 return NULL; 203 } 204 205 spdk_json_write_object_begin(w); 206 spdk_json_write_name(w, "jsonrpc"); 207 spdk_json_write_string(w, "2.0"); 208 209 if (id) { 210 spdk_json_write_name(w, "id"); 211 spdk_json_write_val(w, id); 212 } 213 214 return w; 215 } 216 217 static void 218 end_response(struct spdk_jsonrpc_server_conn *conn, struct spdk_json_write_ctx *w) 219 { 220 spdk_json_write_object_end(w); 221 222 if (!conn->batch) { 223 spdk_json_write_end(w); 224 spdk_jsonrpc_server_write_cb(conn, "\n", 1); 225 conn->json_writer = NULL; 226 } 227 } 228 229 struct spdk_json_write_ctx * 230 spdk_jsonrpc_begin_result(struct spdk_jsonrpc_server_conn *conn, const struct spdk_json_val *id) 231 { 232 struct spdk_json_write_ctx *w; 233 234 w = begin_response(conn, id); 235 if (w == NULL) { 236 return NULL; 237 } 238 239 spdk_json_write_name(w, "result"); 240 241 return w; 242 } 243 244 void 245 spdk_jsonrpc_end_result(struct spdk_jsonrpc_server_conn *conn, struct spdk_json_write_ctx *w) 246 { 247 assert(w != NULL); 248 assert(w == conn->json_writer); 249 250 end_response(conn, w); 251 } 252 253 void 254 spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_server_conn *conn, 255 const struct spdk_json_val *id, 256 int error_code, const char *msg) 257 { 258 struct spdk_json_write_ctx *w; 259 struct spdk_json_val v_null; 260 261 if (id == NULL) { 262 /* For error responses, if id is missing, explicitly respond with "id": null. */ 263 v_null.type = SPDK_JSON_VAL_NULL; 264 id = &v_null; 265 } 266 267 w = begin_response(conn, id); 268 if (w == NULL) { 269 return; 270 } 271 272 spdk_json_write_name(w, "error"); 273 spdk_json_write_object_begin(w); 274 spdk_json_write_name(w, "code"); 275 spdk_json_write_int32(w, error_code); 276 spdk_json_write_name(w, "message"); 277 spdk_json_write_string(w, msg); 278 spdk_json_write_object_end(w); 279 280 end_response(conn, w); 281 } 282 283 SPDK_LOG_REGISTER_TRACE_FLAG("rpc", SPDK_TRACE_RPC) 284