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 #include "spdk/string.h" 34 #include "jsonrpc_internal.h" 35 36 #define RPC_DEFAULT_PORT "5260" 37 38 static struct spdk_jsonrpc_client * 39 _spdk_jsonrpc_client_connect(int domain, int protocol, 40 struct sockaddr *server_addr, socklen_t addrlen) 41 { 42 struct spdk_jsonrpc_client *client; 43 int rc; 44 45 client = calloc(1, sizeof(struct spdk_jsonrpc_client)); 46 if (client == NULL) { 47 return NULL; 48 } 49 50 client->sockfd = socket(domain, SOCK_STREAM, protocol); 51 if (client->sockfd < 0) { 52 SPDK_ERRLOG("socket() failed\n"); 53 free(client); 54 return NULL; 55 } 56 57 rc = connect(client->sockfd, server_addr, addrlen); 58 if (rc != 0) { 59 SPDK_ERRLOG("could not connet JSON-RPC server: %s\n", spdk_strerror(errno)); 60 close(client->sockfd); 61 free(client); 62 return NULL; 63 } 64 65 /* memory malloc for recv-buf */ 66 client->recv_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT); 67 if (!client->recv_buf) { 68 SPDK_ERRLOG("memory malloc for recv-buf failed\n"); 69 close(client->sockfd); 70 free(client); 71 return NULL; 72 } 73 client->recv_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT; 74 75 return client; 76 } 77 78 struct spdk_jsonrpc_client * 79 spdk_jsonrpc_client_connect(const char *rpc_sock_addr, int addr_family) 80 { 81 struct spdk_jsonrpc_client *client; 82 83 if (addr_family == AF_UNIX) { 84 /* Unix Domain Socket */ 85 struct sockaddr_un rpc_sock_addr_unix = {}; 86 int rc; 87 88 rpc_sock_addr_unix.sun_family = AF_UNIX; 89 rc = snprintf(rpc_sock_addr_unix.sun_path, 90 sizeof(rpc_sock_addr_unix.sun_path), 91 "%s", rpc_sock_addr); 92 if (rc < 0 || (size_t)rc >= sizeof(rpc_sock_addr_unix.sun_path)) { 93 SPDK_ERRLOG("RPC Listen address Unix socket path too long\n"); 94 return NULL; 95 } 96 97 client = _spdk_jsonrpc_client_connect(AF_UNIX, 0, 98 (struct sockaddr *)&rpc_sock_addr_unix, 99 sizeof(rpc_sock_addr_unix)); 100 } else { 101 /* TCP/IP socket */ 102 struct addrinfo hints; 103 struct addrinfo *res; 104 char *tmp; 105 char *host, *port; 106 107 tmp = strdup(rpc_sock_addr); 108 if (!tmp) { 109 SPDK_ERRLOG("Out of memory\n"); 110 return NULL; 111 } 112 113 if (spdk_parse_ip_addr(tmp, &host, &port) < 0) { 114 free(tmp); 115 SPDK_ERRLOG("Invalid listen address '%s'\n", rpc_sock_addr); 116 return NULL; 117 } 118 119 if (port == NULL) { 120 port = RPC_DEFAULT_PORT; 121 } 122 123 memset(&hints, 0, sizeof(hints)); 124 hints.ai_family = AF_UNSPEC; 125 hints.ai_socktype = SOCK_STREAM; 126 hints.ai_protocol = IPPROTO_TCP; 127 128 if (getaddrinfo(host, port, &hints, &res) != 0) { 129 free(tmp); 130 SPDK_ERRLOG("Unable to look up RPC connnect address '%s'\n", rpc_sock_addr); 131 return NULL; 132 } 133 134 client = _spdk_jsonrpc_client_connect(res->ai_family, res->ai_protocol, 135 res->ai_addr, res->ai_addrlen); 136 137 freeaddrinfo(res); 138 free(tmp); 139 } 140 141 return client; 142 } 143 144 void 145 spdk_jsonrpc_client_close(struct spdk_jsonrpc_client *client) 146 { 147 if (client->sockfd >= 0) { 148 close(client->sockfd); 149 free(client->recv_buf); 150 client->sockfd = -1; 151 } 152 153 free(client); 154 } 155 156 struct spdk_jsonrpc_client_request * 157 spdk_jsonrpc_client_create_request(void) 158 { 159 struct spdk_jsonrpc_client_request *request; 160 161 request = calloc(1, sizeof(*request)); 162 if (request == NULL) { 163 return NULL; 164 } 165 166 /* memory malloc for send-buf */ 167 request->send_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT); 168 if (!request->send_buf) { 169 SPDK_ERRLOG("memory malloc for send-buf failed\n"); 170 free(request); 171 return NULL; 172 } 173 request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT; 174 175 return request; 176 } 177 178 void 179 spdk_jsonrpc_client_free_request(struct spdk_jsonrpc_client_request *req) 180 { 181 free(req->send_buf); 182 free(req); 183 } 184 185 int 186 spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client, 187 struct spdk_jsonrpc_client_request *request) 188 { 189 ssize_t rc; 190 191 /* Reset offset in request */ 192 request->send_offset = 0; 193 194 while (request->send_len > 0) { 195 rc = send(client->sockfd, request->send_buf + request->send_offset, 196 request->send_len, 0); 197 if (rc <= 0) { 198 if (rc < 0 && errno == EINTR) { 199 rc = 0; 200 } else { 201 return rc; 202 } 203 } 204 205 request->send_offset += rc; 206 request->send_len -= rc; 207 } 208 209 return 0; 210 } 211 212 static int 213 recv_buf_expand(struct spdk_jsonrpc_client *client) 214 { 215 uint8_t *new_buf; 216 217 if (client->recv_buf_size * 2 > SPDK_JSONRPC_SEND_BUF_SIZE_MAX) { 218 return -ENOSPC; 219 } 220 221 new_buf = realloc(client->recv_buf, client->recv_buf_size * 2); 222 if (new_buf == NULL) { 223 SPDK_ERRLOG("Resizing recv_buf failed (current size %zu, new size %zu)\n", 224 client->recv_buf_size, client->recv_buf_size * 2); 225 return -ENOMEM; 226 } 227 228 client->recv_buf = new_buf; 229 client->recv_buf_size *= 2; 230 231 return 0; 232 } 233 234 int 235 spdk_jsonrpc_client_recv_response(struct spdk_jsonrpc_client *client, 236 spdk_jsonrpc_client_response_parser parser_fn, 237 void *parser_ctx) 238 { 239 ssize_t rc = 0; 240 size_t recv_avail; 241 size_t recv_offset = 0; 242 243 client->parser_fn = parser_fn; 244 client->parser_ctx = parser_ctx; 245 246 recv_avail = client->recv_buf_size; 247 248 while (recv_avail > 0) { 249 rc = recv(client->sockfd, client->recv_buf + recv_offset, recv_avail, 0); 250 if (rc < 0) { 251 if (errno == EINTR) { 252 continue; 253 } else { 254 return errno; 255 } 256 } else if (rc == 0) { 257 return -EIO; 258 } 259 260 recv_offset += rc; 261 recv_avail -= rc; 262 263 /* Check to see if we have received a full JSON value. */ 264 rc = spdk_jsonrpc_parse_response(client, client->recv_buf, recv_offset); 265 if (rc == 0) { 266 /* Successfully parsed response */ 267 return 0; 268 } else if (rc != SPDK_JSON_PARSE_INCOMPLETE) { 269 SPDK_ERRLOG("jsonrpc parse request failed\n"); 270 return -EINVAL; 271 } 272 273 /* Expand receive buffer if larger one is needed */ 274 if (recv_avail == 0) { 275 rc = recv_buf_expand(client); 276 if (rc != 0) { 277 return rc; 278 } 279 recv_avail = client->recv_buf_size - recv_offset; 280 } 281 } 282 283 return 0; 284 } 285