1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2016 Intel Corporation.
3376d117cSDaniel Verkamp * All rights reserved.
4376d117cSDaniel Verkamp */
5376d117cSDaniel Verkamp
6376d117cSDaniel Verkamp #include "jsonrpc_internal.h"
74d43844fSSeth Howell #include "spdk/string.h"
85b1b3ddfSPawel Wodkowski #include "spdk/util.h"
9376d117cSDaniel Verkamp
10376d117cSDaniel Verkamp struct spdk_jsonrpc_server *
spdk_jsonrpc_server_listen(int domain,int protocol,struct sockaddr * listen_addr,socklen_t addrlen,spdk_jsonrpc_handle_request_fn handle_request)11e6d1a5acSDaniel Verkamp spdk_jsonrpc_server_listen(int domain, int protocol,
12e6d1a5acSDaniel Verkamp struct sockaddr *listen_addr, socklen_t addrlen,
13376d117cSDaniel Verkamp spdk_jsonrpc_handle_request_fn handle_request)
14376d117cSDaniel Verkamp {
15376d117cSDaniel Verkamp struct spdk_jsonrpc_server *server;
1632999ab9SJim Harris int rc, val, i;
17376d117cSDaniel Verkamp
18376d117cSDaniel Verkamp server = calloc(1, sizeof(struct spdk_jsonrpc_server));
19376d117cSDaniel Verkamp if (server == NULL) {
20376d117cSDaniel Verkamp return NULL;
21376d117cSDaniel Verkamp }
22376d117cSDaniel Verkamp
2301a9118dSPawel Wodkowski TAILQ_INIT(&server->free_conns);
2401a9118dSPawel Wodkowski TAILQ_INIT(&server->conns);
2501a9118dSPawel Wodkowski
2601a9118dSPawel Wodkowski for (i = 0; i < SPDK_JSONRPC_MAX_CONNS; i++) {
2701a9118dSPawel Wodkowski TAILQ_INSERT_TAIL(&server->free_conns, &server->conns_array[i], link);
2801a9118dSPawel Wodkowski }
2901a9118dSPawel Wodkowski
30376d117cSDaniel Verkamp server->handle_request = handle_request;
31376d117cSDaniel Verkamp
32e450b8e7Szhaoshushu.zss server->sockfd = socket(domain, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
33376d117cSDaniel Verkamp if (server->sockfd < 0) {
34376d117cSDaniel Verkamp SPDK_ERRLOG("socket() failed\n");
35376d117cSDaniel Verkamp free(server);
36376d117cSDaniel Verkamp return NULL;
37376d117cSDaniel Verkamp }
38376d117cSDaniel Verkamp
39376d117cSDaniel Verkamp val = 1;
4058549382SGangCao rc = setsockopt(server->sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
4158549382SGangCao if (rc != 0) {
4258549382SGangCao SPDK_ERRLOG("could not set SO_REUSEADDR sock option: %s\n", spdk_strerror(errno));
4358549382SGangCao close(server->sockfd);
4458549382SGangCao free(server);
4558549382SGangCao return NULL;
4658549382SGangCao }
47376d117cSDaniel Verkamp
48376d117cSDaniel Verkamp rc = bind(server->sockfd, listen_addr, addrlen);
49376d117cSDaniel Verkamp if (rc != 0) {
50891c12a6SPawel Wodkowski SPDK_ERRLOG("could not bind JSON-RPC server: %s\n", spdk_strerror(errno));
51376d117cSDaniel Verkamp close(server->sockfd);
52376d117cSDaniel Verkamp free(server);
53376d117cSDaniel Verkamp return NULL;
54376d117cSDaniel Verkamp }
55376d117cSDaniel Verkamp
56376d117cSDaniel Verkamp rc = listen(server->sockfd, 512);
57376d117cSDaniel Verkamp if (rc != 0) {
58376d117cSDaniel Verkamp SPDK_ERRLOG("listen() failed, errno = %d\n", errno);
59376d117cSDaniel Verkamp close(server->sockfd);
60376d117cSDaniel Verkamp free(server);
61376d117cSDaniel Verkamp return NULL;
62376d117cSDaniel Verkamp }
63376d117cSDaniel Verkamp
64376d117cSDaniel Verkamp return server;
65376d117cSDaniel Verkamp }
66376d117cSDaniel Verkamp
6717c006a7Syidong0635 static struct spdk_jsonrpc_request *
jsonrpc_server_dequeue_request(struct spdk_jsonrpc_server_conn * conn)680be5557cSSeth Howell jsonrpc_server_dequeue_request(struct spdk_jsonrpc_server_conn *conn)
6917c006a7Syidong0635 {
7017c006a7Syidong0635 struct spdk_jsonrpc_request *request = NULL;
7117c006a7Syidong0635
7217c006a7Syidong0635 pthread_spin_lock(&conn->queue_lock);
7317c006a7Syidong0635 request = STAILQ_FIRST(&conn->send_queue);
7417c006a7Syidong0635 if (request) {
7517c006a7Syidong0635 STAILQ_REMOVE_HEAD(&conn->send_queue, link);
7617c006a7Syidong0635 }
7717c006a7Syidong0635 pthread_spin_unlock(&conn->queue_lock);
7817c006a7Syidong0635 return request;
7917c006a7Syidong0635 }
8017c006a7Syidong0635
8117c006a7Syidong0635 static void
jsonrpc_server_free_conn_request(struct spdk_jsonrpc_server_conn * conn)820be5557cSSeth Howell jsonrpc_server_free_conn_request(struct spdk_jsonrpc_server_conn *conn)
8317c006a7Syidong0635 {
8417c006a7Syidong0635 struct spdk_jsonrpc_request *request;
8517c006a7Syidong0635
86134590a2SSeth Howell jsonrpc_free_request(conn->send_request);
8717c006a7Syidong0635 conn->send_request = NULL ;
88*2fb672afSKrzysztof Karas
89*2fb672afSKrzysztof Karas pthread_spin_lock(&conn->queue_lock);
90*2fb672afSKrzysztof Karas /* There might still be some requests being processed.
91*2fb672afSKrzysztof Karas * We need to tell them that this connection is closed. */
92*2fb672afSKrzysztof Karas STAILQ_FOREACH(request, &conn->outstanding_queue, link) {
93*2fb672afSKrzysztof Karas request->conn = NULL;
94*2fb672afSKrzysztof Karas }
95*2fb672afSKrzysztof Karas pthread_spin_unlock(&conn->queue_lock);
96*2fb672afSKrzysztof Karas
970be5557cSSeth Howell while ((request = jsonrpc_server_dequeue_request(conn)) != NULL) {
98134590a2SSeth Howell jsonrpc_free_request(request);
9917c006a7Syidong0635 }
10017c006a7Syidong0635 }
10117c006a7Syidong0635
102376d117cSDaniel Verkamp static void
jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn * conn)1030be5557cSSeth Howell jsonrpc_server_conn_close(struct spdk_jsonrpc_server_conn *conn)
104cc740794SDaniel Verkamp {
105cc740794SDaniel Verkamp conn->closed = true;
106cc740794SDaniel Verkamp
107cc740794SDaniel Verkamp if (conn->sockfd >= 0) {
1080be5557cSSeth Howell jsonrpc_server_free_conn_request(conn);
109cc740794SDaniel Verkamp close(conn->sockfd);
110cc740794SDaniel Verkamp conn->sockfd = -1;
1115b1b3ddfSPawel Wodkowski
1125b1b3ddfSPawel Wodkowski if (conn->close_cb) {
1135b1b3ddfSPawel Wodkowski conn->close_cb(conn, conn->close_cb_ctx);
114cc740794SDaniel Verkamp }
115cc740794SDaniel Verkamp }
1165b1b3ddfSPawel Wodkowski }
1175b1b3ddfSPawel Wodkowski
1185b1b3ddfSPawel Wodkowski void
spdk_jsonrpc_server_shutdown(struct spdk_jsonrpc_server * server)1195b1b3ddfSPawel Wodkowski spdk_jsonrpc_server_shutdown(struct spdk_jsonrpc_server *server)
1205b1b3ddfSPawel Wodkowski {
1215b1b3ddfSPawel Wodkowski struct spdk_jsonrpc_server_conn *conn;
1225b1b3ddfSPawel Wodkowski
1235b1b3ddfSPawel Wodkowski close(server->sockfd);
1245b1b3ddfSPawel Wodkowski
1255b1b3ddfSPawel Wodkowski TAILQ_FOREACH(conn, &server->conns, link) {
1260be5557cSSeth Howell jsonrpc_server_conn_close(conn);
1275b1b3ddfSPawel Wodkowski }
1285b1b3ddfSPawel Wodkowski
1295b1b3ddfSPawel Wodkowski free(server);
1305b1b3ddfSPawel Wodkowski }
131cc740794SDaniel Verkamp
132cc740794SDaniel Verkamp static void
jsonrpc_server_conn_remove(struct spdk_jsonrpc_server_conn * conn)1330be5557cSSeth Howell jsonrpc_server_conn_remove(struct spdk_jsonrpc_server_conn *conn)
134376d117cSDaniel Verkamp {
135376d117cSDaniel Verkamp struct spdk_jsonrpc_server *server = conn->server;
136376d117cSDaniel Verkamp
1370be5557cSSeth Howell jsonrpc_server_conn_close(conn);
138376d117cSDaniel Verkamp
139b066126bSPawel Wodkowski pthread_spin_destroy(&conn->queue_lock);
140b066126bSPawel Wodkowski assert(STAILQ_EMPTY(&conn->send_queue));
1414e003b67SDaniel Verkamp
14201a9118dSPawel Wodkowski TAILQ_REMOVE(&server->conns, conn, link);
14301a9118dSPawel Wodkowski TAILQ_INSERT_HEAD(&server->free_conns, conn, link);
144376d117cSDaniel Verkamp }
145376d117cSDaniel Verkamp
1465b1b3ddfSPawel Wodkowski int
spdk_jsonrpc_conn_add_close_cb(struct spdk_jsonrpc_server_conn * conn,spdk_jsonrpc_conn_closed_fn cb,void * ctx)1475b1b3ddfSPawel Wodkowski spdk_jsonrpc_conn_add_close_cb(struct spdk_jsonrpc_server_conn *conn,
1485b1b3ddfSPawel Wodkowski spdk_jsonrpc_conn_closed_fn cb, void *ctx)
1495b1b3ddfSPawel Wodkowski {
1505b1b3ddfSPawel Wodkowski int rc = 0;
1515b1b3ddfSPawel Wodkowski
1525b1b3ddfSPawel Wodkowski pthread_spin_lock(&conn->queue_lock);
1535b1b3ddfSPawel Wodkowski if (conn->close_cb == NULL) {
1545b1b3ddfSPawel Wodkowski conn->close_cb = cb;
1555b1b3ddfSPawel Wodkowski conn->close_cb_ctx = ctx;
1565b1b3ddfSPawel Wodkowski } else {
1575b1b3ddfSPawel Wodkowski rc = conn->close_cb == cb && conn->close_cb_ctx == ctx ? -EEXIST : -ENOSPC;
1585b1b3ddfSPawel Wodkowski }
1595b1b3ddfSPawel Wodkowski pthread_spin_unlock(&conn->queue_lock);
1605b1b3ddfSPawel Wodkowski
1615b1b3ddfSPawel Wodkowski return rc;
1625b1b3ddfSPawel Wodkowski }
1635b1b3ddfSPawel Wodkowski
1645b1b3ddfSPawel Wodkowski int
spdk_jsonrpc_conn_del_close_cb(struct spdk_jsonrpc_server_conn * conn,spdk_jsonrpc_conn_closed_fn cb,void * ctx)1655b1b3ddfSPawel Wodkowski spdk_jsonrpc_conn_del_close_cb(struct spdk_jsonrpc_server_conn *conn,
1665b1b3ddfSPawel Wodkowski spdk_jsonrpc_conn_closed_fn cb, void *ctx)
1675b1b3ddfSPawel Wodkowski {
1685b1b3ddfSPawel Wodkowski int rc = 0;
1695b1b3ddfSPawel Wodkowski
1705b1b3ddfSPawel Wodkowski pthread_spin_lock(&conn->queue_lock);
1715b1b3ddfSPawel Wodkowski if (conn->close_cb == NULL || conn->close_cb != cb || conn->close_cb_ctx != ctx) {
1725b1b3ddfSPawel Wodkowski rc = -ENOENT;
1735b1b3ddfSPawel Wodkowski } else {
1745b1b3ddfSPawel Wodkowski conn->close_cb = NULL;
1755b1b3ddfSPawel Wodkowski }
1765b1b3ddfSPawel Wodkowski pthread_spin_unlock(&conn->queue_lock);
1775b1b3ddfSPawel Wodkowski
1785b1b3ddfSPawel Wodkowski return rc;
1795b1b3ddfSPawel Wodkowski }
1805b1b3ddfSPawel Wodkowski
181376d117cSDaniel Verkamp static int
jsonrpc_server_accept(struct spdk_jsonrpc_server * server)1820be5557cSSeth Howell jsonrpc_server_accept(struct spdk_jsonrpc_server *server)
183376d117cSDaniel Verkamp {
184376d117cSDaniel Verkamp struct spdk_jsonrpc_server_conn *conn;
18501a9118dSPawel Wodkowski int rc, flag;
186376d117cSDaniel Verkamp
187376d117cSDaniel Verkamp rc = accept(server->sockfd, NULL, NULL);
188376d117cSDaniel Verkamp if (rc >= 0) {
18901a9118dSPawel Wodkowski conn = TAILQ_FIRST(&server->free_conns);
19001a9118dSPawel Wodkowski assert(conn != NULL);
19101a9118dSPawel Wodkowski
192376d117cSDaniel Verkamp conn->server = server;
193376d117cSDaniel Verkamp conn->sockfd = rc;
1944e003b67SDaniel Verkamp conn->closed = false;
195376d117cSDaniel Verkamp conn->recv_len = 0;
1964e003b67SDaniel Verkamp conn->outstanding_requests = 0;
197b066126bSPawel Wodkowski STAILQ_INIT(&conn->send_queue);
198*2fb672afSKrzysztof Karas STAILQ_INIT(&conn->outstanding_queue);
1994e003b67SDaniel Verkamp conn->send_request = NULL;
200376d117cSDaniel Verkamp
2017192849eSSeth Howell if (pthread_spin_init(&conn->queue_lock, PTHREAD_PROCESS_PRIVATE)) {
2027192849eSSeth Howell SPDK_ERRLOG("Unable to create queue lock for socket: %d", conn->sockfd);
2037192849eSSeth Howell close(conn->sockfd);
2047192849eSSeth Howell return -1;
2057192849eSSeth Howell }
2067192849eSSeth Howell
207161a3002STomasz Zawadzki flag = fcntl(conn->sockfd, F_GETFL);
208161a3002STomasz Zawadzki if (fcntl(conn->sockfd, F_SETFL, flag | O_NONBLOCK) < 0) {
209891c12a6SPawel Wodkowski SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%s)\n",
210891c12a6SPawel Wodkowski conn->sockfd, spdk_strerror(errno));
211376d117cSDaniel Verkamp close(conn->sockfd);
2127192849eSSeth Howell pthread_spin_destroy(&conn->queue_lock);
213376d117cSDaniel Verkamp return -1;
214376d117cSDaniel Verkamp }
215376d117cSDaniel Verkamp
21601a9118dSPawel Wodkowski TAILQ_REMOVE(&server->free_conns, conn, link);
21701a9118dSPawel Wodkowski TAILQ_INSERT_TAIL(&server->conns, conn, link);
218376d117cSDaniel Verkamp return 0;
219376d117cSDaniel Verkamp }
220376d117cSDaniel Verkamp
221376d117cSDaniel Verkamp if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
222376d117cSDaniel Verkamp return 0;
223376d117cSDaniel Verkamp }
224376d117cSDaniel Verkamp
225376d117cSDaniel Verkamp return -1;
226376d117cSDaniel Verkamp }
227376d117cSDaniel Verkamp
228376d117cSDaniel Verkamp void
jsonrpc_server_handle_request(struct spdk_jsonrpc_request * request,const struct spdk_json_val * method,const struct spdk_json_val * params)229134590a2SSeth Howell jsonrpc_server_handle_request(struct spdk_jsonrpc_request *request,
2302bdec64fSDaniel Verkamp const struct spdk_json_val *method, const struct spdk_json_val *params)
231376d117cSDaniel Verkamp {
2322bdec64fSDaniel Verkamp request->conn->server->handle_request(request, method, params);
233376d117cSDaniel Verkamp }
234376d117cSDaniel Verkamp
235376d117cSDaniel Verkamp void
jsonrpc_server_handle_error(struct spdk_jsonrpc_request * request,int error)236134590a2SSeth Howell jsonrpc_server_handle_error(struct spdk_jsonrpc_request *request, int error)
237376d117cSDaniel Verkamp {
238376d117cSDaniel Verkamp const char *msg;
239376d117cSDaniel Verkamp
240376d117cSDaniel Verkamp switch (error) {
241376d117cSDaniel Verkamp case SPDK_JSONRPC_ERROR_PARSE_ERROR:
242376d117cSDaniel Verkamp msg = "Parse error";
243376d117cSDaniel Verkamp break;
244376d117cSDaniel Verkamp
245376d117cSDaniel Verkamp case SPDK_JSONRPC_ERROR_INVALID_REQUEST:
246376d117cSDaniel Verkamp msg = "Invalid request";
247376d117cSDaniel Verkamp break;
248376d117cSDaniel Verkamp
249376d117cSDaniel Verkamp case SPDK_JSONRPC_ERROR_METHOD_NOT_FOUND:
250376d117cSDaniel Verkamp msg = "Method not found";
251376d117cSDaniel Verkamp break;
252376d117cSDaniel Verkamp
253376d117cSDaniel Verkamp case SPDK_JSONRPC_ERROR_INVALID_PARAMS:
254376d117cSDaniel Verkamp msg = "Invalid parameters";
255376d117cSDaniel Verkamp break;
256376d117cSDaniel Verkamp
257376d117cSDaniel Verkamp case SPDK_JSONRPC_ERROR_INTERNAL_ERROR:
258376d117cSDaniel Verkamp msg = "Internal error";
259376d117cSDaniel Verkamp break;
260376d117cSDaniel Verkamp
261376d117cSDaniel Verkamp default:
262376d117cSDaniel Verkamp msg = "Error";
263376d117cSDaniel Verkamp break;
264376d117cSDaniel Verkamp }
265376d117cSDaniel Verkamp
2662bdec64fSDaniel Verkamp spdk_jsonrpc_send_error_response(request, error, msg);
267376d117cSDaniel Verkamp }
268376d117cSDaniel Verkamp
269376d117cSDaniel Verkamp static int
jsonrpc_server_conn_recv(struct spdk_jsonrpc_server_conn * conn)2700be5557cSSeth Howell jsonrpc_server_conn_recv(struct spdk_jsonrpc_server_conn *conn)
271376d117cSDaniel Verkamp {
272122a7763SPawel Wodkowski ssize_t rc, offset;
273376d117cSDaniel Verkamp size_t recv_avail = SPDK_JSONRPC_RECV_BUF_SIZE - conn->recv_len;
274376d117cSDaniel Verkamp
275376d117cSDaniel Verkamp rc = recv(conn->sockfd, conn->recv_buf + conn->recv_len, recv_avail, 0);
276376d117cSDaniel Verkamp if (rc == -1) {
277376d117cSDaniel Verkamp if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
278376d117cSDaniel Verkamp return 0;
279376d117cSDaniel Verkamp }
2802172c432STomasz Zawadzki SPDK_DEBUGLOG(rpc, "recv() failed: %s\n", spdk_strerror(errno));
281376d117cSDaniel Verkamp return -1;
282376d117cSDaniel Verkamp }
283376d117cSDaniel Verkamp
284376d117cSDaniel Verkamp if (rc == 0) {
2852172c432STomasz Zawadzki SPDK_DEBUGLOG(rpc, "remote closed connection\n");
286bbcb35f5SPawel Wodkowski conn->closed = true;
287bbcb35f5SPawel Wodkowski return 0;
288376d117cSDaniel Verkamp }
289376d117cSDaniel Verkamp
290376d117cSDaniel Verkamp conn->recv_len += rc;
291376d117cSDaniel Verkamp
292122a7763SPawel Wodkowski offset = 0;
293122a7763SPawel Wodkowski do {
294134590a2SSeth Howell rc = jsonrpc_parse_request(conn, conn->recv_buf + offset, conn->recv_len - offset);
295376d117cSDaniel Verkamp if (rc < 0) {
296376d117cSDaniel Verkamp SPDK_ERRLOG("jsonrpc parse request failed\n");
297376d117cSDaniel Verkamp return -1;
298376d117cSDaniel Verkamp }
299376d117cSDaniel Verkamp
300122a7763SPawel Wodkowski offset += rc;
301122a7763SPawel Wodkowski } while (rc > 0);
302122a7763SPawel Wodkowski
303122a7763SPawel Wodkowski if (offset > 0) {
304376d117cSDaniel Verkamp /*
305122a7763SPawel Wodkowski * Successfully parsed a requests - move any data past the end of the
306122a7763SPawel Wodkowski * parsed requests down to the beginning.
307376d117cSDaniel Verkamp */
308122a7763SPawel Wodkowski assert((size_t)offset <= conn->recv_len);
309122a7763SPawel Wodkowski memmove(conn->recv_buf, conn->recv_buf + offset, conn->recv_len - offset);
310122a7763SPawel Wodkowski conn->recv_len -= offset;
311376d117cSDaniel Verkamp }
312376d117cSDaniel Verkamp
313376d117cSDaniel Verkamp return 0;
314376d117cSDaniel Verkamp }
315376d117cSDaniel Verkamp
3164e003b67SDaniel Verkamp void
jsonrpc_server_send_response(struct spdk_jsonrpc_request * request)317134590a2SSeth Howell jsonrpc_server_send_response(struct spdk_jsonrpc_request *request)
3184e003b67SDaniel Verkamp {
3190f842e86SPawel Wodkowski struct spdk_jsonrpc_server_conn *conn = request->conn;
3200f842e86SPawel Wodkowski
321*2fb672afSKrzysztof Karas if (conn == NULL) {
322*2fb672afSKrzysztof Karas /* We cannot respond to the request, because the connection is closed. */
323*2fb672afSKrzysztof Karas SPDK_WARNLOG("Unable to send response: connection closed.\n");
324*2fb672afSKrzysztof Karas jsonrpc_free_request(request);
325*2fb672afSKrzysztof Karas return;
326*2fb672afSKrzysztof Karas }
327*2fb672afSKrzysztof Karas
3284e003b67SDaniel Verkamp /* Queue the response to be sent */
329b066126bSPawel Wodkowski pthread_spin_lock(&conn->queue_lock);
330*2fb672afSKrzysztof Karas STAILQ_REMOVE(&conn->outstanding_queue, request, spdk_jsonrpc_request, link);
331b066126bSPawel Wodkowski STAILQ_INSERT_TAIL(&conn->send_queue, request, link);
332b066126bSPawel Wodkowski pthread_spin_unlock(&conn->queue_lock);
3334e003b67SDaniel Verkamp }
3344e003b67SDaniel Verkamp
335b066126bSPawel Wodkowski
336376d117cSDaniel Verkamp static int
jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn * conn)3370be5557cSSeth Howell jsonrpc_server_conn_send(struct spdk_jsonrpc_server_conn *conn)
338376d117cSDaniel Verkamp {
3394e003b67SDaniel Verkamp struct spdk_jsonrpc_request *request;
340376d117cSDaniel Verkamp ssize_t rc;
341376d117cSDaniel Verkamp
3424e003b67SDaniel Verkamp more:
3434e003b67SDaniel Verkamp if (conn->outstanding_requests == 0) {
3444e003b67SDaniel Verkamp return 0;
3454e003b67SDaniel Verkamp }
3464e003b67SDaniel Verkamp
3474e003b67SDaniel Verkamp if (conn->send_request == NULL) {
3480be5557cSSeth Howell conn->send_request = jsonrpc_server_dequeue_request(conn);
3494e003b67SDaniel Verkamp }
3504e003b67SDaniel Verkamp
3514e003b67SDaniel Verkamp request = conn->send_request;
3524e003b67SDaniel Verkamp if (request == NULL) {
3534e003b67SDaniel Verkamp /* Nothing to send right now */
3544e003b67SDaniel Verkamp return 0;
3554e003b67SDaniel Verkamp }
3564e003b67SDaniel Verkamp
35730b534c9SShuhei Matsumoto if (request->send_offset == 0) {
35830b534c9SShuhei Matsumoto /* A byte for the null terminator is included in the send buffer. */
35930b534c9SShuhei Matsumoto request->send_buf[request->send_len] = '\0';
36030b534c9SShuhei Matsumoto }
36130b534c9SShuhei Matsumoto
3620f842e86SPawel Wodkowski if (request->send_len > 0) {
3634e003b67SDaniel Verkamp rc = send(conn->sockfd, request->send_buf + request->send_offset,
3644e003b67SDaniel Verkamp request->send_len, 0);
365376d117cSDaniel Verkamp if (rc < 0) {
366376d117cSDaniel Verkamp if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
367376d117cSDaniel Verkamp return 0;
368376d117cSDaniel Verkamp }
369376d117cSDaniel Verkamp
3702172c432STomasz Zawadzki SPDK_DEBUGLOG(rpc, "send() failed: %s\n", spdk_strerror(errno));
371376d117cSDaniel Verkamp return -1;
372376d117cSDaniel Verkamp }
373376d117cSDaniel Verkamp
3744e003b67SDaniel Verkamp request->send_offset += rc;
3754e003b67SDaniel Verkamp request->send_len -= rc;
3760f842e86SPawel Wodkowski }
3774e003b67SDaniel Verkamp
3784e003b67SDaniel Verkamp if (request->send_len == 0) {
3794e003b67SDaniel Verkamp /*
3804e003b67SDaniel Verkamp * Full response has been sent.
3814e003b67SDaniel Verkamp * Free it and set send_request to NULL to move on to the next queued response.
3824e003b67SDaniel Verkamp */
3834e003b67SDaniel Verkamp conn->send_request = NULL;
384b3bec079SShuhei Matsumoto jsonrpc_complete_request(request);
3854e003b67SDaniel Verkamp goto more;
3864e003b67SDaniel Verkamp }
387376d117cSDaniel Verkamp
388376d117cSDaniel Verkamp return 0;
389376d117cSDaniel Verkamp }
390376d117cSDaniel Verkamp
391376d117cSDaniel Verkamp int
spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server * server)392376d117cSDaniel Verkamp spdk_jsonrpc_server_poll(struct spdk_jsonrpc_server *server)
393376d117cSDaniel Verkamp {
39401a9118dSPawel Wodkowski int rc;
39501a9118dSPawel Wodkowski struct spdk_jsonrpc_server_conn *conn, *conn_tmp;
396376d117cSDaniel Verkamp
39701a9118dSPawel Wodkowski TAILQ_FOREACH_SAFE(conn, &server->conns, link, conn_tmp) {
398bbcb35f5SPawel Wodkowski /* If we can't receive and there are no outstanding requests close the connection. */
399bbcb35f5SPawel Wodkowski if (conn->closed == true && conn->outstanding_requests == 0) {
4000be5557cSSeth Howell jsonrpc_server_conn_close(conn);
401bbcb35f5SPawel Wodkowski }
402bbcb35f5SPawel Wodkowski
40317c006a7Syidong0635 if (conn->sockfd == -1 && conn->outstanding_requests == 0) {
4040be5557cSSeth Howell jsonrpc_server_conn_remove(conn);
4054e003b67SDaniel Verkamp }
4064e003b67SDaniel Verkamp }
407122e2846SDaniel Verkamp
408122e2846SDaniel Verkamp /* Check listen socket */
40901a9118dSPawel Wodkowski if (!TAILQ_EMPTY(&server->free_conns)) {
4100be5557cSSeth Howell jsonrpc_server_accept(server);
411122e2846SDaniel Verkamp }
412122e2846SDaniel Verkamp
41301a9118dSPawel Wodkowski TAILQ_FOREACH(conn, &server->conns, link) {
414bbcb35f5SPawel Wodkowski if (conn->sockfd == -1) {
4151153b8c5SDaniel Verkamp continue;
4161153b8c5SDaniel Verkamp }
4171153b8c5SDaniel Verkamp
4180be5557cSSeth Howell rc = jsonrpc_server_conn_send(conn);
419376d117cSDaniel Verkamp if (rc != 0) {
4200be5557cSSeth Howell jsonrpc_server_conn_close(conn);
4214e003b67SDaniel Verkamp continue;
422376d117cSDaniel Verkamp }
4234e003b67SDaniel Verkamp
424bbcb35f5SPawel Wodkowski if (!conn->closed) {
4250be5557cSSeth Howell rc = jsonrpc_server_conn_recv(conn);
426376d117cSDaniel Verkamp if (rc != 0) {
4270be5557cSSeth Howell jsonrpc_server_conn_close(conn);
428bbcb35f5SPawel Wodkowski }
429376d117cSDaniel Verkamp }
430376d117cSDaniel Verkamp }
4314e003b67SDaniel Verkamp
432376d117cSDaniel Verkamp return 0;
433376d117cSDaniel Verkamp }
434