1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2018 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "spdk/string.h"
7 #include "jsonrpc_internal.h"
8 #include "spdk/util.h"
9
10 #define RPC_DEFAULT_PORT "5260"
11
12 static int
jsonrpc_client_send_request(struct spdk_jsonrpc_client * client)13 jsonrpc_client_send_request(struct spdk_jsonrpc_client *client)
14 {
15 ssize_t rc;
16 struct spdk_jsonrpc_client_request *request = client->request;
17
18 if (!request) {
19 return 0;
20 }
21
22 if (request->send_len > 0) {
23 rc = send(client->sockfd, request->send_buf + request->send_offset,
24 request->send_len, 0);
25 if (rc < 0) {
26 /* For EINTR we pretend that nothing was send. */
27 if (errno == EINTR) {
28 rc = 0;
29 } else {
30 rc = -errno;
31 SPDK_ERRLOG("poll() failed (%d): %s\n", errno, spdk_strerror(errno));
32 }
33
34 return rc;
35 }
36
37 request->send_offset += rc;
38 request->send_len -= rc;
39 }
40
41 if (request->send_len == 0) {
42 client->request = NULL;
43 spdk_jsonrpc_client_free_request(request);
44 }
45
46 return 0;
47 }
48
49 static int
recv_buf_expand(struct spdk_jsonrpc_client * client)50 recv_buf_expand(struct spdk_jsonrpc_client *client)
51 {
52 uint8_t *new_buf;
53
54 if (client->recv_buf_size * 2 > SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
55 return -ENOSPC;
56 }
57
58 new_buf = realloc(client->recv_buf, client->recv_buf_size * 2);
59 if (new_buf == NULL) {
60 SPDK_ERRLOG("Resizing recv_buf failed (current size %zu, new size %zu)\n",
61 client->recv_buf_size, client->recv_buf_size * 2);
62 return -ENOMEM;
63 }
64
65 client->recv_buf = new_buf;
66 client->recv_buf_size *= 2;
67
68 return 0;
69 }
70
71 static int
jsonrpc_client_resp_ready_count(struct spdk_jsonrpc_client * client)72 jsonrpc_client_resp_ready_count(struct spdk_jsonrpc_client *client)
73 {
74 return client->resp != NULL && client->resp->ready ? 1 : 0;
75 }
76
77 static int
jsonrpc_client_recv(struct spdk_jsonrpc_client * client)78 jsonrpc_client_recv(struct spdk_jsonrpc_client *client)
79 {
80 ssize_t rc;
81
82 if (client->recv_buf == NULL) {
83 client->recv_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT);
84 if (!client->recv_buf) {
85 rc = errno;
86 SPDK_ERRLOG("malloc() failed (%d): %s\n", (int)rc, spdk_strerror(rc));
87 return -rc;
88 }
89 client->recv_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
90 client->recv_offset = 0;
91 } else if (client->recv_offset == client->recv_buf_size - 1) {
92 rc = recv_buf_expand(client);
93 if (rc) {
94 return rc;
95 }
96 }
97
98 rc = recv(client->sockfd, client->recv_buf + client->recv_offset,
99 client->recv_buf_size - client->recv_offset - 1, 0);
100 if (rc < 0) {
101 /* For EINTR we pretend that nothing was received. */
102 if (errno == EINTR) {
103 return 0;
104 } else {
105 rc = -errno;
106 SPDK_ERRLOG("recv() failed (%d): %s\n", errno, spdk_strerror(errno));
107 return rc;
108 }
109 } else if (rc == 0) {
110 return -EIO;
111 }
112
113 client->recv_offset += rc;
114 client->recv_buf[client->recv_offset] = '\0';
115
116 /* Check to see if we have received a full JSON value. */
117 return jsonrpc_parse_response(client);
118 }
119
120 static int
jsonrpc_client_poll(struct spdk_jsonrpc_client * client,int timeout)121 jsonrpc_client_poll(struct spdk_jsonrpc_client *client, int timeout)
122 {
123 int rc;
124 struct pollfd pfd = { .fd = client->sockfd, .events = POLLIN | POLLOUT };
125
126 rc = poll(&pfd, 1, timeout);
127 if (rc == -1) {
128 if (errno == EINTR) {
129 /* For EINTR we pretend that nothing was received nor send. */
130 rc = 0;
131 } else {
132 rc = -errno;
133 SPDK_ERRLOG("poll() failed (%d): %s\n", errno, spdk_strerror(errno));
134 }
135 } else if (rc > 0) {
136 rc = 0;
137
138 if (pfd.revents & POLLOUT) {
139 rc = jsonrpc_client_send_request(client);
140 }
141
142 if (rc == 0 && (pfd.revents & POLLIN)) {
143 rc = jsonrpc_client_recv(client);
144 /* Incomplete message in buffer isn't an error. */
145 if (rc == -EAGAIN) {
146 rc = 0;
147 }
148 }
149 }
150
151 return rc ? rc : jsonrpc_client_resp_ready_count(client);
152 }
153
154 static int
jsonrpc_client_poll_connecting(struct spdk_jsonrpc_client * client,int timeout)155 jsonrpc_client_poll_connecting(struct spdk_jsonrpc_client *client, int timeout)
156 {
157 socklen_t rc_len;
158 int rc;
159
160 struct pollfd pfd = {
161 .fd = client->sockfd,
162 .events = POLLOUT
163 };
164
165 rc = poll(&pfd, 1, timeout);
166 if (rc == 0) {
167 return -ENOTCONN;
168 } else if (rc == -1) {
169 if (errno != EINTR) {
170 SPDK_ERRLOG("poll() failed (%d): %s\n", errno, spdk_strerror(errno));
171 goto err;
172 }
173
174 /* We are still not connected. Caller will have to call us again. */
175 return -ENOTCONN;
176 } else if (pfd.revents & ~POLLOUT) {
177 /* We only poll for POLLOUT */
178 goto err;
179 } else if ((pfd.revents & POLLOUT) == 0) {
180 /* Is this even possible to get here? */
181 return -ENOTCONN;
182 }
183
184 rc_len = sizeof(int);
185 /* connection might fail so need to check SO_ERROR. */
186 if (getsockopt(client->sockfd, SOL_SOCKET, SO_ERROR, &rc, &rc_len) == -1) {
187 goto err;
188 }
189
190 if (rc == 0) {
191 client->connected = true;
192 return 0;
193 }
194
195 err:
196 return -EIO;
197 }
198
199 static int
jsonrpc_client_connect(struct spdk_jsonrpc_client * client,int domain,int protocol,struct sockaddr * server_addr,socklen_t addrlen)200 jsonrpc_client_connect(struct spdk_jsonrpc_client *client, int domain, int protocol,
201 struct sockaddr *server_addr, socklen_t addrlen)
202 {
203 int rc;
204
205 client->sockfd = socket(domain, SOCK_STREAM | SOCK_NONBLOCK, protocol);
206 if (client->sockfd < 0) {
207 rc = errno;
208 SPDK_ERRLOG("socket() failed\n");
209 return -rc;
210 }
211
212 rc = connect(client->sockfd, server_addr, addrlen);
213 if (rc != 0) {
214 rc = errno;
215 if (rc != EINPROGRESS) {
216 SPDK_ERRLOG("could not connect to JSON-RPC server: %s\n", spdk_strerror(errno));
217 goto err;
218 }
219 } else {
220 client->connected = true;
221 }
222
223 return -rc;
224 err:
225 close(client->sockfd);
226 client->sockfd = -1;
227 return -rc;
228 }
229
230 struct spdk_jsonrpc_client *
spdk_jsonrpc_client_connect(const char * addr,int addr_family)231 spdk_jsonrpc_client_connect(const char *addr, int addr_family)
232 {
233 struct spdk_jsonrpc_client *client = calloc(1, sizeof(struct spdk_jsonrpc_client));
234 /* Unix Domain Socket */
235 struct sockaddr_un addr_un = {};
236 char *add_in = NULL;
237 int rc;
238
239 if (client == NULL) {
240 SPDK_ERRLOG("%s\n", spdk_strerror(errno));
241 return NULL;
242 }
243
244 if (addr_family == AF_UNIX) {
245 addr_un.sun_family = AF_UNIX;
246 rc = snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s", addr);
247 if (rc < 0 || (size_t)rc >= sizeof(addr_un.sun_path)) {
248 rc = -EINVAL;
249 SPDK_ERRLOG("RPC Listen address Unix socket path too long\n");
250 goto err;
251 }
252
253 rc = jsonrpc_client_connect(client, AF_UNIX, 0, (struct sockaddr *)&addr_un, sizeof(addr_un));
254 } else {
255 /* TCP/IP socket */
256 struct addrinfo hints;
257 struct addrinfo *res;
258 char *host, *port;
259
260 add_in = strdup(addr);
261 if (!add_in) {
262 rc = -errno;
263 SPDK_ERRLOG("%s\n", spdk_strerror(errno));
264 goto err;
265 }
266
267 rc = spdk_parse_ip_addr(add_in, &host, &port);
268 if (rc) {
269 SPDK_ERRLOG("Invalid listen address '%s'\n", addr);
270 goto err;
271 }
272
273 if (port == NULL) {
274 port = RPC_DEFAULT_PORT;
275 }
276
277 memset(&hints, 0, sizeof(hints));
278 hints.ai_family = AF_UNSPEC;
279 hints.ai_socktype = SOCK_STREAM;
280 hints.ai_protocol = IPPROTO_TCP;
281
282 rc = getaddrinfo(host, port, &hints, &res);
283 if (rc != 0) {
284 SPDK_ERRLOG("Unable to look up RPC connect address '%s' (%d): %s\n", addr, rc, gai_strerror(rc));
285 rc = -(abs(rc));
286 goto err;
287 }
288
289 rc = jsonrpc_client_connect(client, res->ai_family, res->ai_protocol, res->ai_addr,
290 res->ai_addrlen);
291 freeaddrinfo(res);
292 }
293
294 err:
295 if (rc != 0 && rc != -EINPROGRESS) {
296 free(client);
297 client = NULL;
298 errno = -rc;
299 }
300
301 free(add_in);
302 return client;
303 }
304
305 void
spdk_jsonrpc_client_close(struct spdk_jsonrpc_client * client)306 spdk_jsonrpc_client_close(struct spdk_jsonrpc_client *client)
307 {
308 if (client->sockfd >= 0) {
309 close(client->sockfd);
310 }
311
312 free(client->recv_buf);
313 if (client->resp) {
314 spdk_jsonrpc_client_free_response(&client->resp->jsonrpc);
315 }
316
317 free(client);
318 }
319
320 struct spdk_jsonrpc_client_request *
spdk_jsonrpc_client_create_request(void)321 spdk_jsonrpc_client_create_request(void)
322 {
323 struct spdk_jsonrpc_client_request *request;
324
325 request = calloc(1, sizeof(*request));
326 if (request == NULL) {
327 return NULL;
328 }
329
330 /* memory malloc for send-buf */
331 request->send_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT);
332 if (!request->send_buf) {
333 SPDK_ERRLOG("memory malloc for send-buf failed\n");
334 free(request);
335 return NULL;
336 }
337 request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
338
339 return request;
340 }
341
342 void
spdk_jsonrpc_client_free_request(struct spdk_jsonrpc_client_request * req)343 spdk_jsonrpc_client_free_request(struct spdk_jsonrpc_client_request *req)
344 {
345 free(req->send_buf);
346 free(req);
347 }
348
349 int
spdk_jsonrpc_client_poll(struct spdk_jsonrpc_client * client,int timeout)350 spdk_jsonrpc_client_poll(struct spdk_jsonrpc_client *client, int timeout)
351 {
352 if (client->connected) {
353 return jsonrpc_client_poll(client, timeout);
354 } else {
355 return jsonrpc_client_poll_connecting(client, timeout);
356 }
357 }
358
359 int
spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client * client,struct spdk_jsonrpc_client_request * req)360 spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client,
361 struct spdk_jsonrpc_client_request *req)
362 {
363 if (client->request != NULL) {
364 return -ENOSPC;
365 }
366
367 client->request = req;
368 return 0;
369 }
370
371 struct spdk_jsonrpc_client_response *
spdk_jsonrpc_client_get_response(struct spdk_jsonrpc_client * client)372 spdk_jsonrpc_client_get_response(struct spdk_jsonrpc_client *client)
373 {
374 struct spdk_jsonrpc_client_response_internal *r;
375
376 r = client->resp;
377 if (r == NULL || r->ready == false) {
378 return NULL;
379 }
380
381 client->resp = NULL;
382 return &r->jsonrpc;
383 }
384
385 void
spdk_jsonrpc_client_free_response(struct spdk_jsonrpc_client_response * resp)386 spdk_jsonrpc_client_free_response(struct spdk_jsonrpc_client_response *resp)
387 {
388 struct spdk_jsonrpc_client_response_internal *r;
389
390 if (!resp) {
391 return;
392 }
393
394 r = SPDK_CONTAINEROF(resp, struct spdk_jsonrpc_client_response_internal, jsonrpc);
395 free(r->buf);
396 free(r);
397 }
398