[libvirt] [PATCH v2 2/4] util: Export remoteDeserializeTypedParameters internally via util

Erik Skultety eskultet at redhat.com
Wed Feb 3 14:51:53 UTC 2016


Currently, the deserializer is hardcoded into remote_driver which makes
it impossible for admin to use it. One way to achieve a shared implementation
(besides moving the code to another module) would be pass @ret_params_val as a
void pointer as opposed to the remote_typed_param pointer and add a new extra
argument specifying which of those two protocols is being used and typecast
the pointer at the function entry. An example from remote_protocol:

struct remote_typed_param_value {
        int type;
        union {
                int i;
                u_int ui;
                int64_t l;
                uint64_t ul;
                double d;
                int b;
                remote_nonnull_string s;
        } remote_typed_param_value_u;
};
typedef struct remote_typed_param_value remote_typed_param_value;

struct remote_typed_param {
        remote_nonnull_string field;
        remote_typed_param_value value;
};

That would leave us with a bunch of if-then-elses that needed to be used across
the method. This patch takes the other approach using the new datatype
introduced in one of earlier commits.
---
 daemon/remote.c            | 120 ++++----------------------
 src/libvirt_private.syms   |   1 +
 src/remote/remote_driver.c | 209 ++++++++++++---------------------------------
 src/rpc/gendispatch.pl     |  19 +++--
 src/util/virtypedparam.c   | 125 +++++++++++++++++++++++++++
 src/util/virtypedparam.h   |   6 ++
 6 files changed, 213 insertions(+), 267 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 370f442..d655cfd 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -101,12 +101,6 @@ static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr
 static void make_nonnull_nwfilter(remote_nonnull_nwfilter *net_dst, virNWFilterPtr nwfilter_src);
 static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
 
-static virTypedParameterPtr
-remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
-                                 u_int args_params_len,
-                                 int limit,
-                                 int *nparams);
-
 static int
 remoteSerializeTypedParameters(virTypedParameterPtr params,
                                int nparams,
@@ -1495,84 +1489,6 @@ remoteSerializeTypedParameters(virTypedParameterPtr params,
     return rv;
 }
 
-/* Helper to deserialize typed parameters. */
-static virTypedParameterPtr
-remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
-                                 u_int args_params_len,
-                                 int limit,
-                                 int *nparams)
-{
-    size_t i = 0;
-    int rv = -1;
-    virTypedParameterPtr params = NULL;
-
-    /* Check the length of the returned list carefully. */
-    if (limit && args_params_len > limit) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
-        goto cleanup;
-    }
-    if (VIR_ALLOC_N(params, args_params_len) < 0)
-        goto cleanup;
-
-    *nparams = args_params_len;
-
-    /* Deserialise the result. */
-    for (i = 0; i < args_params_len; ++i) {
-        if (virStrcpyStatic(params[i].field,
-                            args_params_val[i].field) == NULL) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Parameter %s too big for destination"),
-                           args_params_val[i].field);
-            goto cleanup;
-        }
-        params[i].type = args_params_val[i].value.type;
-        switch (params[i].type) {
-        case VIR_TYPED_PARAM_INT:
-            params[i].value.i =
-                args_params_val[i].value.remote_typed_param_value_u.i;
-            break;
-        case VIR_TYPED_PARAM_UINT:
-            params[i].value.ui =
-                args_params_val[i].value.remote_typed_param_value_u.ui;
-            break;
-        case VIR_TYPED_PARAM_LLONG:
-            params[i].value.l =
-                args_params_val[i].value.remote_typed_param_value_u.l;
-            break;
-        case VIR_TYPED_PARAM_ULLONG:
-            params[i].value.ul =
-                args_params_val[i].value.remote_typed_param_value_u.ul;
-            break;
-        case VIR_TYPED_PARAM_DOUBLE:
-            params[i].value.d =
-                args_params_val[i].value.remote_typed_param_value_u.d;
-            break;
-        case VIR_TYPED_PARAM_BOOLEAN:
-            params[i].value.b =
-                args_params_val[i].value.remote_typed_param_value_u.b;
-            break;
-        case VIR_TYPED_PARAM_STRING:
-            if (VIR_STRDUP(params[i].value.s,
-                           args_params_val[i].value.remote_typed_param_value_u.s) < 0)
-                goto cleanup;
-            break;
-        default:
-            virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown parameter type: %d"),
-                           params[i].type);
-            goto cleanup;
-        }
-    }
-
-    rv = 0;
-
- cleanup:
-    if (rv < 0) {
-        virTypedParamsFree(params, i);
-        params = NULL;
-    }
-    return params;
-}
-
 static int
 remoteDispatchDomainGetSchedulerParameters(virNetServerPtr server ATTRIBUTE_UNUSED,
                                            virNetServerClientPtr client ATTRIBUTE_UNUSED,
@@ -5392,9 +5308,9 @@ remoteDispatchDomainMigrateBegin3Params(virNetServerPtr server ATTRIBUTE_UNUSED,
     if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
         goto cleanup;
 
-    if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
-                                                    args->params.params_len,
-                                                    0, &nparams)))
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val,
+                                  args->params.params_len,
+                                  0, &params, &nparams) < 0)
         goto cleanup;
 
     if (!(xml = virDomainMigrateBegin3Params(dom, params, nparams,
@@ -5445,9 +5361,9 @@ remoteDispatchDomainMigratePrepare3Params(virNetServerPtr server ATTRIBUTE_UNUSE
         goto cleanup;
     }
 
-    if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
-                                                    args->params.params_len,
-                                                    0, &nparams)))
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val,
+                                  args->params.params_len,
+                                  0, &params, &nparams) < 0)
         goto cleanup;
 
     /* Wacky world of XDR ... */
