xref: /spdk/lib/jsonrpc/jsonrpc_client_tcp.c (revision f6866117acb32c78d5ea7bd76ba330284655af35)
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