Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2018 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/util.h"
7 : : #include "jsonrpc_internal.h"
8 : :
9 : : static int
10 : 4531 : capture_version(const struct spdk_json_val *val, void *out)
11 : : {
12 : 4531 : const struct spdk_json_val **vptr = out;
13 : :
14 [ - + ]: 4531 : if (spdk_json_strequal(val, "2.0") != true) {
15 : 0 : return SPDK_JSON_PARSE_INVALID;
16 : : }
17 : :
18 : 4531 : *vptr = val;
19 : 4531 : return 0;
20 : : }
21 : :
22 : : static int
23 : 4531 : capture_id(const struct spdk_json_val *val, void *out)
24 : : {
25 : 4531 : const struct spdk_json_val **vptr = out;
26 : :
27 [ + - - + ]: 4531 : if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NUMBER) {
28 : 0 : return -EINVAL;
29 : : }
30 : :
31 : 4531 : *vptr = val;
32 : 4531 : return 0;
33 : : }
34 : :
35 : : static int
36 : 4531 : capture_any(const struct spdk_json_val *val, void *out)
37 : : {
38 : 4531 : const struct spdk_json_val **vptr = out;
39 : :
40 : 4531 : *vptr = val;
41 : 4531 : return 0;
42 : : }
43 : :
44 : : static const struct spdk_json_object_decoder jsonrpc_response_decoders[] = {
45 : : {"jsonrpc", offsetof(struct spdk_jsonrpc_client_response, version), capture_version},
46 : : {"id", offsetof(struct spdk_jsonrpc_client_response, id), capture_id, true},
47 : : {"result", offsetof(struct spdk_jsonrpc_client_response, result), capture_any, true},
48 : : {"error", offsetof(struct spdk_jsonrpc_client_response, error), capture_any, true},
49 : : };
50 : :
51 : : int
52 : 4531 : jsonrpc_parse_response(struct spdk_jsonrpc_client *client)
53 : : {
54 : : struct spdk_jsonrpc_client_response_internal *r;
55 : : ssize_t rc;
56 : : size_t buf_len;
57 : : size_t values_cnt;
58 : 4531 : void *end = NULL;
59 : :
60 : :
61 : : /* Check to see if we have received a full JSON value. */
62 : 4531 : rc = spdk_json_parse(client->recv_buf, client->recv_offset, NULL, 0, &end, 0);
63 [ - + ]: 4531 : if (rc == SPDK_JSON_PARSE_INCOMPLETE) {
64 : 0 : return 0;
65 : : }
66 : :
67 [ - + - + ]: 4531 : SPDK_DEBUGLOG(rpc_client, "JSON string is :\n%s\n", client->recv_buf);
68 [ + - - + ]: 4531 : if (rc < 0 || rc > SPDK_JSONRPC_CLIENT_MAX_VALUES) {
69 : 0 : SPDK_ERRLOG("JSON parse error (rc: %zd)\n", rc);
70 : : /*
71 : : * Can't recover from parse error (no guaranteed resync point in streaming JSON).
72 : : * Return an error to indicate that the connection should be closed.
73 : : */
74 : 0 : return -EINVAL;
75 : : }
76 : :
77 : 4531 : values_cnt = rc;
78 : :
79 : 4531 : r = calloc(1, sizeof(*r) + sizeof(struct spdk_json_val) * (values_cnt + 1));
80 [ - + ]: 4531 : if (!r) {
81 : 0 : return -errno;
82 : : }
83 : :
84 [ - + ]: 4531 : if (client->resp) {
85 : 0 : free(r);
86 : 0 : return -ENOSPC;
87 : : }
88 : :
89 : 4531 : client->resp = r;
90 : :
91 : 4531 : r->buf = client->recv_buf;
92 : 4531 : buf_len = client->recv_offset;
93 : 4531 : r->values_cnt = values_cnt;
94 : :
95 : 4531 : client->recv_buf_size = 0;
96 : 4531 : client->recv_offset = 0;
97 : 4531 : client->recv_buf = NULL;
98 : :
99 : : /* Decode a second time now that there is a full JSON value available. */
100 : 4531 : rc = spdk_json_parse(r->buf, buf_len, r->values, values_cnt, &end,
101 : : SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
102 [ - + ]: 4531 : if (rc != (ssize_t)values_cnt) {
103 : 0 : SPDK_ERRLOG("JSON parse error on second pass (rc: %zd, expected: %zu)\n", rc, values_cnt);
104 : 0 : goto err;
105 : : }
106 : :
107 [ - + ]: 4531 : assert(end != NULL);
108 : :
109 [ - + ]: 4531 : if (r->values[0].type != SPDK_JSON_VAL_OBJECT_BEGIN) {
110 : 0 : SPDK_ERRLOG("top-level JSON value was not object\n");
111 : 0 : goto err;
112 : : }
113 : :
114 [ - + ]: 4531 : if (spdk_json_decode_object(r->values, jsonrpc_response_decoders,
115 : 4531 : SPDK_COUNTOF(jsonrpc_response_decoders), &r->jsonrpc)) {
116 : 0 : goto err;
117 : : }
118 : :
119 : 4531 : r->ready = 1;
120 : 4531 : return 1;
121 : :
122 : 0 : err:
123 : 0 : client->resp = NULL;
124 : 0 : spdk_jsonrpc_client_free_response(&r->jsonrpc);
125 : 0 : return -EINVAL;
126 : : }
127 : :
128 : : static int
129 : 9062 : jsonrpc_client_write_cb(void *cb_ctx, const void *data, size_t size)
130 : : {
131 : 9062 : struct spdk_jsonrpc_client_request *request = cb_ctx;
132 : 9062 : size_t new_size = request->send_buf_size;
133 : :
134 [ - + ]: 9062 : while (new_size - request->send_len < size) {
135 [ # # ]: 0 : if (new_size >= SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
136 : 0 : SPDK_ERRLOG("Send buf exceeded maximum size (%zu)\n",
137 : : (size_t)SPDK_JSONRPC_SEND_BUF_SIZE_MAX);
138 : 0 : return -ENOSPC;
139 : : }
140 : :
141 : 0 : new_size *= 2;
142 : : }
143 : :
144 [ - + ]: 9062 : if (new_size != request->send_buf_size) {
145 : : uint8_t *new_buf;
146 : :
147 : 0 : new_buf = realloc(request->send_buf, new_size);
148 [ # # ]: 0 : if (new_buf == NULL) {
149 : 0 : SPDK_ERRLOG("Resizing send_buf failed (current size %zu, new size %zu)\n",
150 : : request->send_buf_size, new_size);
151 : 0 : return -ENOMEM;
152 : : }
153 : :
154 : 0 : request->send_buf = new_buf;
155 : 0 : request->send_buf_size = new_size;
156 : : }
157 : :
158 [ - + - + ]: 9062 : memcpy(request->send_buf + request->send_len, data, size);
159 : 9062 : request->send_len += size;
160 : :
161 : 9062 : return 0;
162 : : }
163 : :
164 : : struct spdk_json_write_ctx *
165 : 4531 : spdk_jsonrpc_begin_request(struct spdk_jsonrpc_client_request *request, int32_t id,
166 : : const char *method)
167 : : {
168 : : struct spdk_json_write_ctx *w;
169 : :
170 : 4531 : w = spdk_json_write_begin(jsonrpc_client_write_cb, request, 0);
171 [ - + ]: 4531 : if (w == NULL) {
172 : 0 : return NULL;
173 : : }
174 : :
175 : 4531 : spdk_json_write_object_begin(w);
176 : 4531 : spdk_json_write_named_string(w, "jsonrpc", "2.0");
177 : :
178 [ + - ]: 4531 : if (id >= 0) {
179 : 4531 : spdk_json_write_named_int32(w, "id", id);
180 : : }
181 : :
182 [ + + ]: 4531 : if (method) {
183 : 57 : spdk_json_write_named_string(w, "method", method);
184 : : }
185 : :
186 : 4531 : return w;
187 : : }
188 : :
189 : : void
190 : 4531 : spdk_jsonrpc_end_request(struct spdk_jsonrpc_client_request *request, struct spdk_json_write_ctx *w)
191 : : {
192 [ - + ]: 4531 : assert(w != NULL);
193 : :
194 : 4531 : spdk_json_write_object_end(w);
195 : 4531 : spdk_json_write_end(w);
196 : 4531 : jsonrpc_client_write_cb(request, "\n", 1);
197 : 4531 : }
198 : :
199 : 3155 : SPDK_LOG_REGISTER_COMPONENT(rpc_client)
|