client messages FEATURE support for subscribed-notification RPCs
diff --git a/src/messages_client.c b/src/messages_client.c
index cb0a17c..064ccfe 100644
--- a/src/messages_client.c
+++ b/src/messages_client.c
@@ -3,7 +3,7 @@
* \author Radek Krejci <rkrejci@cesnet.cz>
* \brief libnetconf2 - NETCONF messages functions
*
- * Copyright (c) 2015 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2021 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -132,7 +132,7 @@
API struct nc_rpc *
nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
- NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype)
+ NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype)
{
struct nc_rpc_edit *rpc;
@@ -172,7 +172,7 @@
API struct nc_rpc *
nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source, const char *url_or_config_src,
- NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
+ NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
{
struct nc_rpc_copy *rpc;
@@ -338,7 +338,7 @@
API struct nc_rpc *
nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
- NC_PARAMTYPE paramtype)
+ NC_PARAMTYPE paramtype)
{
struct nc_rpc_commit *rpc;
@@ -476,7 +476,7 @@
API struct nc_rpc *
nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time, const char *stop_time,
- NC_PARAMTYPE paramtype)
+ NC_PARAMTYPE paramtype)
{
struct nc_rpc_subscribe *rpc;
@@ -519,8 +519,8 @@
API struct nc_rpc *
nc_rpc_getdata(const char *datastore, const char *filter, const char *config_filter, char **origin_filter,
- int origin_filter_count, int negated_origin_filter, uint16_t max_depth, int with_origin,
- NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
+ int origin_filter_count, int negated_origin_filter, uint16_t max_depth, int with_origin, NC_WD_MODE wd_mode,
+ NC_PARAMTYPE paramtype)
{
struct nc_rpc_getdata *rpc = NULL;
int i;
@@ -627,6 +627,141 @@
return (struct nc_rpc *)rpc;
}
+API struct nc_rpc *
+nc_rpc_establishsub(const char *filter, const char *stream_name, const char *start_time,
+ const char *stop_time, const char *encoding, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_establishsub *rpc;
+
+ if (!stream_name) {
+ ERRARG("stream_name");
+ 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_ESTABLISHSUB;
+ if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->filter = strdup(filter);
+ } else {
+ rpc->filter = (char *)filter;
+ }
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->stream = strdup(stream_name);
+ } else {
+ rpc->stream = (char *)stream_name;
+ }
+ if (start_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->start = strdup(start_time);
+ } else {
+ rpc->start = (char *)start_time;
+ }
+ 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->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_modifysub(uint32_t id, const char *filter, const char *stop_time, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_modifysub *rpc;
+
+ if (!id) {
+ ERRARG("id");
+ 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_MODIFYSUB;
+ rpc->id = id;
+ 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->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_deletesub(uint32_t id)
+{
+ struct nc_rpc_deletesub *rpc;
+
+ if (!id) {
+ ERRARG("id");
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_DELETESUB;
+ rpc->id = id;
+
+ return (struct nc_rpc *)rpc;
+}
+
+API struct nc_rpc *
+nc_rpc_killsub(uint32_t id)
+{
+ struct nc_rpc_killsub *rpc;
+
+ if (!id) {
+ ERRARG("id");
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_KILLSUB;
+ rpc->id = id;
+
+ return (struct nc_rpc *)rpc;
+}
+
API void
nc_rpc_free(struct nc_rpc *rpc)
{
@@ -643,6 +778,8 @@
struct nc_rpc_subscribe *rpc_subscribe;
struct nc_rpc_getdata *rpc_getdata;
struct nc_rpc_editdata *rpc_editdata;
+ struct nc_rpc_establishsub *rpc_establishsub;
+ struct nc_rpc_modifysub *rpc_modifysub;
int i;
if (!rpc) {
@@ -746,7 +883,30 @@
free(rpc_editdata->edit_cont);
}
break;
- default:
+ case NC_RPC_ESTABLISHSUB:
+ rpc_establishsub = (struct nc_rpc_establishsub *)rpc;
+ if (rpc_establishsub->free) {
+ free(rpc_establishsub->filter);
+ free(rpc_establishsub->stream);
+ free(rpc_establishsub->start);
+ free(rpc_establishsub->stop);
+ free(rpc_establishsub->encoding);
+ }
+ break;
+ case NC_RPC_MODIFYSUB:
+ rpc_modifysub = (struct nc_rpc_modifysub *)rpc;
+ if (rpc_modifysub->free) {
+ free(rpc_modifysub->filter);
+ free(rpc_modifysub->stop);
+ }
+ break;
+ case NC_RPC_UNKNOWN:
+ case NC_RPC_LOCK:
+ case NC_RPC_UNLOCK:
+ case NC_RPC_KILL:
+ case NC_RPC_DISCARD:
+ case NC_RPC_DELETESUB:
+ case NC_RPC_KILLSUB:
/* nothing special needed */
break;
}
diff --git a/src/messages_client.h b/src/messages_client.h
index 2a7281e..0504bc3 100644
--- a/src/messages_client.h
+++ b/src/messages_client.h
@@ -64,6 +64,12 @@
/* ietf-netconf-nmda */
NC_RPC_GETDATA, /**< \<get-data\> RPC. */
NC_RPC_EDITDATA, /**< \<edit-data\> RPC. */
+
+ /* ietf-subscribed-notifications */
+ NC_RPC_ESTABLISHSUB, /**< \<establish-subscription\> RPC. */
+ NC_RPC_MODIFYSUB, /**< \<modify-subscription\> RPC. */
+ NC_RPC_DELETESUB, /**< \<delete-subscription\> RPC. */
+ NC_RPC_KILLSUB, /**< \<kill-subscription\> RPC. */
} NC_RPC_TYPE;
/**
@@ -139,7 +145,13 @@
};
/**
+ * @struct nc_rpc
* @brief NETCONF client RPC object
+ *
+ * Note that any stored parameters are not checked for validity because it is performed later,
+ * while sending the RPC via a specific NETCONF session (::nc_send_rpc()) since the NETCONF
+ * capabilities of the session are needed for such a check. An RPC object can be sent via any
+ * NETCONF session which supports all the needed NETCONF capabilities for the RPC.
*/
struct nc_rpc;
@@ -166,11 +178,7 @@
/**
* @brief Create a generic NETCONF RPC or action from an XML string
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] xml_str NETCONF RPC data as an XML string.
* @param[in] paramtype How to further manage data parameters.
@@ -181,11 +189,7 @@
/**
* @brief Create NETCONF RPC \<get-config\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] source Source datastore being queried.
* @param[in] filter Optional filter data, an XML subtree or XPath expression (with JSON prefixes).
@@ -194,16 +198,12 @@
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
struct nc_rpc *nc_rpc_getconfig(NC_DATASTORE source, const char *filter, NC_WD_MODE wd_mode,
- NC_PARAMTYPE paramtype);
+ NC_PARAMTYPE paramtype);
/**
* @brief Create NETCONF RPC \<edit-config\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] target Target datastore being edited.
* @param[in] default_op Optional default operation.
@@ -214,16 +214,12 @@
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
struct nc_rpc *nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
- NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype);
+ NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype);
/**
* @brief Create NETCONF RPC \<copy-config\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] target Target datastore.
* @param[in] url_trg Used instead \p target if the target is an URL.
@@ -234,16 +230,12 @@
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
struct nc_rpc *nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source,
- const char *url_or_config_src, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
+ const char *url_or_config_src, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
/**
* @brief Create NETCONF RPC \<delete-config\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] target Target datastore to delete.
* @param[in] url Used instead \p target if the target is an URL.
@@ -255,11 +247,7 @@
/**
* @brief Create NETCONF RPC \<lock\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] target Target datastore of the operation.
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
@@ -269,11 +257,7 @@
/**
* @brief Create NETCONF RPC \<unlock\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] target Target datastore of the operation.
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
@@ -283,11 +267,7 @@
/**
* @brief Create NETCONF RPC \<get\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] filter Optional filter data, an XML subtree or XPath expression (with JSON prefixes).
* @param[in] wd_mode Optional with-defaults capability mode.
@@ -299,11 +279,7 @@
/**
* @brief Create NETCONF RPC \<kill-session\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] session_id Session ID of the session to kill.
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
@@ -313,11 +289,7 @@
/**
* @brief Create NETCONF RPC \<commit\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] confirmed Whether the commit is to be confirmed.
* @param[in] confirm_timeout Optional confirm timeout.
@@ -327,16 +299,12 @@
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
struct nc_rpc *nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
- NC_PARAMTYPE paramtype);
+ NC_PARAMTYPE paramtype);
/**
* @brief Create NETCONF RPC \<discard-changes\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
@@ -345,11 +313,7 @@
/**
* @brief Create NETCONF RPC \<cancel-commit\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] persist_id Optional identification string of a persistent confirmed commit.
* @param[in] paramtype How to further manage data parameters.
@@ -360,11 +324,7 @@
/**
* @brief Create NETCONF RPC \<validate\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] source Source datastore being validated.
* @param[in] url_or_config Used instead \p source if the source is an URL or a config.
@@ -376,11 +336,7 @@
/**
* @brief Create NETCONF RPC \<get-schema\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] identifier Requested model identifier.
* @param[in] version Optional model version, either YANG version (1.0/1.1) or revision date.
@@ -393,11 +349,7 @@
/**
* @brief Create NETCONF RPC \<create-subscription\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] stream_name Optional name of a NETCONF stream to subscribe to.
* @param[in] filter Optional filter data, an XML subtree or XPath expression (with JSON prefixes).
@@ -407,16 +359,12 @@
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
struct nc_rpc *nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time,
- const char *stop_time, NC_PARAMTYPE paramtype);
+ const char *stop_time, NC_PARAMTYPE paramtype);
/**
* @brief Create NETCONF RPC \<get-data\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * 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 or XPath expression (with JSON prefixes).
@@ -431,17 +379,13 @@
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
struct nc_rpc *nc_rpc_getdata(const char *datastore, const char *filter, const char *config_filter, char **origin_filter,
- int origin_filter_count, int neg_origin_filter, uint16_t max_depth, int with_origin,
- NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
+ int origin_filter_count, int neg_origin_filter, uint16_t max_depth, int with_origin, NC_WD_MODE wd_mode,
+ NC_PARAMTYPE paramtype);
/**
* @brief Create NETCONF RPC \<get-data\>
*
- * Note that functions to create any RPC object do not check validity of the provided
- * parameters. It is checked later while sending the RPC via a specific NETCONF session
- * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
- * check. Created object can be sent via any NETCONF session which supports all the
- * needed NETCONF capabilities for the RPC.
+ * For details, see ::nc_rpc.
*
* @param[in] datastore Source datastore, foreign identity so a module name prefix is required.
* @param[in] default_op Optional default operation.
@@ -450,7 +394,58 @@
* @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
*/
struct nc_rpc *nc_rpc_editdata(const char *datastore, NC_RPC_EDIT_DFLTOP default_op, const char *edit_content,
- NC_PARAMTYPE paramtype);
+ NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<establish-subscription\>
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @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] stream_name Name of a NETCONF stream to subscribe to.
+ * @param[in] start_time Optional YANG datetime identifying the start of the subscription.
+ * @param[in] stop_time Optional YANG datetime identifying the end of the subscription.
+ * @param[in] encoding Optional specific encoding to use.
+ * @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_establishsub(const char *filter, const char *stream_name, const char *start_time,
+ const char *stop_time, const char *encoding, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<modify-subscription\>
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] id Subscription ID to modify.
+ * @param[in] filter Optional new filter data, an XML subtree, XPath expression (with JSON prefixes),
+ * or filter reference, selected based on the first character.
+ * @param[in] stop_time Optional new YANG datetime identifying the end of the subscription.
+ * @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_modifysub(uint32_t id, const char *filter, const char *stop_time, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<delete-subscription\>
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] id Subscription ID to delete.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_deletesub(uint32_t id);
+
+/**
+ * @brief Create NETCONF RPC \<kill-subscription\>
+ *
+ * For details, see ::nc_rpc.
+ *
+ * @param[in] id Subscription ID to kill.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_killsub(uint32_t id);
/**
* @brief Free the NETCONF RPC object.
diff --git a/src/messages_p.h b/src/messages_p.h
index f7b5449..b71f69d 100644
--- a/src/messages_p.h
+++ b/src/messages_p.h
@@ -185,6 +185,34 @@
char free;
};
+struct nc_rpc_establishsub {
+ NC_RPC_TYPE type; /**< NC_RPC_ESTABLISHSUB */
+ char *filter; /**< XML subtree (starts with '<'), an XPath (starts with '/'), or reference (start with alpha) */
+ char *stream; /**< stream name */
+ char *start;
+ char *stop;
+ char *encoding;
+ char free;
+};
+
+struct nc_rpc_modifysub {
+ NC_RPC_TYPE type; /**< NC_RPC_MODIFYSUB */
+ uint32_t id;
+ char *filter; /**< XML subtree (starts with '<'), an XPath (starts with '/'), or reference (start with alpha) */
+ char *stop;
+ char free;
+};
+
+struct nc_rpc_deletesub {
+ NC_RPC_TYPE type; /**< NC_RPC_DELETESUB */
+ uint32_t id;
+};
+
+struct nc_rpc_killsub {
+ NC_RPC_TYPE type; /**< NC_RPC_KILLSUB */
+ 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 0606764..cd296ee 100644
--- a/src/session_client.c
+++ b/src/session_client.c
@@ -1846,7 +1846,23 @@
module_name = "ietf-netconf-nmda";
rpc_name = "edit-data";
break;
- default:
+ case NC_RPC_ESTABLISHSUB:
+ module_name = "ietf-subscribed-notifications";
+ rpc_name = "establish-subscription";
+ break;
+ case NC_RPC_MODIFYSUB:
+ module_name = "ietf-subscribed-notifications";
+ rpc_name = "modify-subscription";
+ break;
+ case NC_RPC_DELETESUB:
+ module_name = "ietf-subscribed-notifications";
+ rpc_name = "delete-subscription";
+ break;
+ case NC_RPC_KILLSUB:
+ module_name = "ietf-subscribed-notifications";
+ rpc_name = "kill-subscription";
+ break;
+ case NC_RPC_UNKNOWN:
lyrc = LY_EINT;
break;
}
@@ -2148,6 +2164,10 @@
struct nc_rpc_subscribe *rpc_sub;
struct nc_rpc_getdata *rpc_getd;
struct nc_rpc_editdata *rpc_editd;
+ struct nc_rpc_establishsub *rpc_estsub;
+ 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;
LY_ERR lyrc;
@@ -2213,6 +2233,16 @@
return NC_MSG_ERROR;
}
break;
+ case NC_RPC_ESTABLISHSUB:
+ case NC_RPC_MODIFYSUB:
+ case NC_RPC_DELETESUB:
+ case NC_RPC_KILLSUB:
+ 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;
+ }
+ break;
case NC_RPC_UNKNOWN:
ERRINT;
return NC_MSG_ERROR;
@@ -2538,7 +2568,7 @@
lyd_new_inner(NULL, mod, "create-subscription", 0, &data);
if (rpc_sub->stream) {
- if (lyd_new_term(data, mod, "stream", rpc_sub->stream, 0, &data)) {
+ if (lyd_new_term(data, mod, "stream", rpc_sub->stream, 0, NULL)) {
lyd_free_tree(data);
return NC_MSG_ERROR;
}
@@ -2656,7 +2686,110 @@
}
break;
- default:
+ case NC_RPC_ESTABLISHSUB:
+ rpc_estsub = (struct nc_rpc_establishsub *)rpc;
+
+ lyd_new_inner(NULL, mod, "establish-subscription", 0, &data);
+
+ if (rpc_estsub->filter) {
+ if (!rpc_estsub->filter[0] || (rpc_estsub->filter[0] == '<')) {
+ lyd_new_any(data, mod, "stream-subtree-filter", rpc_estsub->filter, 0, LYD_ANYDATA_XML, 0, &node);
+ } else if (rpc_estsub->filter[0] == '/') {
+ lyd_new_term(data, mod, "stream-xpath-filter", rpc_estsub->filter, 0, &node);
+ } else {
+ lyd_new_term(data, mod, "stream-filter-name", rpc_estsub->filter, 0, &node);
+ }
+ if (!node) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (lyd_new_term(data, mod, "stream", rpc_estsub->stream, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_estsub->start) {
+ if (lyd_new_term(data, mod, "replay-start-time", rpc_estsub->start, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_estsub->stop) {
+ if (lyd_new_term(data, mod, "stop-time", rpc_estsub->stop, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_estsub->encoding) {
+ if (lyd_new_term(data, mod, "encoding", rpc_estsub->encoding, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ break;
+
+ case NC_RPC_MODIFYSUB:
+ rpc_modsub = (struct nc_rpc_modifysub *)rpc;
+
+ lyd_new_inner(NULL, mod, "modify-subscription", 0, &data);
+
+ sprintf(str, "%u", rpc_modsub->id);
+ if (lyd_new_term(data, mod, "id", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_modsub->filter) {
+ if (!rpc_modsub->filter[0] || (rpc_modsub->filter[0] == '<')) {
+ lyd_new_any(data, mod, "stream-subtree-filter", rpc_modsub->filter, 0, LYD_ANYDATA_XML, 0, &node);
+ } else if (rpc_modsub->filter[0] == '/') {
+ lyd_new_term(data, mod, "stream-xpath-filter", rpc_modsub->filter, 0, &node);
+ } else {
+ lyd_new_term(data, mod, "stream-filter-name", rpc_modsub->filter, 0, &node);
+ }
+ if (!node) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_modsub->stop) {
+ if (lyd_new_term(data, mod, "stop-time", rpc_modsub->stop, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ break;
+
+ case NC_RPC_DELETESUB:
+ rpc_delsub = (struct nc_rpc_deletesub *)rpc;
+
+ lyd_new_inner(NULL, mod, "delete-subscription", 0, &data);
+
+ sprintf(str, "%u", rpc_delsub->id);
+ if (lyd_new_term(data, mod, "id", str, 0, NULL)) {
+ lyd_free_tree(data);
+ return NC_MSG_ERROR;
+ }
+ break;
+
+ case NC_RPC_KILLSUB:
+ rpc_killsub = (struct nc_rpc_killsub *)rpc;
+
+ lyd_new_inner(NULL, mod, "kill-subscription", 0, &data);
+
+ sprintf(str, "%u", rpc_killsub->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;
}