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