From b414039c3ccbd12c47be9bae9409f4f0afd1d044 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Tue, 15 Mar 2022 12:45:22 +0900 Subject: [PATCH] lib: tmonitor: Add get APIs for array type attributes This adds internal API for getting array type attributes as below: - tmonitor_get_array_int - tmonitor_get_array_int64 - tmonitor_get_array_uint - tmonitor_get_array_uint64 - tmonitor_get_array_double - tmonitor_get_array_string Since users get dynamically allocated array with length by just passing pointer of pointer for each data type, it should be freed after use. Change-Id: I8f72ff5c6ceebcc4eda8998f2ad4fed47f71e3d5 Signed-off-by: Dongwoo Lee --- include/util/request.h | 1 + lib/tmonitor/tmonitor.c | 179 ++++++++++++++++++++++++++++++++++++++++++ lib/tmonitor/tmonitor.h | 16 ++++ src/monitor/request-handler.c | 129 ++++++++++++++++++++++++------ 4 files changed, 302 insertions(+), 23 deletions(-) diff --git a/include/util/request.h b/include/util/request.h index a0bb183..f9316a6 100644 --- a/include/util/request.h +++ b/include/util/request.h @@ -39,6 +39,7 @@ enum { REQUEST_GET_VALUE_UINT64, REQUEST_GET_VALUE_DOUBLE, REQUEST_GET_VALUE_STRING, + REQUEST_GET_VALUE_ARRAY, REQUEST_MAX, }; diff --git a/lib/tmonitor/tmonitor.c b/lib/tmonitor/tmonitor.c index fa6b22b..d53c655 100644 --- a/lib/tmonitor/tmonitor.c +++ b/lib/tmonitor/tmonitor.c @@ -640,3 +640,182 @@ int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr_id, char * return ret; } + +static int +tmonitor_get_array(int id, int res_id, u_int64_t attr_id, int data_type, void **array, int *length) +{ + char buffer[MAX_BUF_SIZE + 1]; + char _array_str[MAX_BUF_SIZE]; + char *array_item, *array_str = _array_str; + int array_len, array_type; + int buffer_len; + int response_req; + int ret, i; + + buffer_len = sprintf(buffer, "%d:%d:%"PRIu64, + REQUEST_GET_VALUE_ARRAY, res_id, attr_id); + if (send(id, buffer, buffer_len, 0) < 0) { + _E("[libpass] error occurred while sending buffer"); + return -EIO; + } + + /* wait for response */ + buffer_len = recv(id, buffer, MAX_BUF_SIZE, 0); + if (buffer_len <= 0) { + _E("[libpass] socket disconnected"); + return -EIO; + } + + buffer[buffer_len] = '\0'; + if (sscanf(buffer, "%d:%d|%d|%[^:]:%d", &response_req, + &array_type, &array_len, array_str, &ret) < 5) + return -EINVAL; + + if (response_req != REQUEST_GET_VALUE_ARRAY) { + _E("[libpass] wrong response"); + return -EINVAL; + } + + if (data_type != array_type) { + _E("[libpass] wrong data type"); + return -EINVAL; + } + + switch (array_type) { + case DATA_TYPE_INT: + { + int32_t *new_array = malloc(array_len * sizeof(int32_t)); + + if (!new_array) + return -ENOMEM; + + for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++) + new_array[i] = strtol(array_item, NULL, 10); + + *array = (void *)new_array; + *length = array_len; + break; + } + case DATA_TYPE_INT64: + { + int64_t *new_array = malloc(array_len * sizeof(int64_t)); + + if (!new_array) + return -ENOMEM; + + for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++) + new_array[i] = strtoll(array_item, NULL, 10); + + *array = (void *)new_array; + *length = array_len; + break; + } + case DATA_TYPE_UINT: + { + u_int32_t *new_array = malloc(array_len * sizeof(u_int32_t)); + + if (!new_array) + return -ENOMEM; + + for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++) + new_array[i] = strtoul(array_item, NULL, 10); + + *array = (void *)new_array; + *length = array_len; + break; + } + case DATA_TYPE_UINT64: + { + u_int64_t *new_array = malloc(array_len * sizeof(u_int64_t)); + + if (!new_array) + return -ENOMEM; + + for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++) + new_array[i] = strtoull(array_item, NULL, 10); + + *array = (void *)new_array; + *length = array_len; + break; + } + case DATA_TYPE_DOUBLE: + { + double *new_array = malloc(array_len * sizeof(double)); + + if (!new_array) + return -ENOMEM; + + for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++) + new_array[i] = strtod(array_item, NULL); + + *array = (void *)new_array; + *length = array_len; + break; + } + case DATA_TYPE_STRING: + { + char **new_array = calloc(array_len, sizeof(char *)); + + if (!new_array) + return -ENOMEM; + + for (i = 0; (array_item = strsep(&array_str, ",")) != NULL; i++) { + char *new_item = g_strdup(array_item); + + if (!new_item) { + for (int j = i - 1; j >= 0; j--) + free(new_array[j]); + free(new_array); + return -ENOMEM; + } + + new_array[i] = new_item; + } + + *array = (void *)new_array; + *length = array_len; + break; + } + default: + _E("[libpass] not supported array data type"); + return -EINVAL; + } + + return ret; +} + +EXPORT +int tmonitor_get_array_int(int id, int res_id, u_int64_t attr_id, int32_t **array, int *length) +{ + return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_INT, (void **)array, length); +} + +EXPORT +int tmonitor_get_array_int64(int id, int res_id, u_int64_t attr_id, int64_t **array, int *length) +{ + return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_INT64, (void **)array, length); +} + +EXPORT +int tmonitor_get_array_uint(int id, int res_id, u_int64_t attr_id, u_int32_t **array, int *length) +{ + return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT, (void **)array, length); +} + +EXPORT +int tmonitor_get_array_uint64(int id, int res_id, u_int64_t attr_id, u_int64_t **array, int *length) +{ + return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_UINT64, (void **)array, length); +} + +EXPORT +int tmonitor_get_array_double(int id, int res_id, u_int64_t attr_id, double **array, int *length) +{ + return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_DOUBLE, (void **)array, length); +} + +EXPORT +int tmonitor_get_array_string(int id, int res_id, u_int64_t attr_id, char ***array, int *length) +{ + return tmonitor_get_array(id, res_id, attr_id, DATA_TYPE_STRING, (void **)array, length); +} diff --git a/lib/tmonitor/tmonitor.h b/lib/tmonitor/tmonitor.h index ae859c6..d64ad51 100644 --- a/lib/tmonitor/tmonitor.h +++ b/lib/tmonitor/tmonitor.h @@ -226,6 +226,22 @@ int tmonitor_get_value_uint64(int id, int resource_id, u_int64_t attr, u_int64_t int tmonitor_get_value_double(int id, int resource_id, u_int64_t attr, double *value); int tmonitor_get_value_string(int id, int resource_id, u_int64_t attr, char *value); +/** + * @brief Get [int/int64/uint/uint64/double/string] array of resource attribute + * @param[in] Tizen monitor id + * @param[in] Resource id + * @param[in] Resource attribute id + * @param[out] Array retrieved from resource attribute + * @param[out] Length of array + * @return @ 0 on success, otherwise a negative error value + */ +int tmonitor_get_array_int(int id, int res_id, u_int64_t attr, int32_t **array, int *length); +int tmonitor_get_array_int64(int id, int res_id, u_int64_t attr, int64_t **array, int *length); +int tmonitor_get_array_uint(int id, int res_id, u_int64_t attr, u_int32_t **array, int *length); +int tmonitor_get_array_uint64(int id, int res_id, u_int64_t attr, u_int64_t **array, int *length); +int tmonitor_get_array_double(int id, int res_id, u_int64_t attr, double **array, int *length); +int tmonitor_get_array_string(int id, int res_id, u_int64_t attr, char ***array, int *length); + #ifdef __cplusplus } #endif diff --git a/src/monitor/request-handler.c b/src/monitor/request-handler.c index 82d598a..edaabdb 100644 --- a/src/monitor/request-handler.c +++ b/src/monitor/request-handler.c @@ -402,6 +402,30 @@ static int handle_request_get_value_string(struct request_client *client, char * return get_resource_attr_string(res, attr_id, value); } +static int +handle_request_get_value_array(struct request_client *client, char *args, struct array_value **arr) +{ + struct resource *res; + int resource_id; + u_int64_t attr_id; + + if (!client || !args) + return -ENOENT; + + /** + * Format of REQUEST_GET_VALUE_ARRAY args: + * - + */ + if (sscanf(args, "%d:%"PRIu64, &resource_id, &attr_id) < 2) + return -EINVAL; + + res = get_resource_by_id(client, resource_id); + if (!res) + return -EINVAL; + + return get_resource_attr_array(res, attr_id, arr); +} + static int split_request_type_and_args(char *buffer, char **args) { char *request_type_str; @@ -413,13 +437,21 @@ static int split_request_type_and_args(char *buffer, char **args) return atoi(request_type_str); } +#define ADD_RESPONSE(__buf__, __remain__, __format__, ...) { \ + int __len__ = snprintf(__buf__, __remain__, __format__, __VA_ARGS__); \ + __buf__ += __len__; \ + __remain__ -= __len__; \ + if (__remain__ < 0) \ + _E("failed to add response"); \ +} \ + static void handle_request(struct request_client *client, char *buffer) { char _response[REQUEST_BUFFER_MAX]; char *response = _response; char *args; int request_type; - int ret, len; + int ret; int buffer_len = REQUEST_BUFFER_MAX; request_type = split_request_type_and_args(buffer, &args); @@ -428,9 +460,7 @@ static void handle_request(struct request_client *client, char *buffer) * Format of response * - */ - len = snprintf(response, buffer_len, "%d:", request_type); - response += len; - buffer_len -= len; + ADD_RESPONSE(response, buffer_len, "%d:", request_type); switch (request_type) { case REQUEST_CREATE_RESOURCE: @@ -484,9 +514,7 @@ static void handle_request(struct request_client *client, char *buffer) if (ret < 0) _D("failed to get value"); - len = snprintf(response, buffer_len, "%d:", value); - response += len; - buffer_len -= len; + ADD_RESPONSE(response, buffer_len, "%d:", value); } break; case REQUEST_GET_VALUE_INT64: @@ -497,9 +525,7 @@ static void handle_request(struct request_client *client, char *buffer) if (ret < 0) _D("failed to get value"); - len = snprintf(response, buffer_len, "%"PRId64":", value); - response += len; - buffer_len -= len; + ADD_RESPONSE(response, buffer_len, "%"PRId64":", value); } break; case REQUEST_GET_VALUE_UINT: @@ -510,9 +536,7 @@ static void handle_request(struct request_client *client, char *buffer) if (ret < 0) _D("failed to get value"); - len = snprintf(response, buffer_len, "%u:", value); - response += len; - buffer_len -= len; + ADD_RESPONSE(response, buffer_len, "%u:", value); } break; case REQUEST_GET_VALUE_UINT64: @@ -523,9 +547,7 @@ static void handle_request(struct request_client *client, char *buffer) if (ret < 0) _D("failed to get value"); - len = snprintf(response, buffer_len, "%"PRIu64":", value); - response += len; - buffer_len -= len; + ADD_RESPONSE(response, buffer_len, "%"PRIu64":", value); } break; case REQUEST_GET_VALUE_DOUBLE: @@ -536,9 +558,7 @@ static void handle_request(struct request_client *client, char *buffer) if (ret < 0) _D("failed to get value"); - len = snprintf(response, buffer_len, "%lf:", value); - response += len; - buffer_len -= len; + ADD_RESPONSE(response, buffer_len, "%lf:", value); } break; case REQUEST_GET_VALUE_STRING: @@ -549,9 +569,72 @@ static void handle_request(struct request_client *client, char *buffer) if (ret < 0) _D("failed to get value"); - len = snprintf(response, buffer_len, "%s:", value); - response += len; - buffer_len -= len; + ADD_RESPONSE(response, buffer_len, "%s:", value); + } + break; + case REQUEST_GET_VALUE_ARRAY: + { + struct array_value *array; + int i; + + ret = handle_request_get_value_array(client, args, &array); + if (ret < 0) + _D("failed to get value"); + + if (array->length == 0) { + ADD_RESPONSE(response, buffer_len, "%d|%d|:", + array->type, array->length); + break; + } + + ADD_RESPONSE(response, buffer_len, "%d|%d|", array->type, array->length); + + switch (array->type) { + case DATA_TYPE_INT: + for (i = 0; i < array->length - 1; i++) + ADD_RESPONSE(response, buffer_len, "%d,", + ((int32_t *)array->data)[i]); + ADD_RESPONSE(response, buffer_len, "%d:", + ((int32_t *)array->data)[i]); + break; + case DATA_TYPE_INT64: + for (i = 0; i < array->length - 1; i++) + ADD_RESPONSE(response, buffer_len, "%"PRId64",", + ((int64_t *)array->data)[i]); + ADD_RESPONSE(response, buffer_len, "%"PRId64":", + ((int64_t *)array->data)[i]); + break; + case DATA_TYPE_UINT: + for (i = 0; i < array->length - 1; i++) + ADD_RESPONSE(response, buffer_len, "%u,", + ((u_int32_t *)array->data)[i]); + ADD_RESPONSE(response, buffer_len, "%u:", + ((u_int32_t *)array->data)[i]); + break; + case DATA_TYPE_UINT64: + for (i = 0; i < array->length - 1; i++) + ADD_RESPONSE(response, buffer_len, "%"PRIu64",", + ((u_int64_t *)array->data)[i]); + ADD_RESPONSE(response, buffer_len, "%"PRIu64":", + ((u_int64_t *)array->data)[i]); + break; + case DATA_TYPE_DOUBLE: + for (i = 0; i < array->length - 1; i++) + ADD_RESPONSE(response, buffer_len, "%lf,", + ((double *)array->data)[i]); + ADD_RESPONSE(response, buffer_len, "%lf:", + ((double *)array->data)[i]); + break; + case DATA_TYPE_STRING: + for (i = 0; i < array->length - 1; i++) + ADD_RESPONSE(response, buffer_len, "%s,", + ((char **)array->data)[i]); + ADD_RESPONSE(response, buffer_len, "%s:", + ((char **)array->data)[i]); + break; + default: + _E("Not supported data type"); + } } break; default: @@ -559,7 +642,7 @@ static void handle_request(struct request_client *client, char *buffer) ret = -EINVAL; break; } - snprintf(response, buffer_len, "%d", ret); + ADD_RESPONSE(response, buffer_len, "%d", ret); if (send(client->socket_fd, _response, strlen(_response), 0) < 0) _E("Failed to send respones, error: %s", strerror(errno)); -- 2.7.4