You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libsxmp/lib/rpc.c

199 lines
5.7 KiB
C

/*
* Secure X Message Passing Library v2 implementation.
* (c) Askele Group 2013-2015 <http://askele.com>
* (c) Alexander Vdolainen 2013-2015 <avdolainen@gmail.com>
*
* libsxmp is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libsxmp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.";
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <tdata/usrtc.h>
#include <sexpr/sexp.h>
#include <sxmp/sxmp.h>
#include <sxmp/limits.h>
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 sxmp_rpclist_init(usrtc_t *tree)
{
usrtc_init(tree, USRTC_REDBLACK, MAX_RPC_LIST, __cmp_int);
return 0;
}
int sxmp_rpclist_add(usrtc_t *tree, int type, const char *description,
const char *version)
{
rpc_typed_list_t *nlist = NULL;
sxl_rpclist_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(sxl_rpclist_t)))) goto __fail;
else memset(rpc_list, 0, sizeof(sxl_rpclist_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 sxmp_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;
sxl_rpclist_t *rlist;
sxl_rpc_t *rentry = NULL;
if(*fu_name == '!') return EINVAL; /* reserve such names for ither purposes */
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(sxl_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 sxmp_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 SXMP_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 != SXMP_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 SXMP_FILTER_INC:
for(i = *f; i != SXMP_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;
}