xref: /spdk/lib/jsonrpc/jsonrpc_server_tcp.c (revision 60c38d40228d8b35bbfa049452393df89155de6b)
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 	return server;
90 }
91 
92 void
93 spdk_jsonrpc_server_shutdown(struct spdk_jsonrpc_server *server)
94 {
95 	int i;
96 
97 	close(server->sockfd);
98 
99 	for (i = 0; i < server->num_conns; i++) {
100 		close(server->conns[i].sockfd);
101 	}
102 
103 	free(server);
104 }
105 
106 static void
107 spdk_jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn *conn)
108 {
109 	conn->closed = true;
110 
111 	if (conn->sockfd >= 0) {
112 		close(conn->sockfd);
113 		conn->sockfd = -1;
114 	}
115 }
116 
117 static void
118 spdk_jsonrpc_server_conn_remove(struct spdk_jsonrpc_server_conn *conn)
119 {
120 	struct spdk_jsonrpc_server *server = conn->server;
121 	int conn_idx = conn - server->conns;
122 
123 	spdk_jsonrpc_server_conn_close(conn);
124 
125 	spdk_ring_free(conn->send_queue);
126 
127 	/* Swap conn with the last entry in conns */
128 	server->conns[conn_idx] = server->conns[server->num_conns - 1];
129 	server->num_conns--;
130 }
131 
132 static int
133 spdk_jsonrpc_server_accept(struct spdk_jsonrpc_server *server)
134 {
135 	struct spdk_jsonrpc_server_conn *conn;
136 	int rc, conn_idx, nonblock;
137 
138 	rc = accept(server->sockfd, NULL, NULL);
139 	if (rc >= 0) {
140 		assert(server->num_conns < SPDK_JSONRPC_MAX_CONNS);
141 		conn_idx = server->num_conns;
142 		conn = &server->conns[conn_idx];
143 		conn->server = server;
144 		conn->sockfd = rc;
145 		conn->closed = false;
146 		conn->recv_len = 0;
147 		conn->outstanding_requests = 0;
148 		conn->send_request = NULL;
149 		conn->send_queue = spdk_ring_create(SPDK_RING_TYPE_SP_SC, 128, SPDK_ENV_SOCKET_ID_ANY);
150 		if (conn->send_queue == NULL) {
151 			SPDK_ERRLOG("send_queue allocation failed\n");
152 			close(conn->sockfd);
153 			return -1;
154 		}
155 
156 		nonblock = 1;
157 		rc = ioctl(conn->sockfd, FIONBIO, &nonblock);
158 		if (rc != 0) {
159 			SPDK_ERRLOG("ioctl(FIONBIO) failed\n");
160 			close(conn->sockfd);
161 			return -1;
162 		}
163 
164 		server->num_conns++;
165 
166 		return 0;
167 	}
168 
169 	if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
170 		return 0;
171 	}
172 
173 	return -1;
174 }
175 
176 void
177 spdk_jsonrpc_server_handle_request(struct spdk_jsonrpc_request *request,
178 				   const struct spdk_json_val *method, const struct spdk_json_val *params)
179 {
180 	request->conn->server->handle_request(request, method, params);
181 }
182 
183 void
184 spdk_jsonrpc_server_handle_error(struct spdk_jsonrpc_request *request, int error)
185 {
186 	const char *msg;
187 
188 	switch (error) {
189 	case SPDK_JSONRPC_ERROR_PARSE_ERROR:
190 		msg = "Parse error";
191 		break;
192 
193 	case SPDK_JSONRPC_ERROR_INVALID_REQUEST:
194 		msg = "Invalid request";
195 		break;
196 
197 	case SPDK_JSONRPC_ERROR_METHOD_NOT_FOUND:
198 		msg = "Method not found";
199 		break;
200 
201 	case SPDK_JSONRPC_ERROR_INVALID_PARAMS:
202 		msg = "Invalid parameters";
203 		break;
204 
205 	case SPDK_JSONRPC_ERROR_INTERNAL_ERROR:
206 		msg = "Internal error";
207 		break;
208 
209 	default:
210 		msg = "Error";
211 		break;
212 	}
213 
214 	spdk_jsonrpc_send_error_response(request, error, msg);
215 }
216 
217 static int
218 spdk_jsonrpc_server_conn_recv(struct spdk_jsonrpc_server_conn *conn)
219 {
220 	ssize_t rc;
221 	size_t recv_avail = SPDK_JSONRPC_RECV_BUF_SIZE - conn->recv_len;
222 
223 	rc = recv(conn->sockfd, conn->recv_buf + conn->recv_len, recv_avail, 0);
224 	if (rc == -1) {
225 		if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
226 			return 0;
227 		}
228 
229 		SPDK_TRACELOG(SPDK_TRACE_RPC, "recv() failed: %s\n", strerror(errno));
230 		return -1;
231 	}
232 
233 	if (rc == 0) {
234 		SPDK_TRACELOG(SPDK_TRACE_RPC, "remote closed connection\n");
235 		return -1;
236 	}
237 
238 	conn->recv_len += rc;
239 
240 	rc = spdk_jsonrpc_parse_request(conn, conn->recv_buf, conn->recv_len);
241 	if (rc < 0) {
242 		SPDK_ERRLOG("jsonrpc parse request failed\n");
243 		return -1;
244 	}
245 
246 	if (rc > 0) {
247 		/*
248 		 * Successfully parsed a request - move any data past the end of the
249 		 * parsed request down to the beginning.
250 		 */
251 		assert((size_t)rc <= conn->recv_len);
252 		memmove(conn->recv_buf, conn->recv_buf + rc, conn->recv_len - rc);
253 		conn->recv_len -= rc;
254 	}
255 
256 	return 0;
257 }
258 
259 void
260 spdk_jsonrpc_server_send_response(struct spdk_jsonrpc_server_conn *conn,
261 				  struct spdk_jsonrpc_request *request)
262 {
263 	/* Queue the response to be sent */
264 	spdk_ring_enqueue(conn->send_queue, (void **)&request, 1);
265 }
266 
267 static int
268 spdk_jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn *conn)
269 {
270 	struct spdk_jsonrpc_request *request;
271 	ssize_t rc;
272 
273 more:
274 	if (conn->outstanding_requests == 0) {
275 		return 0;
276 	}
277 
278 	if (conn->send_request == NULL) {
279 		if (spdk_ring_dequeue(conn->send_queue, (void **)&conn->send_request, 1) != 1) {
280 			return 0;
281 		}
282 	}
283 
284 	request = conn->send_request;
285 	if (request == NULL) {
286 		/* Nothing to send right now */
287 		return 0;
288 	}
289 
290 	rc = send(conn->sockfd, request->send_buf + request->send_offset,
291 		  request->send_len, 0);
292 	if (rc < 0) {
293 		if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
294 			return 0;
295 		}
296 
297 		SPDK_TRACELOG(SPDK_TRACE_RPC, "send() failed: %s\n", strerror(errno));
298 		return -1;
299 	}
300 
301 	request->send_offset += rc;
302 	request->send_len -= rc;
303 
304 	if (request->send_len == 0) {
305 		/*
306 		 * Full response has been sent.
307 		 * Free it and set send_request to NULL to move on to the next queued response.
308 		 */
309 		conn->send_request = NULL;
310 		spdk_jsonrpc_free_request(request);
311 		goto more;
312 	}
313 
314 	return 0;
315 }
316 
317 int
318 spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server *server)
319 {
320 	int rc, i;
321 	struct spdk_jsonrpc_server_conn *conn;
322 
323 	for (i = 0; i < server->num_conns; i++) {
324 		conn = &server->conns[i];
325 
326 		if (conn->closed) {
327 			struct spdk_jsonrpc_request *request;
328 
329 			/*
330 			 * The client closed the connection, but there may still be requests
331 			 * outstanding; we have no way to cancel outstanding requests, so wait until
332 			 * each outstanding request sends a response (which will be discarded, since
333 			 * the connection is closed).
334 			 */
335 
336 			if (conn->send_request) {
337 				spdk_jsonrpc_free_request(conn->send_request);
338 				conn->send_request = NULL;
339 			}
340 
341 			while (spdk_ring_dequeue(conn->send_queue, (void **)&request, 1) == 1) {
342 				spdk_jsonrpc_free_request(request);
343 			}
344 
345 			if (conn->outstanding_requests == 0) {
346 				SPDK_TRACELOG(SPDK_TRACE_RPC, "all outstanding requests completed\n");
347 				spdk_jsonrpc_server_conn_remove(conn);
348 			}
349 		}
350 	}
351 
352 	/* Check listen socket */
353 	if (server->num_conns < SPDK_JSONRPC_MAX_CONNS) {
354 		spdk_jsonrpc_server_accept(server);
355 	}
356 
357 	for (i = 0; i < server->num_conns; i++) {
358 		conn = &server->conns[i];
359 
360 		if (conn->closed) {
361 			continue;
362 		}
363 
364 		rc = spdk_jsonrpc_server_conn_send(conn);
365 		if (rc != 0) {
366 			spdk_jsonrpc_server_conn_close(conn);
367 			continue;
368 		}
369 
370 		rc = spdk_jsonrpc_server_conn_recv(conn);
371 		if (rc != 0) {
372 			spdk_jsonrpc_server_conn_close(conn);
373 			continue;
374 		}
375 	}
376 
377 	return 0;
378 }
379