* rpc msg C API rearranged to separate socket/connect from connect
This commit is contained in:
parent
8cde7a4ded
commit
2a392ca0e9
11 changed files with 93 additions and 69 deletions
|
|
@ -33,6 +33,7 @@ Expected: February 2021
|
||||||
|
|
||||||
Developers may need to change their code
|
Developers may need to change their code
|
||||||
|
|
||||||
|
* rpc msg C API rearranged to separate socket/connect from connect
|
||||||
* Added `cvv_i` output parameter to `api_path_fmt2api_path()` to see how many cvv entries were used.
|
* Added `cvv_i` output parameter to `api_path_fmt2api_path()` to see how many cvv entries were used.
|
||||||
|
|
||||||
### API changes on existing protocol/config features
|
### API changes on existing protocol/config features
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@ top_srcdir = @top_srcdir@
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
CFLAGS = @CFLAGS@
|
CFLAGS = @CFLAGS@
|
||||||
LINKAGE = @LINKAGE@
|
LINKAGE = @LINKAGE@
|
||||||
ifeq ($(LINKAGE),dynamic)
|
ifeq ($(LINKAGE),static)
|
||||||
CPPFLAGS = @CPPFLAGS@ -fPIC
|
|
||||||
SH_SUFFIX = @SH_SUFFIX@
|
|
||||||
else
|
|
||||||
CPPFLAGS = @CPPFLAGS@
|
CPPFLAGS = @CPPFLAGS@
|
||||||
SH_SUFFIX = a
|
SH_SUFFIX = a
|
||||||
|
else
|
||||||
|
CPPFLAGS = @CPPFLAGS@ -fPIC
|
||||||
|
SH_SUFFIX = @SH_SUFFIX@
|
||||||
endif
|
endif
|
||||||
INSTALLFLAGS = @INSTALLFLAGS@
|
INSTALLFLAGS = @INSTALLFLAGS@
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
|
|
@ -64,10 +64,10 @@ CLIXON_MAJOR = @CLIXON_VERSION_MAJOR@
|
||||||
CLIXON_MINOR = @CLIXON_VERSION_MINOR@
|
CLIXON_MINOR = @CLIXON_VERSION_MINOR@
|
||||||
|
|
||||||
# Use this clixon lib for linking
|
# Use this clixon lib for linking
|
||||||
ifeq ($(LINKAGE),dynamic)
|
ifeq ($(LINKAGE),static)
|
||||||
CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
|
|
||||||
else
|
|
||||||
CLIXON_LIB = libclixon.a
|
CLIXON_LIB = libclixon.a
|
||||||
|
else
|
||||||
|
CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# For dependency. A little strange that we rely on it being built in the src dir
|
# For dependency. A little strange that we rely on it being built in the src dir
|
||||||
|
|
@ -100,10 +100,10 @@ MYLIBSO = lib$(MYNAME)$(SH_SUFFIX).$(CLIXON_MAJOR)
|
||||||
MYLIBLINK = lib$(MYNAME)$(SH_SUFFIX)
|
MYLIBLINK = lib$(MYNAME)$(SH_SUFFIX)
|
||||||
MYLIBSTATIC = lib$(MYNAME).a
|
MYLIBSTATIC = lib$(MYNAME).a
|
||||||
|
|
||||||
ifeq ($(LINKAGE),dynamic)
|
ifeq ($(LINKAGE),static)
|
||||||
MYLIB = $(MYLIBDYNAMIC)
|
|
||||||
else
|
|
||||||
MYLIB = $(MYLIBSTATIC)
|
MYLIB = $(MYLIBSTATIC)
|
||||||
|
else
|
||||||
|
MYLIB = $(MYLIBDYNAMIC)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(MYLIB) $(APPL) test
|
all: $(MYLIB) $(APPL) test
|
||||||
|
|
|
||||||
|
|
@ -75,16 +75,12 @@ int clicon_connect_unix(clicon_handle h, char *sockpath);
|
||||||
|
|
||||||
|
|
||||||
int clicon_rpc_connect_unix(clicon_handle h,
|
int clicon_rpc_connect_unix(clicon_handle h,
|
||||||
struct clicon_msg *msg,
|
|
||||||
char *sockpath,
|
char *sockpath,
|
||||||
char **ret,
|
|
||||||
int *sock0);
|
int *sock0);
|
||||||
|
|
||||||
int clicon_rpc_connect_inet(clicon_handle h,
|
int clicon_rpc_connect_inet(clicon_handle h,
|
||||||
struct clicon_msg *msg,
|
|
||||||
char *dst,
|
char *dst,
|
||||||
uint16_t port,
|
uint16_t port,
|
||||||
char **ret,
|
|
||||||
int *sock0);
|
int *sock0);
|
||||||
|
|
||||||
int clicon_rpc(int s, struct clicon_msg *msg, char **xret);
|
int clicon_rpc(int s, struct clicon_msg *msg, char **xret);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#ifndef _CLIXON_PROTO_CLIENT_H_
|
#ifndef _CLIXON_PROTO_CLIENT_H_
|
||||||
#define _CLIXON_PROTO_CLIENT_H_
|
#define _CLIXON_PROTO_CLIENT_H_
|
||||||
|
|
||||||
|
int clicon_rpc_connect(clicon_handle h, int *sock0);
|
||||||
int clicon_rpc_msg(clicon_handle h, struct clicon_msg *msg, cxobj **xret0,
|
int clicon_rpc_msg(clicon_handle h, struct clicon_msg *msg, cxobj **xret0,
|
||||||
int *sock0);
|
int *sock0);
|
||||||
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
|
int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp);
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ CLIXON_MINOR = @CLIXON_VERSION_MINOR@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
LINKAGE = @LINKAGE@
|
LINKAGE = @LINKAGE@
|
||||||
ifeq ($(LINKAGE),dynamic)
|
ifeq ($(LINKAGE),static)
|
||||||
CFLAGS = -fPIC @CFLAGS@
|
|
||||||
else
|
|
||||||
CFLAGS = @CFLAGS@
|
CFLAGS = @CFLAGS@
|
||||||
|
else
|
||||||
|
CFLAGS = -fPIC @CFLAGS@
|
||||||
endif
|
endif
|
||||||
SH_SUFFIX = @SH_SUFFIX@
|
SH_SUFFIX = @SH_SUFFIX@
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
|
|
@ -107,10 +107,10 @@ MYLIBSO = lib$(MYNAME)$(SH_SUFFIX).$(CLIXON_MAJOR)
|
||||||
MYLIBLINK = lib$(MYNAME)$(SH_SUFFIX)
|
MYLIBLINK = lib$(MYNAME)$(SH_SUFFIX)
|
||||||
MYLIBSTATIC = lib$(MYNAME).a
|
MYLIBSTATIC = lib$(MYNAME).a
|
||||||
|
|
||||||
ifeq ($(LINKAGE),dynamic)
|
ifeq ($(LINKAGE),static)
|
||||||
MYLIB = $(MYLIBDYNAMIC)
|
|
||||||
else
|
|
||||||
MYLIB = $(MYLIBSTATIC)
|
MYLIB = $(MYLIBSTATIC)
|
||||||
|
else
|
||||||
|
MYLIB = $(MYLIBDYNAMIC)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(MYLIB) $(MYLIBLINK)
|
all: $(MYLIB) $(MYLIBLINK)
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,7 @@ clicon_debug_init(int dbglevel,
|
||||||
FILE *f)
|
FILE *f)
|
||||||
{
|
{
|
||||||
_clixon_debug = dbglevel; /* Global variable */
|
_clixon_debug = dbglevel; /* Global variable */
|
||||||
|
_logfile = f;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -562,16 +562,18 @@ clicon_msg_rcv(int s,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_connect_unix(clicon_handle h,
|
clicon_rpc_connect_unix(clicon_handle h,
|
||||||
struct clicon_msg *msg,
|
|
||||||
char *sockpath,
|
char *sockpath,
|
||||||
char **retdata,
|
|
||||||
int *sock0)
|
int *sock0)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int s = -1;
|
int s = -1;
|
||||||
struct stat sb;
|
struct stat sb = {0,};
|
||||||
|
|
||||||
clicon_debug(1, "Send msg on %s", sockpath);
|
clicon_debug(1, "Send msg on %s", sockpath);
|
||||||
|
if (sock0 == NULL){
|
||||||
|
clicon_err(OE_NETCONF, EINVAL, "sock0 expected");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* special error handling to get understandable messages (otherwise ENOENT) */
|
/* special error handling to get understandable messages (otherwise ENOENT) */
|
||||||
if (stat(sockpath, &sb) < 0){
|
if (stat(sockpath, &sb) < 0){
|
||||||
clicon_err(OE_PROTO, errno, "%s: config daemon not running?", sockpath);
|
clicon_err(OE_PROTO, errno, "%s: config daemon not running?", sockpath);
|
||||||
|
|
@ -583,14 +585,9 @@ clicon_rpc_connect_unix(clicon_handle h,
|
||||||
}
|
}
|
||||||
if ((s = clicon_connect_unix(h, sockpath)) < 0)
|
if ((s = clicon_connect_unix(h, sockpath)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc(s, msg, retdata) < 0)
|
|
||||||
goto done;
|
|
||||||
if (sock0 != NULL)
|
|
||||||
*sock0 = s;
|
*sock0 = s;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (sock0 == NULL && s >= 0)
|
|
||||||
close(s);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -608,10 +605,8 @@ clicon_rpc_connect_unix(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_connect_inet(clicon_handle h,
|
clicon_rpc_connect_inet(clicon_handle h,
|
||||||
struct clicon_msg *msg,
|
|
||||||
char *dst,
|
char *dst,
|
||||||
uint16_t port,
|
uint16_t port,
|
||||||
char **retdata,
|
|
||||||
int *sock0)
|
int *sock0)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -619,7 +614,10 @@ clicon_rpc_connect_inet(clicon_handle h,
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
|
|
||||||
clicon_debug(1, "Send msg to %s:%hu", dst, port);
|
clicon_debug(1, "Send msg to %s:%hu", dst, port);
|
||||||
|
if (sock0 == NULL){
|
||||||
|
clicon_err(OE_NETCONF, EINVAL, "sock0 expected");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(port);
|
addr.sin_port = htons(port);
|
||||||
|
|
@ -636,14 +634,9 @@ clicon_rpc_connect_inet(clicon_handle h,
|
||||||
close(s);
|
close(s);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_rpc(s, msg, retdata) < 0)
|
|
||||||
goto done;
|
|
||||||
if (sock0 != NULL)
|
|
||||||
*sock0 = s;
|
*sock0 = s;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (sock0 == NULL && s >= 0)
|
|
||||||
close(s);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,31 +82,16 @@
|
||||||
#include "clixon_netconf_lib.h"
|
#include "clixon_netconf_lib.h"
|
||||||
#include "clixon_proto_client.h"
|
#include "clixon_proto_client.h"
|
||||||
|
|
||||||
/*! Send internal netconf rpc from client to backend
|
/*! Connect to internal netconf socket
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] msg Encoded message. Deallocate with free
|
|
||||||
* @param[out] xret0 Return value from backend as xml tree. Free w xml_free
|
|
||||||
* @param[inout] sock0 If pointer exists, do not close socket to backend on success
|
|
||||||
* and return it here. For keeping a notify socket open
|
|
||||||
* @note sock0 is if connection should be persistent, like a notification/subscribe api
|
|
||||||
* @note xret is populated with yangspec according to standard handle yangspec
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_rpc_msg(clicon_handle h,
|
clicon_rpc_connect(clicon_handle h,
|
||||||
struct clicon_msg *msg,
|
|
||||||
cxobj **xret0,
|
|
||||||
int *sock0)
|
int *sock0)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *sock;
|
char *sock = NULL;
|
||||||
int port;
|
int port;
|
||||||
char *retdata = NULL;
|
|
||||||
cxobj *xret = NULL;
|
|
||||||
|
|
||||||
#ifdef RPC_USERNAME_ASSERT
|
|
||||||
assert(strstr(msg->op_body, "username")!=NULL); /* XXX */
|
|
||||||
#endif
|
|
||||||
clicon_debug(1, "%s request:%s", __FUNCTION__, msg->op_body);
|
|
||||||
if ((sock = clicon_sock(h)) == NULL){
|
if ((sock = clicon_sock(h)) == NULL){
|
||||||
clicon_err(OE_FATAL, 0, "CLICON_SOCK option not set");
|
clicon_err(OE_FATAL, 0, "CLICON_SOCK option not set");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -114,7 +99,7 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
/* What to do if inet socket? */
|
/* What to do if inet socket? */
|
||||||
switch (clicon_sock_family(h)){
|
switch (clicon_sock_family(h)){
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
if (clicon_rpc_connect_unix(h, msg, sock, &retdata, sock0) < 0){
|
if (clicon_rpc_connect_unix(h, sock, sock0) < 0){
|
||||||
#if 0
|
#if 0
|
||||||
if (errno == ESHUTDOWN)
|
if (errno == ESHUTDOWN)
|
||||||
/* Maybe could reconnect on a higher layer, but lets fail
|
/* Maybe could reconnect on a higher layer, but lets fail
|
||||||
|
|
@ -133,10 +118,45 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
clicon_err(OE_FATAL, 0, "CLICON_SOCK_PORT not set");
|
clicon_err(OE_FATAL, 0, "CLICON_SOCK_PORT not set");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (clicon_rpc_connect_inet(h, msg, sock, port, &retdata, sock0) < 0)
|
if (clicon_rpc_connect_inet(h, sock, port, sock0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Send internal netconf rpc from client to backend
|
||||||
|
* @param[in] h CLICON handle
|
||||||
|
* @param[in] msg Encoded message. Deallocate with free
|
||||||
|
* @param[out] xret0 Return value from backend as xml tree. Free w xml_free
|
||||||
|
* @param[inout] sock0 If pointer exists, do not close socket to backend on success
|
||||||
|
* and return it here. For keeping a notify socket open
|
||||||
|
* @note sock0 is if connection should be persistent, like a notification/subscribe api
|
||||||
|
* @note xret is populated with yangspec according to standard handle yangspec
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clicon_rpc_msg(clicon_handle h,
|
||||||
|
struct clicon_msg *msg,
|
||||||
|
cxobj **xret0,
|
||||||
|
int *sock0)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *retdata = NULL;
|
||||||
|
cxobj *xret = NULL;
|
||||||
|
int s = -1;
|
||||||
|
|
||||||
|
#ifdef RPC_USERNAME_ASSERT
|
||||||
|
assert(strstr(msg->op_body, "username")!=NULL); /* XXX */
|
||||||
|
#endif
|
||||||
|
clicon_debug(1, "%s request:%s", __FUNCTION__, msg->op_body);
|
||||||
|
/* Create a socket and connect to it, either UNIX, IPv4 or IPv6 per config options */
|
||||||
|
if (clicon_rpc_connect(h, &s) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clicon_rpc(s, msg, &retdata) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
clicon_debug(1, "%s retdata:%s", __FUNCTION__, retdata);
|
clicon_debug(1, "%s retdata:%s", __FUNCTION__, retdata);
|
||||||
|
|
||||||
if (retdata){
|
if (retdata){
|
||||||
|
|
@ -150,8 +170,15 @@ clicon_rpc_msg(clicon_handle h,
|
||||||
*xret0 = xret;
|
*xret0 = xret;
|
||||||
xret = NULL;
|
xret = NULL;
|
||||||
}
|
}
|
||||||
|
/* If returned, keep socket open, otherwise close it below */
|
||||||
|
if (sock0){
|
||||||
|
*sock0 = s;
|
||||||
|
s = -1;
|
||||||
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (s != -1)
|
||||||
|
close(s);
|
||||||
if (retdata)
|
if (retdata)
|
||||||
free(retdata);
|
free(retdata);
|
||||||
if (xret)
|
if (xret)
|
||||||
|
|
|
||||||
|
|
@ -706,7 +706,7 @@ xpath_first_localonly(cxobj *xcur,
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @code
|
* @code
|
||||||
* cvec *nsc; // namespace context
|
* cvec *nsc; // namespace context
|
||||||
* cxobj **vec;
|
* cxobj **vec = NULL;
|
||||||
* size_t veclen;
|
* size_t veclen;
|
||||||
* if (xpath_vec(xcur, nsc, "//symbol/foo", &vec, &veclen) < 0)
|
* if (xpath_vec(xcur, nsc, "//symbol/foo", &vec, &veclen) < 0)
|
||||||
* err;
|
* err;
|
||||||
|
|
|
||||||
|
|
@ -63,13 +63,14 @@ INSTALLFLAGS = @INSTALLFLAGS@
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
LIBS = @LIBS@
|
LIBS = @LIBS@
|
||||||
CPPFLAGS = @CPPFLAGS@
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
LINKAGE = @LINKAGE@
|
||||||
|
|
||||||
INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib -I$(top_srcdir)/include
|
INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib -I$(top_srcdir)/include
|
||||||
|
|
||||||
ifeq ($(LINKAGE),dynamic)
|
ifeq ($(LINKAGE),static)
|
||||||
CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
|
|
||||||
else
|
|
||||||
CLIXON_LIB = libclixon.a
|
CLIXON_LIB = libclixon.a
|
||||||
|
else
|
||||||
|
CLIXON_LIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# For dependency. A little strange that we rely on it being built in the src dir
|
# For dependency. A little strange that we rely on it being built in the src dir
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ main(int argc,
|
||||||
cbuf *cb = cbuf_new();
|
cbuf *cb = cbuf_new();
|
||||||
clicon_handle h;
|
clicon_handle h;
|
||||||
int dbg = 0;
|
int dbg = 0;
|
||||||
|
int s;
|
||||||
|
|
||||||
/* In the startup, logs to stderr & debug flag set later */
|
/* In the startup, logs to stderr & debug flag set later */
|
||||||
clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR);
|
clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR);
|
||||||
|
|
@ -167,12 +168,15 @@ main(int argc,
|
||||||
if ((msg = clicon_msg_encode(getpid(), "%s", cbuf_get(cb))) < 0)
|
if ((msg = clicon_msg_encode(getpid(), "%s", cbuf_get(cb))) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (strcmp(family, "UNIX")==0){
|
if (strcmp(family, "UNIX")==0){
|
||||||
if (clicon_rpc_connect_unix(h, msg, sockpath, &retdata, NULL) < 0)
|
if (clicon_rpc_connect_unix(h, sockpath, &s) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (clicon_rpc_connect_inet(h, msg, sockpath, 4535, &retdata, NULL) < 0)
|
if (clicon_rpc_connect_inet(h, sockpath, 4535, &s) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (clicon_rpc(s, msg, &retdata) < 0)
|
||||||
|
goto done;
|
||||||
|
close(s);
|
||||||
fprintf(stdout, "%s\n", retdata);
|
fprintf(stdout, "%s\n", retdata);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue