4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "jsonrpc_internal.h"
36 #include "spdk/util.h"
38 struct jsonrpc_request
{
39 const struct spdk_json_val
*version
;
40 const struct spdk_json_val
*method
;
41 const struct spdk_json_val
*params
;
42 const struct spdk_json_val
*id
;
46 capture_val(const struct spdk_json_val
*val
, void *out
)
48 const struct spdk_json_val
**vptr
= out
;
54 static const struct spdk_json_object_decoder jsonrpc_request_decoders
[] = {
55 {"jsonrpc", offsetof(struct jsonrpc_request
, version
), capture_val
},
56 {"method", offsetof(struct jsonrpc_request
, method
), capture_val
},
57 {"params", offsetof(struct jsonrpc_request
, params
), capture_val
, true},
58 {"id", offsetof(struct jsonrpc_request
, id
), capture_val
, true},
62 parse_single_request(struct spdk_jsonrpc_server_conn
*conn
, struct spdk_json_val
*values
)
65 struct jsonrpc_request req
= {};
67 if (spdk_json_decode_object(values
, jsonrpc_request_decoders
,
68 SPDK_COUNTOF(jsonrpc_request_decoders
),
74 if (!req
.version
|| req
.version
->type
!= SPDK_JSON_VAL_STRING
||
75 !spdk_json_strequal(req
.version
, "2.0")) {
79 if (!req
.method
|| req
.method
->type
!= SPDK_JSON_VAL_STRING
) {
85 if (req
.id
->type
!= SPDK_JSON_VAL_STRING
&&
86 req
.id
->type
!= SPDK_JSON_VAL_NUMBER
&&
87 req
.id
->type
!= SPDK_JSON_VAL_NULL
) {
94 if (req
.params
->type
!= SPDK_JSON_VAL_ARRAY_BEGIN
&&
95 req
.params
->type
!= SPDK_JSON_VAL_OBJECT_BEGIN
) {
103 spdk_jsonrpc_server_handle_error(conn
, SPDK_JSONRPC_ERROR_INVALID_REQUEST
, req
.method
, req
.params
,
106 spdk_jsonrpc_server_handle_request(conn
, req
.method
, req
.params
, req
.id
);
111 parse_batch_request(struct spdk_jsonrpc_server_conn
*conn
, struct spdk_json_val
*values
)
113 size_t num_values
, i
;
115 assert(values
[0].type
== SPDK_JSON_VAL_ARRAY_BEGIN
);
116 num_values
= values
[0].len
;
119 assert(conn
->json_writer
== NULL
);
121 if (num_values
== 0) {
122 SPDK_TRACELOG(SPDK_TRACE_RPC
, "empty batch array not allowed");
123 spdk_jsonrpc_server_handle_error(conn
, SPDK_JSONRPC_ERROR_INVALID_REQUEST
, NULL
, NULL
, NULL
);
128 while (i
< num_values
) {
129 struct spdk_json_val
*v
= &values
[i
];
131 parse_single_request(conn
, v
);
132 i
+= spdk_json_val_len(v
);
135 if (conn
->json_writer
) {
137 * There was at least one response - finish the batch array.
139 spdk_json_write_array_end(conn
->json_writer
);
140 spdk_json_write_end(conn
->json_writer
);
141 conn
->json_writer
= NULL
;
146 spdk_jsonrpc_parse_request(struct spdk_jsonrpc_server_conn
*conn
, void *json
, size_t size
)
151 assert(conn
->json_writer
== NULL
);
155 /* Check to see if we have received a full JSON value. */
156 rc
= spdk_json_parse(json
, size
, NULL
, 0, &end
, 0);
157 if (rc
== SPDK_JSON_PARSE_INCOMPLETE
) {
159 } else if (rc
< 0 || rc
> SPDK_JSONRPC_MAX_VALUES
) {
160 SPDK_TRACELOG(SPDK_TRACE_RPC
, "JSON parse error\n");
161 spdk_jsonrpc_server_handle_error(conn
, SPDK_JSONRPC_ERROR_PARSE_ERROR
, NULL
, NULL
, NULL
);
164 * Can't recover from parse error (no guaranteed resync point in streaming JSON).
165 * Return an error to indicate that the connection should be closed.
170 /* Decode a second time now that there is a full JSON value available. */
171 rc
= spdk_json_parse(json
, size
, conn
->values
, SPDK_JSONRPC_MAX_VALUES
, &end
,
172 SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE
);
173 if (rc
< 0 || rc
> SPDK_JSONRPC_MAX_VALUES
) {
174 SPDK_TRACELOG(SPDK_TRACE_RPC
, "JSON parse error on second pass\n");
175 spdk_jsonrpc_server_handle_error(conn
, SPDK_JSONRPC_ERROR_PARSE_ERROR
, NULL
, NULL
, NULL
);
181 if (conn
->values
[0].type
== SPDK_JSON_VAL_OBJECT_BEGIN
) {
182 parse_single_request(conn
, conn
->values
);
183 } else if (conn
->values
[0].type
== SPDK_JSON_VAL_ARRAY_BEGIN
) {
185 parse_batch_request(conn
, conn
->values
);
187 SPDK_TRACELOG(SPDK_TRACE_RPC
, "top-level JSON value was not array or object\n");
188 spdk_jsonrpc_server_handle_error(conn
, SPDK_JSONRPC_ERROR_INVALID_REQUEST
, NULL
, NULL
, NULL
);
194 static struct spdk_json_write_ctx
*
195 begin_response(struct spdk_jsonrpc_server_conn
*conn
, const struct spdk_json_val
*id
)
197 struct spdk_json_write_ctx
*w
= conn
->json_writer
;
200 conn
->json_writer
= w
= spdk_json_write_begin(spdk_jsonrpc_server_write_cb
, conn
, 0);
207 spdk_json_write_object_begin(w
);
208 spdk_json_write_name(w
, "jsonrpc");
209 spdk_json_write_string(w
, "2.0");
212 spdk_json_write_name(w
, "id");
213 spdk_json_write_val(w
, id
);
220 end_response(struct spdk_jsonrpc_server_conn
*conn
, struct spdk_json_write_ctx
*w
)
222 spdk_json_write_object_end(w
);
225 spdk_json_write_end(w
);
226 spdk_jsonrpc_server_write_cb(conn
, "\n", 1);
227 conn
->json_writer
= NULL
;
231 struct spdk_json_write_ctx
*
232 spdk_jsonrpc_begin_result(struct spdk_jsonrpc_server_conn
*conn
, const struct spdk_json_val
*id
)
234 struct spdk_json_write_ctx
*w
;
236 w
= begin_response(conn
, id
);
241 spdk_json_write_name(w
, "result");
247 spdk_jsonrpc_end_result(struct spdk_jsonrpc_server_conn
*conn
, struct spdk_json_write_ctx
*w
)
250 assert(w
== conn
->json_writer
);
252 end_response(conn
, w
);
256 spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_server_conn
*conn
,
257 const struct spdk_json_val
*id
,
258 int error_code
, const char *msg
)
260 struct spdk_json_write_ctx
*w
;
261 struct spdk_json_val v_null
;
264 /* For error responses, if id is missing, explicitly respond with "id": null. */
265 v_null
.type
= SPDK_JSON_VAL_NULL
;
269 w
= begin_response(conn
, id
);
274 spdk_json_write_name(w
, "error");
275 spdk_json_write_object_begin(w
);
276 spdk_json_write_name(w
, "code");
277 spdk_json_write_int32(w
, error_code
);
278 spdk_json_write_name(w
, "message");
279 spdk_json_write_string(w
, msg
);
280 spdk_json_write_object_end(w
);
282 end_response(conn
, w
);
285 SPDK_LOG_REGISTER_TRACE_FLAG("rpc", SPDK_TRACE_RPC
)