Plugin RPC callback interface have been unified between backend, netconf and restconf.
* Backend RPC register callback function (Netconf RPC or restconf operation POST) has been changed from: `backend_rpc_cb_register()` to `rpc_callback_register()`
* Backend RPC callback signature has been changed from: `int cb(clicon_handle h, cxobj *xe, struct client_entry *ce, cbuf *cbret, void *arg)` has been changed to : `int cb(clicon_handle h, cxobj *xe, struct client_entry *ce, cbuf *cbret, void *arg)`
* Frontend netconf and restconf plugins can register callbacks as well with same API as backends.
This commit is contained in:
parent
7a4371e76f
commit
d541c49c6f
20 changed files with 323 additions and 229 deletions
|
|
@ -39,27 +39,12 @@
|
|||
#ifndef _CLIXON_NETCONF_H_
|
||||
#define _CLIXON_NETCONF_H_
|
||||
|
||||
/*
|
||||
* Types
|
||||
*/
|
||||
typedef int (*netconf_cb_t)(
|
||||
clicon_handle h,
|
||||
cxobj *xn, /* Request: <rpc><xn></rpc> */
|
||||
cxobj **xret, /* Return xml tree, eg <rpc-reply>... */
|
||||
void *arg /* Argument given at netconf_register_callback() */
|
||||
);
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
* (Duplicated. Also in netconf_*.h)
|
||||
*/
|
||||
int netconf_output(int s, cbuf *xf, char *msg);
|
||||
|
||||
int netconf_register_callback(clicon_handle h,
|
||||
netconf_cb_t cb, /* Callback called */
|
||||
void *arg, /* Arg to send to callback */
|
||||
char *tag); /* Xml tag when callback is made */
|
||||
|
||||
int netconf_xpath(cxobj *xsearch,
|
||||
cxobj *xfilter,
|
||||
cbuf *xf, cbuf *xf_err,
|
||||
|
|
|
|||
|
|
@ -71,45 +71,48 @@
|
|||
enum transport_type transport = NETCONF_SSH; /* XXX Remove SOAP support */
|
||||
int cc_closed = 0; /* XXX Please remove (or at least hide in handle) this global variable */
|
||||
|
||||
/*! Add netconf xml postamble of message. I.e, xml after the body of the message.
|
||||
* @param[in] cb Netconf packet (cligen buffer)
|
||||
*/
|
||||
int
|
||||
add_preamble(cbuf *xf)
|
||||
add_preamble(cbuf *cb)
|
||||
{
|
||||
if (transport == NETCONF_SOAP)
|
||||
cprintf(xf, "\n<soapenv:Envelope\n xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\">\n"
|
||||
cprintf(cb, "\n<soapenv:Envelope\n xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\">\n"
|
||||
"<soapenv:Body>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_postamble
|
||||
* add netconf xml postamble of message. That is, xml after the body of the message.
|
||||
/*! Add netconf xml postamble of message. I.e, xml after the body of the message.
|
||||
* for soap this is the envelope stuff, for ssh this is ]]>]]>
|
||||
* @param[in] cb Netconf packet (cligen buffer)
|
||||
*/
|
||||
int
|
||||
add_postamble(cbuf *xf)
|
||||
add_postamble(cbuf *cb)
|
||||
{
|
||||
switch (transport){
|
||||
case NETCONF_SSH:
|
||||
cprintf(xf, "]]>]]>"); /* Add RFC4742 end-of-message marker */
|
||||
cprintf(cb, "]]>]]>"); /* Add RFC4742 end-of-message marker */
|
||||
break;
|
||||
case NETCONF_SOAP:
|
||||
cprintf(xf, "\n</soapenv:Body>" "</soapenv:Envelope>");
|
||||
cprintf(cb, "\n</soapenv:Body>" "</soapenv:Envelope>");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_error_preamble
|
||||
/*! Add error_preamble
|
||||
* compared to regular messages (see add_preamble), error message differ in some
|
||||
* protocols (eg soap) by adding a longer and deeper header.
|
||||
* @param[in] cb Netconf packet (cligen buffer)
|
||||
*/
|
||||
int
|
||||
add_error_preamble(cbuf *xf, char *reason)
|
||||
add_error_preamble(cbuf *cb,
|
||||
char *reason)
|
||||
{
|
||||
switch (transport){
|
||||
case NETCONF_SOAP:
|
||||
cprintf(xf, "<soapenv:Envelope xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:xml=\"http://www.w3.org/XML/1998/namespace\">"
|
||||
cprintf(cb, "<soapenv:Envelope xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:xml=\"http://www.w3.org/XML/1998/namespace\">"
|
||||
"<soapenv:Body>"
|
||||
"<soapenv:Fault>"
|
||||
"<soapenv:Code>"
|
||||
|
|
@ -121,26 +124,26 @@ add_error_preamble(cbuf *xf, char *reason)
|
|||
"<detail>", reason);
|
||||
break;
|
||||
default:
|
||||
if (add_preamble(xf) < 0)
|
||||
if (add_preamble(cb) < 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_error_postamble
|
||||
/*! Add error postamble
|
||||
* compared to regular messages (see add_postamble), error message differ in some
|
||||
* protocols (eg soap) by adding a longer and deeper header.
|
||||
* @param[in] cb Netconf packet (cligen buffer)
|
||||
*/
|
||||
int
|
||||
add_error_postamble(cbuf *xf)
|
||||
add_error_postamble(cbuf *cb)
|
||||
{
|
||||
switch (transport){
|
||||
case NETCONF_SOAP:
|
||||
cprintf(xf, "</detail>" "</soapenv:Fault>");
|
||||
cprintf(cb, "</detail>" "</soapenv:Fault>");
|
||||
default: /* fall through */
|
||||
if (add_postamble(xf) < 0)
|
||||
if (add_postamble(cb) < 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -150,7 +153,9 @@ add_error_postamble(cbuf *xf)
|
|||
|
||||
/*! Get "target" attribute, return actual database given candidate or running
|
||||
* Caller must do error handling
|
||||
* @retval dbname Actual database file name
|
||||
* @param[in] xn XML tree
|
||||
* @param[in] path
|
||||
* @retval dbname Actual database file name
|
||||
*/
|
||||
char *
|
||||
netconf_get_target(cxobj *xn,
|
||||
|
|
@ -180,11 +185,11 @@ netconf_get_target(cxobj *xn,
|
|||
*/
|
||||
int
|
||||
netconf_output(int s,
|
||||
cbuf *xf,
|
||||
cbuf *cb,
|
||||
char *msg)
|
||||
{
|
||||
char *buf = cbuf_get(xf);
|
||||
int len = cbuf_len(xf);
|
||||
char *buf = cbuf_get(cb);
|
||||
int len = cbuf_len(cb);
|
||||
int retval = -1;
|
||||
|
||||
clicon_debug(1, "SEND %s", msg);
|
||||
|
|
@ -207,3 +212,4 @@ netconf_output(int s,
|
|||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -262,6 +262,8 @@ netconf_terminate(clicon_handle h)
|
|||
{
|
||||
yang_spec *yspec;
|
||||
|
||||
clixon_plugin_exit(h);
|
||||
rpc_callback_delete_all();
|
||||
clicon_rpc_close_session(h);
|
||||
if ((yspec = clicon_dbspec_yang(h)) != NULL)
|
||||
yspec_free(yspec);
|
||||
|
|
@ -402,7 +404,6 @@ main(int argc,
|
|||
if (event_loop() < 0)
|
||||
goto done;
|
||||
done:
|
||||
clixon_plugin_exit(h);
|
||||
netconf_terminate(h);
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
|
||||
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());
|
||||
|
|
|
|||
|
|
@ -849,8 +849,10 @@ netconf_create_subscription(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! See if there is any callback registered for this tag
|
||||
/*! See if there is any application defined RPC for this tag
|
||||
*
|
||||
* This may either be local client-side or backend. If backend send as netconf
|
||||
* RPC.
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] xn Sub-tree (under xorig) at child of rpc: <rpc><xn></rpc>.
|
||||
* @param[out] xret Return XML, error or OK
|
||||
|
|
@ -871,6 +873,8 @@ netconf_application_rpc(clicon_handle h,
|
|||
yang_stmt *youtput;
|
||||
cxobj *xoutput;
|
||||
cbuf *cb = NULL;
|
||||
cbuf *cbret = NULL;
|
||||
int ret;
|
||||
|
||||
/* First check system / netconf RPC:s */
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
|
|
@ -891,9 +895,9 @@ netconf_application_rpc(clicon_handle h,
|
|||
/* Find yang rpc statement, return yang rpc statement if found */
|
||||
if (yang_abs_schema_nodeid(yspec, cbuf_get(cb), &yrpc) < 0)
|
||||
goto done;
|
||||
|
||||
/* Check if found */
|
||||
if (yrpc != NULL){
|
||||
/* 1. Check xn arguments with input statement. */
|
||||
if ((yinput = yang_find((yang_node*)yrpc, Y_INPUT, NULL)) != NULL){
|
||||
xml_spec_set(xn, yinput); /* needed for xml_spec_populate */
|
||||
if (xml_apply(xn, CX_ELMNT, xml_spec_populate, yinput) < 0)
|
||||
|
|
@ -904,13 +908,20 @@ netconf_application_rpc(clicon_handle h,
|
|||
if (xml_yang_validate_add(xn, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* 1. Check xn arguments with input statement.
|
||||
* 2. Send to backend as clicon_msg-encode()
|
||||
* 3. In backend to similar but there call actual backend
|
||||
*/
|
||||
if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0)
|
||||
if ((cbret = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, 0, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
/* Look for local (client-side) netconf plugins. */
|
||||
if ((ret = rpc_callback_call(h, xn, cbret, NULL)) < 0)
|
||||
goto done;
|
||||
if (ret == 1){ /* Handled locally */
|
||||
if (xml_parse_string(cbuf_get(cbret), NULL, xret) < 0)
|
||||
goto done;
|
||||
}
|
||||
else /* Send to backend */
|
||||
if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0)
|
||||
goto done;
|
||||
/* Sanity check of outgoing XML */
|
||||
if ((youtput = yang_find((yang_node*)yrpc, Y_OUTPUT, NULL)) != NULL){
|
||||
xoutput=xpath_first(*xret, "/");
|
||||
|
|
@ -930,9 +941,10 @@ netconf_application_rpc(clicon_handle h,
|
|||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (cbret)
|
||||
cbuf_free(cbret);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! The central netconf rpc dispatcher. Look at first tag and dispach to sub-functions.
|
||||
|
|
@ -1017,6 +1029,8 @@ netconf_rpc_dispatch(clicon_handle h,
|
|||
}
|
||||
/* Others */
|
||||
else {
|
||||
/* Look for application-defined RPC. This may either be local
|
||||
client-side or backend. If backend send as netconf RPC. */
|
||||
if ((retval = netconf_application_rpc(h, xe, xret)) < 0)
|
||||
goto done;
|
||||
if (retval == 0){ /* not handled by callback */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue