* rpc msg C API rearranged to separate socket/connect from connect

This commit is contained in:
Olof hagsand 2021-01-12 14:03:07 +01:00
parent 8cde7a4ded
commit 2a392ca0e9
11 changed files with 93 additions and 69 deletions

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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;
} }

View file

@ -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) *sock0 = s;
goto done;
if (sock0 != NULL)
*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) *sock0 = s;
goto done;
if (sock0 != NULL)
*sock0 = s;
retval = 0; retval = 0;
done: done:
if (sock0 == NULL && s >= 0)
close(s);
return retval; return retval;
} }

View file

@ -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, int *sock0)
cxobj **xret0,
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)

View file

@ -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;

View file

@ -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

View file

@ -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: