diff --git a/include/sntl/connection.h b/include/sntl/connection.h index 4f3f33c..054843a 100644 --- a/include/sntl/connection.h +++ b/include/sntl/connection.h @@ -181,8 +181,8 @@ int connections_subsystem_setrpclist_function(usrtc_t* (*get_rpc_typed_list_tree #define connections_subsystem_set_rpctlist_call(c, fuu) (c)->set_typed_list_callback = fuu /* connection */ -int connection_initiate (conn_t *co, const char *host, int port, - const char *SSL_cert, perm_ctx_t *pctx); +int connection_initiate (conn_t *co, const char *host, int port, + const char *SSL_cert, perm_ctx_t *pctx); int connection_create(conn_t *co, int sck); @@ -212,5 +212,20 @@ int msg_send_pulse_timed(chnl_t *ch, sexp_t *sx, struct timespec *tio); int msg_send_pulse_nowait(chnl_t *ch, sexp_t *sx); +/* RPC List API */ +#define SNTL_FILTER_INC 0xa +#define SNTL_FILTER_EXC 0xb +#define SNTL_FILTER_END -1 + +int sntl_rpclist_init(usrtc_t *tree); + +int sntl_rpclist_add(usrtc_t *tree, int type, const char *description, + const char *version); + +int sntl_rpclist_add_function(usrtc_t *tree, int type, const char *fu_name, + int (*rpcf)(void *, sexp_t *)); + +int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter); + #endif /* __ESXC_CONNECTION_H_ */ diff --git a/lib/rpclist.c b/lib/rpclist.c index 297cfc7..712df40 100644 --- a/lib/rpclist.c +++ b/lib/rpclist.c @@ -32,13 +32,160 @@ static long __cmp_int(const void *a, const void *b) return *(int *)a - *(int *)b; } +static long __cmp_cstr(const void *a, const void *b) +{ + return strcmp((char *)a, (char *)b); +} + int sntl_rpclist_init(usrtc_t *tree) { usrtc_init(tree, USRTC_REDBLACK, MAX_RPC_LIST, __cmp_int); return 0; } -int sntl_rpclist_add(usrtc_t *tree, int type, const char *description) +int sntl_rpclist_add(usrtc_t *tree, int type, const char *description, + const char *version) { + rpc_typed_list_t *nlist = NULL; + cx_rpc_list_t *rpc_list = NULL; + usrtc_t *rtree = NULL; + usrtc_node_t *node = NULL; + int r = ENOMEM; + + /* check for existing one */ + node = usrtc_lookup(tree, &type); + if(node) return EEXIST; + + /* allocate all */ + if(!(nlist = malloc(sizeof(rpc_typed_list_t)))) goto __fail; + else memset(nlist, 0, sizeof(rpc_typed_list_t)); + if(!(rpc_list = malloc(sizeof(cx_rpc_list_t)))) goto __fail; + else memset(rpc_list, 0, sizeof(cx_rpc_list_t)); + if(!(rtree = malloc(sizeof(usrtc_t)))) goto __fail; + + /* version and description */ + if(!(nlist->description = strdup(description))) goto __fail_a; + if(version) { /* in case of existing version */ + if(!(rpc_list->opt_version = strdup(version))) goto __fail_a; + } + /* initialize all */ + nlist->type_id = type; + nlist->rpc_list = rpc_list; + rpc_list->rpc_tree = rtree; + usrtc_node_init(&(nlist->lnode), nlist); + usrtc_init(rtree, USRTC_SPLAY, MAX_RPC_LIST, __cmp_cstr); + node = &(nlist->lnode); + /* insert it */ + usrtc_insert(tree, node, &(nlist->type_id)); + + return 0; + __fail_a: + if(nlist->description) free(nlist->description); + if(rpc_list->opt_version) free(rpc_list->opt_version); + __fail: + if(nlist) free(nlist); + if(rpc_list) free(rpc_list); + if(rtree) free(rtree); + return r; +} + +int sntl_rpclist_add_function(usrtc_t *tree, int type, const char *fu_name, + int (*rpcf)(void *, sexp_t *)) +{ + usrtc_node_t *node; + rpc_typed_list_t *tlist; + cx_rpc_list_t *rlist; + cx_rpc_t *rentry = NULL; + + node = usrtc_lookup(tree, &type); + if(!node) return ENOENT; + else tlist = (rpc_typed_list_t *)usrtc_node_getdata(node); + rlist = tlist->rpc_list; /* get rpc list */ + + /* ok, we don't allow dupes */ + node = usrtc_lookup(rlist->rpc_tree, fu_name); + if(node) return EEXIST; + if(!(rentry = malloc(sizeof(cx_rpc_t)))) return ENOMEM; + else if(!(rentry->name = strdup(fu_name))) { + free(rentry); + return ENOMEM; + } + + /* init */ + usrtc_node_init(&(rentry->node), rentry); + rentry->rpcf = rpcf; + node = &(rentry->node); + usrtc_insert(rlist->rpc_tree, node, rentry->name); /* insert it */ + + return 0; +} + +int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter) +{ + int r = 0, *f = filter, i; + usrtc_t *destination = NULL; + usrtc_node_t *node; + rpc_typed_list_t *tlist, *tlist_filter; + + if(!filter) return EINVAL; + if(!(destination = malloc(sizeof(usrtc_t)))) return ENOMEM; + else usrtc_init(destination, USRTC_REDBLACK, MAX_RPC_LIST, __cmp_int); + + switch(flag) { + case SNTL_FILTER_EXC: + for(node = usrtc_first(source); ; node = usrtc_next(source, node)) { + tlist = (rpc_typed_list_t *)usrtc_node_getdata(node); + r = ENOENT; + for(i = *f; i != SNTL_FILTER_END; f++, i = *f) { + if(tlist->type_id == i) { + r = 0; break; + } + } + if(r) { /* we should clone it */ + if(!(tlist_filter = malloc(sizeof(rpc_typed_list_t)))) continue; /* skip */ + else { + tlist_filter->type_id = tlist->type_id; + tlist_filter->description = tlist->description; + tlist_filter->rpc_list = tlist->rpc_list; + usrtc_node_init(&(tlist_filter->lnode), tlist_filter); + usrtc_insert(destination, &(tlist_filter->lnode), &(tlist_filter->type_id)); + } + } + + if(node == usrtc_last(source)) break; + } + r = 0; + break; + case SNTL_FILTER_INC: + for(i = *f; i != SNTL_FILTER_END; f++, i = *f) { + node = usrtc_lookup(source, &i); + if(!node) continue; /* skip it at all */ + else tlist = (rpc_typed_list_t *)usrtc_node_getdata(node); + /* clone tlist */ + if(!(tlist_filter = malloc(sizeof(rpc_typed_list_t)))) continue; /* skip */ + else { + tlist_filter->type_id = tlist->type_id; + tlist_filter->description = tlist->description; + tlist_filter->rpc_list = tlist->rpc_list; + usrtc_node_init(&(tlist_filter->lnode), tlist_filter); + usrtc_insert(destination, &(tlist_filter->lnode), &(tlist_filter->type_id)); + } + } + break; + default: + r = EINVAL; + goto __fail; + } + + if(!usrtc_count(destination)) { /* we have an empty list */ + r = EINVAL; + goto __fail; + } + + *dest = destination; + return 0; + __fail: + if(destination) free(destination); + return r; }