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 0 : capture_version(const struct spdk_json_val *val, void *out)
11 : {
12 0 : const struct spdk_json_val **vptr = out;
13 :
14 0 : if (spdk_json_strequal(val, "2.0") != true) {
15 0 : return SPDK_JSON_PARSE_INVALID;
16 : }
17 :
18 0 : *vptr = val;
19 0 : return 0;
20 0 : }
21 :
22 : static int
23 0 : capture_id(const struct spdk_json_val *val, void *out)
24 : {
25 0 : const struct spdk_json_val **vptr = out;
26 :
27 0 : if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NUMBER) {
28 0 : return -EINVAL;
29 : }
30 :
31 0 : *vptr = val;
32 0 : return 0;
33 0 : }
34 :
35 : static int
36 0 : capture_any(const struct spdk_json_val *val, void *out)
37 : {
38 0 : const struct spdk_json_val **vptr = out;
39 :
40 0 : *vptr = val;
41 0 : 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 0 : 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 0 : void *end = NULL;
59 :
60 :
61 : /* Check to see if we have received a full JSON value. */
62 0 : rc = spdk_json_parse(client->recv_buf, client->recv_offset, NULL, 0, &end, 0);
63 0 : if (rc == SPDK_JSON_PARSE_INCOMPLETE) {
64 0 : return 0;
65 : }
66 :
67 0 : SPDK_DEBUGLOG(rpc_client, "JSON string is :\n%s\n", client->recv_buf);
68 0 : 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 0 : values_cnt = rc;
78 :
79 0 : r = calloc(1, sizeof(*r) + sizeof(struct spdk_json_val) * (values_cnt + 1));
80 0 : if (!r) {
81 0 : return -errno;
82 : }
83 :
84 0 : if (client->resp) {
85 0 : free(r);
86 0 : return -ENOSPC;
87 : }
88 :
89 0 : client->resp = r;
90 :
91 0 : r->buf = client->recv_buf;
92 0 : buf_len = client->recv_offset;
93 0 : r->values_cnt = values_cnt;
94 :
95 0 : client->recv_buf_size = 0;
96 0 : client->recv_offset = 0;
97 0 : client->recv_buf = NULL;
98 :
99 : /* Decode a second time now that there is a full JSON value available. */
100 0 : rc = spdk_json_parse(r->buf, buf_len, r->values, values_cnt, &end,
101 : SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
102 0 : 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 0 : assert(end != NULL);
108 :
109 0 : 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 0 : if (spdk_json_decode_object(r->values, jsonrpc_response_decoders,
115 0 : SPDK_COUNTOF(jsonrpc_response_decoders), &r->jsonrpc)) {
116 0 : goto err;
117 : }
118 :
119 0 : r->ready = 1;
120 0 : return 1;
121 :
122 : err:
123 0 : client->resp = NULL;
124 0 : spdk_jsonrpc_client_free_response(&r->jsonrpc);
125 0 : return -EINVAL;
126 0 : }
127 :
128 : static int
129 0 : jsonrpc_client_write_cb(void *cb_ctx, const void *data, size_t size)
130 : {
131 0 : struct spdk_jsonrpc_client_request *request = cb_ctx;
132 0 : size_t new_size = request->send_buf_size;
133 :
134 0 : 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 0 : 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 0 : }
157 :
158 0 : memcpy(request->send_buf + request->send_len, data, size);
159 0 : request->send_len += size;
160 :
161 0 : return 0;
162 0 : }
163 :
164 : struct spdk_json_write_ctx *
165 0 : 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 0 : w = spdk_json_write_begin(jsonrpc_client_write_cb, request, 0);
171 0 : if (w == NULL) {
172 0 : return NULL;
173 : }
174 :
175 0 : spdk_json_write_object_begin(w);
176 0 : spdk_json_write_named_string(w, "jsonrpc", "2.0");
177 :
178 0 : if (id >= 0) {
179 0 : spdk_json_write_named_int32(w, "id", id);
180 0 : }
181 :
182 0 : if (method) {
183 0 : spdk_json_write_named_string(w, "method", method);
184 0 : }
185 :
186 0 : return w;
187 0 : }
188 :
189 : void
190 0 : spdk_jsonrpc_end_request(struct spdk_jsonrpc_client_request *request, struct spdk_json_write_ctx *w)
191 : {
192 0 : assert(w != NULL);
193 :
194 0 : spdk_json_write_object_end(w);
195 0 : spdk_json_write_end(w);
196 0 : jsonrpc_client_write_cb(request, "\n", 1);
197 0 : }
198 :
199 0 : SPDK_LOG_REGISTER_COMPONENT(rpc_client)
|