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