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.
199 lines
5.7 KiB
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;
|
|
}
|