Changed framing between backend and frontend to RFC6242 "chunked-encoding"
This commit is contained in:
parent
9f73014500
commit
db11b5ef99
5 changed files with 227 additions and 16 deletions
|
|
@ -13,6 +13,7 @@ Expected: March 2024
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
* Changed framing between backend and frontend to RFC6242 "chunked-encoding"
|
||||||
* Added micro-second resolution to logs via stderr/stdout
|
* Added micro-second resolution to logs via stderr/stdout
|
||||||
* New command-line debug mechanism
|
* New command-line debug mechanism
|
||||||
* Separation between subject-area and details
|
* Separation between subject-area and details
|
||||||
|
|
@ -38,6 +39,9 @@ Expected: March 2024
|
||||||
### API changes on existing protocol/config features
|
### API changes on existing protocol/config features
|
||||||
Users may have to change how they access the system
|
Users may have to change how they access the system
|
||||||
|
|
||||||
|
* Changed framing between backend and frontend to RFC6242 "chunked-encoding"
|
||||||
|
* Should only affect advanced usage between clixon frontend and backend
|
||||||
|
* This should allow standard netconf utilities to be used as frontend (may be some caveats)
|
||||||
* Revert the creators attribute feature introduced in 6.2. It is now obsoleted.
|
* Revert the creators attribute feature introduced in 6.2. It is now obsoleted.
|
||||||
It is replaced with a configured `creators` and user/application semantics
|
It is replaced with a configured `creators` and user/application semantics
|
||||||
* New `clixon-lib@2024-01-01.yang` revision
|
* New `clixon-lib@2024-01-01.yang` revision
|
||||||
|
|
|
||||||
|
|
@ -205,3 +205,13 @@
|
||||||
* This constant will be removed after the 6.6 release
|
* This constant will be removed after the 6.6 release
|
||||||
*/
|
*/
|
||||||
#define COMPAT_6_5
|
#define COMPAT_6_5
|
||||||
|
|
||||||
|
/*! Use 1.1 RFC 6242 chunked encoding framing for internal use
|
||||||
|
*
|
||||||
|
* Replaces internal IPC
|
||||||
|
* clixon_msg_send2() an clixon_msg_rcv2() and some adjustment code in clixon_proto.c
|
||||||
|
* Following things NYI:
|
||||||
|
* - Emulates old clicon_msg API
|
||||||
|
*/
|
||||||
|
#undef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,11 @@ int clicon_msg_send(int s, const char *descr, struct clicon_msg *msg);
|
||||||
|
|
||||||
int clicon_msg_send1(int s, const char *descr, cbuf *cb);
|
int clicon_msg_send1(int s, const char *descr, cbuf *cb);
|
||||||
|
|
||||||
|
#ifdef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
|
int clixon_msg_send2(int s, const char *descr, cbuf *cb);
|
||||||
|
int clixon_msg_rcv2(int s, const char *descr, cbuf **cb, int *eof);
|
||||||
|
#endif
|
||||||
|
|
||||||
int clicon_msg_rcv(int s, const char *descr, int intr, struct clicon_msg **msg, int *eof);
|
int clicon_msg_rcv(int s, const char *descr, int intr, struct clicon_msg **msg, int *eof);
|
||||||
|
|
||||||
int clicon_msg_rcv1(int s, const char *descr, cbuf *cb, int *eof);
|
int clicon_msg_rcv1(int s, const char *descr, cbuf *cb, int *eof);
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@
|
||||||
#include "clixon_sig.h"
|
#include "clixon_sig.h"
|
||||||
#include "clixon_netconf_lib.h"
|
#include "clixon_netconf_lib.h"
|
||||||
#include "clixon_xml_io.h"
|
#include "clixon_xml_io.h"
|
||||||
|
#include "clixon_netconf_input.h"
|
||||||
#include "clixon_options.h"
|
#include "clixon_options.h"
|
||||||
#include "clixon_proto.h"
|
#include "clixon_proto.h"
|
||||||
|
|
||||||
|
|
@ -255,11 +256,13 @@ clicon_connect_unix(clixon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
static void
|
static void
|
||||||
atomicio_sig_handler(int arg)
|
atomicio_sig_handler(int arg)
|
||||||
{
|
{
|
||||||
_atomicio_sig++;
|
_atomicio_sig++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! Ensure all of data on socket comes through. fn is either read or write
|
/*! Ensure all of data on socket comes through. fn is either read or write
|
||||||
*
|
*
|
||||||
|
|
@ -372,7 +375,7 @@ clicon_msg_send(int s,
|
||||||
else{
|
else{
|
||||||
clixon_debug(CLIXON_DBG_MSG, "Send: %s", msg->op_body);
|
clixon_debug(CLIXON_DBG_MSG, "Send: %s", msg->op_body);
|
||||||
}
|
}
|
||||||
msg_hex(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL2, (char*)msg, ntohl(msg->op_len), __FUNCTION__);
|
msg_hex(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, (char*)msg, ntohl(msg->op_len), __FUNCTION__);
|
||||||
if (atomicio((ssize_t (*)(int, void *, size_t))write,
|
if (atomicio((ssize_t (*)(int, void *, size_t))write,
|
||||||
s, msg, ntohl(msg->op_len)) < 0){
|
s, msg, ntohl(msg->op_len)) < 0){
|
||||||
e = errno;
|
e = errno;
|
||||||
|
|
@ -398,7 +401,7 @@ clicon_msg_send(int s,
|
||||||
*
|
*
|
||||||
* @param[in] s Socket (unix or inet) to communicate with backend
|
* @param[in] s Socket (unix or inet) to communicate with backend
|
||||||
* @param[in] descr Description of peer for logging
|
* @param[in] descr Description of peer for logging
|
||||||
* @param[in] intr If set, make a ^C cause an error
|
* @param[in] intr If set, make a ^C cause an error (OBSOLETE?)
|
||||||
* @param[out] msg Clixon msg data reply structure. Free with free()
|
* @param[out] msg Clixon msg data reply structure. Free with free()
|
||||||
* @param[out] eof Set if eof encountered
|
* @param[out] eof Set if eof encountered
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
@ -415,6 +418,29 @@ clicon_msg_rcv(int s,
|
||||||
int *eof)
|
int *eof)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
#ifdef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
|
struct clicon_msg hdr;
|
||||||
|
size_t mlen;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
|
/* Step 1: emulate a clicon_msg API */
|
||||||
|
if (clixon_msg_rcv2(s, descr, &cb, eof) < 0)
|
||||||
|
goto done;
|
||||||
|
mlen = cbuf_len(cb) + sizeof(hdr);
|
||||||
|
if ((*msg = (struct clicon_msg *)malloc(mlen+1)) == NULL){
|
||||||
|
clicon_err(OE_PROTO, errno, "malloc");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memset(*msg, 0, mlen+1);
|
||||||
|
(*msg)->op_len = htonl(mlen);
|
||||||
|
(*msg)->op_id = 0; // XXX attribute?
|
||||||
|
memcpy(&(*msg)->op_body, cbuf_get(cb), cbuf_len(cb));
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
#else
|
||||||
struct clicon_msg hdr;
|
struct clicon_msg hdr;
|
||||||
int hlen;
|
int hlen;
|
||||||
ssize_t len2;
|
ssize_t len2;
|
||||||
|
|
@ -438,7 +464,7 @@ clicon_msg_rcv(int s,
|
||||||
clixon_err(OE_CFG, errno, "atomicio");
|
clixon_err(OE_CFG, errno, "atomicio");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
msg_hex(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL2, (char*)&hdr, hlen, __FUNCTION__);
|
msg_hex(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, (char*)&hdr, hlen, __FUNCTION__);
|
||||||
if (hlen == 0){
|
if (hlen == 0){
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -448,7 +474,7 @@ clicon_msg_rcv(int s,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
mlen = ntohl(hdr.op_len);
|
mlen = ntohl(hdr.op_len);
|
||||||
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL2, "op-len:%u op-id:%u",
|
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, "op-len:%u op-id:%u",
|
||||||
mlen, ntohl(hdr.op_id));
|
mlen, ntohl(hdr.op_id));
|
||||||
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, "rcv msg len=%d",
|
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, "rcv msg len=%d",
|
||||||
mlen);
|
mlen);
|
||||||
|
|
@ -467,7 +493,7 @@ clicon_msg_rcv(int s,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (len2)
|
if (len2)
|
||||||
msg_hex(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL2, (*msg)->op_body, len2, __FUNCTION__);
|
msg_hex(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, (*msg)->op_body, len2, __FUNCTION__);
|
||||||
if (len2 != mlen - sizeof(hdr)){
|
if (len2 != mlen - sizeof(hdr)){
|
||||||
clixon_err(OE_PROTO, 0, "body too short");
|
clixon_err(OE_PROTO, 0, "body too short");
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
|
|
@ -491,6 +517,7 @@ clicon_msg_rcv(int s,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
#endif /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Receive a message using plain NETCONF
|
/*! Receive a message using plain NETCONF
|
||||||
|
|
@ -568,11 +595,12 @@ clicon_msg_rcv1(int s,
|
||||||
/*! Send a Clixon netconf message plain NETCONF
|
/*! Send a Clixon netconf message plain NETCONF
|
||||||
*
|
*
|
||||||
* @param[in] s socket (unix or inet) to communicate with backend
|
* @param[in] s socket (unix or inet) to communicate with backend
|
||||||
* @param[in] cb data buffer including NETCONF
|
|
||||||
* @param[in] descr Description of peer for logging
|
* @param[in] descr Description of peer for logging
|
||||||
|
* @param[in] cb data buffer including NETCONF (and EOM)
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see clicon_msg_send using internal IPC header
|
* @see clicon_msg_send using internal IPC header
|
||||||
|
* @see clicon_msg_send2 version 2 - chunked
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_msg_send1(int s,
|
clicon_msg_send1(int s,
|
||||||
|
|
@ -597,6 +625,112 @@ clicon_msg_send1(int s,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
|
/*! Send a message using unified NETCONF w chunked framing
|
||||||
|
*
|
||||||
|
* @param[in] s socket (unix or inet) to communicate with backend
|
||||||
|
* @param[in] descr Description of peer for logging
|
||||||
|
* @param[out] msg CLICON msg data reply structure. Free with free()
|
||||||
|
* @see clicon_msg_send using internal IPC header
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_msg_send2(int s,
|
||||||
|
const char *descr,
|
||||||
|
cbuf *cb)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
|
||||||
|
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, "send msg len=%lu", cbuf_len(cb));
|
||||||
|
if (descr)
|
||||||
|
clixon_debug(CLIXON_DBG_MSG, "Send [%s]: %s", descr, cbuf_get(cb));
|
||||||
|
else
|
||||||
|
clixon_debug(CLIXON_DBG_MSG, "Send: %s", cbuf_get(cb));
|
||||||
|
if (netconf_output_encap(NETCONF_SSH_CHUNKED, cb) < 0)
|
||||||
|
goto done;
|
||||||
|
if (atomicio((ssize_t (*)(int, void *, size_t))write,
|
||||||
|
s, cbuf_get(cb), cbuf_len(cb)) < 0){
|
||||||
|
clicon_err(OE_CFG, errno, "atomicio");
|
||||||
|
clicon_log(LOG_WARNING, "%s: write: %s", __FUNCTION__, strerror(errno));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Receive a message using unified NETCONF w chunked framing
|
||||||
|
*
|
||||||
|
* @param[in] s socket (unix or inet) to communicate with backend
|
||||||
|
* @param[out] cb cligen buf struct containing the incoming message
|
||||||
|
* @param[out] eof Set if eof encountered
|
||||||
|
* @retval 0 OK (check eof)
|
||||||
|
* @retval -1 Error
|
||||||
|
* @see netconf_input_cb()
|
||||||
|
* @see clicon_msg_rcv using IPC message struct
|
||||||
|
* @note only NETCONF version 1.0 EOM framing
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_msg_rcv2(int s,
|
||||||
|
const char *descr,
|
||||||
|
cbuf **cb,
|
||||||
|
int *eof)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
unsigned char buf[BUFSIZ];
|
||||||
|
ssize_t buflen = sizeof(buf);
|
||||||
|
int frame_state = 0;
|
||||||
|
size_t frame_size = 0;
|
||||||
|
unsigned char *p = buf;
|
||||||
|
size_t plen;
|
||||||
|
cbuf *cbmsg=NULL;
|
||||||
|
ssize_t len;
|
||||||
|
int eom = 0;
|
||||||
|
cxobj *xtop = NULL;
|
||||||
|
cxobj *xerr = NULL;
|
||||||
|
|
||||||
|
if ((cbmsg = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
eom = 0;
|
||||||
|
while (*eof == 0 && eom == 0) {
|
||||||
|
/* Read input data from socket and append to cbbuf */
|
||||||
|
if ((len = netconf_input_read2(s, buf, buflen, eof)) < 0)
|
||||||
|
goto done;
|
||||||
|
p = buf;
|
||||||
|
plen = len;
|
||||||
|
while (!(*eof) && plen > 0){
|
||||||
|
if (netconf_input_msg2(&p, &plen,
|
||||||
|
cbmsg,
|
||||||
|
NETCONF_SSH_CHUNKED,
|
||||||
|
&frame_state,
|
||||||
|
&frame_size,
|
||||||
|
&eom) < 0)
|
||||||
|
goto done;
|
||||||
|
if (eom == 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
clixon_debug(CLIXON_DBG_MSG, "Recv ext: %s", cbuf_get(cbmsg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clixon_debug(CLIXON_DBG_MSG, "Recv: %s", cbuf_get(cbmsg));
|
||||||
|
if (cb){
|
||||||
|
*cb = cbmsg;
|
||||||
|
cbmsg = NULL;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
clixon_debug(CLIXON_DBG_MSG|CLIXON_DBG_DETAIL, "%s done", __FUNCTION__);
|
||||||
|
if (cbmsg)
|
||||||
|
cbuf_free(cbmsg);
|
||||||
|
if (xtop)
|
||||||
|
xml_free(xtop);
|
||||||
|
if (xerr)
|
||||||
|
xml_free(xerr);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
|
|
||||||
/*! Connect to server, send a clicon_msg message and wait for result using unix socket
|
/*! Connect to server, send a clicon_msg message and wait for result using unix socket
|
||||||
*
|
*
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
|
@ -711,6 +845,28 @@ clicon_rpc(int sock,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
struct clicon_msg *reply = NULL;
|
struct clicon_msg *reply = NULL;
|
||||||
|
#ifdef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
|
cbuf *cbsend = cbuf_new();
|
||||||
|
cbuf *cbrcv = NULL;
|
||||||
|
|
||||||
|
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, "");
|
||||||
|
cprintf(cbsend, "%s", msg->op_body);
|
||||||
|
if (clixon_msg_send2(sock, descr, cbsend) < 0)
|
||||||
|
goto done;
|
||||||
|
if (cbsend)
|
||||||
|
cbuf_free(cbsend);
|
||||||
|
if (clixon_msg_rcv2(sock, descr, &cbrcv, eof) < 0)
|
||||||
|
goto done;
|
||||||
|
if (*eof)
|
||||||
|
goto ok;
|
||||||
|
if (cbrcv){
|
||||||
|
if ((*ret = strdup(cbuf_get(cbrcv))) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cbuf_free(cbrcv);
|
||||||
|
}
|
||||||
|
#else /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
|
|
||||||
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, "");
|
clixon_debug(CLIXON_DBG_MSG | CLIXON_DBG_DETAIL, "");
|
||||||
|
|
@ -720,12 +876,14 @@ clicon_rpc(int sock,
|
||||||
goto done;
|
goto done;
|
||||||
if (*eof)
|
if (*eof)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
||||||
data = reply->op_body; /* assume string */
|
data = reply->op_body; /* assume string */
|
||||||
if (ret && data)
|
if (ret && data)
|
||||||
if ((*ret = strdup(data)) == NULL){
|
if ((*ret = strdup(data)) == NULL){
|
||||||
clixon_err(OE_UNIX, errno, "strdup");
|
clixon_err(OE_UNIX, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
#endif /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -787,6 +945,24 @@ send_msg_reply(int s,
|
||||||
uint32_t datalen)
|
uint32_t datalen)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
#ifdef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (cbuf_append_buf(cb, data, datalen) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_append_buf");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (clixon_msg_send2(s, descr, cb) < 0)
|
||||||
|
goto done;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
#else /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
struct clicon_msg *reply = NULL;
|
struct clicon_msg *reply = NULL;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|
||||||
|
|
@ -803,6 +979,7 @@ send_msg_reply(int s,
|
||||||
done:
|
done:
|
||||||
if (reply)
|
if (reply)
|
||||||
free(reply);
|
free(reply);
|
||||||
|
#endif /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -810,8 +987,7 @@ send_msg_reply(int s,
|
||||||
*
|
*
|
||||||
* @param[in] s Socket to communicate with client
|
* @param[in] s Socket to communicate with client
|
||||||
* @param[in] descr Description of peer for logging
|
* @param[in] descr Description of peer for logging
|
||||||
* @param[in] level
|
* @param[in] msg Data string to send
|
||||||
* @param[in] event
|
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see send_msg_notify_xml
|
* @see send_msg_notify_xml
|
||||||
|
|
@ -819,19 +995,35 @@ send_msg_reply(int s,
|
||||||
static int
|
static int
|
||||||
send_msg_notify(int s,
|
send_msg_notify(int s,
|
||||||
const char *descr,
|
const char *descr,
|
||||||
char *event)
|
char *msg)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
struct clicon_msg *msg = NULL;
|
#ifdef NETCONF_INPUT_UNIFIED_INTERNAL
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if ((msg=clicon_msg_encode(0, "%s", event)) == NULL)
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_msg_send(s, descr, msg) < 0)
|
}
|
||||||
|
cprintf(cb, "%s", msg);
|
||||||
|
if (clixon_msg_send2(s, descr, cb) < 0)
|
||||||
|
goto done;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
#else /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
|
struct clicon_msg *imsg = NULL;
|
||||||
|
|
||||||
|
if ((imsg = clicon_msg_encode(0, "%s", msg)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (clicon_msg_send(s, descr, imsg) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (msg)
|
if (imsg)
|
||||||
free(msg);
|
free(imsg);
|
||||||
|
#endif /* NETCONF_INPUT_UNIFIED_INTERNAL */
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -557,7 +557,7 @@ stream_notify1(clixon_handle h,
|
||||||
* if (stream_notify(h, "NETCONF", "<event><event-class>fault</event-class><reportingEntity><card>Ethernet0</card></reportingEntity><severity>major</severity></event>") < 0)
|
* if (stream_notify(h, "NETCONF", "<event><event-class>fault</event-class><reportingEntity><card>Ethernet0</card></reportingEntity><severity>major</severity></event>") < 0)
|
||||||
* err;
|
* err;
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see stream_notify1 Internal
|
* @see stream_notify_xml Similar but with XML data
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
stream_notify(clixon_handle h,
|
stream_notify(clixon_handle h,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue