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.
308 lines
6.9 KiB
C
308 lines
6.9 KiB
C
#include <stdio.h>
|
|
#define __USE_GNU
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <sys/types.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/connection.h>
|
|
|
|
#include <pthread.h>
|
|
// #include <unistd.h>
|
|
#include <stdint.h>
|
|
#include <getopt.h>
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
void signal_error(int sig, siginfo_t *si, void *ptr)
|
|
{
|
|
void* error_addr;
|
|
void* trace[16];
|
|
int x;
|
|
int trace_size;
|
|
char** messages;
|
|
|
|
fprintf(stderr, "Something is wrong: backtrace: \n");
|
|
uintptr_t fptr = (uintptr_t)(si->si_addr);
|
|
fprintf(stderr, "Signal: %d, function pointer: 0x%.12lX \n", sig, fptr);
|
|
#if __WORDSIZE == 64
|
|
error_addr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_RIP];
|
|
#else
|
|
error_addr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_EIP];
|
|
#endif
|
|
|
|
trace_size = backtrace(trace, 16);
|
|
trace[1] = error_addr;
|
|
|
|
messages = backtrace_symbols(trace, trace_size);
|
|
if (messages)
|
|
{
|
|
for (x = 1; x < trace_size; x++)
|
|
{
|
|
fprintf(stderr, "%s\n", messages[x]);
|
|
}
|
|
free(messages);
|
|
}
|
|
|
|
fprintf(stderr, "end of backtrace\n");
|
|
|
|
exit(1);
|
|
}
|
|
|
|
#endif
|
|
|
|
/* helper functions */
|
|
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 0;
|
|
}
|
|
|
|
/*
|
|
* 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 0;
|
|
}
|
|
|
|
/* list of rpc calls functions */
|
|
usrtc_t *fulist;
|
|
|
|
/* our fake */
|
|
usrtc_t *__rettlist(conn_t *c)
|
|
{
|
|
return fulist;
|
|
}
|
|
|
|
/* RPC functions implementation */
|
|
static int __ar_add(void *m, sexp_t *sx)
|
|
{
|
|
// int timout = rand() % 1000000;
|
|
// usleep(timout);
|
|
sexp_t *lsx = NULL, *sx_iter;
|
|
sxmsg_t *msg = (sxmsg_t *)m;
|
|
int idx, rc = 0;
|
|
|
|
if(sexp_list_cdr(sx, &lsx)) {
|
|
printf("Invalid protocol\n");
|
|
return EINVAL;
|
|
}
|
|
|
|
long int sum = 0;
|
|
SEXP_ITERATE_LIST(lsx, sx_iter, idx) {
|
|
if(!SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) {
|
|
printf("Invalid value type\n");
|
|
return EINVAL;
|
|
}
|
|
sum += atoi(sx_iter->val);
|
|
}
|
|
rc = msg_return(msg, sum);
|
|
return rc;
|
|
}
|
|
|
|
static int __ar_multiply(void *data, sexp_t *sx)
|
|
{
|
|
sexp_t *lsx = NULL;
|
|
int idx;
|
|
sexp_t *sx_iter;
|
|
if(sexp_list_cdr(sx, &lsx)) {
|
|
printf("Invalid protocol\n");
|
|
return EINVAL;
|
|
}
|
|
|
|
long int mult = 0;
|
|
SEXP_ITERATE_LIST(lsx, sx_iter, idx) {
|
|
if(!SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) {
|
|
printf("Invalid value type\n");
|
|
return EINVAL;
|
|
}
|
|
mult *= atoi(sx_iter->val);
|
|
}
|
|
char buf[128];
|
|
sprintf(buf, "(ar_mult_set (%ld))", mult);
|
|
printf("result %s\n", buf);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* define a little bit */
|
|
#define DEFAULT_PORT 13133
|
|
|
|
static void sigpipe_handler(int a)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
// set detailed signal handler
|
|
// struct sigaction sigact, sigpipe;
|
|
// sigact.sa_flags = SA_SIGINFO;
|
|
// sigact.sa_sigaction = signal_error;
|
|
// sigemptyset(&sigact.sa_mask);
|
|
// sigaction(SIGFPE, &sigact, 0);
|
|
// sigaction(SIGILL, &sigact, 0);
|
|
// sigaction(SIGSEGV, &sigact, 0);
|
|
// sigaction(SIGBUS, &sigact, 0);
|
|
|
|
// memset(&sigpipe, 0, sizeof(struct sigaction));
|
|
// sigpipe.sa_handler = sigpipe_handler;
|
|
// sigaction(SIGPIPE, &sigpipe, NULL);
|
|
|
|
char *rootca = NULL, *cert = NULL;
|
|
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;
|
|
}
|
|
|
|
/* all is fine let's init connection subsystem */
|
|
opt = connections_subsystem_init();
|
|
if(opt) {
|
|
fprintf(stderr, "Subsystem init failed: %d\n", opt);
|
|
return opt;
|
|
}
|
|
/* set wroking certificates */
|
|
opt = connections_subsystem_setsslserts(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_subsystem_set_securecheck(conn_sys, __secure_check);
|
|
connections_subsystem_set_sslvalidator(conn_sys, __validate_sslpem);
|
|
/* set a callback, it's optional and doesn't required in server side apps */
|
|
connections_subsystem_set_rpctlist_call(conn_sys, __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;
|
|
}
|
|
/* ok, let's add two functions */
|
|
opt = sntl_rpclist_add_function(fulist, 12, "ar-add", __ar_add);
|
|
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, "ar-multiply", __ar_multiply);
|
|
if(opt) goto __fail;
|
|
|
|
/* ok, setup it */
|
|
connections_subsystem_setrpclist_function(__rettlist);
|
|
|
|
/* now we're ready to run the listen process */
|
|
int srv = __openlistener(port);
|
|
while(1) {
|
|
struct sockaddr_in addr;
|
|
socklen_t len = sizeof(addr);
|
|
conn_t *co = malloc(sizeof(conn_t));
|
|
|
|
int client = accept(srv, (struct sockaddr*)&addr, &len); /* accept connection as usual */
|
|
opt = connection_create(co, client); /* create connection, that's all */
|
|
if(opt) {
|
|
fprintf(stderr, "Cannot create connetion (%d)\n", opt);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|