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 0 : spdk_jsonrpc_set_log_level(enum spdk_log_level level)
22 : {
23 0 : assert(level >= SPDK_LOG_DISABLED);
24 0 : assert(level <= SPDK_LOG_DEBUG);
25 0 : g_rpc_log_level = level;
26 0 : }
27 :
28 : void
29 0 : spdk_jsonrpc_set_log_file(FILE *file)
30 : {
31 0 : g_rpc_log_file = file;
32 0 : }
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 0 : }
43 0 : i++;
44 : }
45 0 : text[j] = '\0';
46 0 : }
47 :
48 : static void
49 15 : 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 15 : if (g_rpc_log_level != SPDK_LOG_DISABLED || g_rpc_log_file != NULL) {
56 0 : remove_newlines(buf);
57 0 : }
58 :
59 15 : 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 0 : }
62 :
63 15 : if (g_rpc_log_file != NULL) {
64 0 : spdk_flog(g_rpc_log_file, NULL, 0, NULL, "%s%s\n", prefix, buf);
65 0 : }
66 15 : }
67 :
68 : static int
69 30 : capture_val(const struct spdk_json_val *val, void *out)
70 : {
71 30 : const struct spdk_json_val **vptr = out;
72 :
73 30 : *vptr = val;
74 30 : 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 10 : parse_single_request(struct spdk_jsonrpc_request *request, struct spdk_json_val *values)
86 : {
87 10 : struct jsonrpc_request req = {};
88 10 : const struct spdk_json_val *params = NULL;
89 :
90 10 : if (spdk_json_decode_object(values, jsonrpc_request_decoders,
91 : SPDK_COUNTOF(jsonrpc_request_decoders),
92 : &req)) {
93 1 : goto invalid;
94 : }
95 :
96 9 : if (req.version && (req.version->type != SPDK_JSON_VAL_STRING ||
97 9 : !spdk_json_strequal(req.version, "2.0"))) {
98 1 : goto invalid;
99 : }
100 :
101 8 : if (!req.method || req.method->type != SPDK_JSON_VAL_STRING) {
102 2 : goto invalid;
103 : }
104 :
105 6 : if (req.id) {
106 6 : if (req.id->type == SPDK_JSON_VAL_STRING ||
107 5 : req.id->type == SPDK_JSON_VAL_NUMBER ||
108 1 : req.id->type == SPDK_JSON_VAL_NULL) {
109 5 : request->id = req.id;
110 5 : } else {
111 0 : goto invalid;
112 : }
113 5 : }
114 :
115 6 : if (req.params) {
116 : /* null json value is as if there were no parameters */
117 6 : if (req.params->type != SPDK_JSON_VAL_NULL) {
118 6 : if (req.params->type != SPDK_JSON_VAL_ARRAY_BEGIN &&
119 1 : req.params->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
120 0 : goto invalid;
121 : }
122 6 : params = req.params;
123 6 : }
124 6 : }
125 :
126 6 : jsonrpc_server_handle_request(request, req.method, params);
127 6 : return;
128 :
129 : invalid:
130 4 : jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
131 10 : }
132 :
133 : static int
134 28 : jsonrpc_server_write_cb(void *cb_ctx, const void *data, size_t size)
135 : {
136 28 : struct spdk_jsonrpc_request *request = cb_ctx;
137 28 : size_t new_size = request->send_buf_size;
138 :
139 28 : while (new_size - request->send_len < size) {
140 0 : 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 0 : new_size *= 2;
147 : }
148 :
149 28 : if (new_size != request->send_buf_size) {
150 : uint8_t *new_buf;
151 :
152 : /* Add extra byte for the null terminator. */
153 0 : new_buf = realloc(request->send_buf, new_size + 1);
154 0 : 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 0 : request->send_buf = new_buf;
161 0 : request->send_buf_size = new_size;
162 0 : }
163 :
164 28 : memcpy(request->send_buf + request->send_len, data, size);
165 28 : request->send_len += size;
166 :
167 28 : return 0;
168 28 : }
169 :
170 : int
171 69 : 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 69 : 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 69 : rc = spdk_json_parse((void *)json, size, NULL, 0, &end, 0);
181 69 : if (rc == SPDK_JSON_PARSE_INCOMPLETE) {
182 54 : return 0;
183 : }
184 :
185 15 : request = calloc(1, sizeof(*request));
186 15 : if (request == NULL) {
187 0 : SPDK_DEBUGLOG(rpc, "Out of memory allocating request\n");
188 0 : return -1;
189 : }
190 :
191 15 : pthread_spin_lock(&conn->queue_lock);
192 15 : conn->outstanding_requests++;
193 15 : STAILQ_INSERT_TAIL(&conn->outstanding_queue, request, link);
194 15 : pthread_spin_unlock(&conn->queue_lock);
195 :
196 15 : request->conn = conn;
197 :
198 15 : len = end - json;
199 15 : request->recv_buffer = malloc(len + 1);
200 15 : 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 15 : memcpy(request->recv_buffer, json, len);
207 15 : request->recv_buffer[len] = '\0';
208 :
209 15 : jsonrpc_log(request->recv_buffer, "request: ");
210 :
211 15 : if (rc > 0 && rc <= SPDK_JSONRPC_MAX_VALUES) {
212 12 : request->values_cnt = rc;
213 12 : request->values = malloc(request->values_cnt * sizeof(request->values[0]));
214 12 : 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 12 : }
221 :
222 15 : request->send_offset = 0;
223 15 : request->send_len = 0;
224 15 : request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
225 : /* Add extra byte for the null terminator. */
226 15 : request->send_buf = malloc(request->send_buf_size + 1);
227 15 : 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 15 : request->response = spdk_json_write_begin(jsonrpc_server_write_cb, request, 0);
234 15 : 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 15 : if (rc <= 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
241 3 : SPDK_DEBUGLOG(rpc, "JSON parse error\n");
242 3 : 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 3 : return -1;
249 : }
250 :
251 : /* Decode a second time now that there is a full JSON value available. */
252 12 : rc = spdk_json_parse(request->recv_buffer, size, request->values, request->values_cnt, &end,
253 : SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
254 12 : 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 12 : assert(end != NULL);
261 :
262 12 : if (request->values[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
263 10 : parse_single_request(request, request->values);
264 12 : } else if (request->values[0].type == SPDK_JSON_VAL_ARRAY_BEGIN) {
265 2 : SPDK_DEBUGLOG(rpc, "Got batch array (not currently supported)\n");
266 2 : jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
267 2 : } 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 12 : return len;
273 69 : }
274 :
275 : struct spdk_jsonrpc_server_conn *
276 0 : spdk_jsonrpc_get_conn(struct spdk_jsonrpc_request *request)
277 : {
278 0 : return request->conn;
279 : }
280 :
281 : /* Never return NULL */
282 : static struct spdk_json_write_ctx *
283 15 : begin_response(struct spdk_jsonrpc_request *request)
284 : {
285 15 : struct spdk_json_write_ctx *w = request->response;
286 :
287 15 : spdk_json_write_object_begin(w);
288 15 : spdk_json_write_named_string(w, "jsonrpc", "2.0");
289 :
290 15 : spdk_json_write_name(w, "id");
291 15 : if (request->id) {
292 5 : spdk_json_write_val(w, request->id);
293 5 : } else {
294 10 : spdk_json_write_null(w);
295 : }
296 :
297 15 : return w;
298 : }
299 :
300 : static void
301 2 : skip_response(struct spdk_jsonrpc_request *request)
302 : {
303 2 : request->send_len = 0;
304 2 : spdk_json_write_end(request->response);
305 2 : request->response = NULL;
306 2 : jsonrpc_server_send_response(request);
307 2 : }
308 :
309 : static void
310 13 : end_response(struct spdk_jsonrpc_request *request)
311 : {
312 13 : spdk_json_write_object_end(request->response);
313 13 : spdk_json_write_end(request->response);
314 13 : request->response = NULL;
315 :
316 13 : jsonrpc_server_write_cb(request, "\n", 1);
317 13 : jsonrpc_server_send_response(request);
318 13 : }
319 :
320 : void
321 15 : jsonrpc_free_request(struct spdk_jsonrpc_request *request)
322 : {
323 : struct spdk_jsonrpc_request *req;
324 : struct spdk_jsonrpc_server_conn *conn;
325 :
326 15 : if (!request) {
327 0 : return;
328 : }
329 :
330 : /* We must send or skip response explicitly */
331 15 : assert(request->response == NULL);
332 :
333 15 : conn = request->conn;
334 15 : if (conn != NULL) {
335 15 : pthread_spin_lock(&conn->queue_lock);
336 15 : conn->outstanding_requests--;
337 15 : STAILQ_FOREACH(req, &conn->outstanding_queue, link) {
338 15 : if (req == request) {
339 15 : STAILQ_REMOVE(&conn->outstanding_queue,
340 : req, spdk_jsonrpc_request, link);
341 15 : break;
342 : }
343 0 : }
344 15 : pthread_spin_unlock(&conn->queue_lock);
345 15 : }
346 15 : free(request->recv_buffer);
347 15 : free(request->values);
348 15 : free(request->send_buf);
349 15 : free(request);
350 15 : }
351 :
352 : void
353 0 : jsonrpc_complete_request(struct spdk_jsonrpc_request *request)
354 : {
355 0 : jsonrpc_log(request->send_buf, "response: ");
356 :
357 0 : jsonrpc_free_request(request);
358 0 : }
359 :
360 : struct spdk_json_write_ctx *
361 6 : spdk_jsonrpc_begin_result(struct spdk_jsonrpc_request *request)
362 : {
363 6 : struct spdk_json_write_ctx *w = begin_response(request);
364 :
365 6 : spdk_json_write_name(w, "result");
366 6 : return w;
367 : }
368 :
369 : void
370 6 : spdk_jsonrpc_end_result(struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w)
371 : {
372 6 : assert(w != NULL);
373 6 : assert(w == request->response);
374 :
375 : /* If there was no ID in request we skip response. */
376 6 : if (request->id && request->id->type != SPDK_JSON_VAL_NULL) {
377 4 : end_response(request);
378 4 : } else {
379 2 : skip_response(request);
380 : }
381 6 : }
382 :
383 : void
384 0 : spdk_jsonrpc_send_bool_response(struct spdk_jsonrpc_request *request, bool value)
385 : {
386 : struct spdk_json_write_ctx *w;
387 :
388 0 : w = spdk_jsonrpc_begin_result(request);
389 0 : assert(w != NULL);
390 0 : spdk_json_write_bool(w, value);
391 0 : spdk_jsonrpc_end_result(request, w);
392 0 : }
393 :
394 : void
395 0 : spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_request *request,
396 : int error_code, const char *msg)
397 : {
398 0 : struct spdk_json_write_ctx *w = begin_response(request);
399 :
400 0 : spdk_json_write_named_object_begin(w, "error");
401 0 : spdk_json_write_named_int32(w, "code", error_code);
402 0 : spdk_json_write_named_string(w, "message", msg);
403 0 : spdk_json_write_object_end(w);
404 :
405 0 : end_response(request);
406 0 : }
407 :
408 : void
409 9 : spdk_jsonrpc_send_error_response_fmt(struct spdk_jsonrpc_request *request,
410 : int error_code, const char *fmt, ...)
411 : {
412 9 : struct spdk_json_write_ctx *w = begin_response(request);
413 : va_list args;
414 :
415 9 : spdk_json_write_named_object_begin(w, "error");
416 9 : spdk_json_write_named_int32(w, "code", error_code);
417 9 : va_start(args, fmt);
418 9 : spdk_json_write_named_string_fmt_v(w, "message", fmt, args);
419 9 : va_end(args);
420 9 : spdk_json_write_object_end(w);
421 :
422 9 : end_response(request);
423 9 : }
424 :
425 2 : SPDK_LOG_REGISTER_COMPONENT(rpc)
|