libnetconf2 REFACTOR initial libyang2 support
diff --git a/src/messages_server.c b/src/messages_server.c
index 33cbba6..197d5f4 100644
--- a/src/messages_server.c
+++ b/src/messages_server.c
@@ -16,7 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
-#include <stdbool.h>
+#include <inttypes.h>
#include <libyang/libyang.h>
@@ -60,7 +60,10 @@
ret->type = NC_RPL_DATA;
ret->wd = wd;
if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
- ret->data = lyd_dup(data, 1);
+ if (lyd_dup_single(data, NULL, LYD_DUP_RECURSIVE, &ret->data)) {
+ free(ret);
+ return NULL;
+ }
} else {
ret->data = data;
}
@@ -73,7 +76,7 @@
}
API struct nc_server_reply *
-nc_server_reply_err(struct nc_server_error *err)
+nc_server_reply_err(struct lyd_node *err)
{
struct nc_server_reply_error *ret;
@@ -89,19 +92,12 @@
}
ret->type = NC_RPL_ERROR;
- ret->err = malloc(sizeof *ret->err);
- if (!ret->err) {
- ERRMEM;
- free(ret);
- return NULL;
- }
- ret->err[0] = err;
- ret->count = 1;
+ ret->err = err;
return (struct nc_server_reply *)ret;
}
API int
-nc_server_reply_add_err(struct nc_server_reply *reply, struct nc_server_error *err)
+nc_server_reply_add_err(struct nc_server_reply *reply, struct lyd_node *err)
{
struct nc_server_reply_error *err_rpl;
@@ -114,17 +110,11 @@
}
err_rpl = (struct nc_server_reply_error *)reply;
- ++err_rpl->count;
- err_rpl->err = nc_realloc(err_rpl->err, err_rpl->count * sizeof *err_rpl->err);
- if (!err_rpl->err) {
- ERRMEM;
- return -1;
- }
- err_rpl->err[err_rpl->count - 1] = err;
+ lyd_insert_sibling(err_rpl->err, err, &err_rpl->err);
return 0;
}
-API const struct nc_server_error *
+API const struct lyd_node *
nc_server_reply_get_last_err(const struct nc_server_reply *reply)
{
struct nc_server_reply_error *err_rpl;
@@ -135,17 +125,147 @@
}
err_rpl = (struct nc_server_reply_error *)reply;
- if (!err_rpl->count) {
+ if (!err_rpl->err) {
return NULL;
}
- return err_rpl->err[err_rpl->count - 1];
+ return err_rpl->err->prev;
}
-API struct nc_server_error *
-nc_err(int tag, ...)
+static const char *
+nc_err_tag2str(NC_ERR tag)
+{
+ switch (tag) {
+ case NC_ERR_IN_USE:
+ return "in-use";
+ case NC_ERR_INVALID_VALUE:
+ return "invalid-value";
+ case NC_ERR_ACCESS_DENIED:
+ return "access-denied";
+ case NC_ERR_ROLLBACK_FAILED:
+ return "rollback-failed";
+ case NC_ERR_OP_NOT_SUPPORTED:
+ return "operation-not-supported";
+ case NC_ERR_TOO_BIG:
+ return "too-big";
+ case NC_ERR_RES_DENIED:
+ return "resource-denied";
+ case NC_ERR_MISSING_ATTR:
+ return "missing-attribute";
+ case NC_ERR_BAD_ATTR:
+ return "bad-attribute";
+ case NC_ERR_UNKNOWN_ATTR:
+ return "unknown-attribute";
+ case NC_ERR_MISSING_ELEM:
+ return "missing-element";
+ case NC_ERR_BAD_ELEM:
+ return "bad-element";
+ case NC_ERR_UNKNOWN_ELEM:
+ return "unknown-element";
+ case NC_ERR_UNKNOWN_NS:
+ return "unknown-namespace";
+ case NC_ERR_LOCK_DENIED:
+ return "lock-denied";
+ case NC_ERR_DATA_EXISTS:
+ return "data-exists";
+ case NC_ERR_DATA_MISSING:
+ return "data-missing";
+ case NC_ERR_OP_FAILED:
+ return "operation-failed";
+ case NC_ERR_MALFORMED_MSG:
+ return "malformed-message";
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static NC_ERR
+nc_err_str2tag(const char *str)
+{
+ if (!strcmp(str, "in-use")) {
+ return NC_ERR_IN_USE;
+ } else if (!strcmp(str, "invalid-value")) {
+ return NC_ERR_INVALID_VALUE;
+ } else if (!strcmp(str, "access-denied")) {
+ return NC_ERR_ACCESS_DENIED;
+ } else if (!strcmp(str, "rollback-failed")) {
+ return NC_ERR_ROLLBACK_FAILED;
+ } else if (!strcmp(str, "operation-not-supported")) {
+ return NC_ERR_OP_NOT_SUPPORTED;
+ } else if (!strcmp(str, "too-big")) {
+ return NC_ERR_TOO_BIG;
+ } else if (!strcmp(str, "resource-denied")) {
+ return NC_ERR_RES_DENIED;
+ } else if (!strcmp(str, "missing-attribute")) {
+ return NC_ERR_MISSING_ATTR;
+ } else if (!strcmp(str, "bad-attribute")) {
+ return NC_ERR_BAD_ATTR;
+ } else if (!strcmp(str, "unknown-attribute")) {
+ return NC_ERR_UNKNOWN_ATTR;
+ } else if (!strcmp(str, "missing-element")) {
+ return NC_ERR_MISSING_ELEM;
+ } else if (!strcmp(str, "bad-element")) {
+ return NC_ERR_BAD_ELEM;
+ } else if (!strcmp(str, "unknown-element")) {
+ return NC_ERR_UNKNOWN_ELEM;
+ } else if (!strcmp(str, "unknown-namespace")) {
+ return NC_ERR_UNKNOWN_NS;
+ } else if (!strcmp(str, "lock-denied")) {
+ return NC_ERR_LOCK_DENIED;
+ } else if (!strcmp(str, "data-exists")) {
+ return NC_ERR_DATA_EXISTS;
+ } else if (!strcmp(str, "data-missing")) {
+ return NC_ERR_DATA_MISSING;
+ } else if (!strcmp(str, "operation-failed")) {
+ return NC_ERR_OP_FAILED;
+ } else if (!strcmp(str, "malformed-message")) {
+ return NC_ERR_MALFORMED_MSG;
+ }
+
+ return 0;
+}
+
+static const char *
+nc_err_type2str(NC_ERR_TYPE type)
+{
+ switch (type) {
+ case NC_ERR_TYPE_TRAN:
+ return "transport";
+ case NC_ERR_TYPE_RPC:
+ return "rpc";
+ case NC_ERR_TYPE_PROT:
+ return "protocol";
+ case NC_ERR_TYPE_APP:
+ return "application";
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static NC_ERR_TYPE
+nc_err_str2type(const char *str)
+{
+ if (!strcmp(str, "transport")) {
+ return NC_ERR_TYPE_TRAN;
+ } else if (!strcmp(str, "rpc")) {
+ return NC_ERR_TYPE_RPC;
+ } else if (!strcmp(str, "protocol")) {
+ return NC_ERR_TYPE_PROT;
+ } else if (!strcmp(str, "application")) {
+ return NC_ERR_TYPE_APP;
+ }
+
+ return 0;
+}
+
+API struct lyd_node *
+nc_err(const struct ly_ctx *ctx, NC_ERR tag, ...)
{
va_list ap;
- struct nc_server_error *ret;
+ struct lyd_node *err = NULL;
NC_ERR_TYPE type;
const char *arg1, *arg2;
uint32_t sid;
@@ -155,15 +275,14 @@
return NULL;
}
- ret = calloc(1, sizeof *ret);
- if (!ret) {
- ERRMEM;
+ /* rpc-error */
+ if (lyd_new_opaq2(NULL, ctx, "rpc-error", NULL, NULL, NC_NS_BASE, &err)) {
return NULL;
}
- ret->sid = -1;
va_start(ap, tag);
+ /* error-type */
switch (tag) {
case NC_ERR_IN_USE:
case NC_ERR_INVALID_VALUE:
@@ -176,141 +295,175 @@
goto fail;
}
break;
-
case NC_ERR_TOO_BIG:
case NC_ERR_RES_DENIED:
- type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
- /* nothing to check */
+ type = (NC_ERR_TYPE)va_arg(ap, int);
break;
-
case NC_ERR_MISSING_ATTR:
case NC_ERR_BAD_ATTR:
case NC_ERR_UNKNOWN_ATTR:
- type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
- arg1 = va_arg(ap, const char *);
- arg2 = va_arg(ap, const char *);
-
+ type = (NC_ERR_TYPE)va_arg(ap, int);
if (type == NC_ERR_TYPE_TRAN) {
ERRARG("type");
goto fail;
}
- nc_err_add_bad_attr(ret, arg1);
- nc_err_add_bad_elem(ret, arg2);
break;
-
case NC_ERR_MISSING_ELEM:
case NC_ERR_BAD_ELEM:
case NC_ERR_UNKNOWN_ELEM:
- type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
- arg1 = va_arg(ap, const char *);
-
+ type = (NC_ERR_TYPE)va_arg(ap, int);
if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
ERRARG("type");
goto fail;
}
- nc_err_add_bad_elem(ret, arg1);
break;
-
case NC_ERR_UNKNOWN_NS:
- type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
- arg1 = va_arg(ap, const char *);
- arg2 = va_arg(ap, const char *);
-
+ type = (NC_ERR_TYPE)va_arg(ap, int);
if ((type != NC_ERR_TYPE_PROT) && (type != NC_ERR_TYPE_APP)) {
ERRARG("type");
goto fail;
}
- nc_err_add_bad_elem(ret, arg1);
- nc_err_add_bad_ns(ret, arg2);
break;
-
case NC_ERR_LOCK_DENIED:
- sid = va_arg(ap, uint32_t);
-
type = NC_ERR_TYPE_PROT;
- nc_err_set_sid(ret, sid);
break;
-
case NC_ERR_DATA_EXISTS:
case NC_ERR_DATA_MISSING:
type = NC_ERR_TYPE_APP;
break;
-
case NC_ERR_OP_FAILED:
- type = (NC_ERR_TYPE)va_arg(ap, int); /* NC_ERR_TYPE enum is automatically promoted to int */
-
+ type = (NC_ERR_TYPE)va_arg(ap, int);
if (type == NC_ERR_TYPE_TRAN) {
ERRARG("type");
goto fail;
}
break;
-
case NC_ERR_MALFORMED_MSG:
type = NC_ERR_TYPE_RPC;
break;
+ default:
+ ERRARG("tag");
+ goto fail;
+ }
+ if (lyd_new_opaq2(err, NULL, "error-type", nc_err_type2str(type), NULL, NC_NS_BASE, NULL)) {
+ goto fail;
+ }
+ /* error-tag */
+ if (lyd_new_opaq2(err, NULL, "error-tag", nc_err_tag2str(tag), NULL, NC_NS_BASE, NULL)) {
+ goto fail;
+ }
+
+ /* error-severity */
+ if (lyd_new_opaq2(err, NULL, "error-severity", "error", NULL, NC_NS_BASE, NULL)) {
+ goto fail;
+ }
+
+ /* error-message */
+ switch (tag) {
+ case NC_ERR_IN_USE:
+ nc_err_set_msg(err, "The request requires a resource that already is in use.", "en");
+ break;
+ case NC_ERR_INVALID_VALUE:
+ nc_err_set_msg(err, "The request specifies an unacceptable value for one or more parameters.", "en");
+ break;
+ case NC_ERR_TOO_BIG:
+ nc_err_set_msg(err, "The request or response (that would be generated) is too large for the implementation to handle.", "en");
+ break;
+ case NC_ERR_MISSING_ATTR:
+ nc_err_set_msg(err, "An expected attribute is missing.", "en");
+ break;
+ case NC_ERR_BAD_ATTR:
+ nc_err_set_msg(err, "An attribute value is not correct.", "en");
+ break;
+ case NC_ERR_UNKNOWN_ATTR:
+ nc_err_set_msg(err, "An unexpected attribute is present.", "en");
+ break;
+ case NC_ERR_MISSING_ELEM:
+ nc_err_set_msg(err, "An expected element is missing.", "en");
+ break;
+ case NC_ERR_BAD_ELEM:
+ nc_err_set_msg(err, "An element value is not correct.", "en");
+ break;
+ case NC_ERR_UNKNOWN_ELEM:
+ nc_err_set_msg(err, "An unexpected element is present.", "en");
+ break;
+ case NC_ERR_UNKNOWN_NS:
+ nc_err_set_msg(err, "An unexpected namespace is present.", "en");
+ break;
+ case NC_ERR_ACCESS_DENIED:
+ nc_err_set_msg(err, "Access to the requested protocol operation or data model is denied because authorization failed.", "en");
+ break;
+ case NC_ERR_LOCK_DENIED:
+ nc_err_set_msg(err, "Access to the requested lock is denied because the lock is currently held by another entity.", "en");
+ break;
+ case NC_ERR_RES_DENIED:
+ nc_err_set_msg(err, "Request could not be completed because of insufficient resources.", "en");
+ break;
+ case NC_ERR_ROLLBACK_FAILED:
+ nc_err_set_msg(err, "Request to roll back some configuration change was not completed for some reason.", "en");
+ break;
+ case NC_ERR_DATA_EXISTS:
+ nc_err_set_msg(err, "Request could not be completed because the relevant data model content already exists.", "en");
+ break;
+ case NC_ERR_DATA_MISSING:
+ nc_err_set_msg(err, "Request could not be completed because the relevant data model content does not exist.", "en");
+ break;
+ case NC_ERR_OP_NOT_SUPPORTED:
+ nc_err_set_msg(err, "Request could not be completed because the requested operation is not supported by this implementation.", "en");
+ break;
+ case NC_ERR_OP_FAILED:
+ nc_err_set_msg(err, "Request could not be completed because the requested operation failed for a non-specific reason.", "en");
+ break;
+ case NC_ERR_MALFORMED_MSG:
+ nc_err_set_msg(err, "A message could not be handled because it failed to be parsed correctly.", "en");
+ break;
default:
ERRARG("tag");
goto fail;
}
+ /* error-info */
switch (tag) {
case NC_ERR_IN_USE:
- nc_err_set_msg(ret, "The request requires a resource that already is in use.", "en");
- break;
case NC_ERR_INVALID_VALUE:
- nc_err_set_msg(ret, "The request specifies an unacceptable value for one or more parameters.", "en");
- break;
+ case NC_ERR_ACCESS_DENIED:
+ case NC_ERR_ROLLBACK_FAILED:
+ case NC_ERR_OP_NOT_SUPPORTED:
case NC_ERR_TOO_BIG:
- nc_err_set_msg(ret, "The request or response (that would be generated) is too large for the implementation to handle.", "en");
+ case NC_ERR_RES_DENIED:
+ case NC_ERR_DATA_EXISTS:
+ case NC_ERR_DATA_MISSING:
+ case NC_ERR_OP_FAILED:
+ case NC_ERR_MALFORMED_MSG:
break;
case NC_ERR_MISSING_ATTR:
- nc_err_set_msg(ret, "An expected attribute is missing.", "en");
- break;
case NC_ERR_BAD_ATTR:
- nc_err_set_msg(ret, "An attribute value is not correct.", "en");
- break;
case NC_ERR_UNKNOWN_ATTR:
- nc_err_set_msg(ret, "An unexpected attribute is present.", "en");
+ arg1 = va_arg(ap, const char *);
+ arg2 = va_arg(ap, const char *);
+
+ nc_err_add_bad_attr(err, arg1);
+ nc_err_add_bad_elem(err, arg2);
break;
case NC_ERR_MISSING_ELEM:
- nc_err_set_msg(ret, "An expected element is missing.", "en");
- break;
case NC_ERR_BAD_ELEM:
- nc_err_set_msg(ret, "An element value is not correct.", "en");
- break;
case NC_ERR_UNKNOWN_ELEM:
- nc_err_set_msg(ret, "An unexpected element is present.", "en");
+ arg1 = va_arg(ap, const char *);
+
+ nc_err_add_bad_elem(err, arg1);
break;
case NC_ERR_UNKNOWN_NS:
- nc_err_set_msg(ret, "An unexpected namespace is present.", "en");
- break;
- case NC_ERR_ACCESS_DENIED:
- nc_err_set_msg(ret, "Access to the requested protocol operation or data model is denied because authorization failed.", "en");
+ arg1 = va_arg(ap, const char *);
+ arg2 = va_arg(ap, const char *);
+
+ nc_err_add_bad_elem(err, arg1);
+ nc_err_add_bad_ns(err, arg2);
break;
case NC_ERR_LOCK_DENIED:
- nc_err_set_msg(ret, "Access to the requested lock is denied because the lock is currently held by another entity.", "en");
- break;
- case NC_ERR_RES_DENIED:
- nc_err_set_msg(ret, "Request could not be completed because of insufficient resources.", "en");
- break;
- case NC_ERR_ROLLBACK_FAILED:
- nc_err_set_msg(ret, "Request to roll back some configuration change was not completed for some reason.", "en");
- break;
- case NC_ERR_DATA_EXISTS:
- nc_err_set_msg(ret, "Request could not be completed because the relevant data model content already exists.", "en");
- break;
- case NC_ERR_DATA_MISSING:
- nc_err_set_msg(ret, "Request could not be completed because the relevant data model content does not exist.", "en");
- break;
- case NC_ERR_OP_NOT_SUPPORTED:
- nc_err_set_msg(ret, "Request could not be completed because the requested operation is not supported by this implementation.", "en");
- break;
- case NC_ERR_OP_FAILED:
- nc_err_set_msg(ret, "Request could not be completed because the requested operation failed for a non-specific reason.", "en");
- break;
- case NC_ERR_MALFORMED_MSG:
- nc_err_set_msg(ret, "A message could not be handled because it failed to be parsed correctly.", "en");
+ sid = va_arg(ap, uint32_t);
+
+ nc_err_set_sid(err, sid);
break;
default:
ERRARG("tag");
@@ -318,67 +471,29 @@
}
va_end(ap);
-
- ret->type = type;
- ret->tag = tag;
- return ret;
+ return err;
fail:
va_end(ap);
- free(ret);
+ lyd_free_siblings(err);
return NULL;
}
-static struct lyxml_elem *
-nc_err_libyang_other_elem(const char *name, const char *content, int cont_len)
-{
- struct lyxml_elem *root = NULL;
- struct lyxml_ns *ns;
-
- root = calloc(1, sizeof *root);
- if (!root) {
- ERRMEM;
- goto error;
- }
- root->prev = root;
- root->name = lydict_insert(server_opts.ctx, name, 0);
- root->content = lydict_insert(server_opts.ctx, content, cont_len);
-
- ns = calloc(1, sizeof *root->ns);
- if (!ns) {
- ERRMEM;
- goto error;
- }
- root->attr = (struct lyxml_attr *)ns;
- ns->type = LYXML_ATTR_NS;
- ns->parent = root;
- ns->value = lydict_insert(server_opts.ctx, "urn:ietf:params:xml:ns:yang:1", 0);
- root->ns = ns;
-
- return root;
-
-error:
- lyxml_free(server_opts.ctx, root);
- return NULL;
-}
-
-API struct nc_server_error *
+API struct lyd_node *
nc_err_libyang(struct ly_ctx *ctx)
{
- struct nc_server_error *e;
- struct lyxml_elem *elem;
+ struct lyd_node *e, *other;
const char *str, *stri, *strj, *strk, *strl, *uniqi, *uniqj;
char *attr, *path;
int len;
- if (!ly_errno) {
+ if (!ly_errcode(ctx)) {
/* LY_SUCCESS */
return NULL;
- } else if (ly_errno == LY_EVALID) {
- switch (ly_vecode(ctx)) {
- /* RFC 6020 section 13 errors */
- case LYVE_NOUNIQ:
- e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
+ } else if ((ly_errcode(ctx) == LY_EVALID) && (ly_vecode(ctx) == LYVE_DATA)) {
+ /* RFC 7950 section 15 errors */
+ if (!strncmp(ly_errmsg(ctx), "Unique data", 11)) {
+ e = nc_err(ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
nc_err_set_app_tag(e, "data-not-unique");
nc_err_set_path(e, ly_errpath(ctx));
@@ -408,20 +523,19 @@
while (1) {
uniqj = strpbrk(uniqi, " \"");
- len = sprintf(path, "%.*s/%.*s", (int)(strj - stri), stri, (int)(uniqj - uniqi), uniqi);
- elem = nc_err_libyang_other_elem("non-unique", path, len);
- if (!elem) {
+ sprintf(path, "%.*s/%.*s", (int)(strj - stri), stri, (int)(uniqj - uniqi), uniqi);
+ if (lyd_new_opaq2(NULL, ctx, "non-unique", path, NULL, "urn:ietf:params:xml:ns:yang:1", &other)) {
free(path);
return e;
}
- nc_err_add_info_other(e, elem);
+ nc_err_add_info_other(e, other);
- len = sprintf(path, "%.*s/%.*s", (int)(strl - strk), strk, (int)(uniqj - uniqi), uniqi);
- elem = nc_err_libyang_other_elem("non-unique", path, len);
- if (!elem) {
+ sprintf(path, "%.*s/%.*s", (int)(strl - strk), strk, (int)(uniqj - uniqi), uniqi);
+ if (lyd_new_opaq2(NULL, ctx, "non-unique", path, NULL, "urn:ietf:params:xml:ns:yang:1", &other)) {
+ free(path);
return e;
}
- nc_err_add_info_other(e, elem);
+ nc_err_add_info_other(e, other);
if (uniqj[0] == '"') {
break;
@@ -429,34 +543,29 @@
uniqi = uniqj + 1;
}
free(path);
- break;
- case LYVE_NOMAX:
- e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
+ } else if (!strncmp(ly_errmsg(ctx), "Too many", 8)) {
+ e = nc_err(ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
nc_err_set_app_tag(e, "too-many-elements");
nc_err_set_path(e, ly_errpath(ctx));
- break;
- case LYVE_NOMIN:
- e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
+ } else if (!strncmp(ly_errmsg(ctx), "Too few", 7)) {
+ e = nc_err(ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
nc_err_set_app_tag(e, "too-few-elements");
nc_err_set_path(e, ly_errpath(ctx));
- break;
- case LYVE_NOMUST:
- e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
+ } else if (!strncmp(ly_errmsg(ctx), "Must condition", 14)) {
+ e = nc_err(ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
if (ly_errapptag(ctx)) {
nc_err_set_app_tag(e, ly_errapptag(ctx));
} else {
nc_err_set_app_tag(e, "must-violation");
}
nc_err_set_path(e, ly_errpath(ctx));
- break;
- case LYVE_NOREQINS:
- case LYVE_NOLEAFREF:
- e = nc_err(NC_ERR_DATA_MISSING);
+ } else if (!strncmp(ly_errmsg(ctx), "Invalid leafref", 15) ||
+ !strncmp(ly_errmsg(ctx), "Invalid instance-identifier", 27)) {
+ e = nc_err(ctx, NC_ERR_DATA_MISSING);
nc_err_set_app_tag(e, "instance-required");
nc_err_set_path(e, ly_errpath(ctx));
- break;
- case LYVE_NOMANDCHOICE:
- e = nc_err(NC_ERR_DATA_MISSING);
+ } else if (!strncmp(ly_errmsg(ctx), "Mandatory choice", 16)) {
+ e = nc_err(ctx, NC_ERR_DATA_MISSING);
nc_err_set_app_tag(e, "missing-choice");
nc_err_set_path(e, ly_errpath(ctx));
@@ -464,29 +573,28 @@
stri = strchr(str, '"');
stri++;
strj = strchr(stri, '"');
- elem = nc_err_libyang_other_elem("missing-choice", stri, strj - stri);
- if (elem) {
- nc_err_add_info_other(e, elem);
+ path = strndup(stri, strj - stri);
+
+ if (lyd_new_opaq2(NULL, ctx, "missing-choice", path, NULL, "urn:ietf:params:xml:ns:yang:1", &other)) {
+ free(path);
+ return e;
}
- break;
- case LYVE_INELEM:
+ nc_err_add_info_other(e, other);
+ free(path);
+ } else if (!strncmp(ly_errmsg(ctx), "Unexpected data", 15)) {
str = ly_errpath(ctx);
if (!str || !strcmp(str, "/")) {
- e = nc_err(NC_ERR_OP_NOT_SUPPORTED, NC_ERR_TYPE_APP);
+ e = nc_err(ctx, NC_ERR_OP_NOT_SUPPORTED, NC_ERR_TYPE_APP);
/* keep default message */
return e;
} else {
- e = nc_err(NC_ERR_UNKNOWN_ELEM, NC_ERR_TYPE_PROT, ly_errpath(ctx));
+ e = nc_err(ctx, NC_ERR_UNKNOWN_ELEM, NC_ERR_TYPE_PROT, ly_errpath(ctx));
}
- break;
- case LYVE_MISSELEM:
- case LYVE_INORDER:
- e = nc_err(NC_ERR_MISSING_ELEM, NC_ERR_TYPE_PROT, ly_errpath(ctx));
- break;
- case LYVE_INVAL:
- e = nc_err(NC_ERR_BAD_ELEM, NC_ERR_TYPE_PROT, ly_errpath(ctx));
- break;
- case LYVE_INATTR:
+ } else if (!strncmp(ly_errmsg(ctx), "Mandatory node", 14)) {
+ e = nc_err(ctx, NC_ERR_MISSING_ELEM, NC_ERR_TYPE_PROT, ly_errpath(ctx));
+ } else if (!strncmp(ly_errmsg(ctx), "Duplicate instance", 18) || !strncmp(ly_errmsg(ctx), "Data for both cases", 19)) {
+ e = nc_err(ctx, NC_ERR_BAD_ELEM, NC_ERR_TYPE_PROT, ly_errpath(ctx));
+ /*case LYVE_INATTR:
case LYVE_MISSATTR:
case LYVE_INMETA:
str = ly_errmsg(ctx);
@@ -499,60 +607,74 @@
strj--;
attr = strndup(stri, (strj - stri) + 1);
if (ly_vecode(ctx) == LYVE_INATTR) {
- e = nc_err(NC_ERR_UNKNOWN_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath(ctx));
+ e = nc_err(ctx, NC_ERR_UNKNOWN_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath(ctx));
} else if (ly_vecode(ctx) == LYVE_MISSATTR) {
- e = nc_err(NC_ERR_MISSING_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath(ctx));
- } else { /* LYVE_INMETA */
- e = nc_err(NC_ERR_BAD_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath(ctx));
+ e = nc_err(ctx, NC_ERR_MISSING_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath(ctx));
+ } else { * LYVE_INMETA *
+ e = nc_err(ctx, NC_ERR_BAD_ATTR, NC_ERR_TYPE_PROT, attr, ly_errpath(ctx));
}
free(attr);
- break;
- case LYVE_NOCONSTR:
- case LYVE_NOWHEN:
- e = nc_err(NC_ERR_INVALID_VALUE, NC_ERR_TYPE_PROT);
- /* LYVE_NOCONSTR (length, range, pattern) can have a specific error-app-tag */
+ break;*/
+ } else if (!strncmp(ly_errmsg(ctx), "When condition", 14) || !strncmp(ly_errmsg(ctx), "Unsatisfied pattern", 19) ||
+ !strncmp(ly_errmsg(ctx), "Unsatisfied length", 18) || !strncmp(ly_errmsg(ctx), "Unsatisfied range", 17)) {
+ e = nc_err(ctx, NC_ERR_INVALID_VALUE, NC_ERR_TYPE_PROT);
+ /* length, range, pattern can have a specific error-app-tag */
if (ly_errapptag(ctx)) {
nc_err_set_app_tag(e, ly_errapptag(ctx));
}
nc_err_set_path(e, ly_errpath(ctx));
- break;
- default:
- e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
- break;
+ } else {
+ e = nc_err(ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
}
} else {
/* non-validation (internal) error */
- e = nc_err(NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
+ e = nc_err(ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
}
nc_err_set_msg(e, ly_errmsg(ctx), "en");
return e;
}
API NC_ERR_TYPE
-nc_err_get_type(const struct nc_server_error *err)
+nc_err_get_type(const struct lyd_node *err)
{
+ struct lyd_node *match;
+
if (!err) {
ERRARG("err");
return 0;
}
- return err->type;
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-type", &match);
+ if (match) {
+ return nc_err_str2type(((struct lyd_node_opaq *)match)->value);
+ }
+
+ return 0;
}
API NC_ERR
-nc_err_get_tag(const struct nc_server_error *err)
+nc_err_get_tag(const struct lyd_node *err)
{
+ struct lyd_node *match;
+
if (!err) {
ERRARG("err");
return 0;
}
- return err->tag;
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-tag", &match);
+ if (match) {
+ return nc_err_str2tag(((struct lyd_node_opaq *)match)->value);
+ }
+
+ return 0;
}
API int
-nc_err_set_app_tag(struct nc_server_error *err, const char *error_app_tag)
+nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
{
+ struct lyd_node *match;
+
if (!err) {
ERRARG("err");
return -1;
@@ -561,28 +683,42 @@
return -1;
}
- if (err->apptag) {
- lydict_remove(server_opts.ctx, err->apptag);
+ /* remove previous node */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
+ if (match) {
+ lyd_free_tree(match);
}
- err->apptag = lydict_insert(server_opts.ctx, error_app_tag, 0);
+
+ if (lyd_new_opaq2(err, NULL, "error-app-tag", error_app_tag, NULL, NC_NS_BASE, NULL)) {
+ return -1;
+ }
return 0;
}
API const char *
-nc_err_get_app_tag(const struct nc_server_error *err)
+nc_err_get_app_tag(const struct lyd_node *err)
{
+ struct lyd_node *match;
+
if (!err) {
ERRARG("err");
return NULL;
}
- return err->apptag;
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
+ if (match) {
+ return ((struct lyd_node_opaq *)match)->value;
+ }
+
+ return NULL;
}
API int
-nc_err_set_path(struct nc_server_error *err, const char *error_path)
+nc_err_set_path(struct lyd_node *err, const char *error_path)
{
+ struct lyd_node *match;
+
if (!err) {
ERRARG("err");
return -1;
@@ -591,28 +727,43 @@
return -1;
}
- if (err->path) {
- lydict_remove(server_opts.ctx, err->path);
+ /* remove previous node */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
+ if (match) {
+ lyd_free_tree(match);
}
- err->path = lydict_insert(server_opts.ctx, error_path, 0);
+
+ if (lyd_new_opaq2(err, NULL, "error-path", error_path, NULL, NC_NS_BASE, NULL)) {
+ return -1;
+ }
return 0;
}
API const char *
-nc_err_get_path(const struct nc_server_error *err)
+nc_err_get_path(const struct lyd_node *err)
{
+ struct lyd_node *match;
+
if (!err) {
ERRARG("err");
return 0;
}
- return err->path;
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
+ if (match) {
+ return ((struct lyd_node_opaq *)match)->value;
+ }
+
+ return NULL;
}
API int
-nc_err_set_msg(struct nc_server_error *err, const char *error_message, const char *lang)
+nc_err_set_msg(struct lyd_node *err, const char *error_message, const char *lang)
{
+ struct lyd_node *match;
+ struct lyd_attr *attr;
+
if (!err) {
ERRARG("err");
return -1;
@@ -621,47 +772,77 @@
return -1;
}
- if (err->message) {
- lydict_remove(server_opts.ctx, err->message);
+ /* remove previous message */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
+ if (match) {
+ lyd_free_tree(match);
}
- err->message = lydict_insert(server_opts.ctx, error_message, 0);
- if (err->message_lang) {
- lydict_remove(server_opts.ctx, err->message_lang);
+ if (lyd_new_opaq2(err, NULL, "error-message", error_message, NULL, NC_NS_BASE, &match)) {
+ return -1;
}
- if (lang) {
- err->message_lang = lydict_insert(server_opts.ctx, lang, 0);
+ if (lang && lyd_new_attr(match, NULL, "xml:lang", lang, &attr)) {
+ lyd_free_tree(match);
+ return -1;
}
return 0;
}
API const char *
-nc_err_get_msg(const struct nc_server_error *err)
+nc_err_get_msg(const struct lyd_node *err)
{
+ struct lyd_node *match;
+
if (!err) {
ERRARG("err");
- return 0;
+ return NULL;
}
- return err->message;
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
+ if (match) {
+ return ((struct lyd_node_opaq *)match)->value;
+ }
+
+ return NULL;
}
API int
-nc_err_set_sid(struct nc_server_error *err, uint32_t session_id)
+nc_err_set_sid(struct lyd_node *err, uint32_t session_id)
{
+ struct lyd_node *match, *info;
+ char buf[22];
+
if (!err) {
ERRARG("err");
return -1;
}
- err->sid = session_id;
+ /* find error-info */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
+ if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
+ return -1;
+ }
+
+ /* remove previous node */
+ lyd_find_sibling_opaq_next(lyd_child(info), "session-id", &match);
+ if (match) {
+ lyd_free_tree(match);
+ }
+
+ sprintf(buf, "%" PRIu32, session_id);
+ if (lyd_new_opaq2(info, NULL, "session-id", buf, NULL, NC_NS_BASE, NULL)) {
+ return -1;
+ }
+
return 0;
}
API int
-nc_err_add_bad_attr(struct nc_server_error *err, const char *attr_name)
+nc_err_add_bad_attr(struct lyd_node *err, const char *attr_name)
{
+ struct lyd_node *info;
+
if (!err) {
ERRARG("err");
return -1;
@@ -670,20 +851,24 @@
return -1;
}
- ++err->attr_count;
- err->attr = nc_realloc(err->attr, err->attr_count * sizeof *err->attr);
- if (!err->attr) {
- ERRMEM;
+ /* find error-info */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
+ if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
return -1;
}
- err->attr[err->attr_count - 1] = lydict_insert(server_opts.ctx, attr_name, 0);
+
+ if (lyd_new_opaq2(info, NULL, "bad-attribute", attr_name, NULL, NC_NS_BASE, NULL)) {
+ return -1;
+ }
return 0;
}
API int
-nc_err_add_bad_elem(struct nc_server_error *err, const char *elem_name)
+nc_err_add_bad_elem(struct lyd_node *err, const char *elem_name)
{
+ struct lyd_node *info;
+
if (!err) {
ERRARG("err");
return -1;
@@ -692,20 +877,24 @@
return -1;
}
- ++err->elem_count;
- err->elem = nc_realloc(err->elem, err->elem_count * sizeof *err->elem);
- if (!err->elem) {
- ERRMEM;
+ /* find error-info */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
+ if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
return -1;
}
- err->elem[err->elem_count - 1] = lydict_insert(server_opts.ctx, elem_name, 0);
+
+ if (lyd_new_opaq2(info, NULL, "bad-element", elem_name, NULL, NC_NS_BASE, NULL)) {
+ return -1;
+ }
return 0;
}
API int
-nc_err_add_bad_ns(struct nc_server_error *err, const char *ns_name)
+nc_err_add_bad_ns(struct lyd_node *err, const char *ns_name)
{
+ struct lyd_node *info;
+
if (!err) {
ERRARG("err");
return -1;
@@ -714,20 +903,24 @@
return -1;
}
- ++err->ns_count;
- err->ns = nc_realloc(err->ns, err->ns_count * sizeof *err->ns);
- if (!err->ns) {
- ERRMEM;
+ /* find error-info */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
+ if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
return -1;
}
- err->ns[err->ns_count - 1] = lydict_insert(server_opts.ctx, ns_name, 0);
+
+ if (lyd_new_opaq2(info, NULL, "bad-namespace", ns_name, NULL, NC_NS_BASE, NULL)) {
+ return -1;
+ }
return 0;
}
API int
-nc_err_add_info_other(struct nc_server_error *err, struct lyxml_elem *other)
+nc_err_add_info_other(struct lyd_node *err, struct lyd_node *other)
{
+ struct lyd_node *info;
+
if (!err) {
ERRARG("err");
return -1;
@@ -736,25 +929,26 @@
return -1;
}
- ++err->other_count;
- err->other = nc_realloc(err->other, err->other_count * sizeof *err->other);
- if (!err->other) {
- ERRMEM;
+ /* find error-info */
+ lyd_find_sibling_opaq_next(lyd_child(err), "error-info", &info);
+ if (!info && lyd_new_opaq2(err, NULL, "error-info", NULL, NULL, NC_NS_BASE, &info)) {
return -1;
}
- err->other[err->other_count - 1] = other;
+
+ lyd_insert_child(info, other);
+
return 0;
}
void
-nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx)
+nc_server_rpc_free(struct nc_server_rpc *rpc)
{
if (!rpc) {
return;
}
- lyxml_free(ctx, rpc->root);
- lyd_free(rpc->tree);
+ lyd_free_tree(rpc->envp);
+ lyd_free_tree(rpc->rpc);
free(rpc);
}
@@ -762,7 +956,6 @@
API void
nc_server_reply_free(struct nc_server_reply *reply)
{
- uint32_t i;
struct nc_server_reply_data *data_rpl;
struct nc_server_reply_error *error_rpl;
@@ -774,7 +967,7 @@
case NC_RPL_DATA:
data_rpl = (struct nc_server_reply_data *)reply;
if (data_rpl->free) {
- lyd_free_withsiblings(data_rpl->data);
+ lyd_free_siblings(data_rpl->data);
}
break;
case NC_RPL_OK:
@@ -782,10 +975,7 @@
break;
case NC_RPL_ERROR:
error_rpl = (struct nc_server_reply_error *)reply;
- for (i = 0; i < error_rpl->count; ++i) {
- nc_err_free(error_rpl->err[i]);
- }
- free(error_rpl->err);
+ lyd_free_siblings(error_rpl->err);
break;
default:
break;
@@ -793,44 +983,12 @@
free(reply);
}
-API void
-nc_err_free(struct nc_server_error *err)
-{
- uint32_t i;
-
- if (!err) {
- return;
- }
-
- lydict_remove(server_opts.ctx, err->apptag);
- lydict_remove(server_opts.ctx, err->path);
- lydict_remove(server_opts.ctx, err->message);
- lydict_remove(server_opts.ctx, err->message_lang);
- for (i = 0; i < err->attr_count; ++i) {
- lydict_remove(server_opts.ctx, err->attr[i]);
- }
- free(err->attr);
- for (i = 0; i < err->elem_count; ++i) {
- lydict_remove(server_opts.ctx, err->elem[i]);
- }
- free(err->elem);
- for (i = 0; i < err->ns_count; ++i) {
- lydict_remove(server_opts.ctx, err->ns[i]);
- }
- free(err->ns);
- for (i = 0; i < err->other_count; ++i) {
- lyxml_free(server_opts.ctx, err->other[i]);
- }
- free(err->other);
- free(err);
-}
-
API struct nc_server_notif *
-nc_server_notif_new(struct lyd_node* event, char *eventtime, NC_PARAMTYPE paramtype)
+nc_server_notif_new(struct lyd_node *event, char *eventtime, NC_PARAMTYPE paramtype)
{
struct nc_server_notif *ntf;
struct lyd_node *elem;
- bool found_notif = false;
+ int found;
if (!event) {
ERRARG("event");
@@ -841,32 +999,15 @@
}
/* check that there is a notification */
- for (elem = event; elem && !found_notif; elem = elem->child) {
-next_node:
- switch (elem->schema->nodetype) {
- case LYS_LEAF:
- /* key, skip it */
- elem = elem->next;
- if (!elem) {
- /* error */
- ERRARG("event");
- return NULL;
- }
- goto next_node;
- case LYS_CONTAINER:
- case LYS_LIST:
- /* ok */
+ found = 0;
+ LYD_TREE_DFS_BEGIN(event, elem) {
+ if (elem->schema->nodetype == LYS_NOTIF) {
+ found = 1;
break;
- case LYS_NOTIF:
- found_notif = true;
- break;
- default:
- /* error */
- ERRARG("event");
- return NULL;
}
+ LYD_TREE_DFS_END(event, elem);
}
- if (!found_notif) {
+ if (!found) {
ERRARG("event");
return NULL;
}
@@ -874,10 +1015,13 @@
ntf = malloc(sizeof *ntf);
if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
ntf->eventtime = strdup(eventtime);
- ntf->tree = lyd_dup(event, 1);
+ if (lyd_dup_single(event, NULL, LYD_DUP_RECURSIVE, &ntf->ntf)) {
+ free(ntf);
+ return NULL;
+ }
} else {
ntf->eventtime = eventtime;
- ntf->tree = event;
+ ntf->ntf = event;
}
ntf->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
@@ -892,7 +1036,7 @@
}
if (notif->free) {
- lyd_free(notif->tree);
+ lyd_free_tree(notif->ntf);
free(notif->eventtime);
}
free(notif);