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