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, flag; 44 45 server = calloc(1, sizeof(struct spdk_jsonrpc_server)); 46 if (server == NULL) { 47 return NULL; 48 } 49 50 server->handle_request = handle_request; 51 52 server->sockfd = socket(domain, SOCK_STREAM, protocol); 53 if (server->sockfd < 0) { 54 SPDK_ERRLOG("socket() failed\n"); 55 free(server); 56 return NULL; 57 } 58 59 val = 1; 60 setsockopt(server->sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 61 if (protocol == IPPROTO_TCP) { 62 setsockopt(server->sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); 63 } 64 65 flag = fcntl(server->sockfd, F_GETFL); 66 if (fcntl(server->sockfd, F_SETFL, flag | O_NONBLOCK) < 0) { 67 SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%s)\n", 68 server->sockfd, spdk_strerror(errno)); 69 close(server->sockfd); 70 free(server); 71 return NULL; 72 } 73 74 rc = bind(server->sockfd, listen_addr, addrlen); 75 if (rc != 0) { 76 SPDK_ERRLOG("could not bind JSON-RPC server: %s\n", spdk_strerror(errno)); 77 close(server->sockfd); 78 free(server); 79 return NULL; 80 } 81 82 rc = listen(server->sockfd, 512); 83 if (rc != 0) { 84 SPDK_ERRLOG("listen() failed, errno = %d\n", errno); 85 close(server->sockfd); 86 free(server); 87 return NULL; 88 } 89 90 return server; 91 } 92 93 void 94 spdk_jsonrpc_server_shutdown(struct spdk_jsonrpc_server *server) 95 { 96 int i; 97 98 close(server->sockfd); 99 100 for (i = 0; i < server->num_conns; i++) { 101 close(server->conns[i].sockfd); 102 } 103 104 free(server); 105 } 106 107 static void 108 spdk_jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn *conn) 109 { 110 conn->closed = true; 111 112 if (conn->sockfd >= 0) { 113 close(conn->sockfd); 114 conn->sockfd = -1; 115 } 116 } 117 118 static void 119 spdk_jsonrpc_server_conn_remove(struct spdk_jsonrpc_server_conn *conn) 120 { 121 struct spdk_jsonrpc_server *server = conn->server; 122 int conn_idx = conn - server->conns; 123 124 spdk_jsonrpc_server_conn_close(conn); 125 126 spdk_ring_free(conn->send_queue); 127 128 /* Swap conn with the last entry in conns */ 129 server->conns[conn_idx] = server->conns[server->num_conns - 1]; 130 server->num_conns--; 131 } 132 133 static int 134 spdk_jsonrpc_server_accept(struct spdk_jsonrpc_server *server) 135 { 136 struct spdk_jsonrpc_server_conn *conn; 137 int rc, conn_idx, flag; 138 139 rc = accept(server->sockfd, NULL, NULL); 140 if (rc >= 0) { 141 assert(server->num_conns < SPDK_JSONRPC_MAX_CONNS); 142 conn_idx = server->num_conns; 143 conn = &server->conns[conn_idx]; 144 conn->server = server; 145 conn->sockfd = rc; 146 conn->closed = false; 147 conn->recv_len = 0; 148 conn->outstanding_requests = 0; 149 conn->send_request = NULL; 150 conn->send_queue = spdk_ring_create(SPDK_RING_TYPE_SP_SC, 128, SPDK_ENV_SOCKET_ID_ANY); 151 if (conn->send_queue == NULL) { 152 SPDK_ERRLOG("send_queue allocation failed\n"); 153 close(conn->sockfd); 154 return -1; 155 } 156 157 flag = fcntl(conn->sockfd, F_GETFL); 158 if (fcntl(conn->sockfd, F_SETFL, flag | O_NONBLOCK) < 0) { 159 SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%s)\n", 160 conn->sockfd, spdk_strerror(errno)); 161 close(conn->sockfd); 162 return -1; 163 } 164 165 server->num_conns++; 166 167 return 0; 168 } 169 170 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { 171 return 0; 172 } 173 174 return -1; 175 } 176 177 void 178 spdk_jsonrpc_server_handle_request(struct spdk_jsonrpc_request *request, 179 const struct spdk_json_val *method, const struct spdk_json_val *params) 180 { 181 request->conn->server->handle_request(request, method, params); 182 } 183 184 void 185 spdk_jsonrpc_server_handle_error(struct spdk_jsonrpc_request *request, int error) 186 { 187 const char *msg; 188 189 switch (error) { 190 case SPDK_JSONRPC_ERROR_PARSE_ERROR: 191 msg = "Parse error"; 192 break; 193 194 case SPDK_JSONRPC_ERROR_INVALID_REQUEST: 195 msg = "Invalid request"; 196 break; 197 198 case SPDK_JSONRPC_ERROR_METHOD_NOT_FOUND: 199 msg = "Method not found"; 200 break; 201 202 case SPDK_JSONRPC_ERROR_INVALID_PARAMS: 203 msg = "Invalid parameters"; 204 break; 205 206 case SPDK_JSONRPC_ERROR_INTERNAL_ERROR: 207 msg = "Internal error"; 208 break; 209 210 default: 211 msg = "Error"; 212 break; 213 } 214 215 spdk_jsonrpc_send_error_response(request, error, msg); 216 } 217 218 static int 219 spdk_jsonrpc_server_conn_recv(struct spdk_jsonrpc_server_conn *conn) 220 { 221 ssize_t rc; 222 size_t recv_avail = SPDK_JSONRPC_RECV_BUF_SIZE - conn->recv_len; 223 224 rc = recv(conn->sockfd, conn->recv_buf + conn->recv_len, recv_avail, 0); 225 if (rc == -1) { 226 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { 227 return 0; 228 } 229 SPDK_DEBUGLOG(SPDK_LOG_RPC, "recv() failed: %s\n", spdk_strerror(errno)); 230 return -1; 231 } 232 233 if (rc == 0) { 234 SPDK_DEBUGLOG(SPDK_LOG_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_DEBUGLOG(SPDK_LOG_RPC, "send() failed: %s\n", spdk_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_DEBUGLOG(SPDK_LOG_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