#include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 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) { 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 int main(int argc, char **argv) { 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 ] -r -u \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) return opt; } return 0; }