@@ -5506,9 +5422,9 @@ remoteDispatchDomainMigratePrepareTunnel3Params(virNetServerPtr server ATTRIBUTE
         goto cleanup;
     }
 
-    if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
-                                                    args->params.params_len,
-                                                    0, &nparams)))
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val,
+                                  args->params.params_len,
+                                  0, &params, &nparams) < 0)
         goto cleanup;
 
     if (!(st = virStreamNew(priv->conn, VIR_STREAM_NONBLOCK)) ||
@@ -5579,9 +5495,9 @@ remoteDispatchDomainMigratePerform3Params(virNetServerPtr server ATTRIBUTE_UNUSE
     if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
         goto cleanup;
 
-    if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
-                                                    args->params.params_len,
-                                                    0, &nparams)))
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val,
+                                  args->params.params_len,
+                                  0, &params, &nparams) < 0)
         goto cleanup;
 
     dconnuri = args->dconnuri == NULL ? NULL : *args->dconnuri;
@@ -5636,9 +5552,9 @@ remoteDispatchDomainMigrateFinish3Params(virNetServerPtr server ATTRIBUTE_UNUSED
         goto cleanup;
     }
 
-    if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
-                                                    args->params.params_len,
-                                                    0, &nparams)))
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val,
+                                  args->params.params_len,
+                                  0, &params, &nparams) < 0)
         goto cleanup;
 
     dom = virDomainMigrateFinish3Params(priv->conn, params, nparams,
@@ -5696,9 +5612,9 @@ remoteDispatchDomainMigrateConfirm3Params(virNetServerPtr server ATTRIBUTE_UNUSE
     if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
         goto cleanup;
 
-    if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
-                                                    args->params.params_len,
-                                                    0, &nparams)))
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val,
+                                  args->params.params_len,
+                                  0, &params, &nparams) < 0)
         goto cleanup;
 
     if (virDomainMigrateConfirm3Params(dom, params, nparams,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5f4322f..f25c6fa 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2350,6 +2350,7 @@ virTypedParameterTypeFromString;
 virTypedParameterTypeToString;
 virTypedParamsCheck;
 virTypedParamsCopy;
+virTypedParamsDeserialize;
 virTypedParamsFilter;
 virTypedParamsGetStringList;
 virTypedParamsReplaceString;
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index d9d7ec8..b4c58e2 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -72,11 +72,6 @@ VIR_LOG_INIT("remote.remote_driver");
 # define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
 #endif
 
-#define remoteDeserializeTypedParameters(ret_params_val, ret_params_len,      \
-                                         limit, params, nparams)              \
-    deserializeTypedParameters(__FUNCTION__, ret_params_val, ret_params_len,  \
-                               limit, params, nparams)
-
 static bool inside_daemon;
 
 struct private_data {
@@ -1747,105 +1742,6 @@ remoteSerializeTypedParameters(virTypedParameterPtr params,
     return rv;
 }
 
-/* Helper to deserialize typed parameters. */
-static int
-deserializeTypedParameters(const char *funcname,
-                           remote_typed_param *ret_params_val,
-                           u_int ret_params_len,
-                           int limit,
-                           virTypedParameterPtr *params,
-                           int *nparams)
-{
-    size_t i = 0;
-    int rv = -1;
-    bool userAllocated = *params != NULL;
-
-    if (ret_params_len > limit) {
-        virReportError(VIR_ERR_RPC,
-                       _("%s: too many parameters '%u' for limit '%d'"),
-                       funcname, ret_params_len, limit);
-        goto cleanup;
-    }
-
-    if (userAllocated) {
-        /* Check the length of the returned list carefully. */
-        if (ret_params_len > *nparams) {
-            virReportError(VIR_ERR_RPC,
-                           _("%s: too many parameters '%u' for nparams '%d'"),
-                           funcname, ret_params_len, *nparams);
-            goto cleanup;
-        }
-    } else {
-        if (VIR_ALLOC_N(*params, ret_params_len) < 0)
-            goto cleanup;
-    }
-    *nparams = ret_params_len;
-
-    /* Deserialise the result. */
-    for (i = 0; i < ret_params_len; ++i) {
-        virTypedParameterPtr param = *params + i;
-        remote_typed_param *ret_param = ret_params_val + i;
-
-        if (virStrcpyStatic(param->field,
-                            ret_param->field) == NULL) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("%s: parameter %s too big for destination"),
-                           funcname, ret_param->field);
-            goto cleanup;
-        }
-
-        param->type = ret_param->value.type;
-        switch (param->type) {
-        case VIR_TYPED_PARAM_INT:
-            param->value.i =
-                ret_param->value.remote_typed_param_value_u.i;
-            break;
-        case VIR_TYPED_PARAM_UINT:
-            param->value.ui =
-                ret_param->value.remote_typed_param_value_u.ui;
-            break;
-        case VIR_TYPED_PARAM_LLONG:
-            param->value.l =
-                ret_param->value.remote_typed_param_value_u.l;
-            break;
-        case VIR_TYPED_PARAM_ULLONG:
-            param->value.ul =
-                ret_param->value.remote_typed_param_value_u.ul;
-            break;
-        case VIR_TYPED_PARAM_DOUBLE:
-            param->value.d =
-                ret_param->value.remote_typed_param_value_u.d;
-            break;
-        case VIR_TYPED_PARAM_BOOLEAN:
-            param->value.b =
-                ret_param->value.remote_typed_param_value_u.b;
-            break;
-        case VIR_TYPED_PARAM_STRING:
-            if (VIR_STRDUP(param->value.s,
-                           ret_param->value.remote_typed_param_value_u.s) < 0)
-                goto cleanup;
-            break;
-        default:
-            virReportError(VIR_ERR_RPC, _("%s: unknown parameter type: %d"),
-                           funcname, param->type);
-            goto cleanup;
-        }
-    }
-
-    rv = 0;
-
- cleanup:
-    if (rv < 0) {
-        if (userAllocated) {
-            virTypedParamsClear(*params, i);
-        } else {
-            virTypedParamsFree(*params, i);
-            *params = NULL;
-        }
-    }
-    return rv;
-}
-
 static int
 remoteDeserializeDomainDiskErrors(remote_domain_disk_error *ret_errors_val,
                                   u_int ret_errors_len,
@@ -1922,12 +1818,12 @@ remoteDomainBlockStatsFlags(virDomainPtr domain,
 
     *nparams = ret.params.params_len;
 
-    /* Deserialise the result. */
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
-                                         &params,
-                                         nparams) < 0)
+    /* Deserialize the result. */
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
+                                  &params,
+                                  nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -1971,11 +1867,11 @@ remoteDomainGetMemoryParameters(virDomainPtr domain,
         goto cleanup;
     }
 
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
-                                         &params,
-                                         nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
+                                  &params,
+                                  nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -2019,11 +1915,11 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
         goto cleanup;
     }
 
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_DOMAIN_NUMA_PARAMETERS_MAX,
-                                         &params,
-                                         nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_NUMA_PARAMETERS_MAX,
+                                  &params,
+                                  nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -2067,11 +1963,11 @@ remoteDomainGetBlkioParameters(virDomainPtr domain,
         goto cleanup;
     }
 
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX,
-                                         &params,
-                                         nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX,
+                                  &params,
+                                  nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -2991,11 +2887,11 @@ static int remoteDomainGetBlockIoTune(virDomainPtr domain,
         goto cleanup;
     }
 
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
-                                         &params,
-                                         nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
+                                  &params,
+                                  nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -3081,9 +2977,10 @@ static int remoteDomainGetCPUStats(virDomainPtr domain,
         virTypedParameterPtr cpu_params = &params[cpu * nparams];
         remote_typed_param *stride = &ret.params.params_val[cpu * ret.nparams];
 
-        if (remoteDeserializeTypedParameters(stride, ret.nparams,
-                                             REMOTE_NODE_CPU_STATS_MAX,
-                                             &cpu_params, &tmp) < 0)
+        if (virTypedParamsDeserialize((virTypedParameterRemotePtr) stride,
+                                      ret.nparams,
+                                      REMOTE_NODE_CPU_STATS_MAX,
+                                      &cpu_params, &tmp) < 0)
             goto cleanup;
     }
 
