From 4f3f729817013b407a343aad788c8b97bf8cecb7 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:14:00 +0800 Subject: [PATCH 1/5] feat: add type neu_ndriver_tag_t --- include/neuron/tag.h | 20 ++++++++++++++-- src/base/tag.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/include/neuron/tag.h b/include/neuron/tag.h index f8d205aa..ad08015e 100644 --- a/include/neuron/tag.h +++ b/include/neuron/tag.h @@ -78,11 +78,11 @@ typedef union { typedef struct { char * name; char * address; - char * description; neu_attribute_e attribute; neu_type_e type; uint8_t precision; double decimal; + char * description; neu_datatag_addr_option_u option; uint8_t meta[NEU_TAG_META_SIZE]; } neu_datatag_t; @@ -133,4 +133,20 @@ int neu_tag_set_static_value_json(neu_datatag_t *tag, neu_json_type_e t, char *neu_tag_dump_static_value(const neu_datatag_t *tag); int neu_tag_load_static_value(neu_datatag_t *tag, const char *s); -#endif \ No newline at end of file +typedef struct { + char * name; + char * address; + neu_attribute_e attribute; + neu_type_e type; + char * params; +} neu_ndriver_tag_t; + +UT_icd *neu_ndriver_tag_get_icd(); + +neu_datatag_t *neu_ndriver_tag_dup(const neu_ndriver_tag_t *tag); +void neu_ndriver_tag_copy(neu_ndriver_tag_t * tag, + const neu_ndriver_tag_t *other); +void neu_ndriver_tag_fini(neu_ndriver_tag_t *tag); +void neu_ndriver_tag_free(neu_ndriver_tag_t *tag); + +#endif diff --git a/src/base/tag.c b/src/base/tag.c index 75e0e0e5..faa4b852 100644 --- a/src/base/tag.c +++ b/src/base/tag.c @@ -721,3 +721,58 @@ int neu_tag_load_static_value(neu_datatag_t *tag, const char *s) return rv; } + +static inline void ndriver_tag_cpy(void *_dst, const void *_src) +{ + neu_ndriver_tag_t *dst = (neu_ndriver_tag_t *) _dst; + neu_ndriver_tag_t *src = (neu_ndriver_tag_t *) _src; + + dst->name = strdup(src->name); + dst->address = strdup(src->address); + dst->attribute = src->attribute; + dst->type = src->type; + dst->params = src->params ? strdup(src->params) : NULL; +} + +static inline void ndriver_tag_dtor(void *_elt) +{ + neu_ndriver_tag_t *elt = (neu_ndriver_tag_t *) _elt; + free(elt->name); + free(elt->address); + free(elt->params); +} + +UT_icd ndriver_tag_icd = { sizeof(neu_datatag_t), NULL, ndriver_tag_cpy, + ndriver_tag_dtor }; + +UT_icd *neu_ndriver_tag_get_icd() +{ + return &ndriver_tag_icd; +} + +neu_datatag_t *neu_ndriver_tag_dup(const neu_ndriver_tag_t *tag) +{ + neu_datatag_t *new = calloc(1, sizeof(*new)); + ndriver_tag_cpy(new, tag); + return new; +} + +void neu_ndriver_tag_copy(neu_ndriver_tag_t * tag, + const neu_ndriver_tag_t *other) +{ + ndriver_tag_dtor(tag); + ndriver_tag_cpy(tag, other); +} + +void neu_ndriver_tag_fini(neu_ndriver_tag_t *tag) +{ + ndriver_tag_dtor(tag); +} + +void neu_ndriver_tag_free(neu_ndriver_tag_t *tag) +{ + if (tag) { + ndriver_tag_dtor(tag); + free(tag); + } +} From 776b031cd6ab9056cab22ae6684a6e0e786595be Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:16:29 +0800 Subject: [PATCH 2/5] feat(core): add message type for getting ndriver tags --- include/neuron/adapter.h | 14 ++++++++++++++ src/adapter/adapter.c | 34 ++++++++++++++++++++++++++++++++++ src/core/manager.c | 2 ++ 3 files changed, 50 insertions(+) diff --git a/include/neuron/adapter.h b/include/neuron/adapter.h index 1cec695f..d6c52fca 100644 --- a/include/neuron/adapter.h +++ b/include/neuron/adapter.h @@ -118,6 +118,8 @@ typedef enum neu_reqresp_type { NEU_REQ_DEL_NDRIVER_MAP, NEU_REQ_GET_NDRIVER_MAPS, NEU_RESP_GET_NDRIVER_MAPS, + NEU_REQ_GET_NDRIVER_TAGS, + NEU_RESP_GET_NDRIVER_TAGS, NEU_REQ_UPDATE_LOG_LEVEL, @@ -215,6 +217,8 @@ static const char *neu_reqresp_type_string_t[] = { [NEU_REQ_DEL_NDRIVER_MAP] = "NEU_REQ_DEL_NDRIVER_MAP", [NEU_REQ_GET_NDRIVER_MAPS] = "NEU_REQ_GET_NDRIVER_MAPS", [NEU_RESP_GET_NDRIVER_MAPS] = "NEU_RESP_GET_NDRIVER_MAPS", + [NEU_REQ_GET_NDRIVER_TAGS] = "NEU_REQ_GET_NDRIVER_TAGS", + [NEU_RESP_GET_NDRIVER_TAGS] = "NEU_RESP_GET_NDRIVER_TAGS", [NEU_REQ_UPDATE_LOG_LEVEL] = "NEU_REQ_UPDATE_LOG_LEVEL", @@ -663,6 +667,16 @@ typedef struct { UT_array *groups; // array of neu_resp_ndriver_map_info_t } neu_resp_get_ndriver_maps_t; +typedef struct { + char ndriver[NEU_NODE_NAME_LEN]; + char driver[NEU_NODE_NAME_LEN]; + char group[NEU_GROUP_NAME_LEN]; +} neu_req_get_ndriver_tags_t; + +typedef struct { + UT_array *tags; // array of neu_ndriver_tag_t +} neu_resp_get_ndriver_tags_t; + typedef struct neu_req_update_log_level { char node[NEU_NODE_NAME_LEN]; } neu_req_update_log_level_t; diff --git a/src/adapter/adapter.c b/src/adapter/adapter.c index 72079361..47504967 100644 --- a/src/adapter/adapter.c +++ b/src/adapter/adapter.c @@ -373,6 +373,11 @@ static int adapter_command(neu_adapter_t *adapter, neu_reqresp_head_t header, strcpy(header.receiver, cmd->node); break; } + case NEU_REQ_GET_NDRIVER_TAGS: { + neu_req_get_ndriver_tags_t *cmd = (neu_req_get_ndriver_tags_t *) data; + strcpy(header.receiver, cmd->ndriver); + break; + } case NEU_REQ_UPDATE_LOG_LEVEL: { neu_req_update_log_level_t *cmd = (neu_req_update_log_level_t *) data; strcpy(header.receiver, cmd->node); @@ -453,6 +458,7 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data) case NEU_RESP_GET_TEMPLATE: case NEU_RESP_GET_TEMPLATES: case NEU_RESP_GET_NDRIVER_MAPS: + case NEU_RESP_GET_NDRIVER_TAGS: case NEU_RESP_GET_GROUP: case NEU_RESP_ERROR: case NEU_REQRESP_TRANS_DATA: @@ -834,6 +840,28 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data) } break; } + case NEU_REQ_GET_NDRIVER_TAGS: { + neu_req_get_ndriver_tags_t *cmd = + (neu_req_get_ndriver_tags_t *) &header[1]; + neu_resp_error_t error = { .error = 0 }; + UT_array * tags = NULL; + + // TODO + (void) cmd; + utarray_new(tags, neu_ndriver_tag_get_icd()); + + neu_msg_exchange(header); + if (error.error != NEU_ERR_SUCCESS) { + header->type = NEU_RESP_ERROR; + reply(adapter, header, &error); + } else { + neu_resp_get_tag_t resp = { .tags = tags }; + header->type = NEU_RESP_GET_NDRIVER_TAGS; + reply(adapter, header, &resp); + } + + break; + } case NEU_REQ_UPDATE_LOG_LEVEL: { neu_resp_error_t error = { 0 }; @@ -1398,6 +1426,12 @@ void *neu_msg_gen(neu_reqresp_head_t *header, void *data) case NEU_RESP_GET_NDRIVER_MAPS: data_size = sizeof(neu_resp_get_ndriver_maps_t); break; + case NEU_REQ_GET_NDRIVER_TAGS: + data_size = sizeof(neu_req_get_ndriver_tags_t); + break; + case NEU_RESP_GET_NDRIVER_TAGS: + data_size = sizeof(neu_resp_get_ndriver_tags_t); + break; case NEU_REQ_UPDATE_LOG_LEVEL: data_size = sizeof(neu_req_update_log_level_t); break; diff --git a/src/core/manager.c b/src/core/manager.c index accd34db..1209feb8 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -789,6 +789,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) case NEU_REQ_WRITE_TAG: case NEU_REQ_GET_NODE_STATE: case NEU_REQ_GET_TAG: + case NEU_REQ_GET_NDRIVER_TAGS: case NEU_REQ_NODE_CTL: case NEU_REQ_UPDATE_GROUP: case NEU_REQ_ADD_GROUP: { @@ -912,6 +913,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) case NEU_RESP_UPDATE_TEMPLATE_TAG: case NEU_RESP_GET_TAG: case NEU_RESP_GET_TEMPLATE_TAG: + case NEU_RESP_GET_NDRIVER_TAGS: case NEU_RESP_GET_GROUP: case NEU_RESP_GET_NODE_SETTING: case NEU_RESP_GET_NODE_STATE: From c35d12f854ddfb345d2be2a563ed299f4964bc32 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:18:51 +0800 Subject: [PATCH 3/5] feat: add json parser for getting ndriver tags --- src/parser/neu_json_ndriver.c | 92 +++++++++++++++++++++++++++++++++++ src/parser/neu_json_ndriver.h | 19 ++++++++ 2 files changed, 111 insertions(+) diff --git a/src/parser/neu_json_ndriver.c b/src/parser/neu_json_ndriver.c index 4880bb72..248ac4ae 100644 --- a/src/parser/neu_json_ndriver.c +++ b/src/parser/neu_json_ndriver.c @@ -164,3 +164,95 @@ int neu_json_encode_get_ndriver_maps_resp(void *json_obj, void *param) return ret; } + +int neu_json_encode_ndriver_tag(void *json_obj, void *param) +{ + int ret = 0; + neu_json_ndriver_tag_t *tag = param; + + neu_json_elem_t elems[] = { + { + .name = "name", + .t = NEU_JSON_STR, + .v.val_str = tag->name, + }, + { + .name = "address", + .t = NEU_JSON_STR, + .v.val_str = tag->address, + }, + { + .name = "attribute", + .t = NEU_JSON_INT, + .v.val_int = tag->attribute, + }, + { + .name = "type", + .t = NEU_JSON_INT, + .v.val_int = tag->type, + }, + }; + + ret = neu_json_encode_field(json_obj, elems, NEU_JSON_ELEM_SIZE(elems)); + if (0 != ret) { + return -1; + } + + neu_json_elem_t params_elem[] = { + { + .name = "params", + .t = NEU_JSON_STR, + .v.val_str = tag->params, + }, + }; + ret = neu_json_encode_field(json_obj, params_elem, + NEU_JSON_ELEM_SIZE(params_elem)); + + return ret; +} + +int neu_json_encode_ndriver_tag_array(void *json_obj, void *param) +{ + neu_json_ndriver_tag_array_t *array = param; + + if (!json_is_array((json_t *) json_obj)) { + return -1; + } + + for (int i = 0; i < array->len; i++) { + json_t *tag_obj = json_object(); + if (NULL == tag_obj || 0 != json_array_append_new(json_obj, tag_obj)) { + return -1; + } + if (0 != neu_json_encode_ndriver_tag(tag_obj, &array->data[i])) { + return -1; + } + } + + return 0; +} + +int neu_json_encode_get_ndriver_tags_resp(void *json_obj, void *param) +{ + int ret = 0; + + void *tags_array = neu_json_array(); + if (NULL == tags_array) { + return -1; + } + + if (0 != neu_json_encode_ndriver_tag_array(tags_array, param)) { + neu_json_encode_free(tags_array); + return -1; + } + + neu_json_elem_t resp_elems[] = { { + .name = "tags", + .t = NEU_JSON_OBJECT, + .v.val_object = tags_array, + } }; + ret = neu_json_encode_field(json_obj, resp_elems, + NEU_JSON_ELEM_SIZE(resp_elems)); + + return ret; +} diff --git a/src/parser/neu_json_ndriver.h b/src/parser/neu_json_ndriver.h index 6abf6d7b..6d5357ac 100644 --- a/src/parser/neu_json_ndriver.h +++ b/src/parser/neu_json_ndriver.h @@ -50,6 +50,25 @@ int neu_json_encode_ndriver_group_array(void *json_obj, void *param); int neu_json_encode_get_ndriver_maps_resp(void *json_object, void *param); +typedef struct { + char * name; + char * address; + int64_t attribute; + int64_t type; + char * params; +} neu_json_ndriver_tag_t; + +int neu_json_encode_ndriver_tag(void *json_obj, void *param); + +typedef struct { + int len; + neu_json_ndriver_tag_t *data; +} neu_json_ndriver_tag_array_t; + +int neu_json_encode_ndriver_tag_array(void *json_obj, void *param); + +int neu_json_encode_get_ndriver_tags_resp(void *json_obj, void *param); + #ifdef __cplusplus } #endif From 129a7a8b5628e0dab6aee0dce44a2c2c3cbbac94 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:25:34 +0800 Subject: [PATCH 4/5] feat(restful): add get ndriver tags api --- plugins/restful/handle.c | 9 ++++ plugins/restful/ndriver_handle.c | 88 ++++++++++++++++++++++++++++++-- plugins/restful/ndriver_handle.h | 4 ++ plugins/restful/rest.c | 4 ++ 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/plugins/restful/handle.c b/plugins/restful/handle.c index dac96443..617cc882 100644 --- a/plugins/restful/handle.c +++ b/plugins/restful/handle.c @@ -125,6 +125,9 @@ static struct neu_http_handler cors_handler[] = { { .url = "/api/v2/ndriver/map", }, + { + .url = "/api/v2/ndriver/tag", + }, }; static struct neu_http_handler rest_handlers[] = { @@ -448,6 +451,12 @@ static struct neu_http_handler rest_handlers[] = { .url = "/api/v2/ndriver/map", .value.handler = handle_get_ndriver_maps, }, + { + .method = NEU_HTTP_METHOD_GET, + .type = NEU_HTTP_HANDLER_FUNCTION, + .url = "/api/v2/ndriver/tag", + .value.handler = handle_get_ndriver_tags, + }, }; void neu_rest_handler(const struct neu_http_handler **handlers, uint32_t *size) diff --git a/plugins/restful/ndriver_handle.c b/plugins/restful/ndriver_handle.c index 485bca22..094bd95e 100644 --- a/plugins/restful/ndriver_handle.c +++ b/plugins/restful/ndriver_handle.c @@ -93,9 +93,9 @@ void handle_get_ndriver_maps(nng_aio *aio) NEU_VALIDATE_JWT(aio); neu_req_get_ndriver_maps_t cmd = { 0 }; - if (neu_http_get_param_str(aio, "ndriver", cmd.ndriver, - sizeof(cmd.ndriver)) <= 0 || - strlen(cmd.ndriver) >= NEU_NODE_NAME_LEN) { + ret = neu_http_get_param_str(aio, "ndriver", cmd.ndriver, + sizeof(cmd.ndriver)); + if (ret <= 0 || (size_t) ret >= sizeof(cmd.ndriver)) { NEU_JSON_RESPONSE_ERROR(NEU_ERR_PARAM_IS_WRONG, { neu_http_response(aio, error_code.error, result_error); }) @@ -146,3 +146,85 @@ void handle_get_ndriver_maps_resp(nng_aio * aio, free(group_arr.groups); utarray_free(groups->groups); } + +void handle_get_ndriver_tags(nng_aio *aio) +{ + int ret = 0; + neu_plugin_t *plugin = neu_rest_get_plugin(); + + NEU_VALIDATE_JWT(aio); + + neu_req_get_ndriver_tags_t cmd = { 0 }; + + ret = neu_http_get_param_str(aio, "ndriver", cmd.ndriver, + sizeof(cmd.ndriver)); + if (ret <= 0 || (size_t) ret >= sizeof(cmd.ndriver)) { + ret = NEU_ERR_PARAM_IS_WRONG; + goto end; + } + + ret = neu_http_get_param_str(aio, "driver", cmd.driver, sizeof(cmd.driver)); + if (ret <= 0 || (size_t) ret >= sizeof(cmd.driver)) { + ret = NEU_ERR_PARAM_IS_WRONG; + goto end; + } + + ret = neu_http_get_param_str(aio, "group", cmd.group, sizeof(cmd.group)); + if (ret <= 0 || (size_t) ret >= sizeof(cmd.group)) { + ret = NEU_ERR_PARAM_IS_WRONG; + goto end; + } + + neu_reqresp_head_t header = { + .ctx = aio, + .type = NEU_REQ_GET_NDRIVER_TAGS, + }; + + if (0 != (ret = neu_plugin_op(plugin, header, &cmd))) { + ret = NEU_ERR_IS_BUSY; + } + +end: + if (0 != ret) { + NEU_JSON_RESPONSE_ERROR(ret, + { neu_http_response(aio, ret, result_error); }); + } +} + +void handle_get_ndriver_tags_resp(nng_aio * aio, + neu_resp_get_ndriver_tags_t *tags) +{ + char * result = NULL; + neu_json_ndriver_tag_array_t tags_res = { 0 }; + + tags_res.len = utarray_len(tags->tags); + tags_res.data = calloc(tags_res.len, sizeof(tags_res.data[0])); + if (NULL == tags_res.data) { + goto end; + } + + for (int i = 0; i < tags_res.len; ++i) { + neu_ndriver_tag_t *tag = utarray_eltptr(tags->tags, (size_t) i); + tags_res.data[i].name = tag->name; + tags_res.data[i].address = tag->address; + tags_res.data[i].attribute = tag->attribute; + tags_res.data[i].type = tag->type; + tags_res.data[i].params = tag->params; + } + + neu_json_encode_by_fn(&tags_res, neu_json_encode_get_ndriver_tags_resp, + &result); + +end: + if (result) { + neu_http_ok(aio, result); + } else { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_EINTERNAL, { + neu_http_response(aio, NEU_ERR_EINTERNAL, result_error); + }); + } + + free(result); + free(tags_res.data); + utarray_free(tags->tags); +} diff --git a/plugins/restful/ndriver_handle.h b/plugins/restful/ndriver_handle.h index 05b3ffbd..28f16951 100644 --- a/plugins/restful/ndriver_handle.h +++ b/plugins/restful/ndriver_handle.h @@ -29,4 +29,8 @@ void handle_get_ndriver_maps(nng_aio *aio); void handle_get_ndriver_maps_resp(nng_aio * aio, neu_resp_get_ndriver_maps_t *groups); +void handle_get_ndriver_tags(nng_aio *aio); +void handle_get_ndriver_tags_resp(nng_aio * aio, + neu_resp_get_ndriver_tags_t *tags); + #endif diff --git a/plugins/restful/rest.c b/plugins/restful/rest.c index 9bd84e3a..e85b6109 100644 --- a/plugins/restful/rest.c +++ b/plugins/restful/rest.c @@ -237,6 +237,10 @@ static int dashb_plugin_request(neu_plugin_t * plugin, handle_get_ndriver_maps_resp(header->ctx, (neu_resp_get_ndriver_maps_t *) data); break; + case NEU_RESP_GET_NDRIVER_TAGS: + handle_get_ndriver_tags_resp(header->ctx, + (neu_resp_get_ndriver_tags_t *) data); + break; default: nlog_fatal("recv unhandle msg: %s", neu_reqresp_type_string(header->type)); From f60e0903a6d4c5422346cec27022b327b622548f Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:27:16 +0800 Subject: [PATCH 5/5] fix: neu_http_get_param boundary check --- src/utils/http.c | 11 ++++++++--- tests/http_test.cc | 11 ++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/utils/http.c b/src/utils/http.c index d8e3ea4b..89902f0c 100644 --- a/src/utils/http.c +++ b/src/utils/http.c @@ -125,10 +125,15 @@ static char *get_param(const char *url, const char *name, size_t *len_p) return NULL; } - int len = strlen(name); - char *p = strstr(query, name); + int len = strlen(name); + if (0 == len || NULL != strpbrk(name, "?&=#")) { + return NULL; + } + + char *p = strstr(query, name); while (NULL != p) { - if (0 == p[len] || '&' == p[len] || '=' == p[len] || '#' == p[len]) { + if (('?' == p[-1] || '&' == p[-1]) && + (0 == p[len] || '&' == p[len] || '=' == p[len] || '#' == p[len])) { break; } p = strstr(p + len, name); diff --git a/tests/http_test.cc b/tests/http_test.cc index 31f4af0c..098dbd59 100644 --- a/tests/http_test.cc +++ b/tests/http_test.cc @@ -41,13 +41,18 @@ TEST(HTTPTest, http_get_param) { .uri = "/?node_id=1", .name = "node=", .val = NULL, .len = 0 }, { .uri = "/?node_id=1", .name = "node&", .val = NULL, .len = 0 }, { .uri = "/?node_id=1", .name = "node_id=", .val = NULL, .len = 0 }, + { .uri = "/?node_id=1", .name = "id", .val = NULL, .len = 0 }, { .uri = "/?node_id", .name = "node_id", .val = "", .len = 0 }, + { .uri = "/?node_id", .name = "id", .val = NULL, .len = 0 }, { .uri = "/?node_id=", .name = "node_id", .val = "", .len = 0 }, + { .uri = "/?node_id=", .name = "id", .val = NULL, .len = 0 }, { .uri = "/?node_id#", .name = "node_id", .val = "#", .len = 0 }, + { .uri = "/?node_id#", .name = "id", .val = NULL, .len = 0 }, { .uri = "/?node_id=1", .name = "node_id", .val = "1", .len = 1 }, { .uri = "/?node_id=1&", .name = "node_id", .val = "1", .len = 1 }, + { .uri = "/?node_id=1&", .name = "id", .val = NULL, .len = 0 }, { .uri = "/?node_id=1&type=1", .name = "node_id", .val = "1", @@ -64,7 +69,11 @@ TEST(HTTPTest, http_get_param) len = 0; const char *val = neu_http_get_param(aio, data[i].name, &len); EXPECT_EQ(len, data[i].len); - EXPECT_EQ(strncmp(val, data[i].val, len), 0); + if (val && data[i].val) { + EXPECT_EQ(strncmp(val, data[i].val, len), 0); + } else { + EXPECT_EQ(val, data[i].val); + } } nng_aio_free(aio);