xref: /spdk/lib/jsonrpc/jsonrpc_server.c (revision 1078198e78653b2f39414c1566740018d76ee73d)
1488570ebSJim Harris /*   SPDX-License-Identifier: BSD-3-Clause
2a4009e7aSShuhei Matsumoto  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
3a4009e7aSShuhei Matsumoto  *   Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4376d117cSDaniel Verkamp  */
5376d117cSDaniel Verkamp 
6376d117cSDaniel Verkamp #include "jsonrpc_internal.h"
7376d117cSDaniel Verkamp 
8b58a5d73SDaniel Verkamp #include "spdk/util.h"
9b58a5d73SDaniel Verkamp 
10a4009e7aSShuhei Matsumoto static enum spdk_log_level g_rpc_log_level = SPDK_LOG_DISABLED;
11a4009e7aSShuhei Matsumoto static FILE *g_rpc_log_file = NULL;
12a4009e7aSShuhei Matsumoto 
13376d117cSDaniel Verkamp struct jsonrpc_request {
14376d117cSDaniel Verkamp 	const struct spdk_json_val *version;
15376d117cSDaniel Verkamp 	const struct spdk_json_val *method;
16376d117cSDaniel Verkamp 	const struct spdk_json_val *params;
17376d117cSDaniel Verkamp 	const struct spdk_json_val *id;
18376d117cSDaniel Verkamp };
19376d117cSDaniel Verkamp 
20a4009e7aSShuhei Matsumoto void
spdk_jsonrpc_set_log_level(enum spdk_log_level level)21a4009e7aSShuhei Matsumoto spdk_jsonrpc_set_log_level(enum spdk_log_level level)
22a4009e7aSShuhei Matsumoto {
23a4009e7aSShuhei Matsumoto 	assert(level >= SPDK_LOG_DISABLED);
24a4009e7aSShuhei Matsumoto 	assert(level <= SPDK_LOG_DEBUG);
25a4009e7aSShuhei Matsumoto 	g_rpc_log_level = level;
26a4009e7aSShuhei Matsumoto }
27a4009e7aSShuhei Matsumoto 
28a4009e7aSShuhei Matsumoto void
spdk_jsonrpc_set_log_file(FILE * file)29a4009e7aSShuhei Matsumoto spdk_jsonrpc_set_log_file(FILE *file)
30a4009e7aSShuhei Matsumoto {
31a4009e7aSShuhei Matsumoto 	g_rpc_log_file = file;
32a4009e7aSShuhei Matsumoto }
33a4009e7aSShuhei Matsumoto 
34a4009e7aSShuhei Matsumoto static void
remove_newlines(char * text)35a4009e7aSShuhei Matsumoto remove_newlines(char *text)
36a4009e7aSShuhei Matsumoto {
37a4009e7aSShuhei Matsumoto 	int i = 0, j = 0;
38a4009e7aSShuhei Matsumoto 
39a4009e7aSShuhei Matsumoto 	while (text[i] != '\0') {
40a4009e7aSShuhei Matsumoto 		if (text[i] != '\n') {
41a4009e7aSShuhei Matsumoto 			text[j++] = text[i];
42a4009e7aSShuhei Matsumoto 		}
43a4009e7aSShuhei Matsumoto 		i++;
44a4009e7aSShuhei Matsumoto 	}
45a4009e7aSShuhei Matsumoto 	text[j] = '\0';
46a4009e7aSShuhei Matsumoto }
47a4009e7aSShuhei Matsumoto 
48a4009e7aSShuhei Matsumoto static void
jsonrpc_log(char * buf,const char * prefix)49a4009e7aSShuhei Matsumoto jsonrpc_log(char *buf, const char *prefix)
50a4009e7aSShuhei Matsumoto {
51*1078198eSShuhei Matsumoto 	/* Some custom applications have enabled SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS
52*1078198eSShuhei Matsumoto 	 * to allow comments in JSON RPC objects. To keep backward compatibility of
53*1078198eSShuhei Matsumoto 	 * these applications, remove newlines only if JSON RPC logging is enabled.
54a4009e7aSShuhei Matsumoto 	 */
55*1078198eSShuhei Matsumoto 	if (g_rpc_log_level != SPDK_LOG_DISABLED || g_rpc_log_file != NULL) {
56a4009e7aSShuhei Matsumoto 		remove_newlines(buf);
57*1078198eSShuhei Matsumoto 	}
58a4009e7aSShuhei Matsumoto 
59a4009e7aSShuhei Matsumoto 	if (g_rpc_log_level != SPDK_LOG_DISABLED) {
60a4009e7aSShuhei Matsumoto 		spdk_log(g_rpc_log_level, NULL, 0, NULL, "%s%s\n", prefix, buf);
61a4009e7aSShuhei Matsumoto 	}
62a4009e7aSShuhei Matsumoto 
63a4009e7aSShuhei Matsumoto 	if (g_rpc_log_file != NULL) {
64a4009e7aSShuhei Matsumoto 		spdk_flog(g_rpc_log_file, NULL, 0, NULL, "%s%s\n", prefix, buf);
65a4009e7aSShuhei Matsumoto 	}
66a4009e7aSShuhei Matsumoto }
67a4009e7aSShuhei Matsumoto 
68376d117cSDaniel Verkamp static int
capture_val(const struct spdk_json_val * val,void * out)69376d117cSDaniel Verkamp capture_val(const struct spdk_json_val *val, void *out)
70376d117cSDaniel Verkamp {
71376d117cSDaniel Verkamp 	const struct spdk_json_val **vptr = out;
72376d117cSDaniel Verkamp 
73376d117cSDaniel Verkamp 	*vptr = val;
74376d117cSDaniel Verkamp 	return 0;
75376d117cSDaniel Verkamp }
76376d117cSDaniel Verkamp 
77376d117cSDaniel Verkamp static const struct spdk_json_object_decoder jsonrpc_request_decoders[] = {
78da7673f7SDaniel Verkamp 	{"jsonrpc", offsetof(struct jsonrpc_request, version), capture_val, true},
79376d117cSDaniel Verkamp 	{"method", offsetof(struct jsonrpc_request, method), capture_val},
80376d117cSDaniel Verkamp 	{"params", offsetof(struct jsonrpc_request, params), capture_val, true},
81376d117cSDaniel Verkamp 	{"id", offsetof(struct jsonrpc_request, id), capture_val, true},
82376d117cSDaniel Verkamp };
83376d117cSDaniel Verkamp 
84376d117cSDaniel Verkamp static void
parse_single_request(struct spdk_jsonrpc_request * request,struct spdk_json_val * values)85977fd230SDaniel Verkamp parse_single_request(struct spdk_jsonrpc_request *request, struct spdk_json_val *values)
86376d117cSDaniel Verkamp {
87376d117cSDaniel Verkamp 	struct jsonrpc_request req = {};
8859339feaSJan Kryl 	const struct spdk_json_val *params = NULL;
89376d117cSDaniel Verkamp 
90376d117cSDaniel Verkamp 	if (spdk_json_decode_object(values, jsonrpc_request_decoders,
91b58a5d73SDaniel Verkamp 				    SPDK_COUNTOF(jsonrpc_request_decoders),
92376d117cSDaniel Verkamp 				    &req)) {
9363978010SPawel Wodkowski 		goto invalid;
94376d117cSDaniel Verkamp 	}
95376d117cSDaniel Verkamp 
96aa67900aSDaniel Verkamp 	if (req.version && (req.version->type != SPDK_JSON_VAL_STRING ||
97aa67900aSDaniel Verkamp 			    !spdk_json_strequal(req.version, "2.0"))) {
9863978010SPawel Wodkowski 		goto invalid;
99376d117cSDaniel Verkamp 	}
100376d117cSDaniel Verkamp 
101376d117cSDaniel Verkamp 	if (!req.method || req.method->type != SPDK_JSON_VAL_STRING) {
10263978010SPawel Wodkowski 		goto invalid;
103376d117cSDaniel Verkamp 	}
104376d117cSDaniel Verkamp 
105376d117cSDaniel Verkamp 	if (req.id) {
106977fd230SDaniel Verkamp 		if (req.id->type == SPDK_JSON_VAL_STRING ||
10763978010SPawel Wodkowski 		    req.id->type == SPDK_JSON_VAL_NUMBER ||
10863978010SPawel Wodkowski 		    req.id->type == SPDK_JSON_VAL_NULL) {
10963978010SPawel Wodkowski 			request->id = req.id;
1102bdec64fSDaniel Verkamp 		} else  {
11163978010SPawel Wodkowski 			goto invalid;
112376d117cSDaniel Verkamp 		}
113376d117cSDaniel Verkamp 	}
114376d117cSDaniel Verkamp 
115376d117cSDaniel Verkamp 	if (req.params) {
11659339feaSJan Kryl 		/* null json value is as if there were no parameters */
11759339feaSJan Kryl 		if (req.params->type != SPDK_JSON_VAL_NULL) {
118376d117cSDaniel Verkamp 			if (req.params->type != SPDK_JSON_VAL_ARRAY_BEGIN &&
119376d117cSDaniel Verkamp 			    req.params->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
12063978010SPawel Wodkowski 				goto invalid;
121376d117cSDaniel Verkamp 			}
12259339feaSJan Kryl 			params = req.params;
12359339feaSJan Kryl 		}
124376d117cSDaniel Verkamp 	}
125376d117cSDaniel Verkamp 
126134590a2SSeth Howell 	jsonrpc_server_handle_request(request, req.method, params);
12763978010SPawel Wodkowski 	return;
12863978010SPawel Wodkowski 
12963978010SPawel Wodkowski invalid:
130134590a2SSeth Howell 	jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
131376d117cSDaniel Verkamp }
132376d117cSDaniel Verkamp 
133d270cd36SPawel Kaminski static int
jsonrpc_server_write_cb(void * cb_ctx,const void * data,size_t size)1340be5557cSSeth Howell jsonrpc_server_write_cb(void *cb_ctx, const void *data, size_t size)
135d270cd36SPawel Kaminski {
136d270cd36SPawel Kaminski 	struct spdk_jsonrpc_request *request = cb_ctx;
137d270cd36SPawel Kaminski 	size_t new_size = request->send_buf_size;
138d270cd36SPawel Kaminski 
139d270cd36SPawel Kaminski 	while (new_size - request->send_len < size) {
140d270cd36SPawel Kaminski 		if (new_size >= SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
141d270cd36SPawel Kaminski 			SPDK_ERRLOG("Send buf exceeded maximum size (%zu)\n",
142d270cd36SPawel Kaminski 				    (size_t)SPDK_JSONRPC_SEND_BUF_SIZE_MAX);
143d270cd36SPawel Kaminski 			return -1;
144d270cd36SPawel Kaminski 		}
145d270cd36SPawel Kaminski 
146d270cd36SPawel Kaminski 		new_size *= 2;
147d270cd36SPawel Kaminski 	}
148d270cd36SPawel Kaminski 
149d270cd36SPawel Kaminski 	if (new_size != request->send_buf_size) {
150d270cd36SPawel Kaminski 		uint8_t *new_buf;
151d270cd36SPawel Kaminski 
15230b534c9SShuhei Matsumoto 		/* Add extra byte for the null terminator. */
15330b534c9SShuhei Matsumoto 		new_buf = realloc(request->send_buf, new_size + 1);
154d270cd36SPawel Kaminski 		if (new_buf == NULL) {
155d270cd36SPawel Kaminski 			SPDK_ERRLOG("Resizing send_buf failed (current size %zu, new size %zu)\n",
156d270cd36SPawel Kaminski 				    request->send_buf_size, new_size);
157d270cd36SPawel Kaminski 			return -1;
158d270cd36SPawel Kaminski 		}
159d270cd36SPawel Kaminski 
160d270cd36SPawel Kaminski 		request->send_buf = new_buf;
161d270cd36SPawel Kaminski 		request->send_buf_size = new_size;
162d270cd36SPawel Kaminski 	}
163d270cd36SPawel Kaminski 
164d270cd36SPawel Kaminski 	memcpy(request->send_buf + request->send_len, data, size);
165d270cd36SPawel Kaminski 	request->send_len += size;
166d270cd36SPawel Kaminski 
167d270cd36SPawel Kaminski 	return 0;
168d270cd36SPawel Kaminski }
169d270cd36SPawel Kaminski 
170376d117cSDaniel Verkamp int
jsonrpc_parse_request(struct spdk_jsonrpc_server_conn * conn,const void * json,size_t size)171134590a2SSeth Howell jsonrpc_parse_request(struct spdk_jsonrpc_server_conn *conn, const void *json, size_t size)
172376d117cSDaniel Verkamp {
173977fd230SDaniel Verkamp 	struct spdk_jsonrpc_request *request;
174376d117cSDaniel Verkamp 	ssize_t rc;
17563978010SPawel Wodkowski 	size_t len;
176376d117cSDaniel Verkamp 	void *end = NULL;
177376d117cSDaniel Verkamp 
17863978010SPawel Wodkowski 	/* Check to see if we have received a full JSON value. It is safe to cast away const
17963978010SPawel Wodkowski 	 * as we don't decode in place. */
18063978010SPawel Wodkowski 	rc = spdk_json_parse((void *)json, size, NULL, 0, &end, 0);
181376d117cSDaniel Verkamp 	if (rc == SPDK_JSON_PARSE_INCOMPLETE) {
182376d117cSDaniel Verkamp 		return 0;
183977fd230SDaniel Verkamp 	}
184977fd230SDaniel Verkamp 
185977fd230SDaniel Verkamp 	request = calloc(1, sizeof(*request));
186977fd230SDaniel Verkamp 	if (request == NULL) {
1872172c432STomasz Zawadzki 		SPDK_DEBUGLOG(rpc, "Out of memory allocating request\n");
188977fd230SDaniel Verkamp 		return -1;
189977fd230SDaniel Verkamp 	}
190977fd230SDaniel Verkamp 
1912fb672afSKrzysztof Karas 	pthread_spin_lock(&conn->queue_lock);
1924e003b67SDaniel Verkamp 	conn->outstanding_requests++;
1932fb672afSKrzysztof Karas 	STAILQ_INSERT_TAIL(&conn->outstanding_queue, request, link);
1942fb672afSKrzysztof Karas 	pthread_spin_unlock(&conn->queue_lock);
1954e003b67SDaniel Verkamp 
196977fd230SDaniel Verkamp 	request->conn = conn;
19763978010SPawel Wodkowski 
19863978010SPawel Wodkowski 	len = end - json;
19963978010SPawel Wodkowski 	request->recv_buffer = malloc(len + 1);
20063978010SPawel Wodkowski 	if (request->recv_buffer == NULL) {
20163978010SPawel Wodkowski 		SPDK_ERRLOG("Failed to allocate buffer to copy request (%zu bytes)\n", len + 1);
202134590a2SSeth Howell 		jsonrpc_free_request(request);
20363978010SPawel Wodkowski 		return -1;
20463978010SPawel Wodkowski 	}
20563978010SPawel Wodkowski 
20663978010SPawel Wodkowski 	memcpy(request->recv_buffer, json, len);
20763978010SPawel Wodkowski 	request->recv_buffer[len] = '\0';
20863978010SPawel Wodkowski 
209a4009e7aSShuhei Matsumoto 	jsonrpc_log(request->recv_buffer, "request: ");
210a4009e7aSShuhei Matsumoto 
21163978010SPawel Wodkowski 	if (rc > 0 && rc <= SPDK_JSONRPC_MAX_VALUES) {
21263978010SPawel Wodkowski 		request->values_cnt = rc;
21363978010SPawel Wodkowski 		request->values = malloc(request->values_cnt * sizeof(request->values[0]));
21463978010SPawel Wodkowski 		if (request->values == NULL) {
21563978010SPawel Wodkowski 			SPDK_ERRLOG("Failed to allocate buffer for JSON values (%zu bytes)\n",
21663978010SPawel Wodkowski 				    request->values_cnt * sizeof(request->values[0]));
217134590a2SSeth Howell 			jsonrpc_free_request(request);
21863978010SPawel Wodkowski 			return -1;
21963978010SPawel Wodkowski 		}
22063978010SPawel Wodkowski 	}
22163978010SPawel Wodkowski 
2224e003b67SDaniel Verkamp 	request->send_offset = 0;
2234e003b67SDaniel Verkamp 	request->send_len = 0;
224c7852cf9SDaniel Verkamp 	request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
22530b534c9SShuhei Matsumoto 	/* Add extra byte for the null terminator. */
22630b534c9SShuhei Matsumoto 	request->send_buf = malloc(request->send_buf_size + 1);
227c7852cf9SDaniel Verkamp 	if (request->send_buf == NULL) {
228c7852cf9SDaniel Verkamp 		SPDK_ERRLOG("Failed to allocate send_buf (%zu bytes)\n", request->send_buf_size);
229134590a2SSeth Howell 		jsonrpc_free_request(request);
230c7852cf9SDaniel Verkamp 		return -1;
231c7852cf9SDaniel Verkamp 	}
232977fd230SDaniel Verkamp 
2330be5557cSSeth Howell 	request->response = spdk_json_write_begin(jsonrpc_server_write_cb, request, 0);
234a15dcb0bSPawel Kaminski 	if (request->response == NULL) {
235a15dcb0bSPawel Kaminski 		SPDK_ERRLOG("Failed to allocate response JSON write context.\n");
236134590a2SSeth Howell 		jsonrpc_free_request(request);
237a15dcb0bSPawel Kaminski 		return -1;
238a15dcb0bSPawel Kaminski 	}
239a15dcb0bSPawel Kaminski 
24063978010SPawel Wodkowski 	if (rc <= 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
2412172c432STomasz Zawadzki 		SPDK_DEBUGLOG(rpc, "JSON parse error\n");
242134590a2SSeth Howell 		jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_PARSE_ERROR);
243376d117cSDaniel Verkamp 
244376d117cSDaniel Verkamp 		/*
245376d117cSDaniel Verkamp 		 * Can't recover from parse error (no guaranteed resync point in streaming JSON).
246376d117cSDaniel Verkamp 		 * Return an error to indicate that the connection should be closed.
247376d117cSDaniel Verkamp 		 */
248376d117cSDaniel Verkamp 		return -1;
249376d117cSDaniel Verkamp 	}
250376d117cSDaniel Verkamp 
251376d117cSDaniel Verkamp 	/* Decode a second time now that there is a full JSON value available. */
25263978010SPawel Wodkowski 	rc = spdk_json_parse(request->recv_buffer, size, request->values, request->values_cnt, &end,
253376d117cSDaniel Verkamp 			     SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
254376d117cSDaniel Verkamp 	if (rc < 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
2552172c432STomasz Zawadzki 		SPDK_DEBUGLOG(rpc, "JSON parse error on second pass\n");
256134590a2SSeth Howell 		jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_PARSE_ERROR);
257376d117cSDaniel Verkamp 		return -1;
258376d117cSDaniel Verkamp 	}
259376d117cSDaniel Verkamp 
260376d117cSDaniel Verkamp 	assert(end != NULL);
261376d117cSDaniel Verkamp 
26263978010SPawel Wodkowski 	if (request->values[0].type == SPDK_JSON_VAL_OBJECT_BEGIN) {
26363978010SPawel Wodkowski 		parse_single_request(request, request->values);
26463978010SPawel Wodkowski 	} else if (request->values[0].type == SPDK_JSON_VAL_ARRAY_BEGIN) {
2652172c432STomasz Zawadzki 		SPDK_DEBUGLOG(rpc, "Got batch array (not currently supported)\n");
266134590a2SSeth Howell 		jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
267376d117cSDaniel Verkamp 	} else {
2682172c432STomasz Zawadzki 		SPDK_DEBUGLOG(rpc, "top-level JSON value was not array or object\n");
269134590a2SSeth Howell 		jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_INVALID_REQUEST);
270376d117cSDaniel Verkamp 	}
271376d117cSDaniel Verkamp 
27263978010SPawel Wodkowski 	return len;
273376d117cSDaniel Verkamp }
274376d117cSDaniel Verkamp 
2755b1b3ddfSPawel Wodkowski struct spdk_jsonrpc_server_conn *
spdk_jsonrpc_get_conn(struct spdk_jsonrpc_request * request)2765b1b3ddfSPawel Wodkowski spdk_jsonrpc_get_conn(struct spdk_jsonrpc_request *request)
2775b1b3ddfSPawel Wodkowski {
2785b1b3ddfSPawel Wodkowski 	return request->conn;
2795b1b3ddfSPawel Wodkowski }
2805b1b3ddfSPawel Wodkowski 
281a15dcb0bSPawel Kaminski /* Never return NULL */
282376d117cSDaniel Verkamp static struct spdk_json_write_ctx *
begin_response(struct spdk_jsonrpc_request * request)2834e003b67SDaniel Verkamp begin_response(struct spdk_jsonrpc_request *request)
284376d117cSDaniel Verkamp {
285a15dcb0bSPawel Kaminski 	struct spdk_json_write_ctx *w = request->response;
286376d117cSDaniel Verkamp 
287376d117cSDaniel Verkamp 	spdk_json_write_object_begin(w);
28873f79a5cSShuhei Matsumoto 	spdk_json_write_named_string(w, "jsonrpc", "2.0");
289376d117cSDaniel Verkamp 
290376d117cSDaniel Verkamp 	spdk_json_write_name(w, "id");
29163978010SPawel Wodkowski 	if (request->id) {
29263978010SPawel Wodkowski 		spdk_json_write_val(w, request->id);
29363978010SPawel Wodkowski 	} else {
29463978010SPawel Wodkowski 		spdk_json_write_null(w);
29563978010SPawel Wodkowski 	}
296376d117cSDaniel Verkamp 
297376d117cSDaniel Verkamp 	return w;
298376d117cSDaniel Verkamp }
299376d117cSDaniel Verkamp 
300376d117cSDaniel Verkamp static void
skip_response(struct spdk_jsonrpc_request * request)3010f842e86SPawel Wodkowski skip_response(struct spdk_jsonrpc_request *request)
3020f842e86SPawel Wodkowski {
3030f842e86SPawel Wodkowski 	request->send_len = 0;
304a15dcb0bSPawel Kaminski 	spdk_json_write_end(request->response);
305a15dcb0bSPawel Kaminski 	request->response = NULL;
306134590a2SSeth Howell 	jsonrpc_server_send_response(request);
3070f842e86SPawel Wodkowski }
3080f842e86SPawel Wodkowski 
3090f842e86SPawel Wodkowski static void
end_response(struct spdk_jsonrpc_request * request)310a15dcb0bSPawel Kaminski end_response(struct spdk_jsonrpc_request *request)
311376d117cSDaniel Verkamp {
312a15dcb0bSPawel Kaminski 	spdk_json_write_object_end(request->response);
313a15dcb0bSPawel Kaminski 	spdk_json_write_end(request->response);
314a15dcb0bSPawel Kaminski 	request->response = NULL;
315a15dcb0bSPawel Kaminski 
3160be5557cSSeth Howell 	jsonrpc_server_write_cb(request, "\n", 1);
317134590a2SSeth Howell 	jsonrpc_server_send_response(request);
3184e003b67SDaniel Verkamp }
3194e003b67SDaniel Verkamp 
3204e003b67SDaniel Verkamp void
jsonrpc_free_request(struct spdk_jsonrpc_request * request)321134590a2SSeth Howell jsonrpc_free_request(struct spdk_jsonrpc_request *request)
3224e003b67SDaniel Verkamp {
3232fb672afSKrzysztof Karas 	struct spdk_jsonrpc_request *req;
3242fb672afSKrzysztof Karas 	struct spdk_jsonrpc_server_conn *conn;
3252fb672afSKrzysztof Karas 
32663978010SPawel Wodkowski 	if (!request) {
32763978010SPawel Wodkowski 		return;
32863978010SPawel Wodkowski 	}
32963978010SPawel Wodkowski 
330a15dcb0bSPawel Kaminski 	/* We must send or skip response explicitly */
331a15dcb0bSPawel Kaminski 	assert(request->response == NULL);
332a15dcb0bSPawel Kaminski 
3332fb672afSKrzysztof Karas 	conn = request->conn;
3342fb672afSKrzysztof Karas 	if (conn != NULL) {
3352fb672afSKrzysztof Karas 		pthread_spin_lock(&conn->queue_lock);
3362fb672afSKrzysztof Karas 		conn->outstanding_requests--;
3372fb672afSKrzysztof Karas 		STAILQ_FOREACH(req, &conn->outstanding_queue, link) {
3382fb672afSKrzysztof Karas 			if (req == request) {
3392fb672afSKrzysztof Karas 				STAILQ_REMOVE(&conn->outstanding_queue,
3402fb672afSKrzysztof Karas 					      req, spdk_jsonrpc_request, link);
3412fb672afSKrzysztof Karas 				break;
3422fb672afSKrzysztof Karas 			}
3432fb672afSKrzysztof Karas 		}
3442fb672afSKrzysztof Karas 		pthread_spin_unlock(&conn->queue_lock);
3452fb672afSKrzysztof Karas 	}
34663978010SPawel Wodkowski 	free(request->recv_buffer);
34763978010SPawel Wodkowski 	free(request->values);
348c7852cf9SDaniel Verkamp 	free(request->send_buf);
3494e003b67SDaniel Verkamp 	free(request);
350376d117cSDaniel Verkamp }
351376d117cSDaniel Verkamp 
352b3bec079SShuhei Matsumoto void
jsonrpc_complete_request(struct spdk_jsonrpc_request * request)353b3bec079SShuhei Matsumoto jsonrpc_complete_request(struct spdk_jsonrpc_request *request)
354b3bec079SShuhei Matsumoto {
355a4009e7aSShuhei Matsumoto 	jsonrpc_log(request->send_buf, "response: ");
356a4009e7aSShuhei Matsumoto 
357b3bec079SShuhei Matsumoto 	jsonrpc_free_request(request);
358b3bec079SShuhei Matsumoto }
359b3bec079SShuhei Matsumoto 
360376d117cSDaniel Verkamp struct spdk_json_write_ctx *
spdk_jsonrpc_begin_result(struct spdk_jsonrpc_request * request)3612bdec64fSDaniel Verkamp spdk_jsonrpc_begin_result(struct spdk_jsonrpc_request *request)
362376d117cSDaniel Verkamp {
363a15dcb0bSPawel Kaminski 	struct spdk_json_write_ctx *w = begin_response(request);
364376d117cSDaniel Verkamp 
365376d117cSDaniel Verkamp 	spdk_json_write_name(w, "result");
366376d117cSDaniel Verkamp 	return w;
367376d117cSDaniel Verkamp }
368376d117cSDaniel Verkamp 
369376d117cSDaniel Verkamp void
spdk_jsonrpc_end_result(struct spdk_jsonrpc_request * request,struct spdk_json_write_ctx * w)3702bdec64fSDaniel Verkamp spdk_jsonrpc_end_result(struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w)
371376d117cSDaniel Verkamp {
372376d117cSDaniel Verkamp 	assert(w != NULL);
373a15dcb0bSPawel Kaminski 	assert(w == request->response);
374376d117cSDaniel Verkamp 
375a15dcb0bSPawel Kaminski 	/* If there was no ID in request we skip response. */
376a15dcb0bSPawel Kaminski 	if (request->id && request->id->type != SPDK_JSON_VAL_NULL) {
377a15dcb0bSPawel Kaminski 		end_response(request);
378a15dcb0bSPawel Kaminski 	} else {
379a15dcb0bSPawel Kaminski 		skip_response(request);
380a15dcb0bSPawel Kaminski 	}
381376d117cSDaniel Verkamp }
382376d117cSDaniel Verkamp 
383376d117cSDaniel Verkamp void
spdk_jsonrpc_send_bool_response(struct spdk_jsonrpc_request * request,bool value)384d73077b8Syidong0635 spdk_jsonrpc_send_bool_response(struct spdk_jsonrpc_request *request, bool value)
385d73077b8Syidong0635 {
386d73077b8Syidong0635 	struct spdk_json_write_ctx *w;
387d73077b8Syidong0635 
388d73077b8Syidong0635 	w = spdk_jsonrpc_begin_result(request);
389d73077b8Syidong0635 	assert(w != NULL);
390d73077b8Syidong0635 	spdk_json_write_bool(w, value);
391d73077b8Syidong0635 	spdk_jsonrpc_end_result(request, w);
392d73077b8Syidong0635 }
393d73077b8Syidong0635 
394d73077b8Syidong0635 void
spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_request * request,int error_code,const char * msg)3952bdec64fSDaniel Verkamp spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_request *request,
396376d117cSDaniel Verkamp 				 int error_code, const char *msg)
397376d117cSDaniel Verkamp {
398a15dcb0bSPawel Kaminski 	struct spdk_json_write_ctx *w = begin_response(request);
399376d117cSDaniel Verkamp 
40073f79a5cSShuhei Matsumoto 	spdk_json_write_named_object_begin(w, "error");
40173f79a5cSShuhei Matsumoto 	spdk_json_write_named_int32(w, "code", error_code);
40273f79a5cSShuhei Matsumoto 	spdk_json_write_named_string(w, "message", msg);
403376d117cSDaniel Verkamp 	spdk_json_write_object_end(w);
404376d117cSDaniel Verkamp 
405a15dcb0bSPawel Kaminski 	end_response(request);
406376d117cSDaniel Verkamp }
407376d117cSDaniel Verkamp 
40897cb1713SPawel Wodkowski void
spdk_jsonrpc_send_error_response_fmt(struct spdk_jsonrpc_request * request,int error_code,const char * fmt,...)40997cb1713SPawel Wodkowski spdk_jsonrpc_send_error_response_fmt(struct spdk_jsonrpc_request *request,
41097cb1713SPawel Wodkowski 				     int error_code, const char *fmt, ...)
41197cb1713SPawel Wodkowski {
412a15dcb0bSPawel Kaminski 	struct spdk_json_write_ctx *w = begin_response(request);
41397cb1713SPawel Wodkowski 	va_list args;
41497cb1713SPawel Wodkowski 
41573f79a5cSShuhei Matsumoto 	spdk_json_write_named_object_begin(w, "error");
41673f79a5cSShuhei Matsumoto 	spdk_json_write_named_int32(w, "code", error_code);
41797cb1713SPawel Wodkowski 	va_start(args, fmt);
41873f79a5cSShuhei Matsumoto 	spdk_json_write_named_string_fmt_v(w, "message", fmt, args);
41997cb1713SPawel Wodkowski 	va_end(args);
42097cb1713SPawel Wodkowski 	spdk_json_write_object_end(w);
42197cb1713SPawel Wodkowski 
422a15dcb0bSPawel Kaminski 	end_response(request);
42397cb1713SPawel Wodkowski }
42497cb1713SPawel Wodkowski 
4252172c432STomasz Zawadzki SPDK_LOG_REGISTER_COMPONENT(rpc)
426