the part of code clean up;
parent
0572e707c5
commit
472e772ec9
@ -1,505 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <stdio.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#define __USE_GNU
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <Winsock2.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#else
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <uuid/uuid.h>
|
|
||||||
#include <execinfo.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <tdata/usrtc.h>
|
|
||||||
#include <sexpr/sexp.h>
|
|
||||||
#include <sntl/limits.h>
|
|
||||||
#include <sntl/sntllv2.h>
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
// #include <unistd.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define DEBUG
|
|
||||||
#define FREE(x) { if (x) { free(x); x = NULL; } }
|
|
||||||
#define MAX_STREAMS INT_MAX
|
|
||||||
|
|
||||||
typedef struct __datastream_type {
|
|
||||||
int dsid;
|
|
||||||
usrtc_node_t node;
|
|
||||||
// readdir_r
|
|
||||||
DIR *dp;
|
|
||||||
struct dirent dent;
|
|
||||||
struct dirent *dres;
|
|
||||||
} datastream_t;
|
|
||||||
|
|
||||||
usrtc_t *_rd_streams;
|
|
||||||
int _rd_last_id = 0;
|
|
||||||
pthread_rwlock_t _lock;
|
|
||||||
|
|
||||||
/* helper functions */
|
|
||||||
static long __cmp_int(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
return *(int *)a - *(int *)b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void dump_dirent(struct dirent *d, char *buf)
|
|
||||||
{
|
|
||||||
if (d == NULL) return;
|
|
||||||
strcat(buf, "\"");
|
|
||||||
strcat(buf, d->d_name);
|
|
||||||
strcat(buf, "\" ");
|
|
||||||
switch(d->d_type)
|
|
||||||
{
|
|
||||||
case DT_REG:
|
|
||||||
strcat(buf, "\"regular\"");
|
|
||||||
break;
|
|
||||||
case DT_DIR:
|
|
||||||
strcat(buf, "\"directory\"");
|
|
||||||
break;
|
|
||||||
case DT_BLK:
|
|
||||||
strcat(buf, "\"block\"");
|
|
||||||
break;
|
|
||||||
case DT_CHR:
|
|
||||||
strcat(buf, "\"char\"");
|
|
||||||
break;
|
|
||||||
case DT_FIFO:
|
|
||||||
strcat(buf, "\"fifo\"");
|
|
||||||
break;
|
|
||||||
case DT_LNK:
|
|
||||||
strcat(buf, "\"link\"");
|
|
||||||
break;
|
|
||||||
case DT_UNKNOWN:
|
|
||||||
strcat(buf, "\"unknown\"");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
strcat(buf, "\"another\"");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int __openlistener(int port)
|
|
||||||
{
|
|
||||||
int sd;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
|
|
||||||
sd = socket(PF_INET, SOCK_STREAM, 0);
|
|
||||||
bzero(&addr, sizeof(addr));
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) {
|
|
||||||
perror("can't bind port");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
if ( listen(sd, 10) != 0 ) {
|
|
||||||
perror("Can't configure listening port");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
return sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Validation of the SSL certificate
|
|
||||||
* this function must be exist.
|
|
||||||
*/
|
|
||||||
static int __validate_sslpem(conn_t *co)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* validate - authorize user with password
|
|
||||||
*/
|
|
||||||
static int __secure_check(conn_t *co)
|
|
||||||
{
|
|
||||||
return SNE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* typed list callback
|
|
||||||
*/
|
|
||||||
static int __set_typed_list_callback(conn_t *co, int ch, char *desc)
|
|
||||||
{
|
|
||||||
printf("allowed channel %d (%s)\n", ch, desc);
|
|
||||||
return SNE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* list of rpc calls functions */
|
|
||||||
usrtc_t *fulist;
|
|
||||||
|
|
||||||
/* our fake */
|
|
||||||
usrtc_t *__rettlist(conn_t *c)
|
|
||||||
{
|
|
||||||
return fulist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RPC functions implementation */
|
|
||||||
static int __dir_open(void *m, sexp_t *sx)
|
|
||||||
{
|
|
||||||
sexp_t *lsx = NULL;
|
|
||||||
sxmsg_t *msg = (sxmsg_t *)m;
|
|
||||||
char *buf;
|
|
||||||
size_t ln = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
char dbuf[2048];
|
|
||||||
print_sexp(dbuf, sizeof(dbuf), sx);
|
|
||||||
printf("%s: got sx '%s'\n", __FUNCTION__, dbuf);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
if(sexp_list_cdr(sx, &lsx) || !sx->list->next || !sx->list->next->val) {
|
|
||||||
printf("Invalid protocol\n");
|
|
||||||
return sxmsg_return(msg, SNE_BADPROTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *dir_name = strdup(sx->list->next->val);
|
|
||||||
|
|
||||||
if ( usrtc_isfull(_rd_streams) ) {
|
|
||||||
return sxmsg_return(msg, SNE_TOOLONG);
|
|
||||||
}
|
|
||||||
|
|
||||||
datastream_t *item;
|
|
||||||
if ( !(item = malloc(sizeof(datastream_t))) ) {
|
|
||||||
return sxmsg_return(msg, SNE_ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find free id */
|
|
||||||
pthread_rwlock_wrlock(&_lock);
|
|
||||||
do {
|
|
||||||
if (_rd_last_id == INT_MAX)
|
|
||||||
_rd_last_id = 1;
|
|
||||||
else
|
|
||||||
++_rd_last_id;
|
|
||||||
} while (usrtc_lookup(_rd_streams, &_rd_last_id));
|
|
||||||
|
|
||||||
/* create rd stream */
|
|
||||||
DIR *dp = NULL;
|
|
||||||
if ( !(dp = opendir(dir_name)) ) {
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
FREE(item);
|
|
||||||
FREE(dir_name);
|
|
||||||
return sxmsg_return(msg, SNE_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
FREE(dir_name);
|
|
||||||
|
|
||||||
/* init stream */
|
|
||||||
item->dsid = _rd_last_id;
|
|
||||||
item->dp = dp;
|
|
||||||
item->dres = NULL;
|
|
||||||
usrtc_node_init(&(item->node), item);
|
|
||||||
usrtc_insert(_rd_streams, &(item->node), &item->dsid);
|
|
||||||
|
|
||||||
buf = sxmsg_rapidbuf(msg);
|
|
||||||
ln = snprintf(buf, MAX_RBBUF_LEN, "(dir-stream %d)", item->dsid);
|
|
||||||
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("%s: stream %d has been opened\n", __FUNCTION__, item->dsid);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
return sxmsg_rreply(msg, ln + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __dir_read(void *m, sexp_t *sx)
|
|
||||||
{
|
|
||||||
sexp_t *lsx = NULL;
|
|
||||||
sxmsg_t *msg = (sxmsg_t *)m;
|
|
||||||
char *buf;
|
|
||||||
size_t ln = 0;
|
|
||||||
int stid = -1;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
char dbuf[2048];
|
|
||||||
print_sexp(dbuf, sizeof(dbuf), sx);
|
|
||||||
printf("%s: got sx '%s'\n", __FUNCTION__, dbuf);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
if (sexp_list_cdr(sx, &lsx) || !sx->list->next || !sx->list->next->val
|
|
||||||
|| (0 >= (stid = atoi(sx->list->next->val) )) )
|
|
||||||
{
|
|
||||||
printf("Invalid protocol\n");
|
|
||||||
return sxmsg_return(msg, SNE_BADPROTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get stream item */
|
|
||||||
datastream_t *item;
|
|
||||||
usrtc_node_t *node;
|
|
||||||
pthread_rwlock_rdlock(&_lock);
|
|
||||||
if ( !(node = usrtc_lookup(_rd_streams, &stid)) ) {
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
return sxmsg_return(msg, SNE_INVALINDEX);
|
|
||||||
}
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
|
|
||||||
pthread_rwlock_wrlock(&_lock);
|
|
||||||
item = usrtc_node_getdata(node);
|
|
||||||
if (readdir_r(item->dp, &(item->dent), &(item->dres))) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("%s: readdir_r() is failed (%d)\n", __FUNCTION__, errno);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
return sxmsg_return(msg, SNE_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item->dres) {
|
|
||||||
buf = sxmsg_rapidbuf(msg);
|
|
||||||
ln = snprintf(buf, MAX_RBBUF_LEN, "(dir-end %d)", item->dsid);
|
|
||||||
goto __finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
char dump[2048];
|
|
||||||
sprintf(dump, "(dir-entry (");
|
|
||||||
dump_dirent(item->dres, dump);
|
|
||||||
strcat(dump, "))");
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("%s: dump = '%s'\n", __FUNCTION__, dump);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
buf = sxmsg_rapidbuf(msg);
|
|
||||||
ln = snprintf(buf, MAX_RBBUF_LEN, "%s", dump);
|
|
||||||
|
|
||||||
__finish:
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
return sxmsg_rreply(msg, ln + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __dir_close(void *m, sexp_t *sx)
|
|
||||||
{
|
|
||||||
sexp_t *lsx = NULL;
|
|
||||||
sxmsg_t *msg = (sxmsg_t *)m;
|
|
||||||
int stid = -1;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
char dbuf[2048];
|
|
||||||
print_sexp(dbuf, sizeof(dbuf), sx);
|
|
||||||
printf("%s: got sx '%s'\n", __FUNCTION__, dbuf);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
if (sexp_list_cdr(sx, &lsx) || !sx->list->next || !sx->list->next->val
|
|
||||||
|| (0 >= (stid = atoi(sx->list->next->val) )) )
|
|
||||||
{
|
|
||||||
printf("Invalid protocol\n");
|
|
||||||
return sxmsg_return(msg, SNE_BADPROTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get stream item */
|
|
||||||
datastream_t *item;
|
|
||||||
usrtc_node_t *node;
|
|
||||||
pthread_rwlock_rdlock(&_lock);
|
|
||||||
if ( !(node = usrtc_lookup(_rd_streams, &stid)) ) {
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
return sxmsg_return(msg, ENOENT);
|
|
||||||
}
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
|
|
||||||
pthread_rwlock_wrlock(&_lock);
|
|
||||||
item = usrtc_node_getdata(node);
|
|
||||||
closedir(item->dp);
|
|
||||||
usrtc_delete(_rd_streams, node);
|
|
||||||
FREE(item);
|
|
||||||
pthread_rwlock_unlock(&_lock);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("%s: stream %d has been closed\n", __FUNCTION__, stid);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
return sxmsg_return(msg, SNE_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* define a little bit */
|
|
||||||
#define DEFAULT_PORT 13133
|
|
||||||
|
|
||||||
static void sigpipe_handler(int a)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct startbundle {
|
|
||||||
int client;
|
|
||||||
conn_sys_t *ssys;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void *__starter_thread(void *stb);
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
|
|
||||||
char *rootca = NULL, *cert = NULL;
|
|
||||||
conn_sys_t *ssys = connections_create();
|
|
||||||
int port = DEFAULT_PORT;
|
|
||||||
int opt;
|
|
||||||
|
|
||||||
while((opt = getopt(argc, argv, "p:r:u:")) != -1) {
|
|
||||||
switch(opt) {
|
|
||||||
case 'p':
|
|
||||||
port = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
rootca = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
cert = strdup(optarg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "usage: %s [-p <PORTNUM>] -r <PATH to Root CA> -u <PATH"
|
|
||||||
" to SSL certificate>\n", argv[0]);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!rootca) {
|
|
||||||
fprintf(stderr, "Root CA not pointed.\n Failure.\n");
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!cert) {
|
|
||||||
fprintf(stderr, "User certificate not pointed.\n Failure.\n");
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sntl_init();
|
|
||||||
|
|
||||||
/* all is fine let's init connection subsystem */
|
|
||||||
if(!ssys) {
|
|
||||||
fprintf(stderr, "Subsystem init failed: %d\n", opt);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
/* set wroking certificates */
|
|
||||||
opt = connections_setsslserts(ssys, rootca, cert, cert);
|
|
||||||
if(opt) {
|
|
||||||
fprintf(stderr, "Subsystem init failed (set SSL x.509 pems): %d\n", opt);
|
|
||||||
return opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clean up */
|
|
||||||
free(rootca);
|
|
||||||
free(cert);
|
|
||||||
|
|
||||||
/* set important callbacks to do the security checking */
|
|
||||||
connections_set_authcheck(ssys, __secure_check);
|
|
||||||
connections_set_sslvalidate(ssys, __validate_sslpem);
|
|
||||||
/* set a callback, it's optional and doesn't required in server side apps */
|
|
||||||
connections_set_channelcall(ssys, __set_typed_list_callback);
|
|
||||||
|
|
||||||
/* ok, now we need to construct RPC lists (channels) */
|
|
||||||
if(!(fulist = malloc(sizeof(usrtc_t)))) {
|
|
||||||
fprintf(stderr, "Cannot allocate memory for RPC lists\n Failure.\n");
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
opt = sntl_rpclist_init(fulist);
|
|
||||||
if(opt) {
|
|
||||||
fprintf(stderr, "Failed to init rpc list\n Failure.\n");
|
|
||||||
return opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we will add one channel with type id 12 "Demo rpc list" */
|
|
||||||
opt = sntl_rpclist_add(fulist, 12, "Demo RPC list", NULL);
|
|
||||||
if(opt) {
|
|
||||||
fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n");
|
|
||||||
return opt;
|
|
||||||
}
|
|
||||||
opt = sntl_rpclist_add(fulist, 1, "Public", NULL);
|
|
||||||
if(opt) {
|
|
||||||
fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n");
|
|
||||||
return opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ok, let's add stream functions */
|
|
||||||
opt = sntl_rpclist_add_function(fulist, 12, "dir-open", __dir_open);
|
|
||||||
if(opt) {
|
|
||||||
__fail:
|
|
||||||
fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n");
|
|
||||||
return opt;
|
|
||||||
}
|
|
||||||
opt = sntl_rpclist_add_function(fulist, 12, "dir-read", __dir_read);
|
|
||||||
if(opt) goto __fail;
|
|
||||||
opt = sntl_rpclist_add_function(fulist, 12, "dir-close", __dir_close);
|
|
||||||
if(opt) goto __fail;
|
|
||||||
|
|
||||||
/* ok, setup it */
|
|
||||||
connections_set_rpcvalidator(ssys, __rettlist);
|
|
||||||
|
|
||||||
/* create stream tree */
|
|
||||||
if(!(_rd_streams = malloc(sizeof(usrtc_t)) ))
|
|
||||||
return ENOMEM;
|
|
||||||
usrtc_init(_rd_streams, USRTC_REDBLACK, MAX_STREAMS, __cmp_int);
|
|
||||||
|
|
||||||
/* now we're ready to run the listen process */
|
|
||||||
int srv = __openlistener(port);
|
|
||||||
pthread_t starter;
|
|
||||||
while(1) {
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
socklen_t len = sizeof(addr);
|
|
||||||
struct startbundle bundle;
|
|
||||||
conn_t *co;
|
|
||||||
|
|
||||||
bundle.ssys = ssys;
|
|
||||||
|
|
||||||
int client = accept(srv, (struct sockaddr*)&addr, &len); /* accept connection as usual */
|
|
||||||
blub(".");
|
|
||||||
co = connection_master_link(ssys, client, NULL);
|
|
||||||
|
|
||||||
if(!co) {
|
|
||||||
fprintf(stderr, "Cannot create connetion (%d)\n", errno);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
bundle.client = client;
|
|
||||||
pthread_create(&starter, NULL, __starter_thread, &bundle);
|
|
||||||
pthread_detach(starter);
|
|
||||||
// pthread_join(starter, &co);
|
|
||||||
//__starter_thread(&bundle);
|
|
||||||
usleep(2000);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
connections_destroy(ssys);
|
|
||||||
|
|
||||||
sntl_finalize();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *__starter_thread(void *stb)
|
|
||||||
{
|
|
||||||
struct startbundle *s = (struct startbundle *)stb;
|
|
||||||
int client = s->client;
|
|
||||||
conn_sys_t *ssys = s->ssys;
|
|
||||||
conn_t *co = connection_master_link(ssys, client, NULL);
|
|
||||||
|
|
||||||
if(!co) {
|
|
||||||
fprintf(stderr, "Cannot create connetion (%d)\n", errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
return co;
|
|
||||||
}
|
|
Loading…
Reference in New Issue