connections separated;
parent
aeab862738
commit
2d20080776
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#define EBADE 1
|
||||
#define NETDB_SUCCESS 0
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <sexpr/sexp.h>
|
||||
|
||||
#include <sntl/connection.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));
|
||||
usrtc_node_t *node;
|
||||
|
||||
if(!ent) return ENOMEM;
|
||||
else node = &ent->node;
|
||||
|
||||
if(!(ent->name = strdup(name))) {
|
||||
free(ent);
|
||||
return ENOMEM;
|
||||
} else ent->rpcf = rpcf;
|
||||
|
||||
usrtc_node_init(node, ent);
|
||||
usrtc_insert(tree, node, ent->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __destroy_rpc_list_tree(usrtc_t *tree)
|
||||
{
|
||||
usrtc_node_t *node;
|
||||
cx_rpc_t *ent;
|
||||
|
||||
for(node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) {
|
||||
ent = (cx_rpc_t *)usrtc_node_getdata(node);
|
||||
usrtc_delete(tree, node);
|
||||
free(ent->name);
|
||||
free(ent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* negotiation functions */
|
||||
/**
|
||||
* Proto: (auth-set-credentials "<login>" "<password>")
|
||||
* Return - message return; opcode as a return of this function.
|
||||
* in batch mode message with 0 index used always
|
||||
*/
|
||||
static int __set_credentials(void *cctx, sexp_t *sx)
|
||||
{
|
||||
register int idx;
|
||||
conn_t *co = (conn_t *)cctx;
|
||||
conn_sys_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(idx > 0 && isx->aty != SEXP_DQUOTE) return SNE_BADPROTO;
|
||||
if(idx == 1) login = isx->val;
|
||||
else if(idx == 2) passwd = isx->val;
|
||||
else if(idx > 2) return SNE_BADPROTO;
|
||||
}
|
||||
|
||||
if(!login || !passwd) return SNE_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;
|
||||
}
|
||||
|
||||
if(ssys->secure_check) return ssys->secure_check(co);
|
||||
else return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
static int __get_channels_list(void *cctx, sexp_t *sx)
|
||||
{
|
||||
conn_t *co = (conn_t *)cctx;
|
||||
conn_sys_t *ssys = co->ssys;
|
||||
sx_msg_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 len, ulen = 0;
|
||||
|
||||
/* we will avoid S-exp scanning here */
|
||||
|
||||
buf += sizeof(sntllv2_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 */
|
||||
list_ent = (rpc_typed_list_t *)usrtc_node_getdata(node);
|
||||
ulen += snprintf(buf + ulen, maxlen - ulen, "(:%d \"%s\")",
|
||||
list_ent->type_id, list_ent->description);
|
||||
}
|
||||
ulen += snprintf(buf + ulen, maxlen - ulen, ")");
|
||||
msg->payload_length = ulen + sizeof(sntllv2_head_t);
|
||||
|
||||
return SNE_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;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
static int __init_systemrpc_tree(usrtc_t *rtree)
|
||||
{
|
||||
/* batch mode negotiation context functions */
|
||||
if(__insert_rpc_function(rtree, "auth-set-credentials", __set_credentials)) goto __fail;
|
||||
if(__insert_rpc_function(rtree, "get-channels-list", __get_channels_list)) goto __fail;
|
||||
if(__insert_rpc_function(rtree, "set-channels-list", __set_channels_list)) goto __fail;
|
||||
|
||||
return 0;
|
||||
|
||||
__fail:
|
||||
__destroy_rpc_list_tree(rtree);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
int connections_init(conn_sys_t *ssys)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if(!ssys) return EINVAL;
|
||||
else memset(ssys, 0, sizeof(conn_sys_t));
|
||||
|
||||
if(!(ssys->connections = malloc(sizeof(usrtc_t)))) return ENOMEM;
|
||||
|
||||
/* init connections list */
|
||||
usrtc_init(ssys->connections, USRTC_REDBLACK, MAX_CONNECTIONS,
|
||||
__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)))) {
|
||||
r = ENOMEM;
|
||||
goto __lfini;
|
||||
} else {
|
||||
if(!(ssys->system_rpc->rpc_tree = malloc(sizeof(usrtc_t)))) {
|
||||
r = ENOMEM;
|
||||
goto __lfini;
|
||||
}
|
||||
usrtc_init(ssys->system_rpc->rpc_tree, USRTC_SPLAY, 256, __cmp_cstr);
|
||||
r = __init_systemrpc_tree(ssys->system_rpc->rpc_tree);
|
||||
if(r) {
|
||||
free(ssys->system_rpc->rpc_tree);
|
||||
goto __lfini;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
__lfini:
|
||||
if(ssys->system_rpc) free(ssys->system_rpc);
|
||||
pthread_rwlock_destroy(&(ssys->rwlock));
|
||||
__fini:
|
||||
if(ssys->connections) free(ssys->connections);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
conn_sys_t *connections_create(void)
|
||||
{
|
||||
int r = 0;
|
||||
conn_sys_t *nsys = malloc(sizeof(conn_sys_t));
|
||||
|
||||
if(!nsys) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = connections_init(nsys);
|
||||
if(r) {
|
||||
errno = r;
|
||||
free(nsys);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nsys;
|
||||
}
|
Loading…
Reference in New Issue