|
|
|
@ -38,11 +38,12 @@
|
|
|
|
|
#include <tdata/usrtc.h>
|
|
|
|
|
#include <sexpr/sexp.h>
|
|
|
|
|
|
|
|
|
|
#include <sntl/sntllv2.h>
|
|
|
|
|
#include <sxmp/limits.h>
|
|
|
|
|
#include <sxmp/sxmp.h>
|
|
|
|
|
|
|
|
|
|
static int __insert_rpc_function(usrtc_t *tree, const char *name, int (*rpcf)(void *, sexp_t *))
|
|
|
|
|
{
|
|
|
|
|
cx_rpc_t *ent = malloc(sizeof(cx_rpc_t));
|
|
|
|
|
sxl_rpc_t *ent = malloc(sizeof(sxl_rpc_t));
|
|
|
|
|
usrtc_node_t *node;
|
|
|
|
|
|
|
|
|
|
if(!ent) return ENOMEM;
|
|
|
|
@ -62,10 +63,10 @@ static int __insert_rpc_function(usrtc_t *tree, const char *name, int (*rpcf)(vo
|
|
|
|
|
static void __destroy_rpc_list_tree(usrtc_t *tree)
|
|
|
|
|
{
|
|
|
|
|
usrtc_node_t *node;
|
|
|
|
|
cx_rpc_t *ent;
|
|
|
|
|
sxl_rpc_t *ent;
|
|
|
|
|
|
|
|
|
|
for(node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) {
|
|
|
|
|
ent = (cx_rpc_t *)usrtc_node_getdata(node);
|
|
|
|
|
ent = (sxl_rpc_t *)usrtc_node_getdata(node);
|
|
|
|
|
usrtc_delete(tree, node);
|
|
|
|
|
free(ent->name);
|
|
|
|
|
free(ent);
|
|
|
|
@ -83,45 +84,45 @@ static void __destroy_rpc_list_tree(usrtc_t *tree)
|
|
|
|
|
static int __set_credentials(void *cctx, sexp_t *sx)
|
|
|
|
|
{
|
|
|
|
|
register int idx;
|
|
|
|
|
conn_t *co = (conn_t *)cctx;
|
|
|
|
|
conn_sys_t *ssys = co->ssys;
|
|
|
|
|
sxlink_t *co = (sxlink_t *)cctx;
|
|
|
|
|
sxhub_t *ssys = co->ssys;
|
|
|
|
|
sexp_t *isx;
|
|
|
|
|
char *login = NULL;
|
|
|
|
|
char *passwd = NULL;
|
|
|
|
|
|
|
|
|
|
/* take a deal with S-exp */
|
|
|
|
|
SEXP_ITERATE_LIST(sx, isx, idx) {
|
|
|
|
|
if(isx->ty == SEXP_LIST) return SNE_BADPROTO;
|
|
|
|
|
if(isx->ty == SEXP_LIST) return SXE_BADPROTO;
|
|
|
|
|
|
|
|
|
|
if(idx > 0 && isx->aty != SEXP_DQUOTE) return SNE_BADPROTO;
|
|
|
|
|
if(idx > 0 && isx->aty != SEXP_DQUOTE) return SXE_BADPROTO;
|
|
|
|
|
if(idx == 1) login = isx->val;
|
|
|
|
|
else if(idx == 2) passwd = isx->val;
|
|
|
|
|
else if(idx > 2) return SNE_BADPROTO;
|
|
|
|
|
else if(idx > 2) return SXE_BADPROTO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!login || !passwd) return SNE_BADPROTO;
|
|
|
|
|
if(!login || !passwd) return SXE_BADPROTO;
|
|
|
|
|
|
|
|
|
|
co->pctx->login = strdup(login);
|
|
|
|
|
co->pctx->passwd = strdup(passwd);
|
|
|
|
|
if(!co->pctx->login || !co->pctx->passwd) {
|
|
|
|
|
if(co->pctx->login) free(co->pctx->login);
|
|
|
|
|
if(co->pctx->passwd) free(co->pctx->passwd);
|
|
|
|
|
return SNE_ENOMEM;
|
|
|
|
|
return SXE_ENOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(ssys->secure_check) return ssys->secure_check(co);
|
|
|
|
|
else return SNE_SUCCESS;
|
|
|
|
|
else return SXE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __get_channels_list(void *cctx, sexp_t *sx)
|
|
|
|
|
{
|
|
|
|
|
conn_t *co = (conn_t *)cctx;
|
|
|
|
|
conn_sys_t *ssys = co->ssys;
|
|
|
|
|
sxlink_t *co = (sxlink_t *)cctx;
|
|
|
|
|
sxhub_t *ssys = co->ssys;
|
|
|
|
|
sxmsg_t *msg = co->messages[0];
|
|
|
|
|
char *buf = msg->payload;
|
|
|
|
|
usrtc_node_t *node;
|
|
|
|
|
rpc_typed_list_t *list_ent;
|
|
|
|
|
size_t maxlen = 65535 - sizeof(sntllv2_head_t);
|
|
|
|
|
size_t maxlen = 65535 - sizeof(sxmplv2_head_t);
|
|
|
|
|
size_t ulen = 0;
|
|
|
|
|
|
|
|
|
|
/* we will avoid S-exp scanning here */
|
|
|
|
@ -129,8 +130,8 @@ static int __get_channels_list(void *cctx, sexp_t *sx)
|
|
|
|
|
/* call the function */
|
|
|
|
|
if(ssys->get_rpc_typed_list_tree)
|
|
|
|
|
co->rpc_list = ssys->get_rpc_typed_list_tree(co);
|
|
|
|
|
if(!co->rpc_list) return SNE_EPERM;
|
|
|
|
|
//buf += sizeof(sntllv2_head_t);
|
|
|
|
|
if(!co->rpc_list) return SXE_EPERM;
|
|
|
|
|
//buf += sizeof(sxmplv2_head_t);
|
|
|
|
|
ulen += snprintf(buf + ulen, maxlen - ulen, "(set-channels-list ");
|
|
|
|
|
for(node = usrtc_first(co->rpc_list); node != NULL;
|
|
|
|
|
node = usrtc_next(co->rpc_list, node)) { /* fill the list */
|
|
|
|
@ -142,49 +143,49 @@ static int __get_channels_list(void *cctx, sexp_t *sx)
|
|
|
|
|
msg->mhead.payload_length = ulen + 1;
|
|
|
|
|
|
|
|
|
|
/* we're ready for messaging mode */
|
|
|
|
|
co->flags |= SNSX_MESSAGINGMODE;
|
|
|
|
|
co->flags |= SXMP_MESSAGINGMODE;
|
|
|
|
|
|
|
|
|
|
return SNE_SUCCESS;
|
|
|
|
|
return SXE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __set_channels_list(void *cctx, sexp_t *sx)
|
|
|
|
|
{
|
|
|
|
|
register int idx;
|
|
|
|
|
conn_t *co = (conn_t *)cctx;
|
|
|
|
|
conn_sys_t *ssys = co->ssys;
|
|
|
|
|
sxlink_t *co = (sxlink_t *)cctx;
|
|
|
|
|
sxhub_t *ssys = co->ssys;
|
|
|
|
|
sexp_t *isx, *iisx;
|
|
|
|
|
int id, r;
|
|
|
|
|
|
|
|
|
|
SEXP_ITERATE_LIST(sx, isx, idx) {
|
|
|
|
|
if(!idx) continue;
|
|
|
|
|
|
|
|
|
|
if(isx->ty != SEXP_LIST) return SNE_BADPROTO;
|
|
|
|
|
if(sexp_list_length(isx) != 2) return SNE_BADPROTO;
|
|
|
|
|
if(isx->ty != SEXP_LIST) return SXE_BADPROTO;
|
|
|
|
|
if(sexp_list_length(isx) != 2) return SXE_BADPROTO;
|
|
|
|
|
|
|
|
|
|
/* get id */
|
|
|
|
|
sexp_list_car(isx, &iisx);
|
|
|
|
|
if(iisx->ty == SEXP_LIST) return SNE_BADPROTO;
|
|
|
|
|
if(iisx->aty != SEXP_BASIC) return SNE_BADPROTO;
|
|
|
|
|
if(iisx->val[0] != ':') return SNE_BADPROTO;
|
|
|
|
|
if(iisx->ty == SEXP_LIST) return SXE_BADPROTO;
|
|
|
|
|
if(iisx->aty != SEXP_BASIC) return SXE_BADPROTO;
|
|
|
|
|
if(iisx->val[0] != ':') return SXE_BADPROTO;
|
|
|
|
|
id = atoi(iisx->val + sizeof(char));
|
|
|
|
|
|
|
|
|
|
/* get short description */
|
|
|
|
|
sexp_list_cdr(isx, &iisx);
|
|
|
|
|
if(iisx->ty == SEXP_LIST) return SNE_BADPROTO;
|
|
|
|
|
if(iisx->aty != SEXP_DQUOTE) return SNE_BADPROTO;
|
|
|
|
|
if(iisx->ty == SEXP_LIST) return SXE_BADPROTO;
|
|
|
|
|
if(iisx->aty != SEXP_DQUOTE) return SXE_BADPROTO;
|
|
|
|
|
|
|
|
|
|
/* ok, here we go */
|
|
|
|
|
if(ssys->set_typed_list_callback) {
|
|
|
|
|
r = ssys->set_typed_list_callback(co, id, iisx->val);
|
|
|
|
|
if(r != SNE_SUCCESS) return r;
|
|
|
|
|
if(r != SXE_SUCCESS) return r;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* we're ready for messaging mode */
|
|
|
|
|
co->flags |= SNSX_MESSAGINGMODE;
|
|
|
|
|
co->flags &= ~SNSX_BATCHMODE;
|
|
|
|
|
co->flags |= SXMP_MESSAGINGMODE;
|
|
|
|
|
co->flags &= ~SXMP_BATCHMODE;
|
|
|
|
|
|
|
|
|
|
return SNE_SUCCESS;
|
|
|
|
|
return SXE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __init_systemrpc_tree(usrtc_t *rtree)
|
|
|
|
@ -206,23 +207,23 @@ static long __cmp_cstr(const void *a, const void *b)
|
|
|
|
|
return (long)strcmp((const char *)a, (const char *)b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int connections_init(conn_sys_t *ssys)
|
|
|
|
|
int links_init(sxhub_t *ssys)
|
|
|
|
|
{
|
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
|
|
if(!ssys) return EINVAL;
|
|
|
|
|
else memset(ssys, 0, sizeof(conn_sys_t));
|
|
|
|
|
else memset(ssys, 0, sizeof(sxhub_t));
|
|
|
|
|
|
|
|
|
|
if(!(ssys->connections = malloc(sizeof(usrtc_t)))) return ENOMEM;
|
|
|
|
|
if(!(ssys->links = malloc(sizeof(usrtc_t)))) return ENOMEM;
|
|
|
|
|
|
|
|
|
|
/* init connections list */
|
|
|
|
|
usrtc_init(ssys->connections, USRTC_REDBLACK, MAX_CONNECTIONS,
|
|
|
|
|
/* init links list */
|
|
|
|
|
usrtc_init(ssys->links, USRTC_REDBLACK, MAX_LINKS,
|
|
|
|
|
__cmp_cstr);
|
|
|
|
|
if((r = pthread_rwlock_init(&(ssys->rwlock), NULL)))
|
|
|
|
|
goto __fini;
|
|
|
|
|
|
|
|
|
|
/* init RPC list related functions */
|
|
|
|
|
if(!(ssys->system_rpc = malloc(sizeof(cx_rpc_list_t)))) {
|
|
|
|
|
if(!(ssys->system_rpc = malloc(sizeof(sxl_rpclist_t)))) {
|
|
|
|
|
r = ENOMEM;
|
|
|
|
|
goto __lfini;
|
|
|
|
|
} else {
|
|
|
|
@ -244,42 +245,42 @@ int connections_init(conn_sys_t *ssys)
|
|
|
|
|
if(ssys->system_rpc) free(ssys->system_rpc);
|
|
|
|
|
pthread_rwlock_destroy(&(ssys->rwlock));
|
|
|
|
|
__fini:
|
|
|
|
|
if(ssys->connections) free(ssys->connections);
|
|
|
|
|
if(ssys->links) free(ssys->links);
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int connections_free(conn_sys_t *ssys)
|
|
|
|
|
int links_free(sxhub_t *ssys)
|
|
|
|
|
{
|
|
|
|
|
__destroy_rpc_list_tree(ssys->system_rpc->rpc_tree);
|
|
|
|
|
free(ssys->system_rpc->rpc_tree);
|
|
|
|
|
free(ssys->system_rpc);
|
|
|
|
|
free(ssys->connections);
|
|
|
|
|
free(ssys->links);
|
|
|
|
|
pthread_rwlock_destroy(&(ssys->rwlock));
|
|
|
|
|
SSL_CTX_free(ssys->ctx);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int connections_destroy(conn_sys_t *ssys)
|
|
|
|
|
int links_destroy(sxhub_t *ssys)
|
|
|
|
|
{
|
|
|
|
|
int r = connections_free(ssys);
|
|
|
|
|
int r = links_free(ssys);
|
|
|
|
|
free(ssys);
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conn_sys_t *connections_create(void)
|
|
|
|
|
sxhub_t *links_create(void)
|
|
|
|
|
{
|
|
|
|
|
int r = 0;
|
|
|
|
|
conn_sys_t *nsys = malloc(sizeof(conn_sys_t));
|
|
|
|
|
sxhub_t *nsys = malloc(sizeof(sxhub_t));
|
|
|
|
|
|
|
|
|
|
if(!nsys) {
|
|
|
|
|
errno = ENOMEM;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = connections_init(nsys);
|
|
|
|
|
r = links_init(nsys);
|
|
|
|
|
if(r) {
|
|
|
|
|
errno = r;
|
|
|
|
|
free(nsys);
|
|
|
|
@ -289,7 +290,7 @@ conn_sys_t *connections_create(void)
|
|
|
|
|
return nsys;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int connections_setsslserts(conn_sys_t *ssys, const char *rootca,
|
|
|
|
|
int links_setsslserts(sxhub_t *ssys, const char *rootca,
|
|
|
|
|
const char *certpem, const char *certkey)
|
|
|
|
|
{
|
|
|
|
|
int r = ENOMEM;
|
|
|
|
@ -316,31 +317,31 @@ struct __scerrcode {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct __scerrcode __lerr[] = {
|
|
|
|
|
{SNE_SUCCESS, "Success"},
|
|
|
|
|
{SNE_FAILED, "Failed, invalid parameters given"},
|
|
|
|
|
{SNE_ENOMEM, "Not enough memory"},
|
|
|
|
|
{SNE_BADPROTO, "Bad protocol"},
|
|
|
|
|
{SNE_ENORPC, "No such RPC exists"},
|
|
|
|
|
{SNE_EPERM, "Permission denied"},
|
|
|
|
|
{SNE_TOOLONG, "Message data payload too long to be sent with one message pass"},
|
|
|
|
|
{SNE_EBUSY, "Index or working threads are busy"},
|
|
|
|
|
{SNE_WOULDBLOCK, "Call will block operation"},
|
|
|
|
|
{SNE_LINKERROR, "Connection link error"},
|
|
|
|
|
{SNE_NOSUCHMSG, "No such message"},
|
|
|
|
|
{SNE_NOSUCHCHAN, "No such channel"},
|
|
|
|
|
{SNE_ETIMEDOUT, "Timeout exceed"},
|
|
|
|
|
{SNE_IGNORED, "Function call was ignored"},
|
|
|
|
|
{SNE_REPLYREQ, "Reply required to the message"},
|
|
|
|
|
{SNE_RAPIDMSG, "Message is a rapid reply and dialog closed"},
|
|
|
|
|
{SNE_ESSL, "SSL error occurs on connection link"},
|
|
|
|
|
{SNE_NOCHANNELS, "No channels available"},
|
|
|
|
|
{SNE_MCHANNELS, "Active channels limit exceed"},
|
|
|
|
|
{SNE_MMESSAGES, "Active messages limit exceed"},
|
|
|
|
|
{SNE_LINKBROKEN, "Connection link was broken"},
|
|
|
|
|
{SNE_INVALINDEX, "Invalid index given"},
|
|
|
|
|
{SXE_SUCCESS, "Success"},
|
|
|
|
|
{SXE_FAILED, "Failed, invalid parameters given"},
|
|
|
|
|
{SXE_ENOMEM, "Not enough memory"},
|
|
|
|
|
{SXE_BADPROTO, "Bad protocol"},
|
|
|
|
|
{SXE_ENORPC, "No such RPC exists"},
|
|
|
|
|
{SXE_EPERM, "Permission denied"},
|
|
|
|
|
{SXE_TOOLONG, "Message data payload too long to be sent with one message pass"},
|
|
|
|
|
{SXE_EBUSY, "Index or working threads are busy"},
|
|
|
|
|
{SXE_WOULDBLOCK, "Call will block operation"},
|
|
|
|
|
{SXE_LINKERROR, "Connection link error"},
|
|
|
|
|
{SXE_NOSUCHMSG, "No such message"},
|
|
|
|
|
{SXE_NOSUCHCHAN, "No such channel"},
|
|
|
|
|
{SXE_ETIMEDOUT, "Timeout exceed"},
|
|
|
|
|
{SXE_IGNORED, "Function call was ignored"},
|
|
|
|
|
{SXE_REPLYREQ, "Reply required to the message"},
|
|
|
|
|
{SXE_RAPIDMSG, "Message is a rapid reply and dialog closed"},
|
|
|
|
|
{SXE_ESSL, "SSL error occurs on connection link"},
|
|
|
|
|
{SXE_NOCHANNELS, "No channels available"},
|
|
|
|
|
{SXE_MCHANNELS, "Active channels limit exceed"},
|
|
|
|
|
{SXE_MMESSAGES, "Active messages limit exceed"},
|
|
|
|
|
{SXE_LINKBROKEN, "Connection link was broken"},
|
|
|
|
|
{SXE_INVALINDEX, "Invalid index given"},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const char *sntll_errno2cstr(int ec)
|
|
|
|
|
{
|
|
|
|
|
return __lerr[ec - __SNTL_EPREFIX].desc;
|
|
|
|
|
return __lerr[ec - __SXMP_EPREFIX].desc;
|
|
|
|
|
}
|
|
|
|
|