LCOV - code coverage report
Current view: top level - spdk/lib/jsonrpc - jsonrpc_client_tcp.c (source / functions) Hit Total Coverage
Test: Combined Lines: 96 208 46.2 %
Date: 2024-07-12 16:53:48 Functions: 13 15 86.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 38 114 33.3 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2018 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/string.h"
       7                 :            : #include "jsonrpc_internal.h"
       8                 :            : #include "spdk/util.h"
       9                 :            : 
      10                 :            : #define RPC_DEFAULT_PORT        "5260"
      11                 :            : 
      12                 :            : static int
      13                 :    1056088 : jsonrpc_client_send_request(struct spdk_jsonrpc_client *client)
      14                 :            : {
      15                 :            :         ssize_t rc;
      16                 :    1056088 :         struct spdk_jsonrpc_client_request *request = client->request;
      17                 :            : 
      18         [ +  + ]:    1056088 :         if (!request) {
      19                 :    1051195 :                 return 0;
      20                 :            :         }
      21                 :            : 
      22         [ +  - ]:       4893 :         if (request->send_len > 0) {
      23                 :       4893 :                 rc = send(client->sockfd, request->send_buf + request->send_offset,
      24                 :            :                           request->send_len, 0);
      25         [ -  + ]:       4893 :                 if (rc < 0) {
      26                 :            :                         /* For EINTR we pretend that nothing was send. */
      27         [ #  # ]:          0 :                         if (errno == EINTR) {
      28                 :          0 :                                 rc = 0;
      29                 :            :                         } else {
      30                 :          0 :                                 rc = -errno;
      31                 :          0 :                                 SPDK_ERRLOG("poll() failed (%d): %s\n", errno, spdk_strerror(errno));
      32                 :            :                         }
      33                 :            : 
      34                 :          0 :                         return rc;
      35                 :            :                 }
      36                 :            : 
      37                 :       4893 :                 request->send_offset += rc;
      38                 :       4893 :                 request->send_len -= rc;
      39                 :            :         }
      40                 :            : 
      41         [ +  - ]:       4893 :         if (request->send_len == 0) {
      42                 :       4893 :                 client->request = NULL;
      43                 :       4893 :                 spdk_jsonrpc_client_free_request(request);
      44                 :            :         }
      45                 :            : 
      46                 :       4893 :         return 0;
      47                 :            : }
      48                 :            : 
      49                 :            : static int
      50                 :          0 : recv_buf_expand(struct spdk_jsonrpc_client *client)
      51                 :            : {
      52                 :            :         uint8_t *new_buf;
      53                 :            : 
      54         [ #  # ]:          0 :         if (client->recv_buf_size * 2 > SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
      55                 :          0 :                 return -ENOSPC;
      56                 :            :         }
      57                 :            : 
      58                 :          0 :         new_buf = realloc(client->recv_buf, client->recv_buf_size * 2);
      59         [ #  # ]:          0 :         if (new_buf == NULL) {
      60                 :          0 :                 SPDK_ERRLOG("Resizing recv_buf failed (current size %zu, new size %zu)\n",
      61                 :            :                             client->recv_buf_size, client->recv_buf_size * 2);
      62                 :          0 :                 return -ENOMEM;
      63                 :            :         }
      64                 :            : 
      65                 :          0 :         client->recv_buf = new_buf;
      66                 :          0 :         client->recv_buf_size *= 2;
      67                 :            : 
      68                 :          0 :         return 0;
      69                 :            : }
      70                 :            : 
      71                 :            : static int
      72                 :    1051195 : jsonrpc_client_resp_ready_count(struct spdk_jsonrpc_client *client)
      73                 :            : {
      74   [ -  +  -  -  :    1051195 :         return client->resp != NULL && client->resp->ready ? 1 : 0;
                   -  - ]
      75                 :            : }
      76                 :            : 
      77                 :            : static int
      78                 :       4893 : jsonrpc_client_recv(struct spdk_jsonrpc_client *client)
      79                 :            : {
      80                 :            :         ssize_t rc;
      81                 :            : 
      82         [ +  - ]:       4893 :         if (client->recv_buf == NULL) {
      83                 :       4893 :                 client->recv_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT);
      84         [ -  + ]:       4893 :                 if (!client->recv_buf) {
      85                 :          0 :                         rc = errno;
      86                 :          0 :                         SPDK_ERRLOG("malloc() failed (%d): %s\n", (int)rc, spdk_strerror(rc));
      87                 :          0 :                         return -rc;
      88                 :            :                 }
      89                 :       4893 :                 client->recv_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
      90                 :       4893 :                 client->recv_offset = 0;
      91         [ #  # ]:          0 :         } else if (client->recv_offset == client->recv_buf_size - 1) {
      92                 :          0 :                 rc = recv_buf_expand(client);
      93         [ #  # ]:          0 :                 if (rc) {
      94                 :          0 :                         return rc;
      95                 :            :                 }
      96                 :            :         }
      97                 :            : 
      98                 :       4893 :         rc = recv(client->sockfd, client->recv_buf + client->recv_offset,
      99                 :       4893 :                   client->recv_buf_size - client->recv_offset - 1, 0);
     100         [ -  + ]:       4893 :         if (rc < 0) {
     101                 :            :                 /* For EINTR we pretend that nothing was received. */
     102         [ #  # ]:          0 :                 if (errno == EINTR) {
     103                 :          0 :                         return 0;
     104                 :            :                 } else {
     105                 :          0 :                         rc = -errno;
     106                 :          0 :                         SPDK_ERRLOG("recv() failed (%d): %s\n", errno, spdk_strerror(errno));
     107                 :          0 :                         return rc;
     108                 :            :                 }
     109         [ -  + ]:       4893 :         } else if (rc == 0) {
     110                 :          0 :                 return -EIO;
     111                 :            :         }
     112                 :            : 
     113                 :       4893 :         client->recv_offset += rc;
     114                 :       4893 :         client->recv_buf[client->recv_offset] = '\0';
     115                 :            : 
     116                 :            :         /* Check to see if we have received a full JSON value. */
     117                 :       4893 :         return jsonrpc_parse_response(client);
     118                 :            : }
     119                 :            : 
     120                 :            : static int
     121                 :    1056088 : jsonrpc_client_poll(struct spdk_jsonrpc_client *client, int timeout)
     122                 :            : {
     123                 :            :         int rc;
     124                 :    1056088 :         struct pollfd pfd = { .fd = client->sockfd, .events = POLLIN | POLLOUT };
     125                 :            : 
     126                 :    1056088 :         rc = poll(&pfd, 1, timeout);
     127         [ -  + ]:    1056088 :         if (rc == -1) {
     128         [ #  # ]:          0 :                 if (errno == EINTR) {
     129                 :            :                         /* For EINTR we pretend that nothing was received nor send. */
     130                 :          0 :                         rc = 0;
     131                 :            :                 } else {
     132                 :          0 :                         rc = -errno;
     133                 :          0 :                         SPDK_ERRLOG("poll() failed (%d): %s\n", errno, spdk_strerror(errno));
     134                 :            :                 }
     135         [ +  - ]:    1056088 :         } else if (rc > 0) {
     136                 :    1056088 :                 rc = 0;
     137                 :            : 
     138         [ +  - ]:    1056088 :                 if (pfd.revents & POLLOUT) {
     139                 :    1056088 :                         rc = jsonrpc_client_send_request(client);
     140                 :            :                 }
     141                 :            : 
     142   [ +  -  +  + ]:    1056088 :                 if (rc == 0 && (pfd.revents & POLLIN)) {
     143                 :       4893 :                         rc = jsonrpc_client_recv(client);
     144                 :            :                         /* Incomplete message in buffer isn't an error. */
     145         [ -  + ]:       4893 :                         if (rc == -EAGAIN) {
     146                 :          0 :                                 rc = 0;
     147                 :            :                         }
     148                 :            :                 }
     149                 :            :         }
     150                 :            : 
     151         [ +  + ]:    1056088 :         return rc ? rc : jsonrpc_client_resp_ready_count(client);
     152                 :            : }
     153                 :            : 
     154                 :            : static int
     155                 :          0 : jsonrpc_client_poll_connecting(struct spdk_jsonrpc_client *client, int timeout)
     156                 :            : {
     157                 :          0 :         socklen_t rc_len;
     158                 :          0 :         int rc;
     159                 :            : 
     160                 :          0 :         struct pollfd pfd = {
     161                 :          0 :                 .fd = client->sockfd,
     162                 :            :                 .events = POLLOUT
     163                 :            :         };
     164                 :            : 
     165                 :          0 :         rc = poll(&pfd, 1, timeout);
     166         [ #  # ]:          0 :         if (rc == 0) {
     167                 :          0 :                 return -ENOTCONN;
     168         [ #  # ]:          0 :         } else if (rc == -1) {
     169         [ #  # ]:          0 :                 if (errno != EINTR) {
     170                 :          0 :                         SPDK_ERRLOG("poll() failed (%d): %s\n", errno, spdk_strerror(errno));
     171                 :          0 :                         goto err;
     172                 :            :                 }
     173                 :            : 
     174                 :            :                 /* We are still not connected. Caller will have to call us again. */
     175                 :          0 :                 return -ENOTCONN;
     176         [ #  # ]:          0 :         } else if (pfd.revents & ~POLLOUT) {
     177                 :            :                 /* We only poll for POLLOUT */
     178                 :          0 :                 goto err;
     179         [ #  # ]:          0 :         } else if ((pfd.revents & POLLOUT) == 0) {
     180                 :            :                 /* Is this even possible to get here? */
     181                 :          0 :                 return -ENOTCONN;
     182                 :            :         }
     183                 :            : 
     184                 :          0 :         rc_len = sizeof(int);
     185                 :            :         /* connection might fail so need to check SO_ERROR. */
     186         [ #  # ]:          0 :         if (getsockopt(client->sockfd, SOL_SOCKET, SO_ERROR, &rc, &rc_len) == -1) {
     187                 :          0 :                 goto err;
     188                 :            :         }
     189                 :            : 
     190         [ #  # ]:          0 :         if (rc == 0) {
     191                 :          0 :                 client->connected = true;
     192                 :          0 :                 return 0;
     193                 :            :         }
     194                 :            : 
     195                 :          0 : err:
     196                 :          0 :         return -EIO;
     197                 :            : }
     198                 :            : 
     199                 :            : static int
     200                 :       2158 : jsonrpc_client_connect(struct spdk_jsonrpc_client *client, int domain, int protocol,
     201                 :            :                        struct sockaddr *server_addr, socklen_t addrlen)
     202                 :            : {
     203                 :            :         int rc;
     204                 :            : 
     205                 :       2158 :         client->sockfd = socket(domain, SOCK_STREAM | SOCK_NONBLOCK, protocol);
     206         [ -  + ]:       2158 :         if (client->sockfd < 0) {
     207                 :          0 :                 rc = errno;
     208                 :          0 :                 SPDK_ERRLOG("socket() failed\n");
     209                 :          0 :                 return -rc;
     210                 :            :         }
     211                 :            : 
     212                 :       2158 :         rc = connect(client->sockfd, server_addr, addrlen);
     213         [ -  + ]:       2158 :         if (rc != 0) {
     214                 :          0 :                 rc = errno;
     215         [ #  # ]:          0 :                 if (rc != EINPROGRESS) {
     216                 :          0 :                         SPDK_ERRLOG("could not connect to JSON-RPC server: %s\n", spdk_strerror(errno));
     217                 :          0 :                         goto err;
     218                 :            :                 }
     219                 :            :         } else {
     220                 :       2158 :                 client->connected = true;
     221                 :            :         }
     222                 :            : 
     223                 :       2158 :         return -rc;
     224                 :          0 : err:
     225                 :          0 :         close(client->sockfd);
     226                 :          0 :         client->sockfd = -1;
     227                 :          0 :         return -rc;
     228                 :            : }
     229                 :            : 
     230                 :            : struct spdk_jsonrpc_client *
     231                 :       2158 : spdk_jsonrpc_client_connect(const char *addr, int addr_family)
     232                 :            : {
     233                 :       2158 :         struct spdk_jsonrpc_client *client = calloc(1, sizeof(struct spdk_jsonrpc_client));
     234                 :            :         /* Unix Domain Socket */
     235                 :       2158 :         struct sockaddr_un addr_un = {};
     236                 :       2158 :         char *add_in = NULL;
     237                 :            :         int rc;
     238                 :            : 
     239         [ -  + ]:       2158 :         if (client == NULL) {
     240                 :          0 :                 SPDK_ERRLOG("%s\n", spdk_strerror(errno));
     241                 :          0 :                 return NULL;
     242                 :            :         }
     243                 :            : 
     244         [ +  - ]:       2158 :         if (addr_family == AF_UNIX) {
     245                 :       2158 :                 addr_un.sun_family = AF_UNIX;
     246                 :       2158 :                 rc = snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s", addr);
     247   [ +  -  -  + ]:       2158 :                 if (rc < 0 || (size_t)rc >= sizeof(addr_un.sun_path)) {
     248                 :          0 :                         rc = -EINVAL;
     249                 :          0 :                         SPDK_ERRLOG("RPC Listen address Unix socket path too long\n");
     250                 :          0 :                         goto err;
     251                 :            :                 }
     252                 :            : 
     253                 :       2158 :                 rc = jsonrpc_client_connect(client, AF_UNIX, 0, (struct sockaddr *)&addr_un, sizeof(addr_un));
     254                 :            :         } else {
     255                 :            :                 /* TCP/IP socket */
     256                 :          0 :                 struct addrinfo         hints;
     257                 :          0 :                 struct addrinfo         *res;
     258                 :          0 :                 char *host, *port;
     259                 :            : 
     260         [ #  # ]:          0 :                 add_in = strdup(addr);
     261         [ #  # ]:          0 :                 if (!add_in) {
     262                 :          0 :                         rc = -errno;
     263                 :          0 :                         SPDK_ERRLOG("%s\n", spdk_strerror(errno));
     264                 :          0 :                         goto err;
     265                 :            :                 }
     266                 :            : 
     267                 :          0 :                 rc = spdk_parse_ip_addr(add_in, &host, &port);
     268         [ #  # ]:          0 :                 if (rc) {
     269                 :          0 :                         SPDK_ERRLOG("Invalid listen address '%s'\n", addr);
     270                 :          0 :                         goto err;
     271                 :            :                 }
     272                 :            : 
     273         [ #  # ]:          0 :                 if (port == NULL) {
     274                 :          0 :                         port = RPC_DEFAULT_PORT;
     275                 :            :                 }
     276                 :            : 
     277                 :          0 :                 memset(&hints, 0, sizeof(hints));
     278                 :          0 :                 hints.ai_family = AF_UNSPEC;
     279                 :          0 :                 hints.ai_socktype = SOCK_STREAM;
     280                 :          0 :                 hints.ai_protocol = IPPROTO_TCP;
     281                 :            : 
     282                 :          0 :                 rc = getaddrinfo(host, port, &hints, &res);
     283         [ #  # ]:          0 :                 if (rc != 0) {
     284                 :          0 :                         SPDK_ERRLOG("Unable to look up RPC connect address '%s' (%d): %s\n", addr, rc, gai_strerror(rc));
     285                 :          0 :                         rc = -(abs(rc));
     286                 :          0 :                         goto err;
     287                 :            :                 }
     288                 :            : 
     289                 :          0 :                 rc = jsonrpc_client_connect(client, res->ai_family, res->ai_protocol, res->ai_addr,
     290                 :          0 :                                             res->ai_addrlen);
     291                 :          0 :                 freeaddrinfo(res);
     292                 :            :         }
     293                 :            : 
     294                 :       2158 : err:
     295   [ -  +  -  - ]:       2158 :         if (rc != 0 && rc != -EINPROGRESS) {
     296                 :          0 :                 free(client);
     297                 :          0 :                 client = NULL;
     298                 :          0 :                 errno = -rc;
     299                 :            :         }
     300                 :            : 
     301                 :       2158 :         free(add_in);
     302                 :       2158 :         return client;
     303                 :            : }
     304                 :            : 
     305                 :            : void
     306                 :       2158 : spdk_jsonrpc_client_close(struct spdk_jsonrpc_client *client)
     307                 :            : {
     308         [ +  - ]:       2158 :         if (client->sockfd >= 0) {
     309                 :       2158 :                 close(client->sockfd);
     310                 :            :         }
     311                 :            : 
     312                 :       2158 :         free(client->recv_buf);
     313         [ -  + ]:       2158 :         if (client->resp) {
     314                 :          0 :                 spdk_jsonrpc_client_free_response(&client->resp->jsonrpc);
     315                 :            :         }
     316                 :            : 
     317                 :       2158 :         free(client);
     318                 :       2158 : }
     319                 :            : 
     320                 :            : struct spdk_jsonrpc_client_request *
     321                 :       4893 : spdk_jsonrpc_client_create_request(void)
     322                 :            : {
     323                 :            :         struct spdk_jsonrpc_client_request *request;
     324                 :            : 
     325                 :       4893 :         request = calloc(1, sizeof(*request));
     326         [ -  + ]:       4893 :         if (request == NULL) {
     327                 :          0 :                 return NULL;
     328                 :            :         }
     329                 :            : 
     330                 :            :         /* memory malloc for send-buf */
     331                 :       4893 :         request->send_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT);
     332         [ -  + ]:       4893 :         if (!request->send_buf) {
     333                 :          0 :                 SPDK_ERRLOG("memory malloc for send-buf failed\n");
     334                 :          0 :                 free(request);
     335                 :          0 :                 return NULL;
     336                 :            :         }
     337                 :       4893 :         request->send_buf_size = SPDK_JSONRPC_SEND_BUF_SIZE_INIT;
     338                 :            : 
     339                 :       4893 :         return request;
     340                 :            : }
     341                 :            : 
     342                 :            : void
     343                 :       4893 : spdk_jsonrpc_client_free_request(struct spdk_jsonrpc_client_request *req)
     344                 :            : {
     345                 :       4893 :         free(req->send_buf);
     346                 :       4893 :         free(req);
     347                 :       4893 : }
     348                 :            : 
     349                 :            : int
     350                 :    1056088 : spdk_jsonrpc_client_poll(struct spdk_jsonrpc_client *client, int timeout)
     351                 :            : {
     352   [ +  +  +  - ]:    1056088 :         if (client->connected) {
     353                 :    1056088 :                 return jsonrpc_client_poll(client, timeout);
     354                 :            :         } else {
     355                 :          0 :                 return jsonrpc_client_poll_connecting(client, timeout);
     356                 :            :         }
     357                 :            : }
     358                 :            : 
     359                 :            : int
     360                 :       4893 : spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client,
     361                 :            :                                  struct spdk_jsonrpc_client_request *req)
     362                 :            : {
     363         [ -  + ]:       4893 :         if (client->request != NULL) {
     364                 :          0 :                 return -ENOSPC;
     365                 :            :         }
     366                 :            : 
     367                 :       4893 :         client->request = req;
     368                 :       4893 :         return 0;
     369                 :            : }
     370                 :            : 
     371                 :            : struct spdk_jsonrpc_client_response *
     372                 :       4893 : spdk_jsonrpc_client_get_response(struct spdk_jsonrpc_client *client)
     373                 :            : {
     374                 :            :         struct spdk_jsonrpc_client_response_internal *r;
     375                 :            : 
     376                 :       4893 :         r = client->resp;
     377   [ +  -  -  +  :       4893 :         if (r == NULL || r->ready == false) {
                   -  + ]
     378                 :          0 :                 return NULL;
     379                 :            :         }
     380                 :            : 
     381                 :       4893 :         client->resp = NULL;
     382                 :       4893 :         return &r->jsonrpc;
     383                 :            : }
     384                 :            : 
     385                 :            : void
     386                 :       4893 : spdk_jsonrpc_client_free_response(struct spdk_jsonrpc_client_response *resp)
     387                 :            : {
     388                 :            :         struct spdk_jsonrpc_client_response_internal *r;
     389                 :            : 
     390         [ -  + ]:       4893 :         if (!resp) {
     391                 :          0 :                 return;
     392                 :            :         }
     393                 :            : 
     394                 :       4893 :         r = SPDK_CONTAINEROF(resp, struct spdk_jsonrpc_client_response_internal, jsonrpc);
     395                 :       4893 :         free(r->buf);
     396                 :       4893 :         free(r);
     397                 :            : }

Generated by: LCOV version 1.14