Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation. All rights reserved.
3 : : * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 : : */
5 : :
6 : : #include "jsonrpc_internal.h"
7 : :
8 : : #include "spdk/util.h"
9 : :
10 : : static enum spdk_log_level g_rpc_log_level = SPDK_LOG_DISABLED;
11 : : static FILE *g_rpc_log_file = NULL;
12 : :
13 : : struct jsonrpc_request {
14 : : const struct spdk_json_val *version;
15 : : const struct spdk_json_val *method;
16 : : const struct spdk_json_val *params;
17 : : const struct spdk_json_val *id;
18 : : };
19 : :
20 : : void
21 : 3000 : spdk_jsonrpc_set_log_level(enum spdk_log_level level)
22 : : {
23 [ - + ]: 3000 : assert(level >= SPDK_LOG_DISABLED);
24 [ - + ]: 3000 : assert(level <= SPDK_LOG_DEBUG);
25 : 3000 : g_rpc_log_level = level;
26 : 3000 : }
27 : :
28 : : void
29 : 3000 : spdk_jsonrpc_set_log_file(FILE *file)
30 : : {
31 : 3000 : g_rpc_log_file = file;
32 : 3000 : }
33 : :
34 : : static void
35 : 0 : remove_newlines(char *text)
36 : : {
37 : 0 : int i = 0, j = 0;
38 : :
39 [ # # ]: 0 : while (text[i] != '\0') {
40 [ # # ]: 0 : if (text[i] != '\n') {
41 : 0 : text[j++] = text[i];
42 : : }
43 : 0 : i++;
44 : : }
45 : 0 : text[j] = '\0';
46 : 0 : }
47 : :
48 : : static void
49 : 90327 : jsonrpc_log(char *buf, const char *prefix)
50 : : {
51 : : /* Some custom applications have enabled SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS
52 : : * to allow comments in JSON RPC objects. To keep backward compatibility of
53 : : * these applications, remove newlines only if JSON RPC logging is enabled.
54 : : */
55 [ + - - + ]: 90327 : if (g_rpc_log_level != SPDK_LOG_DISABLED || g_rpc_log_file != NULL) {
56 : 0 : remove_newlines(buf);
57 : : }
58 : :
59 [ - + ]: 90327 : if (g_rpc_log_level != SPDK_LOG_DISABLED) {
60 : 0 : spdk_log(g_rpc_log_level, NULL, 0, NULL, "%s%s\n", prefix, buf);
61 : : }
62 : :
63 [ - + ]: 90327 : if (g_rpc_log_file != NULL) {
64 : 0 : spdk_flog(g_rpc_log_file, NULL, 0, NULL, "%s%s\n", prefix, buf);
65 : : }
66 : 90327 : }
67 : :
68 : : static int
69 : 167366 : capture_val(const struct spdk_json_val *val, void *out)
70 : : {
71 : 167366 : const struct spdk_json_val **vptr = out;
72 : :
73 : 167366 : *vptr = val;
74 : 167366 : return 0;
75 : : }
76 : :
77 : : static const struct spdk_json_object_decoder jsonrpc_request_decoders[] = {
78 : : {"jsonrpc", offsetof(struct jsonrpc_request, version), capture_val, true},
79 : : {"method", offsetof(struct jsonrpc_request, method), capture_val},
80 : : {"params", offsetof(struct jsonrpc_request, params), capture_val, true},
81 : : {"id", offsetof(struct jsonrpc_request, id), capture_val, true},
82 : : };
83 : :
84 : : static void
85 : 45192 : parse_single_request(struct spdk_jsonrpc_request *request, struct spdk_json_val *values)
86 : : {
87 : 45192 : struct jsonrpc_request req = {};
88 : 45192 : const struct spdk_json_val *params = NULL;
89 : :
90 [ + + ]: 45192 : if (spdk_json_decode_object(values, jsonrpc_request_decoders,
91 : : SPDK_COUNTOF(jsonrpc_request_decoders),
92 : : &req)) {
93 : 3 : goto invalid;
94 : : }
95 : :
96 [ + - + - ]: 45189 : if (req.version && (req.version->type != SPDK_JSON_VAL_STRING ||
97 [ + + ]: 45189 : !spdk_json_strequal(req.version, "2.0"))) {
98 : 3 : goto invalid;
99 : : }
100 : :
101 [ + - + + ]: 45186 : if (!req.method || req.method->type != SPDK_JSON_VAL_STRING) {
102 : 6 : goto invalid;
103 : : }
104 : :
105 [ + + ]: 45180 : if (req.id) {
106 [ + - ]: 45177 : if (req.id->type == SPDK_JSON_VAL_STRING ||
107 [ + + ]: 45177 : req.id->type == SPDK_JSON_VAL_NUMBER ||
108 [ + - ]: 3 : req.id->type == SPDK_JSON_VAL_NULL) {
109 : 45177 : request->id = req.id;
110 : : } else {
111 : 0 : goto invalid;
112 : : }
113 : : }
114 : :
115 [ + + ]: 45180 : if (req.params) {
116 : : /* null json value is as if there were no parameters */
117 [ + + ]: 31808 : if (req.params->type != SPDK_JSON_VAL_NULL) {
118 [ + + ]: 31266 : if (req.params->type != SPDK_JSON_VAL_ARRAY_BEGIN &&
119 [ - + ]: 31251 : req.params->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
120 : 0 : goto invalid;
121 : : }
122 : 31266 : params = req.params;
123 : : }
124 : : }
125 : :
126 : 45180 : jsonrpc_server_handle_request(request, req.method, params);
127 : 45180 : return;
128 : :
129 : 12 : invalid:
130 : 12 : jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
131 : : }
132 : :
133 : : static int
134 : 95651 : jsonrpc_server_write_cb(void *cb_ctx, const void *data, size_t size)
135 : : {
136 : 95651 : struct spdk_jsonrpc_request *request = cb_ctx;
137 : 95651 : size_t new_size = request->send_buf_size;
138 : :
139 [ + + ]: 95655 : while (new_size - request->send_len < size) {
140 [ - + ]: 4 : if (new_size >= SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
141 : 0 : SPDK_ERRLOG("Send buf exceeded maximum size (%zu)\n",
142 : : (size_t)SPDK_JSONRPC_SEND_BUF_SIZE_MAX);
143 : 0 : return -1;
144 : : }
145 : :
146 : 4 : new_size *= 2;
147 : : }
148 : :
149 [ + + ]: 95651 : if (new_size != request->send_buf_size) {
150 : : uint8_t *new_buf;
151 : :
152 : : /* Add extra byte for the null terminator. */
153 : 4 : new_buf = realloc(request->send_buf, new_size + 1);
154 [ - + ]: 4 : if (new_buf == NULL) {
155 : 0 : SPDK_ERRLOG("Resizing send_buf failed (current size %zu, new size %zu)\n",
156 : : request->send_buf_size, new_size);
157 : 0 : return -1;
158 : : }
159 : :
160 : 4 : request->send_buf = new_buf;
161 : 4 : request->send_buf_size = new_size;
162 : : }
163 : :
164 [ - + - + ]: 95651 : memcpy(request->send_buf + request->send_len, data, size);
165 : 95651 : request->send_len += size;
166 : :
167 : 95651 : return 0;
168 : : }
169 : :
170 : : int
171 : 90531 : jsonrpc_parse_request(struct spdk_jsonrpc_server_conn *conn, const void *json, size_t size)
172 : : {
173 : : struct spdk_jsonrpc_request *request;
174 : : ssize_t rc;
175 : : size_t len;
176 : 90531 : void *end = NULL;
177 : :
178 : : /* Check to see if we have received a full JSON value. It is safe to cast away const
179 : : * as we don't decode in place. */
180 : 90531 : rc = spdk_json_parse((void *)json, size, NULL, 0, &end, 0);
181 [ + + ]: 90531 : if (rc == SPDK_JSON_PARSE_INCOMPLETE) {
182 : 45324 : return 0;
183 : : }
184 : :
185 : 45207 : request = calloc(1, sizeof(*request));
186 [ - + ]: 45207 : if (request == NULL) {
187 [ # # # # ]: 0 : SPDK_DEBUGLOG(rpc, "Out of memory allocating request\n");
188 : 0 : return -1;
189 : : }
190 : :
191 [ - + ]: 45207 : pthread_spin_lock(&conn->queue_lock);
192 : 45207 : conn->outstanding_requests++;
193 : 45207 : STAILQ_INSERT_TAIL(&conn->outstanding_queue, request, link);
194 [ - + ]: 45207 : pthread_spin_unlock(&conn->queue_lock);
195 : :
196 : 45207 : request->conn = conn;
197 : :
198 : 45207 : len = end - json;
199 : 45207 : request->recv_buffer = malloc(len + 1);
200 [ - + ]: 45207 : if (request->recv_buffer == NULL) {
201 : 0 : SPDK_ERRLOG("Failed to allocate buffer to copy request (%zu bytes)\n", len + 1);
202 : 0 : jsonrpc_free_request(request);
203 : 0 : return -1;
204 : : }
205 : :
206 [ - + - + ]: 45207 : memcpy(request->recv_buffer, json, len);
207 : 45207 : request->recv_buffer[len] = '\0';
208 : :
209 : 45207 : jsonrpc_log(request->recv_buffer, "request: ");
210 : :
211 [ + + + - ]: 45207 : if (rc > 0 && rc <= SPDK_JSONRPC_MAX_VALUES) {
212 : 45198 : request->values_cnt = rc;
213 : 45198 : request->values = malloc(request->values_cnt * sizeof(request->values[0]));
214 [ - + ]: 45198 : if (request->values == NULL) {
215 : 0 : SPDK_ERRLOG("Failed to allocate buffer for JSON values (%zu bytes)\n",
216 : : request->values_cnt * sizeof(request->values[0]));
217 : 0 : jsonrpc_free_request(request);
218 : 0 : return -1;
219 : : }
220 : : }
221 : :
222 : 45207 : request->send_offset = 0;
223 : 45207 : request->send_len = 0;
224 : 45207 : request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
225 : : /* Add extra byte for the null terminator. */
226 : 45207 : request->send_buf = malloc(request->send_buf_size + 1);
227 [ - + ]: 45207 : if (request->send_buf == NULL) {
228 : 0 : SPDK_ERRLOG("Failed to allocate send_buf (%zu bytes)\n", request->send_buf_size);
229 : 0 : jsonrpc_free_request(request);
230 : 0 : return -1;
231 : : }
232 : :
233 : 45207 : request->response = spdk_json_write_begin(jsonrpc_server_write_cb, request, 0);
234 [ - + ]: 45207 : if (request->response == NULL) {
235 : 0 : SPDK_ERRLOG("Failed to allocate response JSON write context.\n");
236 : 0 : jsonrpc_free_request(request);
237 : 0 : return -1;
238 : : }
239 : :
240 [ + + - + ]: 45207 : if (rc <= 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
241 [ - + - + ]: 9 : SPDK_DEBUGLOG(rpc, "JSON parse error\n");
242 : 9 : jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_PARSE_ERROR);
243 : :
244 : : /*
245 : : * Can't recover from parse error (no guaranteed resync point in streaming JSON).
246 : : * Return an error to indicate that the connection should be closed.
247 : : */
248 : 9 : return -1;
249 : : }
250 : :
251 : : /* Decode a second time now that there is a full JSON value available. */
252 : 45198 : rc = spdk_json_parse(request->recv_buffer, size, request->values, request->values_cnt, &end,
253 : : SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
254 [ + - - + ]: 45198 : if (rc < 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
255 [ # # # # ]: 0 : SPDK_DEBUGLOG(rpc, "JSON parse error on second pass\n");
256 : 0 : jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_PARSE_ERROR);
257 : 0 : return -1;
258 : : }
259 : :
260 [ - + ]: 45198 : assert(end != NULL);
261 : :
262 [ + + ]: 45198 : if (request->values[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
263 : 45192 : parse_single_request(request, request->values);
264 [ + - ]: 6 : } else if (request->values[0].type == SPDK_JSON_VAL_ARRAY_BEGIN) {
265 [ - + - + ]: 6 : SPDK_DEBUGLOG(rpc, "Got batch array (not currently supported)\n");
266 : 6 : jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
267 : : } else {
268 [ # # # # ]: 0 : SPDK_DEBUGLOG(rpc, "top-level JSON value was not array or object\n");
269 : 0 : jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
270 : : }
271 : :
272 : 45198 : return len;
273 : : }
274 : :
275 : : struct spdk_jsonrpc_server_conn *
276 : 18 : spdk_jsonrpc_get_conn(struct spdk_jsonrpc_request *request)
277 : : {
278 : 18 : return request->conn;
279 : : }
280 : :
281 : : /* Never return NULL */
282 : : static struct spdk_json_write_ctx *
283 : 45201 : begin_response(struct spdk_jsonrpc_request *request)
284 : : {
285 : 45201 : struct spdk_json_write_ctx *w = request->response;
286 : :
287 : 45201 : spdk_json_write_object_begin(w);
288 : 45201 : spdk_json_write_named_string(w, "jsonrpc", "2.0");
289 : :
290 : 45201 : spdk_json_write_name(w, "id");
291 [ + + ]: 45201 : if (request->id) {
292 : 45171 : spdk_json_write_val(w, request->id);
293 : : } else {
294 : 30 : spdk_json_write_null(w);
295 : : }
296 : :
297 : 45201 : return w;
298 : : }
299 : :
300 : : static void
301 : 6 : skip_response(struct spdk_jsonrpc_request *request)
302 : : {
303 : 6 : request->send_len = 0;
304 : 6 : spdk_json_write_end(request->response);
305 : 6 : request->response = NULL;
306 : 6 : jsonrpc_server_send_response(request);
307 : 6 : }
308 : :
309 : : static void
310 : 45195 : end_response(struct spdk_jsonrpc_request *request)
311 : : {
312 : 45195 : spdk_json_write_object_end(request->response);
313 : 45195 : spdk_json_write_end(request->response);
314 : 45195 : request->response = NULL;
315 : :
316 : 45195 : jsonrpc_server_write_cb(request, "\n", 1);
317 : 45195 : jsonrpc_server_send_response(request);
318 : 45195 : }
319 : :
320 : : void
321 : 76316 : jsonrpc_free_request(struct spdk_jsonrpc_request *request)
322 : : {
323 : : struct spdk_jsonrpc_request *req;
324 : : struct spdk_jsonrpc_server_conn *conn;
325 : :
326 [ + + ]: 76316 : if (!request) {
327 : 31115 : return;
328 : : }
329 : :
330 : : /* We must send or skip response explicitly */
331 [ - + ]: 45201 : assert(request->response == NULL);
332 : :
333 : 45201 : conn = request->conn;
334 [ + - ]: 45201 : if (conn != NULL) {
335 [ - + ]: 45201 : pthread_spin_lock(&conn->queue_lock);
336 : 45201 : conn->outstanding_requests--;
337 [ + + ]: 45201 : STAILQ_FOREACH(req, &conn->outstanding_queue, link) {
338 [ + - ]: 45 : if (req == request) {
339 [ + - + - : 45 : STAILQ_REMOVE(&conn->outstanding_queue,
- - - - ]
340 : : req, spdk_jsonrpc_request, link);
341 : 45 : break;
342 : : }
343 : : }
344 [ - + ]: 45201 : pthread_spin_unlock(&conn->queue_lock);
345 : : }
346 : 45201 : free(request->recv_buffer);
347 : 45201 : free(request->values);
348 : 45201 : free(request->send_buf);
349 : 45201 : free(request);
350 : : }
351 : :
352 : : void
353 : 45120 : jsonrpc_complete_request(struct spdk_jsonrpc_request *request)
354 : : {
355 : 45120 : jsonrpc_log(request->send_buf, "response: ");
356 : :
357 : 45120 : jsonrpc_free_request(request);
358 : 45120 : }
359 : :
360 : : struct spdk_json_write_ctx *
361 : 43534 : spdk_jsonrpc_begin_result(struct spdk_jsonrpc_request *request)
362 : : {
363 : 43534 : struct spdk_json_write_ctx *w = begin_response(request);
364 : :
365 : 43534 : spdk_json_write_name(w, "result");
366 : 43534 : return w;
367 : : }
368 : :
369 : : void
370 : 43534 : spdk_jsonrpc_end_result(struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w)
371 : : {
372 [ - + ]: 43534 : assert(w != NULL);
373 [ - + ]: 43534 : assert(w == request->response);
374 : :
375 : : /* If there was no ID in request we skip response. */
376 [ + + + + ]: 43534 : if (request->id && request->id->type != SPDK_JSON_VAL_NULL) {
377 : 43528 : end_response(request);
378 : : } else {
379 : 6 : skip_response(request);
380 : : }
381 : 43534 : }
382 : :
383 : : void
384 : 13807 : spdk_jsonrpc_send_bool_response(struct spdk_jsonrpc_request *request, bool value)
385 : : {
386 : : struct spdk_json_write_ctx *w;
387 : :
388 : 13807 : w = spdk_jsonrpc_begin_result(request);
389 [ - + ]: 13807 : assert(w != NULL);
390 : 13807 : spdk_json_write_bool(w, value);
391 : 13807 : spdk_jsonrpc_end_result(request, w);
392 : 13807 : }
393 : :
394 : : void
395 : 1533 : spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_request *request,
396 : : int error_code, const char *msg)
397 : : {
398 : 1533 : struct spdk_json_write_ctx *w = begin_response(request);
399 : :
400 : 1533 : spdk_json_write_named_object_begin(w, "error");
401 : 1533 : spdk_json_write_named_int32(w, "code", error_code);
402 : 1533 : spdk_json_write_named_string(w, "message", msg);
403 : 1533 : spdk_json_write_object_end(w);
404 : :
405 : 1533 : end_response(request);
406 : 1533 : }
407 : :
408 : : void
409 : 134 : spdk_jsonrpc_send_error_response_fmt(struct spdk_jsonrpc_request *request,
410 : : int error_code, const char *fmt, ...)
411 : : {
412 : 134 : struct spdk_json_write_ctx *w = begin_response(request);
413 : 96 : va_list args;
414 : :
415 : 134 : spdk_json_write_named_object_begin(w, "error");
416 : 134 : spdk_json_write_named_int32(w, "code", error_code);
417 : 134 : va_start(args, fmt);
418 : 134 : spdk_json_write_named_string_fmt_v(w, "message", fmt, args);
419 : 134 : va_end(args);
420 : 134 : spdk_json_write_object_end(w);
421 : :
422 : 134 : end_response(request);
423 : 134 : }
424 : :
425 : 2987 : SPDK_LOG_REGISTER_COMPONENT(rpc)
|