@@ -5480,10 +5377,10 @@ remoteDomainBuildEventCallbackTunable(virNetClientProgramPtr prog ATTRIBUTE_UNUS
     int nparams = 0;
     virObjectEventPtr event = NULL;
 
-    if (remoteDeserializeTypedParameters(msg->params.params_val,
-                                         msg->params.params_len,
-                                         REMOTE_DOMAIN_EVENT_TUNABLE_MAX,
-                                         &params, &nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) msg->params.params_val,
+                                  msg->params.params_len,
+                                  REMOTE_DOMAIN_EVENT_TUNABLE_MAX,
+                                  &params, &nparams) < 0)
         return;
 
     dom = get_nonnull_domain(conn, msg->dom);
@@ -6720,11 +6617,11 @@ remoteDomainGetInterfaceParameters(virDomainPtr domain,
         goto cleanup;
     }
 
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_DOMAIN_INTERFACE_PARAMETERS_MAX,
-                                         &params,
-                                         nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_INTERFACE_PARAMETERS_MAX,
+                                  &params,
+                                  nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -6900,11 +6797,11 @@ remoteNodeGetMemoryParameters(virConnectPtr conn,
         goto cleanup;
     }
 
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_NODE_MEMORY_PARAMETERS_MAX,
-                                         &params,
-                                         nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_NODE_MEMORY_PARAMETERS_MAX,
+                                  &params,
+                                  nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -7021,10 +6918,10 @@ remoteDomainGetJobStats(virDomainPtr domain,
 
     *type = ret.type;
 
-    if (remoteDeserializeTypedParameters(ret.params.params_val,
-                                         ret.params.params_len,
-                                         REMOTE_DOMAIN_JOB_STATS_MAX,
-                                         params, nparams) < 0)
+    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
+                                  ret.params.params_len,
+                                  REMOTE_DOMAIN_JOB_STATS_MAX,
+                                  params, nparams) < 0)
         goto cleanup;
 
     rv = 0;
