xref: /spdk/lib/jsonrpc/jsonrpc_server_tcp.c (revision edbca2a67610cf6ebb9755c839e307d1d18375da)
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_remove(struct spdk_jsonrpc_server_conn *conn)
112 {
113 	struct spdk_jsonrpc_server *server = conn->server;
114 	int conn_idx = conn - server->conns;
115 
116 	close(conn->sockfd);
117 
118 	/* Swap conn with the last entry in conns */
119 	server->conns[conn_idx] = server->conns[server->num_conns - 1];
120 	server->num_conns--;
121 }
122 
123 static int
124 spdk_jsonrpc_server_accept(struct spdk_jsonrpc_server *server)
125 {
126 	struct spdk_jsonrpc_server_conn *conn;
127 	struct pollfd *pfd;
128 	int rc, conn_idx, nonblock;
129 
130 	rc = accept(server->sockfd, NULL, NULL);
131 	if (rc >= 0) {
132 		assert(server->num_conns < SPDK_JSONRPC_MAX_CONNS);
133 		conn_idx = server->num_conns;
134 		conn = &server->conns[conn_idx];
135 		conn->server = server;
136 		conn->sockfd = rc;
137 		conn->recv_len = 0;
138 		conn->send_len = 0;
139 		conn->json_writer = 0;
140 
141 		nonblock = 1;
142 		rc = ioctl(conn->sockfd, FIONBIO, &nonblock);
143 		if (rc != 0) {
144 			SPDK_ERRLOG("ioctl(FIONBIO) failed\n");
145 			close(conn->sockfd);
146 			return -1;
147 		}
148 
149 		/* Add connection to pollfds */
150 		pfd = &server->pollfds[conn_idx + 1];
151 		pfd->fd = conn->sockfd;
152 		pfd->events = POLLIN | POLLOUT;
153 
154 		server->num_conns++;
155 
156 		return 0;
157 	}
158 
159 	if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
160 		return 0;
161 	}
162 
163 	return -1;
164 }
165 
166 int
167 spdk_jsonrpc_server_write_cb(void *cb_ctx, const void *data, size_t size)
168 {
169 	struct spdk_jsonrpc_server_conn *conn = cb_ctx;
170 
171 	if (SPDK_JSONRPC_SEND_BUF_SIZE - conn->send_len < size) {
172 		SPDK_ERRLOG("Not enough space in send buf\n");
173 		return -1;
174 	}
175 
176 	memcpy(conn->send_buf + conn->send_len, data, size);
177 	conn->send_len += size;
178 
179 	return 0;
180 }
181 
182 void
183 spdk_jsonrpc_server_handle_request(struct spdk_jsonrpc_server_conn *conn,
184 				   const struct spdk_json_val *method, const struct spdk_json_val *params,
185 				   const struct spdk_json_val *id)
186 {
187 	conn->server->handle_request(conn, method, params, id);
188 }
189 
190 void
191 spdk_jsonrpc_server_handle_error(struct spdk_jsonrpc_server_conn *conn, int error,
192 				 const struct spdk_json_val *method, const struct spdk_json_val *params,
193 				 const struct spdk_json_val *id)
194 {
195 	const char *msg;
196 
197 	switch (error) {
198 	case SPDK_JSONRPC_ERROR_PARSE_ERROR:
199 		msg = "Parse error";
200 		break;
201 
202 	case SPDK_JSONRPC_ERROR_INVALID_REQUEST:
203 		msg = "Invalid request";
204 		break;
205 
206 	case SPDK_JSONRPC_ERROR_METHOD_NOT_FOUND:
207 		msg = "Method not found";
208 		break;
209 
210 	case SPDK_JSONRPC_ERROR_INVALID_PARAMS:
211 		msg = "Invalid parameters";
212 		break;
213 
214 	case SPDK_JSONRPC_ERROR_INTERNAL_ERROR:
215 		msg = "Internal error";
216 		break;
217 
218 	default:
219 		msg = "Error";
220 		break;
221 	}
222 
223 	spdk_jsonrpc_send_error_response(conn, id, error, msg);
224 }
225 
226 static int
227 spdk_jsonrpc_server_conn_recv(struct spdk_jsonrpc_server_conn *conn)
228 {
229 	ssize_t rc;
230 	size_t recv_avail = SPDK_JSONRPC_RECV_BUF_SIZE - conn->recv_len;
231 
232 	rc = recv(conn->sockfd, conn->recv_buf + conn->recv_len, recv_avail, 0);
233 	if (rc == -1) {
234 		if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
235 			return 0;
236 		}
237 
238 		SPDK_TRACELOG(SPDK_TRACE_RPC, "recv() failed: %s\n", strerror(errno));
239 		return -1;
240 	}
241 
242 	if (rc == 0) {
243 		SPDK_TRACELOG(SPDK_TRACE_RPC, "remote closed connection\n");
244 		return -1;
245 	}
246 
247 	conn->recv_len += rc;
248 
249 	rc = spdk_jsonrpc_parse_request(conn, conn->recv_buf, conn->recv_len);
250 	if (rc < 0) {
251 		SPDK_ERRLOG("jsonrpc parse request failed\n");
252 		return -1;
253 	}
254 
255 	if (rc > 0) {
256 		/*
257 		 * Successfully parsed a request - move any data past the end of the
258 		 * parsed request down to the beginning.
259 		 */
260 		assert((size_t)rc <= conn->recv_len);
261 		memmove(conn->recv_buf, conn->recv_buf + rc, conn->recv_len - rc);
262 		conn->recv_len -= rc;
263 	}
264 
265 	return 0;
266 }
267 
268 static int
269 spdk_jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn *conn)
270 {
271 	ssize_t rc;
272 
273 	rc = send(conn->sockfd, conn->send_buf, conn->send_len, 0);
274 	if (rc < 0) {
275 		if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
276 			return 0;
277 		}
278 
279 		SPDK_TRACELOG(SPDK_TRACE_RPC, "send() failed: %s\n", strerror(errno));
280 		return -1;
281 	}
282 
283 	if (rc == 0) {
284 		SPDK_TRACELOG(SPDK_TRACE_RPC, "remote closed connection\n");
285 		return -1;
286 	}
287 
288 	conn->send_len -= rc;
289 
290 	return 0;
291 }
292 
293 int
294 spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server *server)
295 {
296 	int rc, i;
297 	struct pollfd *pfd;
298 	struct spdk_jsonrpc_server_conn *conn;
299 
300 	rc = poll(server->pollfds, server->num_conns + 1, 0);
301 
302 	if (rc < 0) {
303 		if (errno == EINTR) {
304 			return 0;
305 		}
306 
307 		SPDK_ERRLOG("jsonrpc poll() failed\n");
308 		return -1;
309 	}
310 
311 	if (rc == 0) {
312 		/* No sockets are ready */
313 		return 0;
314 	}
315 
316 	/* Check listen socket */
317 	if (server->num_conns < SPDK_JSONRPC_MAX_CONNS) {
318 		pfd = &server->pollfds[0];
319 		if (pfd->revents) {
320 			spdk_jsonrpc_server_accept(server);
321 		}
322 		pfd->revents = 0;
323 	}
324 
325 	for (i = 0; i < server->num_conns; i++) {
326 		pfd = &server->pollfds[i + 1];
327 		conn = &server->conns[i];
328 		if (conn->send_len) {
329 			/*
330 			 * If there is any data to send, keep sending it until the send buffer
331 			 *  is empty.  Each response should be allowed the full send buffer, so
332 			 *  don't accept any new requests until the previous response is sent out.
333 			 */
334 			if (pfd->revents & POLLOUT) {
335 				rc = spdk_jsonrpc_server_conn_send(conn);
336 				if (rc != 0) {
337 					SPDK_TRACELOG(SPDK_TRACE_RPC, "closing conn due to send failure\n");
338 					spdk_jsonrpc_server_conn_remove(conn);
339 				}
340 			}
341 		} else {
342 			/*
343 			 * No data to send - we can receive a new request.
344 			 */
345 			if (pfd->revents & POLLIN) {
346 				rc = spdk_jsonrpc_server_conn_recv(conn);
347 				if (rc != 0) {
348 					SPDK_TRACELOG(SPDK_TRACE_RPC, "closing conn due to recv failure\n");
349 					spdk_jsonrpc_server_conn_remove(conn);
350 				}
351 			}
352 		}
353 		pfd->revents = 0;
354 	}
355 
356 	return 0;
357 }
358