1 /*************************************************************************
3 * Copyright 2019 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
26 #include <cjson/cJSON.h>
31 #include "sysrepo/values.h"
32 #include "libyang/libyang.h"
36 #define EMEM printf("Memory allocation failed (%s:%d)", __FILE__, __LINE__);
38 static int op_set_srval(struct lyd_node *node, char *path, int dup, sr_val_t *val, char **val_buf)
41 struct lyd_node_leaf_list *leaf;
52 sr_val_set_xpath(val, path);
55 val->data.int64_val = 0;
57 switch (node->schema->nodetype) {
59 val->type = ((struct lys_node_container *)node->schema)->presence ? SR_CONTAINER_PRESENCE_T : SR_CONTAINER_T;
62 val->type = SR_LIST_T;
66 leaf = (struct lyd_node_leaf_list *)node;
68 switch (leaf->value_type) {
70 val->type = SR_BINARY_T;
71 str = leaf->value.binary;
73 sr_val_set_str_data(val, val->type, str);
75 val->data.string_val = (char *)str;
77 if (NULL == val->data.binary_val) {
83 val->type = SR_BITS_T;
84 str = leaf->value_str;
86 sr_val_set_str_data(val, val->type, str);
88 val->data.string_val = (char *)str;
92 val->type = SR_BOOL_T;
93 val->data.bool_val = leaf->value.bln;
96 val->type = SR_DECIMAL64_T;
97 val->data.decimal64_val = (double)leaf->value.dec64;
98 for (i = 0; i < ((struct lys_node_leaf *)leaf->schema)->type.info.dec64.dig; i++) {
99 /* shift decimal point */
100 val->data.decimal64_val *= 0.1;
104 val->type = SR_LEAF_EMPTY_T;
107 val->type = SR_ENUM_T;
108 str = leaf->value.enm->name;
110 sr_val_set_str_data(val, val->type, str);
112 val->data.string_val = (char *)str;
114 if (NULL == val->data.enum_val) {
120 val->type = SR_IDENTITYREF_T;
122 str = malloc(strlen(lys_main_module(leaf->value.ident->module)->name) + 1 + strlen(leaf->value.ident->name) + 1);
127 sprintf((char *)str, "%s:%s", lys_main_module(leaf->value.ident->module)->name, leaf->value.ident->name);
128 val->data.identityref_val = (char *)str;
130 (*val_buf) = (char *)str;
134 val->type = SR_INSTANCEID_T;
136 sr_val_set_str_data(val, val->type, leaf->value_str);
138 val->data.string_val = (char *)leaf->value_str;
142 val->type = SR_STRING_T;
143 str = leaf->value.string;
145 sr_val_set_str_data(val, val->type, str);
147 val->data.string_val = (char *)str;
149 if (NULL == val->data.string_val) {
155 val->type = SR_INT8_T;
156 val->data.int8_val = leaf->value.int8;
159 val->type = SR_UINT8_T;
160 val->data.uint8_val = leaf->value.uint8;
163 val->type = SR_INT16_T;
164 val->data.int16_val = leaf->value.int16;
167 val->type = SR_UINT16_T;
168 val->data.uint16_val = leaf->value.uint16;
171 val->type = SR_INT32_T;
172 val->data.int32_val = leaf->value.int32;
175 val->type = SR_UINT32_T;
176 val->data.uint32_val = leaf->value.uint32;
179 val->type = SR_INT64_T;
180 val->data.int64_val = leaf->value.int64;
183 val->type = SR_UINT64_T;
184 val->data.uint64_val = leaf->value.uint64;
186 case LY_TYPE_LEAFREF:
187 leaf = (struct lyd_node_leaf_list *)leaf->value.leafref;
190 //LY_DERIVED, LY_UNION
191 val->type = SR_UNKNOWN_T;
196 val->type = SR_UNKNOWN_T;
203 static int op_add_srval(sr_val_t **values, size_t *values_cnt, struct lyd_node *node)
205 char *path, *buf = NULL;
208 if (sr_realloc_values(*values_cnt, *values_cnt + 1, values) != SR_ERR_OK) {
213 path = lyd_path(node);
214 ret = op_set_srval(node, path, 1, &(*values)[*values_cnt - 1], &buf);
221 static void add_attrtibutes(sr_val_t **values_list, size_t *values_cnt, struct lyd_node *node)
223 struct lyd_node *iter = NULL;
225 LY_TREE_FOR(node->child, iter) {
226 if (op_add_srval(values_list, values_cnt, iter)) {
227 printf("Could not transform libyang into sysrepo values...\n");
230 if (iter->schema->nodetype == LYS_CONTAINER || iter->schema->nodetype == LYS_LIST)
232 add_attrtibutes(values_list, values_cnt, iter);
238 static int send_dummy_notif(sr_session_ctx_t *sess, const char *module_name, const char *notif_object)
242 struct ly_ctx *ctx = NULL;
243 struct lyd_node *data = NULL, *iter = NULL;
244 sr_schema_t *schemas = NULL;
245 size_t schema_cnt = 0;
246 sr_val_t *vnotif = NULL;
247 size_t num_values= 0;
249 ctx = ly_ctx_new("/etc/sysrepo/yang", LY_CTX_ALLIMPLEMENTED);
252 printf("Creating context failed...\n");
253 return SR_ERR_OPERATION_FAILED;
256 rc = sr_list_schemas(sess, &schemas, &schema_cnt);
259 printf("Could not list the schemas from the sysrepo session...\n");
260 return SR_ERR_OPERATION_FAILED;
263 const char *schema_path = NULL;
265 for (size_t i = 0; i < schema_cnt; i++)
267 schema_path = schemas[i].revision.file_path_yang;
269 if (NULL != schema_path && 0 == strcmp(module_name, schemas[i].module_name)) {
270 printf("Trying to install schema: %s\n", schema_path);
271 if (NULL == lys_parse_path(ctx, schema_path, LYS_IN_YANG))
273 fprintf(stderr, "Failed to parse schema file '%s': %s (%s)",
274 schema_path, ly_errmsg(ctx), ly_errpath(ctx));
275 return SR_ERR_OPERATION_FAILED;
282 printf("Successfully loaded schemas, trying now to parse the JSON...\n");
284 data = lyd_parse_mem(ctx, notif_object, LYD_JSON, LYD_OPT_NOTIF, NULL);
287 printf("Could not create JSON object, not valid!\n");
288 return SR_ERR_VALIDATION_FAILED;
291 printf("Successfully parsed the JSON notification object...\n");
293 add_attrtibutes(&vnotif, &num_values, data);
297 printf("Could not generate objects for sending inside the notif...\n");
298 return SR_ERR_OPERATION_FAILED;
301 rc = sr_event_notif_send(sess, lyd_path(data), vnotif, num_values, SR_EV_NOTIF_DEFAULT);
304 printf("Error: could not send notification...\n");
305 return SR_ERR_OPERATION_FAILED;
309 ly_ctx_destroy(ctx, NULL);
311 sr_free_values(vnotif, num_values);
313 printf("Successfully sent notification from module=%s with %d number of atttributes\n", module_name, num_values);
319 main(int argc, char **argv)
321 sr_conn_ctx_t *connection = NULL;
322 sr_session_ctx_t *session = NULL;
323 sr_subscription_ctx_t *subscription = NULL;
326 setbuf(stdout, NULL);
327 setbuf(stderr, NULL);
329 const char *notif_object = NULL;
330 const char *module_name = NULL;
333 printf("%s <module_name> <notification-object>\n", argv[0]);
336 module_name = argv[1];
337 notif_object = argv[2];
339 /* connect to sysrepo */
340 rc = sr_connect("generic_notifications", SR_CONN_DEFAULT, &connection);
341 if (SR_ERR_OK != rc) {
342 fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
347 rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session);
348 if (SR_ERR_OK != rc) {
349 fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
353 rc = send_dummy_notif(session, module_name, notif_object);
354 if (SR_ERR_OK != rc) {
355 fprintf(stderr, "Error by send_dummy_notif: %s\n", sr_strerror(rc));
359 printf("Application exit reached, exiting.\n");
364 if (NULL != subscription) {
365 sr_unsubscribe(session, subscription);
367 if (NULL != session) {
368 sr_session_stop(session);
370 if (NULL != connection) {
371 sr_disconnect(connection);
373 printf("Error encountered. Exiting...");