@@ -7802,11 +7699,11 @@ remoteConnectGetAllDomainStats(virConnectPtr conn,
         if (!(elem->dom = get_nonnull_domain(conn, rec->dom)))
             goto cleanup;
 
-        if (remoteDeserializeTypedParameters(rec->params.params_val,
-                                             rec->params.params_len,
-                                             REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX,
-                                             &elem->params,
-                                             &elem->nparams))
+        if (virTypedParamsDeserialize((virTypedParameterRemotePtr) rec->params.params_val,
+                                      rec->params.params_len,
+                                      REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX,
+                                      &elem->params,
+                                      &elem->nparams))
             goto cleanup;
 
         tmpret[i] = elem;
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index 3740130..d7f42b1 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -557,10 +557,11 @@ elsif ($mode eq "server") {
                     }
                     push(@args_list, "$1");
                     push(@args_list, "n$1");
-                    push(@getters_list, "    if (($1 = remoteDeserializeTypedParameters(args->$1.$1_val,\n" .
-                                        "                                                   args->$1.$1_len,\n" .
-                                        "                                                   $2,\n" .
-                                        "                                                   &n$1)) == NULL)\n" .
+                    push(@getters_list, "    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->$1.$1_val,\n" .
+                                        "                                  args->$1.$1_len,\n" .
+                                        "                                  $2,\n" .
+                                        "                                  &$1,\n" .
+                                        "                                  &n$1) < 0)\n" .
                                         "        goto cleanup;\n");
                     push(@free_list, "    virTypedParamsFree($1, n$1);");
                 } elsif ($args_member =~ m/<\S+>;/ or $args_member =~ m/\[\S+\];/) {
@@ -1356,11 +1357,11 @@ elsif ($mode eq "client") {
                     }
                 } elsif ($ret_member =~ m/^remote_typed_param (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
                     splice(@args_list, int($3), 0, ("virTypedParameterPtr $1"));
-                    push(@ret_list2, "if (remoteDeserializeTypedParameters(ret.$1.$1_val,\n" .
-                                     "                                         ret.$1.$1_len,\n" .
-                                     "                                         $2,\n" .
-                                     "                                         &$1,\n" .
-                                     "                                         n$1) < 0)\n" .
+                    push(@ret_list2, "if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.$1.$1_val,\n" .
+                                     "                                  ret.$1.$1_len,\n" .
+                                     "                                  $2,\n" .
+                                     "                                  &$1,\n" .
+                                     "                                  n$1) < 0)\n" .
                                      "        goto cleanup;\n");
                     $single_ret_cleanup = 1;
                 } elsif ($ret_member =~ m/^remote_typed_param (\S+)<\S+>;/) {
diff --git a/src/util/virtypedparam.c b/src/util/virtypedparam.c
index f3ce157..f1e7cf2 100644
--- a/src/util/virtypedparam.c
+++ b/src/util/virtypedparam.c
@@ -1315,3 +1315,128 @@ virTypedParamsFree(virTypedParameterPtr params,
     virTypedParamsClear(params, nparams);
     VIR_FREE(params);
 }
+
+
+/**
+ * virTypedParamsDeserialize:
+ * @remote_params: protocol data to be deserialized (obtained from remote side)
+ * @remote_params_len: number of parameters returned in @remote_params
+ * @limit: user specified maximum limit to @remote_params_len
+ * @params: pointer which will hold the deserialized @remote_params data
+ * @nparams: number of entries in @params
+ *
+ * This function will attempt to deserialize protocol-encoded data obtained
+ * from remote side. Two modes of operation are supported, depending on the
+ * caller's design:
+ * 1) Older APIs do not rely on deserializer allocating memory for @params,
+ *    thus calling the deserializer twice, once to find out the actual number of
+ *    parameters for @params to hold, followed by an allocation of @params and
+ *    a second call to the deserializer to actually retrieve the data.
+ * 2) Newer APIs rely completely on the deserializer to allocate the right
+ *    ammount of memory for @params to hold all the data obtained in
+ *    @remote_params.
+ *
+ * If used with model 1, two checks are performed, first one comparing the user
+ * specified limit to the actual size of remote data and the second one
+ * verifying the user allocated amount of memory is indeed capable of holding
+ * remote data @remote_params.
+ * With model 2, only the first check against @limit is performed.
+ *
+ * Returns 0 on success or -1 in case of an error.
+ */
+int
+virTypedParamsDeserialize(virTypedParameterRemotePtr remote_params,
+                          unsigned int remote_params_len,
+                          int limit,
+                          virTypedParameterPtr *params,
+                          int *nparams)
+{
+    size_t i = 0;
+    int rv = -1;
+    bool userAllocated = *params != NULL;
+
+    if (limit && remote_params_len > limit) {
+        virReportError(VIR_ERR_RPC,
+                       _("too many parameters '%u' for limit '%d'"),
+                       remote_params_len, limit);
+        goto cleanup;
+    }
+
+    if (userAllocated) {
+        /* Check the length of the returned list carefully. */
+        if (remote_params_len > *nparams) {
+            virReportError(VIR_ERR_RPC,
+                           _("too many parameters '%u' for nparams '%d'"),
+                           remote_params_len, *nparams);
+            goto cleanup;
+        }
+    } else {
+        if (VIR_ALLOC_N(*params, remote_params_len) < 0)
+            goto cleanup;
+    }
+    *nparams = remote_params_len;
+
+    /* Deserialize the result. */
+    for (i = 0; i < remote_params_len; ++i) {
+        virTypedParameterPtr param = *params + i;
+        virTypedParameterRemotePtr remote_param = remote_params + i;
+
+        if (virStrcpyStatic(param->field,
+                            remote_param->field) == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("parameter %s too big for destination"),
+                           remote_param->field);
+            goto cleanup;
+        }
+
+        param->type = remote_param->value.type;
+        switch (param->type) {
+        case VIR_TYPED_PARAM_INT:
+            param->value.i =
+                remote_param->value.remote_typed_param_value.i;
+            break;
+        case VIR_TYPED_PARAM_UINT:
+            param->value.ui =
+                remote_param->value.remote_typed_param_value.ui;
+            break;
+        case VIR_TYPED_PARAM_LLONG:
+            param->value.l =
+                remote_param->value.remote_typed_param_value.l;
+            break;
+        case VIR_TYPED_PARAM_ULLONG:
+            param->value.ul =
+                remote_param->value.remote_typed_param_value.ul;
+            break;
+        case VIR_TYPED_PARAM_DOUBLE:
+            param->value.d =
+                remote_param->value.remote_typed_param_value.d;
+            break;
+        case VIR_TYPED_PARAM_BOOLEAN:
+            param->value.b =
+                remote_param->value.remote_typed_param_value.b;
+            break;
+        case VIR_TYPED_PARAM_STRING:
+            if (VIR_STRDUP(param->value.s,
+                           remote_param->value.remote_typed_param_value.s) < 0)
+                goto cleanup;
+            break;
+        default:
+            virReportError(VIR_ERR_RPC, _("unknown parameter type: %d"),
+                           param->type);
+            goto cleanup;
+        }
+    }
+
+    rv = 0;
+
+ cleanup:
+    if (rv < 0) {
+        if (userAllocated) {
+            virTypedParamsClear(*params, i);
+        } else {
+            virTypedParamsFree(*params, i);
+            *params = NULL;
+        }
+    }
+    return rv;
+}
diff --git a/src/util/virtypedparam.h b/src/util/virtypedparam.h
index 7dd3a78..98bf3aa 100644
--- a/src/util/virtypedparam.h
+++ b/src/util/virtypedparam.h
@@ -104,6 +104,12 @@ int virTypedParamsCopy(virTypedParameterPtr *dst,
 
 char *virTypedParameterToString(virTypedParameterPtr param);
 
+int virTypedParamsDeserialize(virTypedParameterRemotePtr remote_params,
+                              unsigned int remote_params_len,
+                              int limit,
+                              virTypedParameterPtr *params,
+                              int *nparams);
+
 VIR_ENUM_DECL(virTypedParameter)
 
 # define VIR_TYPED_PARAMS_DEBUG(params, nparams)                            \
-- 
2.4.3




More information about the libvir-list mailing list