xref: /spdk/lib/jsonrpc/jsonrpc_server_tcp.c (revision 2bcabb20043c52f45a3168b1e1e30c25242e4855)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "jsonrpc_internal.h"
35 
36 struct spdk_jsonrpc_server *
37 spdk_jsonrpc_server_listen(int domain, int protocol,
38 			   struct sockaddr *listen_addr, socklen_t addrlen,
39 			   spdk_jsonrpc_handle_request_fn handle_request)
40 {
41 	struct spdk_jsonrpc_server *server;
42 	int rc, val;
43 
44 	server = calloc(1, sizeof(struct spdk_jsonrpc_server));
45 	if (server == NULL) {
46 		return NULL;
47 	}
48 
49 	server->handle_request = handle_request;
50 
51 	server->sockfd = socket(domain, SOCK_STREAM, protocol);
52 	if (server->sockfd < 0) {
53 		SPDK_ERRLOG("socket() failed\n");
54 		free(server);
55 		return NULL;
56 	}
57 
58 	val = 1;
59 	setsockopt(server->sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
60 	if (protocol == IPPROTO_TCP) {
61 		setsockopt(server->sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
62 	}
63 
64 	val = 1;
65 	rc = ioctl(server->sockfd, FIONBIO, &val);
66 	if (rc != 0) {
67 		SPDK_ERRLOG("ioctl(FIONBIO) failed\n");
68 		close(server->sockfd);
69 		free(server);
70 		return NULL;
71 	}
72 
73 	rc = bind(server->sockfd, listen_addr, addrlen);
74 	if (rc != 0) {
75 		SPDK_ERRLOG("could not bind JSON-RPC server: %s\n", strerror(errno));
76 		close(server->sockfd);
77 		free(server);
78 		return NULL;
79 	}
80 
81 	rc = listen(server->sockfd, 512);
82 	if (rc != 0) {
83 		SPDK_ERRLOG("listen() failed, errno = %d\n", errno);
84 		close(server->sockfd);
85 		free(server);
86 		return NULL;
87 	}
88 
89 	/* Put listen socket in pollfds[0] */
90 	server->pollfds[0].fd = server->sockfd;
91 	server->pollfds[0].events = POLLIN;
92 
93 	return server;
94 }
95 
96 void
97 spdk_jsonrpc_server_shutdown(struct spdk_jsonrpc_server *server)
98 {
99 	int i;
100 
101 	close(server->sockfd);
102 
103 	for (i = 0; i < server->num_conns; i++) {
104 		close(server->conns[i].sockfd);
105 	}
106 
107 	free(server);
108 }
109 
110 static void
111 spdk_jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn *conn)
112 {
113 	conn->closed = true;
114 
115 	/* Set the pollfd fd to a negative value so it is ignored by poll() */
116 	conn->pfd->fd = -1;
117 
118 	if (conn->sockfd >= 0) {
119 		close(conn->sockfd);
120 		conn->sockfd = -1;
121 	}
122 }
123 
124 static void
125 spdk_jsonrpc_server_conn_remove(struct spdk_jsonrpc_server_conn *conn)
126 {
127 	struct spdk_jsonrpc_server *server = conn->server;
128 	int conn_idx = conn - server->conns;
129 
130 	spdk_jsonrpc_server_conn_close(conn);
131 
132 	spdk_ring_free(conn->send_queue);
133 
134 	/* Swap conn with the last entry in conns */
135 	server->conns[conn_idx] = server->conns[server->num_conns - 1];
136 	server->num_conns--;
137 }
138 
139 static int
140 spdk_jsonrpc_server_accept(struct spdk_jsonrpc_server *server)
141 {
142 	struct spdk_jsonrpc_server_conn *conn;
143 	struct pollfd *pfd;
144 	int rc, conn_idx, nonblock;
145 
146 	rc = accept(server->sockfd, NULL, NULL);
147 	if (rc >= 0) {
148 		assert(server->num_conns < SPDK_JSONRPC_MAX_CONNS);
149 		conn_idx = server->num_conns;
150 		conn = &server->conns[conn_idx];
151 		conn->server = server;
152 		conn->sockfd = rc;
153 		conn->closed = false;
154 		conn->recv_len = 0;
155 		conn->outstanding_requests = 0;
156 		conn->send_request = NULL;
157 		conn->send_queue = spdk_ring_create(SPDK_RING_TYPE_SP_SC, 128, SPDK_ENV_SOCKET_ID_ANY);
158 		if (conn->send_queue == NULL) {
159 			SPDK_ERRLOG("send_queue allocation failed\n");
160 			close(conn->sockfd);
161 			return -1;
162 		}
163 
164 		nonblock = 1;
165 		rc = ioctl(conn->sockfd, FIONBIO, &nonblock);
166 		if (rc != 0) {
167 			SPDK_ERRLOG("ioctl(FIONBIO) failed\n");
168 			close(conn->sockfd);
169 			return -1;
170 		}
171 
172 		/* Add connection to pollfds */
173 		pfd = &server->pollfds[conn_idx + 1];
174 		pfd->fd = conn->sockfd;
175 		pfd->events = POLLIN | POLLOUT;
176 		pfd->revents = 0;
177 		conn->pfd = pfd;
178 
179 		server->num_conns++;
180 
181 		return 0;
182 	}
183 
184 	if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
185 		return 0;
186 	}
187 
188 	return -1;
189 }
190 
191 void
192 spdk_jsonrpc_server_handle_request(struct spdk_jsonrpc_request *request,
193 				   const struct spdk_json_val *method, const struct spdk_json_val *params)
194 {
195 	request->conn->server->handle_request(request, method, params);
196 }
197 
198 void
199 spdk_jsonrpc_server_handle_error(struct spdk_jsonrpc_request *request, int error)
200 {
201 	const char *msg;
202 
203 	switch (error) {
204 	case SPDK_JSONRPC_ERROR_PARSE_ERROR:
205 		msg = "Parse error";
206 		break;
207 
208 	case SPDK_JSONRPC_ERROR_INVALID_REQUEST:
209 		msg = "Invalid request";
210 		break;
211 
212 	case SPDK_JSONRPC_ERROR_METHOD_NOT_FOUND:
213 		msg = "Method not found";
214 		break;
215 
216 	case SPDK_JSONRPC_ERROR_INVALID_PARAMS:
217 		msg = "Invalid parameters";
218 		break;
219 
220 	case SPDK_JSONRPC_ERROR_INTERNAL_ERROR:
221 		msg = "Internal error";
222 		break;
223 
224 	default:
225 		msg = "Error";
226 		break;
227 	}
228 
229 	spdk_jsonrpc_send_error_response(request, error, msg);
230 }
231 
232 static int
233 spdk_jsonrpc_server_conn_recv(struct spdk_jsonrpc_server_conn *conn)
234 {
235 	ssize_t rc;
236 	size_t recv_avail = SPDK_JSONRPC_RECV_BUF_SIZE - conn->recv_len;
237 
238 	rc = recv(conn->sockfd, conn->recv_buf + conn->recv_len, recv_avail, 0);
239 	if (rc == -1) {
240 		if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
241 			return 0;
242 		}
243 
244 		SPDK_TRACELOG(SPDK_TRACE_RPC, "recv() failed: %s\n", strerror(errno));
245 		return -1;
246 	}
247 
248 	if (rc == 0) {
249 		SPDK_TRACELOG(SPDK_TRACE_RPC, "remote closed connection\n");
250 		return -1;
251 	}
252 
253 	conn->recv_len += rc;
254 
255 	rc = spdk_jsonrpc_parse_request(conn, conn->recv_buf, conn->recv_len);
256 	if (rc < 0) {
257 		SPDK_ERRLOG("jsonrpc parse request failed\n");
258 		return -1;
259 	}
260 
261 	if (rc > 0) {
262 		/*
263 		 * Successfully parsed a request - move any data past the end of the
264 		 * parsed request down to the beginning.
265 		 */
266 		assert((size_t)rc <= conn->recv_len);
267 		memmove(conn->recv_buf, conn->recv_buf + rc, conn->recv_len - rc);
268 		conn->recv_len -= rc;
269 	}
270 
271 	return 0;
272 }
273 
274 void
275 spdk_jsonrpc_server_send_response(struct spdk_jsonrpc_server_conn *conn,
276 				  struct spdk_jsonrpc_request *request)
277 {
278 	/* Queue the response to be sent */
279 	spdk_ring_enqueue(conn->send_queue, (void **)&request, 1);
280 }
281 
282 static int
283 spdk_jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn *conn)
284 {
285 	struct spdk_jsonrpc_request *request;
286 	ssize_t rc;
287 
288 more:
289 	if (conn->outstanding_requests == 0) {
290 		return 0;
291 	}
292 
293 	if (conn->send_request == NULL) {
294 		if (spdk_ring_dequeue(conn->send_queue, (void **)&conn->send_request, 1) != 1) {
295 			return 0;
296 		}
297 	}
298 
299 	request = conn->send_request;
300 	if (request == NULL) {
301 		/* Nothing to send right now */
302 		return 0;
303 	}
304 
305 	rc = send(conn->sockfd, request->send_buf + request->send_offset,
306 		  request->send_len, 0);
307 	if (rc < 0) {
308 		if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
309 			return 0;
310 		}
311 
312 		SPDK_TRACELOG(SPDK_TRACE_RPC, "send() failed: %s\n", strerror(errno));
313 		return -1;
314 	}
315 
316 	request->send_offset += rc;
317 	request->send_len -= rc;
318 
319 	if (request->send_len == 0) {
320 		/*
321 		 * Full response has been sent.
322 		 * Free it and set send_request to NULL to move on to the next queued response.
323 		 */
324 		conn->send_request = NULL;
325 		spdk_jsonrpc_free_request(request);
326 		goto more;
327 	}
328 
329 	return 0;
330 }
331 
332 int
333 spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server *server)
334 {
335 	int rc, i;
336 	struct pollfd *pfd;
337 	struct spdk_jsonrpc_server_conn *conn;
338 
339 	for (i = 0; i < server->num_conns; i++) {
340 		conn = &server->conns[i];
341 
342 		if (conn->closed) {
343 			struct spdk_jsonrpc_request *request;
344 
345 			/*
346 			 * The client closed the connection, but there may still be requests
347 			 * outstanding; we have no way to cancel outstanding requests, so wait until
348 			 * each outstanding request sends a response (which will be discarded, since
349 			 * the connection is closed).
350 			 */
351 
352 			if (conn->send_request) {
353 				spdk_jsonrpc_free_request(conn->send_request);
354 				conn->send_request = NULL;
355 			}
356 
357 			while (spdk_ring_dequeue(conn->send_queue, (void **)&request, 1) == 1) {
358 				spdk_jsonrpc_free_request(request);
359 			}
360 
361 			if (conn->outstanding_requests == 0) {
362 				SPDK_TRACELOG(SPDK_TRACE_RPC, "all outstanding requests completed\n");
363 				spdk_jsonrpc_server_conn_remove(conn);
364 			}
365 
366 			continue;
367 		}
368 	}
369 
370 	rc = poll(server->pollfds, server->num_conns + 1, 0);
371 
372 	if (rc < 0) {
373 		if (errno == EINTR) {
374 			return 0;
375 		}
376 
377 		SPDK_ERRLOG("jsonrpc poll() failed\n");
378 		return -1;
379 	}
380 
381 	if (rc == 0) {
382 		/* No sockets are ready */
383 		return 0;
384 	}
385 
386 	/* Check listen socket */
387 	if (server->num_conns < SPDK_JSONRPC_MAX_CONNS) {
388 		pfd = &server->pollfds[0];
389 		if (pfd->revents) {
390 			spdk_jsonrpc_server_accept(server);
391 		}
392 		pfd->revents = 0;
393 	}
394 
395 	for (i = 0; i < server->num_conns; i++) {
396 		pfd = &server->pollfds[i + 1];
397 		conn = &server->conns[i];
398 
399 		if (pfd->revents & POLLOUT) {
400 			rc = spdk_jsonrpc_server_conn_send(conn);
401 			if (rc != 0) {
402 				SPDK_TRACELOG(SPDK_TRACE_RPC, "closing conn due to send failure\n");
403 				spdk_jsonrpc_server_conn_close(conn);
404 				continue;
405 			}
406 		}
407 
408 		if (pfd->revents & POLLIN) {
409 			rc = spdk_jsonrpc_server_conn_recv(conn);
410 			if (rc != 0) {
411 				SPDK_TRACELOG(SPDK_TRACE_RPC, "closing conn due to recv failure\n");
412 				spdk_jsonrpc_server_conn_close(conn);
413 				continue;
414 			}
415 		}
416 
417 		if (pfd->revents & (POLLERR | POLLNVAL)) {
418 			SPDK_TRACELOG(SPDK_TRACE_RPC, "closing conn due to poll() flag %d\n",
419 				      (int)pfd->revents);
420 			spdk_jsonrpc_server_conn_close(conn);
421 			continue;
422 		}
423 
424 		pfd->revents = 0;
425 	}
426 
427 	return 0;
428 }
429