4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "jsonrpc_internal.h"
35 #include "spdk/string.h"
36 #include "spdk/util.h"
38 struct spdk_jsonrpc_server
*
39 spdk_jsonrpc_server_listen(int domain
, int protocol
,
40 struct sockaddr
*listen_addr
, socklen_t addrlen
,
41 spdk_jsonrpc_handle_request_fn handle_request
)
43 struct spdk_jsonrpc_server
*server
;
46 server
= calloc(1, sizeof(struct spdk_jsonrpc_server
));
51 TAILQ_INIT(&server
->free_conns
);
52 TAILQ_INIT(&server
->conns
);
54 for (i
= 0; i
< SPDK_JSONRPC_MAX_CONNS
; i
++) {
55 TAILQ_INSERT_TAIL(&server
->free_conns
, &server
->conns_array
[i
], link
);
58 server
->handle_request
= handle_request
;
60 server
->sockfd
= socket(domain
, SOCK_STREAM
, protocol
);
61 if (server
->sockfd
< 0) {
62 SPDK_ERRLOG("socket() failed\n");
68 setsockopt(server
->sockfd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(val
));
69 if (protocol
== IPPROTO_TCP
) {
70 setsockopt(server
->sockfd
, IPPROTO_TCP
, TCP_NODELAY
, &val
, sizeof(val
));
73 flag
= fcntl(server
->sockfd
, F_GETFL
);
74 if (fcntl(server
->sockfd
, F_SETFL
, flag
| O_NONBLOCK
) < 0) {
75 SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%s)\n",
76 server
->sockfd
, spdk_strerror(errno
));
77 close(server
->sockfd
);
82 rc
= bind(server
->sockfd
, listen_addr
, addrlen
);
84 SPDK_ERRLOG("could not bind JSON-RPC server: %s\n", spdk_strerror(errno
));
85 close(server
->sockfd
);
90 rc
= listen(server
->sockfd
, 512);
92 SPDK_ERRLOG("listen() failed, errno = %d\n", errno
);
93 close(server
->sockfd
);
102 spdk_jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn
*conn
)
106 if (conn
->sockfd
>= 0) {
110 if (conn
->close_cb
) {
111 conn
->close_cb(conn
, conn
->close_cb_ctx
);
117 spdk_jsonrpc_server_shutdown(struct spdk_jsonrpc_server
*server
)
119 struct spdk_jsonrpc_server_conn
*conn
;
121 close(server
->sockfd
);
123 TAILQ_FOREACH(conn
, &server
->conns
, link
) {
124 spdk_jsonrpc_server_conn_close(conn
);
131 spdk_jsonrpc_server_conn_remove(struct spdk_jsonrpc_server_conn
*conn
)
133 struct spdk_jsonrpc_server
*server
= conn
->server
;
135 spdk_jsonrpc_server_conn_close(conn
);
137 pthread_spin_destroy(&conn
->queue_lock
);
138 assert(STAILQ_EMPTY(&conn
->send_queue
));
140 TAILQ_REMOVE(&server
->conns
, conn
, link
);
141 TAILQ_INSERT_HEAD(&server
->free_conns
, conn
, link
);
145 spdk_jsonrpc_conn_add_close_cb(struct spdk_jsonrpc_server_conn
*conn
,
146 spdk_jsonrpc_conn_closed_fn cb
, void *ctx
)
150 pthread_spin_lock(&conn
->queue_lock
);
151 if (conn
->close_cb
== NULL
) {
153 conn
->close_cb_ctx
= ctx
;
155 rc
= conn
->close_cb
== cb
&& conn
->close_cb_ctx
== ctx
? -EEXIST
: -ENOSPC
;
157 pthread_spin_unlock(&conn
->queue_lock
);
163 spdk_jsonrpc_conn_del_close_cb(struct spdk_jsonrpc_server_conn
*conn
,
164 spdk_jsonrpc_conn_closed_fn cb
, void *ctx
)
168 pthread_spin_lock(&conn
->queue_lock
);
169 if (conn
->close_cb
== NULL
|| conn
->close_cb
!= cb
|| conn
->close_cb_ctx
!= ctx
) {
172 conn
->close_cb
= NULL
;
174 pthread_spin_unlock(&conn
->queue_lock
);
180 spdk_jsonrpc_server_accept(struct spdk_jsonrpc_server
*server
)
182 struct spdk_jsonrpc_server_conn
*conn
;
185 rc
= accept(server
->sockfd
, NULL
, NULL
);
187 conn
= TAILQ_FIRST(&server
->free_conns
);
188 assert(conn
!= NULL
);
190 conn
->server
= server
;
192 conn
->closed
= false;
194 conn
->outstanding_requests
= 0;
195 pthread_spin_init(&conn
->queue_lock
, PTHREAD_PROCESS_PRIVATE
);
196 STAILQ_INIT(&conn
->send_queue
);
197 conn
->send_request
= NULL
;
199 flag
= fcntl(conn
->sockfd
, F_GETFL
);
200 if (fcntl(conn
->sockfd
, F_SETFL
, flag
| O_NONBLOCK
) < 0) {
201 SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%s)\n",
202 conn
->sockfd
, spdk_strerror(errno
));
207 TAILQ_REMOVE(&server
->free_conns
, conn
, link
);
208 TAILQ_INSERT_TAIL(&server
->conns
, conn
, link
);
212 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
) {
220 spdk_jsonrpc_server_handle_request(struct spdk_jsonrpc_request
*request
,
221 const struct spdk_json_val
*method
, const struct spdk_json_val
*params
)
223 request
->conn
->server
->handle_request(request
, method
, params
);
227 spdk_jsonrpc_server_handle_error(struct spdk_jsonrpc_request
*request
, int error
)
232 case SPDK_JSONRPC_ERROR_PARSE_ERROR
:
236 case SPDK_JSONRPC_ERROR_INVALID_REQUEST
:
237 msg
= "Invalid request";
240 case SPDK_JSONRPC_ERROR_METHOD_NOT_FOUND
:
241 msg
= "Method not found";
244 case SPDK_JSONRPC_ERROR_INVALID_PARAMS
:
245 msg
= "Invalid parameters";
248 case SPDK_JSONRPC_ERROR_INTERNAL_ERROR
:
249 msg
= "Internal error";
257 spdk_jsonrpc_send_error_response(request
, error
, msg
);
261 spdk_jsonrpc_server_conn_recv(struct spdk_jsonrpc_server_conn
*conn
)
264 size_t recv_avail
= SPDK_JSONRPC_RECV_BUF_SIZE
- conn
->recv_len
;
266 rc
= recv(conn
->sockfd
, conn
->recv_buf
+ conn
->recv_len
, recv_avail
, 0);
268 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
) {
271 SPDK_DEBUGLOG(SPDK_LOG_RPC
, "recv() failed: %s\n", spdk_strerror(errno
));
276 SPDK_DEBUGLOG(SPDK_LOG_RPC
, "remote closed connection\n");
281 conn
->recv_len
+= rc
;
285 rc
= spdk_jsonrpc_parse_request(conn
, conn
->recv_buf
+ offset
, conn
->recv_len
- offset
);
287 SPDK_ERRLOG("jsonrpc parse request failed\n");
296 * Successfully parsed a requests - move any data past the end of the
297 * parsed requests down to the beginning.
299 assert((size_t)offset
<= conn
->recv_len
);
300 memmove(conn
->recv_buf
, conn
->recv_buf
+ offset
, conn
->recv_len
- offset
);
301 conn
->recv_len
-= offset
;
308 spdk_jsonrpc_server_send_response(struct spdk_jsonrpc_request
*request
)
310 struct spdk_jsonrpc_server_conn
*conn
= request
->conn
;
312 /* Queue the response to be sent */
313 pthread_spin_lock(&conn
->queue_lock
);
314 STAILQ_INSERT_TAIL(&conn
->send_queue
, request
, link
);
315 pthread_spin_unlock(&conn
->queue_lock
);
318 static struct spdk_jsonrpc_request
*
319 spdk_jsonrpc_server_dequeue_request(struct spdk_jsonrpc_server_conn
*conn
)
321 struct spdk_jsonrpc_request
*request
= NULL
;
323 pthread_spin_lock(&conn
->queue_lock
);
324 request
= STAILQ_FIRST(&conn
->send_queue
);
326 STAILQ_REMOVE_HEAD(&conn
->send_queue
, link
);
328 pthread_spin_unlock(&conn
->queue_lock
);
334 spdk_jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn
*conn
)
336 struct spdk_jsonrpc_request
*request
;
340 if (conn
->outstanding_requests
== 0) {
344 if (conn
->send_request
== NULL
) {
345 conn
->send_request
= spdk_jsonrpc_server_dequeue_request(conn
);
348 request
= conn
->send_request
;
349 if (request
== NULL
) {
350 /* Nothing to send right now */
354 if (request
->send_len
> 0) {
355 rc
= send(conn
->sockfd
, request
->send_buf
+ request
->send_offset
,
356 request
->send_len
, 0);
358 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
|| errno
== EINTR
) {
362 SPDK_DEBUGLOG(SPDK_LOG_RPC
, "send() failed: %s\n", spdk_strerror(errno
));
366 request
->send_offset
+= rc
;
367 request
->send_len
-= rc
;
370 if (request
->send_len
== 0) {
372 * Full response has been sent.
373 * Free it and set send_request to NULL to move on to the next queued response.
375 conn
->send_request
= NULL
;
376 spdk_jsonrpc_free_request(request
);
384 spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server
*server
)
387 struct spdk_jsonrpc_server_conn
*conn
, *conn_tmp
;
389 TAILQ_FOREACH_SAFE(conn
, &server
->conns
, link
, conn_tmp
) {
390 /* If we can't receive and there are no outstanding requests close the connection. */
391 if (conn
->closed
== true && conn
->outstanding_requests
== 0) {
392 spdk_jsonrpc_server_conn_close(conn
);
395 if (conn
->sockfd
== -1) {
396 struct spdk_jsonrpc_request
*request
;
399 * The client closed the connection, but there may still be requests
400 * outstanding; we have no way to cancel outstanding requests, so wait until
401 * each outstanding request sends a response (which will be discarded, since
402 * the connection is closed).
405 spdk_jsonrpc_free_request(conn
->send_request
);
406 conn
->send_request
= NULL
;
408 while ((request
= spdk_jsonrpc_server_dequeue_request(conn
)) != NULL
) {
409 spdk_jsonrpc_free_request(request
);
412 if (conn
->outstanding_requests
== 0) {
413 SPDK_DEBUGLOG(SPDK_LOG_RPC
, "all outstanding requests completed\n");
414 spdk_jsonrpc_server_conn_remove(conn
);
419 /* Check listen socket */
420 if (!TAILQ_EMPTY(&server
->free_conns
)) {
421 spdk_jsonrpc_server_accept(server
);
424 TAILQ_FOREACH(conn
, &server
->conns
, link
) {
425 if (conn
->sockfd
== -1) {
429 rc
= spdk_jsonrpc_server_conn_send(conn
);
431 spdk_jsonrpc_server_conn_close(conn
);
436 rc
= spdk_jsonrpc_server_conn_recv(conn
);
438 spdk_jsonrpc_server_conn_close(conn
);