messages FEATURE support for yang-push RPCs
diff --git a/src/messages_client.c b/src/messages_client.c
index 064ccfe..817a60f 100644
--- a/src/messages_client.c
+++ b/src/messages_client.c
@@ -762,6 +762,251 @@
return (struct nc_rpc *)rpc;
}
+API struct nc_rpc *
+nc_rpc_establishpush_periodic(const char *datastore, const char *filter, const char *stop_time, const char *encoding,
+ uint32_t period, const char *anchor_time, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_establishpush *rpc;
+
+ if (!datastore) {
+ ERRARG("datastore");
+ return NULL;
+ } else if (!period) {
+ ERRARG("period");
+ return NULL;
+ }
+
+ if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+ ERR("Filter is not an XML subtree, an XPath expression, not a filter reference (invalid first char '%c').", filter[0]);
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_ESTABLISHPUSH;
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->datastore = strdup(datastore);
+ } else {
+ rpc->datastore = (char *)datastore;
+ }
+ if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->filter = strdup(filter);
+ } else {
+ rpc->filter = (char *)filter;
+ }
+ if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->stop = strdup(stop_time);
+ } else {
+ rpc->stop = (char *)stop_time;
+ }
+ if (encoding && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->encoding = strdup(encoding);
+ } else {
+ rpc->encoding = (char *)encoding;
+ }
+ rpc->periodic = 1;
+ rpc->period = period;
+ if (anchor_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->anchor_time = strdup(anchor_time);
+ } else {
+ rpc->anchor_time = (char *)anchor_time;
+ }
+ rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_establishpush_onchange(const char *datastore, const char *filter, const char *stop_time, const char *encoding,
+ uint32_t dampening_period, int sync_on_start, const char **excluded_change, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_establishpush *rpc;
+ uint32_t i;
+
+ if (!datastore) {
+ ERRARG("datastore");
+ return NULL;
+ }
+
+ if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+ ERR("Filter is not an XML subtree, an XPath expression, not a filter reference (invalid first char '%c').", filter[0]);
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_ESTABLISHPUSH;
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->datastore = strdup(datastore);
+ } else {
+ rpc->datastore = (char *)datastore;
+ }
+ if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->filter = strdup(filter);
+ } else {
+ rpc->filter = (char *)filter;
+ }
+ if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->stop = strdup(stop_time);
+ } else {
+ rpc->stop = (char *)stop_time;
+ }
+ if (encoding && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->encoding = strdup(encoding);
+ } else {
+ rpc->encoding = (char *)encoding;
+ }
+ rpc->periodic = 0;
+ rpc->dampening_period = dampening_period;
+ rpc->sync_on_start = sync_on_start;
+ if (excluded_change && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->excluded_change = NULL;
+ for (i = 0; excluded_change[i]; ++i) {
+ rpc->excluded_change = realloc(rpc->excluded_change, (i + 2) * sizeof *rpc->excluded_change);
+ rpc->excluded_change[i] = strdup(excluded_change[i]);
+ rpc->excluded_change[i + 1] = NULL;
+ }
+ } else {
+ rpc->excluded_change = (char **)excluded_change;
+ }
+ rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_modifypush_periodic(uint32_t id, const char *datastore, const char *filter, const char *stop_time, uint32_t period,
+ const char *anchor_time, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_modifypush *rpc;
+
+ if (!id) {
+ ERRARG("id");
+ return NULL;
+ } else if (!datastore) {
+ ERRARG("datastore");
+ return NULL;
+ }
+
+ if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+ ERR("Filter is not an XML subtree, an XPath expression, not a filter reference (invalid first char '%c').", filter[0]);
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_MODIFYPUSH;
+ rpc->id = id;
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->datastore = strdup(datastore);
+ } else {
+ rpc->datastore = (char *)datastore;
+ }
+ if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->filter = strdup(filter);
+ } else {
+ rpc->filter = (char *)filter;
+ }
+ if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->stop = strdup(stop_time);
+ } else {
+ rpc->stop = (char *)stop_time;
+ }
+ rpc->periodic = 1;
+ rpc->period = period;
+ if (anchor_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->anchor_time = strdup(anchor_time);
+ } else {
+ rpc->anchor_time = (char *)anchor_time;
+ }
+ rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_modifypush_onchange(uint32_t id, const char *datastore, const char *filter, const char *stop_time,
+ uint32_t dampening_period, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_modifypush *rpc;
+
+ if (!id) {
+ ERRARG("id");
+ return NULL;
+ } else if (!datastore) {
+ ERRARG("datastore");
+ return NULL;
+ }
+
+ if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+ ERR("Filter is not an XML subtree, an XPath expression, not a filter reference (invalid first char '%c').", filter[0]);
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_MODIFYPUSH;
+ rpc->id = id;
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->datastore = strdup(datastore);
+ } else {
+ rpc->datastore = (char *)datastore;
+ }
+ if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->filter = strdup(filter);
+ } else {
+ rpc->filter = (char *)filter;
+ }
+ if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->stop = strdup(stop_time);
+ } else {
+ rpc->stop = (char *)stop_time;
+ }
+ rpc->periodic = 0;
+ rpc->dampening_period = dampening_period;
+ rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_resyncsub(uint32_t id)
+{
+ struct nc_rpc_resyncsub *rpc;
+
+ if (!id) {
+ ERRARG("id");
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_RESYNCSUB;
+ rpc->id = id;
+
+ return (struct nc_rpc *)rpc;
+}
+
API void
nc_rpc_free(struct nc_rpc *rpc)
{
@@ -780,6 +1025,8 @@
struct nc_rpc_editdata *rpc_editdata;
struct nc_rpc_establishsub *rpc_establishsub;
struct nc_rpc_modifysub *rpc_modifysub;
+ struct nc_rpc_establishpush *rpc_establishpush;
+ struct nc_rpc_modifypush *rpc_modifypush;
int i;
if (!rpc) {
@@ -900,6 +1147,36 @@
free(rpc_modifysub->stop);
}
break;
+ case NC_RPC_ESTABLISHPUSH:
+ rpc_establishpush = (struct nc_rpc_establishpush *)rpc;
+ if (rpc_establishpush->free) {
+ free(rpc_establishpush->datastore);
+ free(rpc_establishpush->filter);
+ free(rpc_establishpush->stop);
+ free(rpc_establishpush->encoding);
+ if (rpc_establishpush->periodic) {
+ free(rpc_establishpush->anchor_time);
+ } else {
+ if (rpc_establishpush->excluded_change) {
+ for (i = 0; rpc_establishpush->excluded_change[i]; ++i) {
+ free(rpc_establishpush->excluded_change[i]);
+ }
+ free(rpc_establishpush->excluded_change);
+ }
+ }
+ }
+ break;
+ case NC_RPC_MODIFYPUSH:
+ rpc_modifypush = (struct nc_rpc_modifypush *)rpc;
+ if (rpc_modifypush->free) {
+ free(rpc_modifypush->datastore);
+ free(rpc_modifypush->filter);
+ free(rpc_modifypush->stop);
+ if (rpc_modifypush->periodic) {
+ free(rpc_modifypush->anchor_time);
+ }
+ }
+ break;
case NC_RPC_UNKNOWN:
case NC_RPC_LOCK:
case NC_RPC_UNLOCK:
@@ -907,6 +1184,7 @@
case NC_RPC_DISCARD:
case NC_RPC_DELETESUB:
case NC_RPC_KILLSUB:
+ case NC_RPC_RESYNCSUB:
/* nothing special needed */
break;
}
diff --git a/src/messages_client.h b/src/messages_client.h
index 0504bc3..6feecab 100644
--- a/src/messages_client.h
+++ b/src/messages_client.h
@@ -70,6 +70,11 @@
NC_RPC_MODIFYSUB, /**< \<modify-subscription\> RPC. */
NC_RPC_DELETESUB, /**< \<delete-subscription\> RPC. */
NC_RPC_KILLSUB, /**< \<kill-subscription\> RPC. */
+
+ /* ietf-yang-push */
+ NC_RPC_ESTABLISHPUSH, /**< \<establish-subscription\> RPC with augments. */
+ NC_RPC_MODIFYPUSH, /**< \<modify-subscription\> RPC with augments. */
+ NC_RPC_RESYNCSUB, /**< \<resync-subscription\> RPC. */
} NC_RPC_TYPE;
/**
@@ -448,6 +453,89 @@
struct nc_rpc *nc_rpc_killsub(uint32_t id);
/**
+ * @brief Create NETCONF RPC \<establish-subscription\> with augments from ietf-yang-push for a periodic subscription
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] datastore Source datastore, foreign identity so a module name prefix is required.
+ * @param[in] filter Optional filter data, an XML subtree, XPath expression (with JSON prefixes),
+ * or filter reference, selected based on the first character.
+ * @param[in] stop_time Optional YANG datetime identifying the end of the subscription.
+ * @param[in] encoding Optional specific encoding to use.
+ * @param[in] period Subscription period in centiseconds (0.01s).
+ * @param[in] anchor_time Optional anchor datetime for the period.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_establishpush_periodic(const char *datastore, const char *filter, const char *stop_time,
+ const char *encoding, uint32_t period, const char *anchor_time, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<establish-subscription\> with augments from ietf-yang-push for an on-change subscription
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] datastore Source datastore, foreign identity so a module name prefix is required.
+ * @param[in] filter Optional filter data, an XML subtree, XPath expression (with JSON prefixes),
+ * or filter reference, selected based on the first character.
+ * @param[in] stop_time Optional YANG datetime identifying the end of the subscription.
+ * @param[in] encoding Optional specific encoding to use.
+ * @param[in] dampening_period Optional dampening period of the notifications.
+ * @param[in] sync_on_start Whether to send a full push-update notification on subscription start.
+ * @param[in] excluded_change Optional NULL-terminated array of excluded changes.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_establishpush_onchange(const char *datastore, const char *filter, const char *stop_time,
+ const char *encoding, uint32_t dampening_period, int sync_on_start, const char **excluded_change,
+ NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<modify-subscription\> with augments from ietf-yang-push for a periodic subscription
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] id Subscription ID to modify.
+ * @param[in] datastore Source datastore, foreign identity so a module name prefix is required.
+ * @param[in] filter Optional filter data, an XML subtree, XPath expression (with JSON prefixes),
+ * or filter reference, selected based on the first character.
+ * @param[in] stop_time Optional YANG datetime identifying the end of the subscription.
+ * @param[in] period Subscription period in centiseconds (0.01s).
+ * @param[in] anchor_time Optional anchor datetime for the period.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_modifypush_periodic(uint32_t id, const char *datastore, const char *filter, const char *stop_time,
+ uint32_t period, const char *anchor_time, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<modify-subscription\> with augments from ietf-yang-push for an on-change subscription
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] id Subscription ID to modify.
+ * @param[in] datastore Source datastore, foreign identity so a module name prefix is required.
+ * @param[in] filter Optional filter data, an XML subtree, XPath expression (with JSON prefixes),
+ * or filter reference, selected based on the first character.
+ * @param[in] stop_time Optional YANG datetime identifying the end of the subscription.
+ * @param[in] dampening_period Optional dampening period of the notifications.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_modifypush_onchange(uint32_t id, const char *datastore, const char *filter, const char *stop_time,
+ uint32_t dampening_period, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<resync-subscription\>
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] id Subscription ID to resync.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_resyncsub(uint32_t id);
+
+/**
* @brief Free the NETCONF RPC object.
*
* @param[in] rpc Object to free.
diff --git a/src/messages_p.h b/src/messages_p.h
index b71f69d..2d9cd85 100644
--- a/src/messages_p.h
+++ b/src/messages_p.h
@@ -213,6 +213,49 @@
uint32_t id;
};
+struct nc_rpc_establishpush {
+ NC_RPC_TYPE type; /**< NC_RPC_ESTABLISHPUSH */
+ char *datastore;
+ char *filter; /**< XML subtree (starts with '<'), an XPath (starts with '/'), or reference (start with alpha) */
+ char *stop;
+ char *encoding;
+ int periodic;
+ union {
+ struct {
+ uint32_t period;
+ char *anchor_time;
+ };
+ struct {
+ uint32_t dampening_period;
+ int sync_on_start;
+ char **excluded_change;
+ };
+ };
+ char free;
+};
+
+struct nc_rpc_modifypush {
+ NC_RPC_TYPE type; /**< NC_RPC_MODIFYPUSH */
+ uint32_t id;
+ char *datastore;
+ char *filter; /**< XML subtree (starts with '<'), an XPath (starts with '/'), or reference (start with alpha) */
+ char *stop;
+ int periodic;
+ union {
+ struct {
+ uint32_t period;
+ char *anchor_time;
+ };
+ uint32_t dampening_period;
+ };
+ char free;
+};
+
+struct nc_rpc_resyncsub {
+ NC_RPC_TYPE type; /**< NC_RPC_RESYNCSUB */
+ uint32_t id;
+};
+
void nc_server_rpc_free(struct nc_server_rpc *rpc);
void nc_client_err_clean(struct nc_err *err, struct ly_ctx *ctx);
diff --git a/src/session_client.c b/src/session_client.c
index bdcfc4b..c7f6c15 100644
--- a/src/session_client.c
+++ b/src/session_client.c
@@ -1752,8 +1752,7 @@
struct ly_in *in;
struct lyd_node *tree, *op2;
const struct lys_module *mod;
- const char *module_name = NULL;
- const char *rpc_name = NULL;
+ const char *module_name = NULL, *rpc_name = NULL, *module_check = NULL;
switch (rpc->type) {
case NC_RPC_ACT_GENERIC:
@@ -1864,6 +1863,20 @@
module_name = "ietf-subscribed-notifications";
rpc_name = "kill-subscription";
break;
+ case NC_RPC_ESTABLISHPUSH:
+ module_name = "ietf-subscribed-notifications";
+ rpc_name = "establish-subscription";
+ module_check = "ietf-yang-push";
+ break;
+ case NC_RPC_MODIFYPUSH:
+ module_name = "ietf-subscribed-notifications";
+ rpc_name = "modify-subscription";
+ module_check = "ietf-yang-push";
+ break;
+ case NC_RPC_RESYNCSUB:
+ module_name = "ietf-yang-push";
+ rpc_name = "resync-subscription";
+ break;
case NC_RPC_UNKNOWN:
lyrc = LY_EINT;
break;
@@ -1879,6 +1892,12 @@
/* create the operation node */
lyrc = lyd_new_inner(NULL, mod, rpc_name, 0, op);
}
+ if (module_check) {
+ if (!ly_ctx_get_module_implemented(session->ctx, module_check)) {
+ ERR("Session %u: missing \"%s\" schema in the context.", session->id, module_check);
+ return -1;
+ }
+ }
if (lyrc) {
return -1;
@@ -2172,8 +2191,11 @@
struct nc_rpc_modifysub *rpc_modsub;
struct nc_rpc_deletesub *rpc_delsub;
struct nc_rpc_killsub *rpc_killsub;
- struct lyd_node *data, *node;
- const struct lys_module *mod = NULL, *ietfncwd;
+ struct nc_rpc_establishpush *rpc_estpush;
+ struct nc_rpc_modifypush *rpc_modpush;
+ struct nc_rpc_resyncsub *rpc_resyncsub;
+ struct lyd_node *data, *node, *cont;
+ const struct lys_module *mod = NULL, *mod2 = NULL, *ietfncwd;
LY_ERR lyrc;
int i;
char str[11];
@@ -2247,6 +2269,26 @@
return NC_MSG_ERROR;
}
break;
+ case NC_RPC_ESTABLISHPUSH:
+ case NC_RPC_MODIFYPUSH:
+ mod = ly_ctx_get_module_implemented(session->ctx, "ietf-subscribed-notifications");
+ if (!mod) {
+ ERR("Session %u: missing \"ietf-subscribed-notifications\" schema in the context.", session->id);
+ return NC_MSG_ERROR;
+ }
+ mod2 = ly_ctx_get_module_implemented(session->ctx, "ietf-yang-push");
+ if (!mod2) {
+ ERR("Session %u: missing \"ietf-yang-push\" schema in the context.", session->id);
+ return NC_MSG_ERROR;
+ }
+ break;
+ case NC_RPC_RESYNCSUB:
+ mod = ly_ctx_get_module_implemented(session->ctx, "ietf-yang-push");
+ if (!mod) {
+ ERR("Session %u: missing \"ietf-yang-push\" schema in the context.", session->id);
+ return NC_MSG_ERROR;
+ }
+ break;
case NC_RPC_UNKNOWN:
ERRINT;
return NC_MSG_ERROR;
@@ -2793,6 +2835,175 @@
}
break;
+ case NC_RPC_ESTABLISHPUSH:
+ rpc_estpush = (struct nc_rpc_establishpush *)rpc;
+
+ lyd_new_inner(NULL, mod, "establish-subscription", 0, &data);
+
+ if (lyd_new_term(data, mod2, "datastore", rpc_estpush->datastore, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_estpush->filter) {
+ if (!rpc_estpush->filter[0] || (rpc_estpush->filter[0] == '<')) {
+ lyd_new_any(data, mod2, "datastore-subtree-filter", rpc_estpush->filter, 0, LYD_ANYDATA_XML, 0, &node);
+ } else if (rpc_estpush->filter[0] == '/') {
+ lyd_new_term(data, mod2, "datastore-xpath-filter", rpc_estpush->filter, 0, &node);
+ } else {
+ lyd_new_term(data, mod2, "selection-filter-ref", rpc_estpush->filter, 0, &node);
+ }
+ if (!node) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_estpush->stop) {
+ if (lyd_new_term(data, mod, "stop-time", rpc_estpush->stop, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_estpush->encoding) {
+ if (lyd_new_term(data, mod, "encoding", rpc_estpush->encoding, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_estpush->periodic) {
+ if (lyd_new_inner(data, mod2, "periodic", 0, &cont)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ sprintf(str, "%" PRIu32, rpc_estpush->period);
+ if (lyd_new_term(cont, mod2, "period", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_estpush->anchor_time) {
+ if (lyd_new_term(cont, mod2, "anchor-time", rpc_estpush->anchor_time, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ } else {
+ if (lyd_new_inner(data, mod2, "on-change", 0, &cont)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_estpush->dampening_period) {
+ sprintf(str, "%" PRIu32, rpc_estpush->dampening_period);
+ if (lyd_new_term(cont, mod2, "dampening-period", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (lyd_new_term(cont, mod2, "sync-on-start", rpc_estpush->sync_on_start ? "true" : "false", 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_estpush->excluded_change) {
+ for (i = 0; rpc_estpush->excluded_change[i]; ++i) {
+ if (lyd_new_term(cont, mod2, "excluded-change", rpc_estpush->excluded_change[i], 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ }
+ }
+ break;
+
+ case NC_RPC_MODIFYPUSH:
+ rpc_modpush = (struct nc_rpc_modifypush *)rpc;
+
+ lyd_new_inner(NULL, mod, "modify-subscription", 0, &data);
+
+ sprintf(str, "%u", rpc_modpush->id);
+ if (lyd_new_term(data, mod, "id", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (lyd_new_term(data, mod2, "datastore", rpc_modpush->datastore, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_modpush->filter) {
+ if (!rpc_modpush->filter[0] || (rpc_modpush->filter[0] == '<')) {
+ lyd_new_any(data, mod2, "datastore-subtree-filter", rpc_modpush->filter, 0, LYD_ANYDATA_XML, 0, &node);
+ } else if (rpc_modpush->filter[0] == '/') {
+ lyd_new_term(data, mod2, "datastore-xpath-filter", rpc_modpush->filter, 0, &node);
+ } else {
+ lyd_new_term(data, mod2, "selection-filter-ref", rpc_modpush->filter, 0, &node);
+ }
+ if (!node) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_modpush->stop) {
+ if (lyd_new_term(data, mod, "stop-time", rpc_modpush->stop, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_modpush->periodic) {
+ if (lyd_new_inner(data, mod2, "periodic", 0, &cont)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ sprintf(str, "%" PRIu32, rpc_modpush->period);
+ if (lyd_new_term(cont, mod2, "period", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_modpush->anchor_time) {
+ if (lyd_new_term(cont, mod2, "anchor-time", rpc_modpush->anchor_time, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ } else {
+ if (lyd_new_inner(data, mod2, "on-change", 0, &cont)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_modpush->dampening_period) {
+ sprintf(str, "%" PRIu32, rpc_modpush->dampening_period);
+ if (lyd_new_term(cont, mod2, "dampening-period", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ }
+ break;
+
+ case NC_RPC_RESYNCSUB:
+ rpc_resyncsub = (struct nc_rpc_resyncsub *)rpc;
+
+ lyd_new_inner(NULL, mod, "resync-subscription", 0, &data);
+
+ sprintf(str, "%u", rpc_resyncsub->id);
+ if (lyd_new_term(data, mod, "id", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ break;
+
case NC_RPC_UNKNOWN:
ERRINT;
return NC_MSG_ERROR;