LCOV - code coverage report
Current view: top level - lib/jsonrpc - jsonrpc_client.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 92 0.0 %
Date: 2024-12-14 14:12:25 Functions: 0 8 0.0 %

          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/util.h"
       7             : #include "jsonrpc_internal.h"
       8             : 
       9             : static int
      10           0 : capture_version(const struct spdk_json_val *val, void *out)
      11             : {
      12           0 :         const struct spdk_json_val **vptr = out;
      13             : 
      14           0 :         if (spdk_json_strequal(val, "2.0") != true) {
      15           0 :                 return SPDK_JSON_PARSE_INVALID;
      16             :         }
      17             : 
      18           0 :         *vptr = val;
      19           0 :         return 0;
      20             : }
      21             : 
      22             : static int
      23           0 : capture_id(const struct spdk_json_val *val, void *out)
      24             : {
      25           0 :         const struct spdk_json_val **vptr = out;
      26             : 
      27           0 :         if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NUMBER) {
      28           0 :                 return -EINVAL;
      29             :         }
      30             : 
      31           0 :         *vptr = val;
      32           0 :         return 0;
      33             : }
      34             : 
      35             : static int
      36           0 : capture_any(const struct spdk_json_val *val, void *out)
      37             : {
      38           0 :         const struct spdk_json_val **vptr = out;
      39             : 
      40           0 :         *vptr = val;
      41           0 :         return 0;
      42             : }
      43             : 
      44             : static const struct spdk_json_object_decoder jsonrpc_response_decoders[] = {
      45             :         {"jsonrpc", offsetof(struct spdk_jsonrpc_client_response, version), capture_version},
      46             :         {"id", offsetof(struct spdk_jsonrpc_client_response, id), capture_id, true},
      47             :         {"result", offsetof(struct spdk_jsonrpc_client_response, result), capture_any, true},
      48             :         {"error", offsetof(struct spdk_jsonrpc_client_response, error), capture_any, true},
      49             : };
      50             : 
      51             : int
      52           0 : jsonrpc_parse_response(struct spdk_jsonrpc_client *client)
      53             : {
      54             :         struct spdk_jsonrpc_client_response_internal *r;
      55             :         ssize_t rc;
      56             :         size_t buf_len;
      57             :         size_t values_cnt;
      58           0 :         void *end = NULL;
      59             : 
      60             : 
      61             :         /* Check to see if we have received a full JSON value. */
      62           0 :         rc = spdk_json_parse(client->recv_buf, client->recv_offset, NULL, 0, &end, 0);
      63           0 :         if (rc == SPDK_JSON_PARSE_INCOMPLETE) {
      64           0 :                 return 0;
      65             :         }
      66             : 
      67           0 :         SPDK_DEBUGLOG(rpc_client, "JSON string is :\n%s\n", client->recv_buf);
      68           0 :         if (rc < 0 || rc > SPDK_JSONRPC_CLIENT_MAX_VALUES) {
      69           0 :                 SPDK_ERRLOG("JSON parse error (rc: %zd)\n", rc);
      70             :                 /*
      71             :                  * Can't recover from parse error (no guaranteed resync point in streaming JSON).
      72             :                  * Return an error to indicate that the connection should be closed.
      73             :                  */
      74           0 :                 return -EINVAL;
      75             :         }
      76             : 
      77           0 :         values_cnt = rc;
      78             : 
      79           0 :         r = calloc(1, sizeof(*r) + sizeof(struct spdk_json_val) * (values_cnt + 1));
      80           0 :         if (!r) {
      81           0 :                 return -errno;
      82             :         }
      83             : 
      84           0 :         if (client->resp) {
      85           0 :                 free(r);
      86           0 :                 return -ENOSPC;
      87             :         }
      88             : 
      89           0 :         client->resp = r;
      90             : 
      91           0 :         r->buf = client->recv_buf;
      92           0 :         buf_len = client->recv_offset;
      93           0 :         r->values_cnt = values_cnt;
      94             : 
      95           0 :         client->recv_buf_size = 0;
      96           0 :         client->recv_offset = 0;
      97           0 :         client->recv_buf = NULL;
      98             : 
      99             :         /* Decode a second time now that there is a full JSON value available. */
     100           0 :         rc = spdk_json_parse(r->buf, buf_len, r->values, values_cnt, &end,
     101             :                              SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE);
     102           0 :         if (rc != (ssize_t)values_cnt) {
     103           0 :                 SPDK_ERRLOG("JSON parse error on second pass (rc: %zd, expected: %zu)\n", rc, values_cnt);
     104           0 :                 goto err;
     105             :         }
     106             : 
     107           0 :         assert(end != NULL);
     108             : 
     109           0 :         if (r->values[0].type != SPDK_JSON_VAL_OBJECT_BEGIN) {
     110           0 :                 SPDK_ERRLOG("top-level JSON value was not object\n");
     111           0 :                 goto err;
     112             :         }
     113             : 
     114           0 :         if (spdk_json_decode_object(r->values, jsonrpc_response_decoders,
     115           0 :                                     SPDK_COUNTOF(jsonrpc_response_decoders), &r->jsonrpc)) {
     116           0 :                 goto err;
     117             :         }
     118             : 
     119           0 :         r->ready = 1;
     120           0 :         return 1;
     121             : 
     122           0 : err:
     123           0 :         client->resp = NULL;
     124           0 :         spdk_jsonrpc_client_free_response(&r->jsonrpc);
     125           0 :         return -EINVAL;
     126             : }
     127             : 
     128             : static int
     129           0 : jsonrpc_client_write_cb(void *cb_ctx, const void *data, size_t size)
     130             : {
     131           0 :         struct spdk_jsonrpc_client_request *request = cb_ctx;
     132           0 :         size_t new_size = request->send_buf_size;
     133             : 
     134           0 :         while (new_size - request->send_len < size) {
     135           0 :                 if (new_size >= SPDK_JSONRPC_SEND_BUF_SIZE_MAX) {
     136           0 :                         SPDK_ERRLOG("Send buf exceeded maximum size (%zu)\n",
     137             :                                     (size_t)SPDK_JSONRPC_SEND_BUF_SIZE_MAX);
     138           0 :                         return -ENOSPC;
     139             :                 }
     140             : 
     141           0 :                 new_size *= 2;
     142             :         }
     143             : 
     144           0 :         if (new_size != request->send_buf_size) {
     145             :                 uint8_t *new_buf;
     146             : 
     147           0 :                 new_buf = realloc(request->send_buf, new_size);
     148           0 :                 if (new_buf == NULL) {
     149           0 :                         SPDK_ERRLOG("Resizing send_buf failed (current size %zu, new size %zu)\n",
     150             :                                     request->send_buf_size, new_size);
     151           0 :                         return -ENOMEM;
     152             :                 }
     153             : 
     154           0 :                 request->send_buf = new_buf;
     155           0 :                 request->send_buf_size = new_size;
     156             :         }
     157             : 
     158           0 :         memcpy(request->send_buf + request->send_len, data, size);
     159           0 :         request->send_len += size;
     160             : 
     161           0 :         return 0;
     162             : }
     163             : 
     164             : struct spdk_json_write_ctx *
     165           0 : spdk_jsonrpc_begin_request(struct spdk_jsonrpc_client_request *request, int32_t id,
     166             :                            const char *method)
     167             : {
     168             :         struct spdk_json_write_ctx *w;
     169             : 
     170           0 :         w = spdk_json_write_begin(jsonrpc_client_write_cb, request, 0);
     171           0 :         if (w == NULL) {
     172           0 :                 return NULL;
     173             :         }
     174             : 
     175           0 :         spdk_json_write_object_begin(w);
     176           0 :         spdk_json_write_named_string(w, "jsonrpc", "2.0");
     177             : 
     178           0 :         if (id >= 0) {
     179           0 :                 spdk_json_write_named_int32(w, "id", id);
     180             :         }
     181             : 
     182           0 :         if (method) {
     183           0 :                 spdk_json_write_named_string(w, "method", method);
     184             :         }
     185             : 
     186           0 :         return w;
     187             : }
     188             : 
     189             : void
     190           0 : spdk_jsonrpc_end_request(struct spdk_jsonrpc_client_request *request, struct spdk_json_write_ctx *w)
     191             : {
     192           0 :         assert(w != NULL);
     193             : 
     194           0 :         spdk_json_write_object_end(w);
     195           0 :         spdk_json_write_end(w);
     196           0 :         jsonrpc_client_write_cb(request, "\n", 1);
     197           0 : }
     198             : 
     199           0 : SPDK_LOG_REGISTER_COMPONENT(rpc_client)

Generated by: LCOV version 1.15