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/string.h"
7 : : #include "jsonrpc_internal.h"
8 : : #include "spdk/util.h"
9 : :
10 : : #define RPC_DEFAULT_PORT "5260"
11 : :
12 : : static int
13 : 943741 : jsonrpc_client_send_request(struct spdk_jsonrpc_client *client)
14 : : {
15 : : ssize_t rc;
16 : 943741 : struct spdk_jsonrpc_client_request *request = client->request;
17 : :
18 [ + + ]: 943741 : if (!request) {
19 : 939434 : return 0;
20 : : }
21 : :
22 [ + - ]: 4307 : if (request->send_len > 0) {
23 : 4307 : rc = send(client->sockfd, request->send_buf + request->send_offset,
24 : : request->send_len, 0);
25 [ - + ]: 4307 : if (rc < 0) {
26 : : /* For EINTR we pretend that nothing was send. */
27 [ # # ]: 0 : if (errno == EINTR) {
28 : 0 : rc = 0;
29 : : } 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 : 4307 : request->send_offset += rc;
38 : 4307 : request->send_len -= rc;
39 : : }
40 : :
41 [ + - ]: 4307 : if (request->send_len == 0) {
42 : 4307 : client->request = NULL;
43 : 4307 : spdk_jsonrpc_client_free_request(request);
44 : : }
45 : :
46 : 4307 : return 0;
47 : : }
48 : :
49 : : static int
50 : 0 : recv_buf_expand(struct spdk_jsonrpc_client *client)
51 : : {
52 : : 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 : : }
70 : :
71 : : static int
72 : 939434 : jsonrpc_client_resp_ready_count(struct spdk_jsonrpc_client *client)
73 : : {
74 [ - + - - : 939434 : return client->resp != NULL && client->resp->ready ? 1 : 0;
- - ]
75 : : }
76 : :
77 : : static int
78 : 4307 : jsonrpc_client_recv(struct spdk_jsonrpc_client *client)
79 : : {
80 : : ssize_t rc;
81 : :
82 [ + - ]: 4307 : if (client->recv_buf == NULL) {
83 : 4307 : client->recv_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT);
84 [ - + ]: 4307 : 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 : 4307 : client->recv_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
90 : 4307 : 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 : : }
97 : :
98 : 4307 : rc = recv(client->sockfd, client->recv_buf + client->recv_offset,
99 : 4307 : client->recv_buf_size - client->recv_offset - 1, 0);
100 [ - + ]: 4307 : 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 [ - + ]: 4307 : } else if (rc == 0) {
110 : 0 : return -EIO;
111 : : }
112 : :
113 : 4307 : client->recv_offset += rc;
114 : 4307 : client->recv_buf[client->recv_offset] = '\0';
115 : :
116 : : /* Check to see if we have received a full JSON value. */
117 : 4307 : return jsonrpc_parse_response(client);
118 : : }
119 : :
120 : : static int
121 : 943741 : jsonrpc_client_poll(struct spdk_jsonrpc_client *client, int timeout)
122 : : {
123 : : int rc;
124 : 943741 : struct pollfd pfd = { .fd = client->sockfd, .events = POLLIN | POLLOUT };
125 : :
126 : 943741 : rc = poll(&pfd, 1, timeout);
127 [ - + ]: 943741 : if (rc == -1) {
128 [ # # ]: 0 : if (errno == EINTR) {
129 : : /* For EINTR we pretend that nothing was received nor send. */
130 : 0 : rc = 0;
131 : : } else {
132 : 0 : rc = -errno;
133 : 0 : SPDK_ERRLOG("poll() failed (%d): %s\n", errno, spdk_strerror(errno));
134 : : }
135 [ + - ]: 943741 : } else if (rc > 0) {
136 : 943741 : rc = 0;
137 : :
138 [ + - ]: 943741 : if (pfd.revents & POLLOUT) {
139 : 943741 : rc = jsonrpc_client_send_request(client);
140 : : }
141 : :
142 [ + - + + ]: 943741 : if (rc == 0 && (pfd.revents & POLLIN)) {
143 : 4307 : rc = jsonrpc_client_recv(client);
144 : : /* Incomplete message in buffer isn't an error. */
145 [ - + ]: 4307 : if (rc == -EAGAIN) {
146 : 0 : rc = 0;
147 : : }
148 : : }
149 : : }
150 : :
151 [ + + ]: 943741 : return rc ? rc : jsonrpc_client_resp_ready_count(client);
152 : : }
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 : 0 : err:
196 : 0 : return -EIO;
197 : : }
198 : :
199 : : static int
200 : 1475 : 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 : 1475 : client->sockfd = socket(domain, SOCK_STREAM | SOCK_NONBLOCK, protocol);
206 [ - + ]: 1475 : if (client->sockfd < 0) {
207 : 0 : rc = errno;
208 : 0 : SPDK_ERRLOG("socket() failed\n");
209 : 0 : return -rc;
210 : : }
211 : :
212 : 1475 : rc = connect(client->sockfd, server_addr, addrlen);
213 [ - + ]: 1475 : 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 : : } else {
220 : 1475 : client->connected = true;
221 : : }
222 : :
223 : 1475 : return -rc;
224 : 0 : err:
225 : 0 : close(client->sockfd);
226 : 0 : client->sockfd = -1;
227 : 0 : return -rc;
228 : : }
229 : :
230 : : struct spdk_jsonrpc_client *
231 : 1475 : spdk_jsonrpc_client_connect(const char *addr, int addr_family)
232 : : {
233 : 1475 : struct spdk_jsonrpc_client *client = calloc(1, sizeof(struct spdk_jsonrpc_client));
234 : : /* Unix Domain Socket */
235 : 1475 : struct sockaddr_un addr_un = {};
236 : 1475 : char *add_in = NULL;
237 : : int rc;
238 : :
239 [ - + ]: 1475 : if (client == NULL) {
240 : 0 : SPDK_ERRLOG("%s\n", spdk_strerror(errno));
241 : 0 : return NULL;
242 : : }
243 : :
244 [ + - ]: 1475 : if (addr_family == AF_UNIX) {
245 : 1475 : addr_un.sun_family = AF_UNIX;
246 : 1475 : rc = snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s", addr);
247 [ + - - + ]: 1475 : 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 : 1475 : rc = jsonrpc_client_connect(client, AF_UNIX, 0, (struct sockaddr *)&addr_un, sizeof(addr_un));
254 : : } 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 : : }
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 : : }
293 : :
294 : 1475 : err:
295 [ - + - - ]: 1475 : if (rc != 0 && rc != -EINPROGRESS) {
296 : 0 : free(client);
297 : 0 : client = NULL;
298 : 0 : errno = -rc;
299 : : }
300 : :
301 : 1475 : free(add_in);
302 : 1475 : return client;
303 : : }
304 : :
305 : : void
306 : 1475 : spdk_jsonrpc_client_close(struct spdk_jsonrpc_client *client)
307 : : {
308 [ + - ]: 1475 : if (client->sockfd >= 0) {
309 : 1475 : close(client->sockfd);
310 : : }
311 : :
312 : 1475 : free(client->recv_buf);
313 [ - + ]: 1475 : if (client->resp) {
314 : 0 : spdk_jsonrpc_client_free_response(&client->resp->jsonrpc);
315 : : }
316 : :
317 : 1475 : free(client);
318 : 1475 : }
319 : :
320 : : struct spdk_jsonrpc_client_request *
321 : 4307 : spdk_jsonrpc_client_create_request(void)
322 : : {
323 : : struct spdk_jsonrpc_client_request *request;
324 : :
325 : 4307 : request = calloc(1, sizeof(*request));
326 [ - + ]: 4307 : if (request == NULL) {
327 : 0 : return NULL;
328 : : }
329 : :
330 : : /* memory malloc for send-buf */
331 : 4307 : request->send_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT);
332 [ - + ]: 4307 : 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 : 4307 : request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
338 : :
339 : 4307 : return request;
340 : : }
341 : :
342 : : void
343 : 4307 : spdk_jsonrpc_client_free_request(struct spdk_jsonrpc_client_request *req)
344 : : {
345 : 4307 : free(req->send_buf);
346 : 4307 : free(req);
347 : 4307 : }
348 : :
349 : : int
350 : 943741 : spdk_jsonrpc_client_poll(struct spdk_jsonrpc_client *client, int timeout)
351 : : {
352 [ + + + - ]: 943741 : if (client->connected) {
353 : 943741 : return jsonrpc_client_poll(client, timeout);
354 : : } else {
355 : 0 : return jsonrpc_client_poll_connecting(client, timeout);
356 : : }
357 : : }
358 : :
359 : : int
360 : 4307 : spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client,
361 : : struct spdk_jsonrpc_client_request *req)
362 : : {
363 [ - + ]: 4307 : if (client->request != NULL) {
364 : 0 : return -ENOSPC;
365 : : }
366 : :
367 : 4307 : client->request = req;
368 : 4307 : return 0;
369 : : }
370 : :
371 : : struct spdk_jsonrpc_client_response *
372 : 4307 : spdk_jsonrpc_client_get_response(struct spdk_jsonrpc_client *client)
373 : : {
374 : : struct spdk_jsonrpc_client_response_internal *r;
375 : :
376 : 4307 : r = client->resp;
377 [ + - - + : 4307 : if (r == NULL || r->ready == false) {
- + ]
378 : 0 : return NULL;
379 : : }
380 : :
381 : 4307 : client->resp = NULL;
382 : 4307 : return &r->jsonrpc;
383 : : }
384 : :
385 : : void
386 : 4307 : spdk_jsonrpc_client_free_response(struct spdk_jsonrpc_client_response *resp)
387 : : {
388 : : struct spdk_jsonrpc_client_response_internal *r;
389 : :
390 [ - + ]: 4307 : if (!resp) {
391 : 0 : return;
392 : : }
393 : :
394 : 4307 : r = SPDK_CONTAINEROF(resp, struct spdk_jsonrpc_client_response_internal, jsonrpc);
395 : 4307 : free(r->buf);
396 : 4307 : free(r);
397 : : }
|