xref: /spdk/lib/jsonrpc/jsonrpc_client.c (revision a6dbe3721eb3b5990707fc3e378c95e505dd8ab5)
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
capture_version(const struct spdk_json_val * val,void * out)10 capture_version(const struct spdk_json_val *val, void *out)
11 {
12 	const struct spdk_json_val **vptr = out;
13 
14 	if (spdk_json_strequal(val, "2.0") != true) {
15 		return SPDK_JSON_PARSE_INVALID;
16 	}
17 
18 	*vptr = val;
19 	return 0;
20 }
21 
22 static int
capture_id(const struct spdk_json_val * val,void * out)23 capture_id(const struct spdk_json_val *val, void *out)
24 {
25 	const struct spdk_json_val **vptr = out;
26 
27 	if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NUMBER) {
28 		return -EINVAL;
29 	}
30 
31 	*vptr = val;
32 	return 0;
33 }
34 
35 static int
capture_any(const struct spdk_json_val * val,void * out)36 capture_any(const struct spdk_json_val *val, void *out)
37 {
38 	const struct spdk_json_val **vptr = out;
39 
40 	*vptr = val;
41 	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
jsonrpc_parse_response(struct spdk_jsonrpc_client * client)52 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 	void *end = NULL;
59 
60 
61 	/* Check to see if we have received a full JSON value. */
62 	rc = spdk_json_parse(client->recv_buf, client->recv_offset, NULL, 0, &end, 0);
63 	if (rc == SPDK_JSON_PARSE_INCOMPLETE) {
64 		return 0;
65 	}
66 
67 	SPDK_DEBUGLOG(rpc_client, "JSON string is :\n%s\n", client->recv_buf);
68 	if (rc < 0 || rc > SPDK_JSONRPC_CLIENT_MAX_VALUES) {
69 		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 		return -EINVAL;
75 	}
76 
77 	values_cnt = rc;
78 
79 	r = calloc(1, sizeof(*r) + sizeof(struct spdk_json_val) * (values_cnt + 1));
80 	if (!r) {
81 		return -errno;
82 	}
83 
84 	if (client->resp) {
85 		free(r);
86 		return -ENOSPC;
87 	}
88 
89 	client->resp = r;
90 
91 	r->buf = client->recv_buf;
92 	buf_len = client->recv_offset;
93 	r->values_cnt = values_cnt;
94 
95 	client->recv_buf_size = 0;
96 	client->recv_offset = 0;
97 	client->recv_buf = NULL;
98 
99 	/* Decode a second time now that there is a full JSON value available. */
100 	rc = spdk_json_parse(r->buf, buf_len, r->values, values_cnt, &end,
101 			     SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
102 	if (rc != (ssize_t)values_cnt) {
103 		SPDK_ERRLOG("JSON parse error on second pass (rc: %zd, expected: %zu)\n", rc, values_cnt);
104 		goto err;
105 	}
106 
107 	assert(end != NULL);
108 
109 	if (r->values[0].type != SPDK_JSON_VAL_OBJECT_BEGIN) {
110 		SPDK_ERRLOG("top-level JSON value was not object\n");
111 		goto err;
112 	}
113 
114 	if (spdk_json_decode_object(r->values, jsonrpc_response_decoders,
115 				    SPDK_COUNTOF(jsonrpc_response_decoders), &r->jsonrpc)) {
116 		goto err;
117 	}
118 
119 	r->ready = 1;
120 	return 1;
121 
122 err:
123 	client->resp = NULL;
124 	spdk_jsonrpc_client_free_response(&r->jsonrpc);
125 	return -EINVAL;
126 }
127 
128 static int
jsonrpc_client_write_cb(void * cb_ctx,const void * data,size_t size)129 jsonrpc_client_write_cb(void *cb_ctx, const void *data, size_t size)
130 {
131 	struct spdk_jsonrpc_client_request *request = cb_ctx;
132 	size_t new_size = request->send_buf_size;
133 
134 	while (new_size - request->send_len < size) {
135 		if (new_size >= SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
136 			SPDK_ERRLOG("Send buf exceeded maximum size (%zu)\n",
137 				    (size_t)SPDK_JSONRPC_SEND_BUF_SIZE_MAX);
138 			return -ENOSPC;
139 		}
140 
141 		new_size *= 2;
142 	}
143 
144 	if (new_size != request->send_buf_size) {
145 		uint8_t *new_buf;
146 
147 		new_buf = realloc(request->send_buf, new_size);
148 		if (new_buf == NULL) {
149 			SPDK_ERRLOG("Resizing send_buf failed (current size %zu, new size %zu)\n",
150 				    request->send_buf_size, new_size);
151 			return -ENOMEM;
152 		}
153 
154 		request->send_buf = new_buf;
155 		request->send_buf_size = new_size;
156 	}
157 
158 	memcpy(request->send_buf + request->send_len, data, size);
159 	request->send_len += size;
160 
161 	return 0;
162 }
163 
164 struct spdk_json_write_ctx *
spdk_jsonrpc_begin_request(struct spdk_jsonrpc_client_request * request,int32_t id,const char * method)165 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 	w = spdk_json_write_begin(jsonrpc_client_write_cb, request, 0);
171 	if (w == NULL) {
172 		return NULL;
173 	}
174 
175 	spdk_json_write_object_begin(w);
176 	spdk_json_write_named_string(w, "jsonrpc", "2.0");
177 
178 	if (id >= 0) {
179 		spdk_json_write_named_int32(w, "id", id);
180 	}
181 
182 	if (method) {
183 		spdk_json_write_named_string(w, "method", method);
184 	}
185 
186 	return w;
187 }
188 
189 void
spdk_jsonrpc_end_request(struct spdk_jsonrpc_client_request * request,struct spdk_json_write_ctx * w)190 spdk_jsonrpc_end_request(struct spdk_jsonrpc_client_request *request, struct spdk_json_write_ctx *w)
191 {
192 	assert(w != NULL);
193 
194 	spdk_json_write_object_end(w);
195 	spdk_json_write_end(w);
196 	jsonrpc_client_write_cb(request, "\n", 1);
197 }
198 
199 SPDK_LOG_REGISTER_COMPONENT(rpc_client)
200