From 15fb867657d930919a88ef92e69436562bf3663d Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 30 Jan 2016 03:24:40 +0200 Subject: [PATCH] added first stupid example; will test it later; --- Makefile.am | 14 +- configure.ac | 21 +-- examples/.gitignore | 2 + examples/Makefile.am | 25 +++ examples/filelist.h | 4 + examples/filelistc.c | 382 ++++++++++++++++++++++++++++++++++++++++- examples/filelistd.c | 12 +- tests/Makefile.am | 46 ----- tests/lv2ftp-proto.txt | 30 ---- tests/lv2ftpc.c | 352 ------------------------------------- 10 files changed, 426 insertions(+), 462 deletions(-) create mode 100644 examples/.gitignore create mode 100644 examples/Makefile.am delete mode 100644 tests/Makefile.am delete mode 100644 tests/lv2ftp-proto.txt delete mode 100644 tests/lv2ftpc.c diff --git a/Makefile.am b/Makefile.am index d2f7e32..2b1aa22 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,18 +1,12 @@ ## Process this file with automake to produce Makefile.in -#if BUILD_EXAMPLES -#EXAMPLES = examples -#else -#EXAMPLES = -#endif - -if BUILD_TESTS -TESTS = tests +if BUILD_EXAMPLES +EXAMPLES = examples else -TESTS = +EXAMPLES = endif -SUBDIRS = include lib man $(TESTS) +SUBDIRS = include lib man $(EXAMPLES) libsxmpdocdir = ${prefix}/doc/libsxmp libsxmpdoc_DATA = \ diff --git a/configure.ac b/configure.ac index e49ea52..641c095 100644 --- a/configure.ac +++ b/configure.ac @@ -16,23 +16,14 @@ dnl ***************** dnl ***** options ***** dnl ***************** -#AC_ARG_ENABLE([build_examples], -# AS_HELP_STRING([--enable-build-examples], [Enable examples build])) +AC_ARG_ENABLE([build_examples], + AS_HELP_STRING([--enable-build-examples], [Enable examples build])) -#AS_IF([test "x$enable_build_examples" = "xyes"], [ -# AC_DEFINE([BUILD_EXAMPLES], 1, [build of examples enabled]) -#]) - -#AM_CONDITIONAL(BUILD_EXAMPLES, test "x$enable_build_examples" = "xyes") - -AC_ARG_ENABLE([build_tests], - AS_HELP_STRING([--enable-build-tests], [Enable build of tests])) - -AS_IF([test "x$enable_build_tests" = "xyes"], [ - AC_DEFINE([BUILD_TESTS], 1, [build of tests enabled]) +AS_IF([test "x$enable_build_examples" = "xyes"], [ + AC_DEFINE([BUILD_EXAMPLES], 1, [build of examples enabled]) ]) -AM_CONDITIONAL(BUILD_TESTS, test "x$enable_build_tests" = "xyes") +AM_CONDITIONAL(BUILD_EXAMPLES, test "x$enable_build_examples" = "xyes") PKG_CHECK_MODULES(OPENSSL, [openssl]) @@ -61,4 +52,4 @@ lib/libsxmp.pc lib/Makefile include/Makefile man/Makefile -tests/Makefile]) +examples/Makefile]) diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..4d41f76 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,2 @@ +filelistc +filelistd diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..415658d --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,25 @@ +## AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \ + -DCNFPATH=\""$(prefix)/etc"\" \ + -I../include \ + -I../lib + +AM_CFLAGS = -Wall -g + +# where to find libsxmp +libsxmp = ../lib/.libs/libsxmp.la + +bin_PROGRAMS = filelistd filelistc + +filelistd_SOURCES = filelistd.c +filelistd_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ + $(LIBUUID_LIBS) $(libsxmp) -lpthread + +filelistc_SOURCES = filelistc.c +filelistc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ + $(LIBUUID_LIBS) $(libsxmp) -lpthread + diff --git a/examples/filelist.h b/examples/filelist.h index 3c152b7..cfb718b 100644 --- a/examples/filelist.h +++ b/examples/filelist.h @@ -38,6 +38,10 @@ #define DEFAULT_PORT 10240 +#define READONLY_CHANNEL 8 +#define WRITE_CHANNEL 16 +#define CONTROL_CHANNEL 20 + #define DEBUG #define FREE(x) { if (x) { free(x); x = NULL; } } #define MAX_STREAMS INT_MAX diff --git a/examples/filelistc.c b/examples/filelistc.c index b0aa0f7..11d72dd 100644 --- a/examples/filelistc.c +++ b/examples/filelistc.c @@ -61,10 +61,386 @@ #include #include "filelist.h" +#include "../config.h" + +#define FULL_PROGRAM_NAME "File lister client" + +struct _remote_host { + char *root_x509; + char *user_x509; + char *hostname; + char *login; + char *password; + int port; + sxhub_t *hub; + sxlink_t *link; +}; + +struct _icmd { + int id; + int opt; + char *cmdname; + int (*__fu)(FILE *, struct _remote_host *, const char *); +}; + +/* supported commands */ +enum commands { + __LISTDIR = 0, +}; + +static int __remote_ls(FILE *, struct _remote_host *, const char *); + +struct _icmd _tool[] = { + { .id = __LISTDIR, .opt = 0, .cmdname = "ls", .__fu = __remote_ls }, + { .id = 0, .opt = 0, .cmdname = NULL, .__fu = NULL }, +}; + +/* + * This function might be used to check supported RPC calls + * i.e. for each channel type id this callback is called. + * Whereas the place to check it with ID and description. + * Should return SXE_SUCCESS if supported. + */ +static int __rpcscheck_onclient(sxlink_t *l, int ch_tid, char *description) +{ + return SXE_SUCCESS; +} + +/* supplemetary functions to make code more readable */ +static int __close_dir_stream(sxchnl_t *c, int sid) +{ + int r = SXE_SUCCESS; + char *remote_rpc; + size_t remote_rpc_len; + sxmsg_t *msg = NULL; + + remote_rpc_len = strlen("dir-close") + sizeof(char)*16; + if(!(remote_rpc = malloc(remote_rpc_len))) return ENOMEM; + else remote_rpc_len = snprintf(remote_rpc, remote_rpc_len, "(dir-close %d)", sid); + + r = sxmsg_send(c, remote_rpc, remote_rpc_len, &msg); + if(r == SXE_RAPIDMSG) sxmsg_clean(msg); + else if(r == SXE_REPLYREQ) r = sxmsg_return(msg, SXE_SUCCESS); + + return r; +} + +/* our commands or tools implementation */ +static int __remote_ls(FILE *fso, struct _remote_host *rh, const char *opts) +{ + char *remote_rpc; + size_t remote_rpc_len; + sxmsg_t *msg = NULL; + sxchnl_t *rpc_channel = NULL; + sexp_t *sx, *isx, *iisx; + char *remote_reply = NULL, *dname, *dtype; + int rrc = 0, stream_id = 0, i, ii; + + /* ok determine the lenght */ + remote_rpc_len = strlen("dir-open") + 12*sizeof(char) + + (opts ? strlen ("./") : strlen(opts)); + if(!(remote_rpc = malloc(remote_rpc_len))) return ENOMEM; + else remote_rpc_len = snprintf(remote_rpc, remote_rpc_len, + "(dir-open \"%s\")", opts ? "./" : opts); + + /* firstly open the required channel with required type */ + if(!(rpc_channel = sxchannel_open(rh->link, READONLY_CHANNEL))) { + rrc = errno; + goto __fini; + } + + rrc = sxmsg_send(rpc_channel, remote_rpc, remote_rpc_len, &msg); + if(rrc == SXE_RAPIDMSG || rrc == SXE_REPLYREQ) { + remote_reply = strdup(sxmsg_payload(msg)); + + if(rrc == SXE_RAPIDMSG) sxmsg_clean(msg); + else rrc = sxmsg_return(msg, SXE_SUCCESS); + } + + if(!remote_reply && (rrc != 0 || rrc != SXE_SUCCESS)) goto __fini; + else sx = parse_sexp(remote_reply, strlen(remote_reply)); + + if(!sx) { rrc = EINVAL; goto __fini; } + + /* ok, now we will take a pass with our received S expression */ + rrc = EINVAL; + SEXP_ITERATE_LIST(sx, isx, i) { + if(isx->ty == SEXP_LIST) stream_id = -1; + if(!i && strcmp(isx->val, "dir-stream")) stream_id = -1; + + if(i == 1 && !stream_id) stream_id = atoi(isx->val); + } + + /* free all the stuff */ + destroy_sexp(sx); + free(remote_reply); remote_reply = NULL; + + if(stream_id < 0) goto __fini; + else rrc = SXE_SUCCESS; + + free(remote_rpc); + + /* now we're ready to read contents from the remote host */ + remote_rpc_len = strlen("dir-read") + sizeof(char)*32; + if(!(remote_rpc = malloc(remote_rpc_len))) { rrc = ENOMEM; goto __fini; } + else remote_rpc_len = snprintf(remote_rpc, remote_rpc_len, "(dir-read %d)", stream_id); + + /* print header */ + fprintf(fso, "%-24s | %-12s\n", "Name", "Type"); + fprintf(fso, "---------------------------------------\n"); + while(1) { + rrc = sxmsg_send(rpc_channel, remote_rpc, remote_rpc_len, &msg); + + if(rrc == SXE_RAPIDMSG || rrc == SXE_REPLYREQ) { + remote_reply = strdup(sxmsg_payload(msg)); + + if(rrc == SXE_RAPIDMSG) sxmsg_clean(msg); + else rrc = sxmsg_return(msg, SXE_SUCCESS); + } else goto __fini; + + if(!remote_reply) goto __fini; + else if(!(sx = parse_sexp(remote_reply, strlen(remote_reply)))) { + rrc = ENOMEM; + goto __fini; + } + + rrc = EINVAL; + SEXP_ITERATE_LIST(sx, isx, i) { + if(!i && isx->ty == SEXP_LIST) { rrc = EINVAL; goto __fini; } + if(!i && !strcmp(isx->val, "dir-end")) { + rrc = __close_dir_stream(rpc_channel, stream_id); + goto __fini; + } + + if(i && isx->ty != SEXP_LIST) { rrc = EINVAL; goto __fini; } + else if(i) { + SEXP_ITERATE_LIST(isx, iisx, ii) { + if(!ii) dname = iisx->val; + else dtype = iisx->val; + } + fprintf(fso, "%-24s | %-12s\n", dname, dtype); + } + } + + /* free it */ + destroy_sexp(sx); + free(remote_reply); remote_reply = NULL; + } + + __fini: + if(remote_reply) free(remote_reply); + if(remote_rpc) free(remote_rpc); + i = SXE_SUCCESS; + if(rpc_channel) i = sxchannel_close(rpc_channel); + + if(rrc == SXE_SUCCESS && i == SXE_SUCCESS) rrc = 0; + + return rrc; +} + +static int __remote_host_connect(struct _remote_host *rh) +{ + int r = 0; + + sxhub_set_channelcall(rh->hub, __rpcscheck_onclient); + + /* here we go, connect to the hist i.e. create a link to it */ + rh->link = sxlink_connect(rh->hub, rh->hostname, rh->port, rh->user_x509, + rh->login, rh->password); + if(!rh->link) r = errno; + + return r; +} + +static void __help_print(FILE *fso, const char *fmtname) +{ + fprintf(fso, "\n%s\n\n", FULL_PROGRAM_NAME); + + /* usage options */ + fprintf(fso, "Usage:\n"); + fprintf(fso, "\t%s -r | --root-x509 -u | --user-x509 -H | --hostname " + " -l | --login -P | --password -c | --command " + " [-o | --command-options ] [-p | --port ]\n", fmtname); + + /* defaults */ + fprintf(fso, "\t%s -h | --help\n", fmtname); + fprintf(fso, "\t%s -v | --version\n", fmtname); + + /* options description */ + fprintf(fso, "\nOptions:\n"); + fprintf(fso, "\t%-33s Set pathname of the remote root X.509 public certificate.\n", "-r | --root-x509 "); + fprintf(fso, "\t%-33s Set pathname of the user X.509 public and private certificate.\n", + "-u | --user-x509 "); + fprintf(fso, "\t%-33s Hostname or IP address of the remote host.\n", "-H | --hostname "); + fprintf(fso, "\t%-33s Set remote login name.\n", "-l | --login "); + fprintf(fso, "\t%-33s Set remote user password.\n", "-P | --password "); + fprintf(fso, "\t%-33s Command to run on the remote host.\n", "-c | --command "); + fprintf(fso, "\t%-33s Options for a command to run on the remote host [default: NULL].\n", + "-o | --command-options "); + fprintf(fso, "\t%-33s Remote host listening port number [default: %d].\n", + "-p | --port ", DEFAULT_PORT); + fprintf(fso, "\t%-33s Show help screen.\n", "-h | --help"); + fprintf(fso, "\t%-33s Print version information.\n", "-v | --version"); + return; +} + +static void __version_print(FILE *fso) +{ + fprintf(fso, "\nFile list example client.\n"); + fprintf(fso, "Examples bundle for %s %s.\n", PACKAGE_NAME, PACKAGE_VERSION); + return; +} int main(int argc, char **argv) { - int opt; - - return 0; + char *rootca, *cert, *host, *cmd; + char *login, *password, *options; + int port = DEFAULT_PORT, opt, i = 0; + int (*toolfunction)(FILE *, struct _remote_host *, const char *) = NULL; + struct _remote_host *rh = malloc(sizeof(struct _remote_host)); + sxhub_t *lhub; + + if(!rh) return ENOMEM; + else memset(rh, 0, sizeof(struct _remote_host)); + + rootca = cert = host = cmd = NULL; + login = password = options = NULL; + + while(1) { + int option_index = 0; + static struct option long_options[] = { + /* These options a generic ones. */ + {"help", no_argument, NULL, 'h'}, /* print out help and version info */ + {"version", no_argument, NULL, 'v'}, /* just out a version info */ + /* The following options about settings . */ + {"root-x509", required_argument, NULL, 'r'}, + {"user-x509", required_argument, NULL, 'u'}, + {"hostname", required_argument, NULL, 'H'}, + {"port", required_argument, NULL, 'p'}, + {"login", required_argument, NULL, 'l'}, + {"password", required_argument, NULL, 'P'}, + {"command", required_argument, NULL, 'c'}, + {"command-options", required_argument, NULL, 'o'}, + { NULL, 0, NULL, 0 }, + }; + + if((opt = getopt_long(argc, argv, "hvr:u:H:p:l:P:c:o:", long_options, + &option_index)) == -1) break; + + switch(opt) { + case 'h': + __help_print(stdout, argv[0]); + return 0; + break; + case 'v': + __version_print(stdout); + return 0; + break; + case 'r': + if(!(rootca = strdup(optarg))) return ENOMEM; + break; + case 'u': + if(!(cert = strdup(optarg))) return ENOMEM; + break; + case 'H': + if(!(host = strdup(optarg))) return ENOMEM; + break; + case 'l': + if(!(login = strdup(optarg))) return ENOMEM; + break; + case 'P': + if(!(password = strdup(optarg))) return ENOMEM; + break; + case 'c': + if(!(cmd = strdup(optarg))) return ENOMEM; + break; + case 'o': + if(!(options = strdup(optarg))) return ENOMEM; + break; + case 'p': + port = atoi(optarg); + break; + } + } + + /* ok validate all before doing any stuff */ + if(!rootca || !cert) { + fprintf(stderr, "One or more x.509 certificates files not pointed.\n"); + __help_print(stderr, argv[0]); + return EINVAL; + } + if(!login || !password) { + fprintf(stderr, "Login or password not pointed.\n"); + __help_print(stderr, argv[0]); + return EINVAL; + } + if(port <= 0) { + fprintf(stderr, "Port number has invalid value.\n"); + __help_print(stderr, argv[0]); + return EINVAL; + } + /* ok, check up for the command */ + if(!cmd) { + fprintf(stderr, "No command given.\n"); + __help_print(stderr, argv[0]); + return EINVAL; + } + + /* try to lookup it */ + while(_tool[i].cmdname != NULL) { + if(!strcmp(_tool[i].cmdname, cmd)) { + if(_tool[i].opt && !options) { + fprintf(stderr, "Command %s required options.\n", cmd); + __help_print(stderr, argv[0]); + return EINVAL; + } + toolfunction = _tool[i].__fu; + } + } + if(!toolfunction) { + fprintf(stderr, "No such function `%s' exist.\n", cmd); + __help_print(stderr, argv[0]); + return EINVAL; + } + + /* initialize sxmp first */ + sxmp_init(); /* init library */ + lhub = sxhub_create(); /* create sxhub for link creation */ + if(!lhub) return ENOMEM; + + i = sxhub_setsslserts(lhub, rootca, cert, cert); + if(i) return i; + + /* ok setup our structure */ + rh->port = port; + rh->root_x509 = rootca; + rh->user_x509 = cert; + rh->hostname = host; + rh->login = login; + rh->password = password; + rh->hub = lhub; + + i = __remote_host_connect(rh); + if(i) { + fprintf(stderr, "Failed to create link to %s@%s:%d with %d.\n", rh->login, rh->hostname, + rh->port, i); + } else { + i = toolfunction(stdout, rh, options); + if(i) fprintf(stderr, "Failed to run RPC on %s@%s:%d with %d.\n", rh->login, rh->hostname, + rh->port, i); + + sxlink_close(rh->link); /* don't forget to do this */ + } + + /* free all stuff */ + if(rh->root_x509) free(rh->root_x509); + if(rh->user_x509) free(rh->user_x509); + if(rh->hostname) free(rh->hostname); + if(rh->password) free(rh->password); + if(rh->login) free(rh->login); + free(rh); + + if(lhub) sxhub_destroy(lhub); + + return i; } diff --git a/examples/filelistd.c b/examples/filelistd.c index 40bb8db..45fb4c2 100644 --- a/examples/filelistd.c +++ b/examples/filelistd.c @@ -169,7 +169,7 @@ static int __validate_sslpem(sxlink_t *l) * We don't overview this tuff here, just * always allow. */ -static int __secure_check(conn_t *co) +static int __secure_check(sxlink_t *l) { return SXE_SUCCESS; } @@ -385,8 +385,8 @@ int main(int argc, char **argv) return opt; } - /* we will add one channel with type id 12 "Demo rpc list" */ - opt = sxmp_rpclist_add(fulist, 12, "Demo RPC list", NULL); + /* we will add one channel with type id READONLY_CHANNEL for read only operations */ + opt = sxmp_rpclist_add(fulist, READONLY_CHANNEL, "Read only operations", NULL); if(opt) { fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n"); return opt; @@ -398,15 +398,15 @@ int main(int argc, char **argv) } /* ok, let's add stream functions */ - opt = sxmp_rpclist_add_function(fulist, 12, "dir-open", __dir_open); + opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "dir-open", __dir_open); if(opt) { __fail: fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n"); return opt; } - opt = sxmp_rpclist_add_function(fulist, 12, "dir-read", __dir_read); + opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "dir-read", __dir_read); if(opt) goto __fail; - opt = sxmp_rpclist_add_function(fulist, 12, "dir-close", __dir_close); + opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "dir-close", __dir_close); if(opt) goto __fail; /* ok, setup it */ diff --git a/tests/Makefile.am b/tests/Makefile.am deleted file mode 100644 index 6a35c76..0000000 --- a/tests/Makefile.am +++ /dev/null @@ -1,46 +0,0 @@ -## AUTOMAKE_OPTIONS = foreign - -AM_CPPFLAGS = \ - -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ - -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ - -DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \ - -DCNFPATH=\""$(prefix)/etc"\" \ - -I../include \ - -I../lib - -AM_CFLAGS = -Wall -g - -# where to find libsntl -libsntl = ../lib/.libs/libsntl.la - -if !COND_WIN32 - -bin_PROGRAMS = lv2sd lv2sc lv2ftpd lv2ftpc - -lv2sd_SOURCES = lv2sd.c -lv2sd_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ - $(LIBUUID_LIBS) $(libsntl) -lpthread - -lv2sc_SOURCES = lv2sc.c -lv2sc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ - $(LIBUUID_LIBS) $(libsntl) -lpthread - -lv2ftpd_SOURCES = lv2ftpd.c -lv2ftpd_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ - $(LIBUUID_LIBS) $(libsntl) -lpthread - -lv2ftpc_SOURCES = lv2ftpc.c -lv2ftpc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ - $(LIBUUID_LIBS) $(libsntl) -lpthread - - -else COND_WIN32 - -bin_PROGRAMS = lv2sc - -lv2sc_SOURCES = lv2sc.c -lv2sc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ - $(LIBUUID_LIBS) $(libsntl) -lws2_32 - -endif COND_WIN32 - diff --git a/tests/lv2ftp-proto.txt b/tests/lv2ftp-proto.txt deleted file mode 100644 index 191fa40..0000000 --- a/tests/lv2ftp-proto.txt +++ /dev/null @@ -1,30 +0,0 @@ -1. lv2ftp isn's serious, just a test and benchmark of the sntllv2 -2. there are few stages: -2.1 Simple v.1 - This protocol is enough to donwload a directory subtree with files. -2.1.1 Directory workout - * Open directory stream: (dir-open "") - * Return: error, or rapidly replies with (dir-stream ) - * Read directory entry: (dir-read ) - * Return: error, or rapidly replies with the following: - * (dir-end ) - * (dir-entry "" ""), where filetype the following: - * regular - regular file - * directory - directory - * block - block device - * char - char device - * fifo - named pipe - * link - symbolic link - * socket - socket - * unknown - unknown file type - * Close directory entry: (dir-close ) - * Return: error or SNE_SUCCESS -2.1.2 File workout - * Open file: (file-open "") - * Return: error, or rapidly replies with (file-id ) - * Get simple stat: (file-stat ) - * Return error, or rapidle replies with (file-stat ) - * Read file data: (file-read ) - * Return error, or rapidly replies with 30k(raw data, in base64 it will be more) (file-data "") - * Close file: (file-close ) - * Return error or SNE_SUCCESS diff --git a/tests/lv2ftpc.c b/tests/lv2ftpc.c deleted file mode 100644 index 2a80f23..0000000 --- a/tests/lv2ftpc.c +++ /dev/null @@ -1,352 +0,0 @@ -#include -#define __USE_GNU -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include - -#define DEBUG -#define FREE(x) { if (x) { free(x); x = NULL; } } -/* define a little bit */ -#define DEFAULT_PORT 13133 -#define CHANNEL_COUNT 200 -#define CLIENT_COUNT 256 -#define MESSAGES_PER_SESSION 10000 -#define ITERATION_COUNT 1000 - -#define FAILS_ONLY - -struct testdata { - int uc; - pthread_mutex_t ulock; - conn_t *co; -}; - -static int __init_testdata(struct testdata *t, conn_t *co) -{ - t->uc = 0; - pthread_mutex_init(&t->ulock, NULL); - t->co = co; - return 0; -} - -static void __wait_completion(struct testdata *t) -{ - pthread_mutex_lock(&t->ulock); - if(t->uc) { - pthread_mutex_lock(&t->ulock); - } - return; -} - -static int __set_typed_list_callback(conn_t *co, int ch, char *desc) -{ - printf("allowed channel %d (%s)\n", ch, desc); - return SNE_SUCCESS; -} - -static void *__addsthrd(void *a) -{ - struct testdata *t = a; - conn_t *co = t->co; - chnl_t *mch; - sxmsg_t *msg; - char mmbuf[1024]; - size_t ln; - int mr, i; - - pthread_mutex_lock(&t->ulock); - t->uc++; - pthread_mutex_unlock(&t->ulock); - - /* here we go */ - mch = sxchannel_open(co, 12); - if(!mch) { - fprintf(stderr, "Failed to openchannel with %d\n", errno); - goto __fini; - } - - for(i = 0; i < MESSAGES_PER_SESSION; i++) { - ln = snprintf(mmbuf, 1024, "(ar-add (10 10))"); - mr = sxmsg_send(mch, mmbuf, ln, &msg); - switch(mr) { - case SNE_RAPIDMSG: - //fprintf(stdout, "Rapidly replied: %s\n", (char *)sxmsg_payload(msg)); - sxmsg_clean(msg); - break; - case SNE_REPLYREQ: - if(sxmsg_datalen(msg)) fprintf(stdout, "Replied (confirmation required): %s\n", - (char *)sxmsg_payload(msg)); - mr = sxmsg_return(msg, SNE_SUCCESS); - fprintf(stderr, "mr = %d\n", mr); - break; - case SNE_SUCCESS: - fprintf(stdout, "Success.\n"); - break; - default: - fprintf(stderr, "ERROR: %d\n", mr); - break; - } - } - - sxchannel_close(mch); - - __fini: - t->uc--; - if(t->uc <= 1) pthread_mutex_unlock(&t->ulock); - - return NULL; -} - -int msg_send(chnl_t *ch, const char *mmbuf, size_t buflen, sxmsg_t *msg, char **rs) -{ -#ifdef DEBUG - printf("%s: got sx '%s'\n", __FUNCTION__, mmbuf); -#endif /* DEBUG */ - - int mr = sxmsg_send(ch, mmbuf, buflen, &msg); - switch(mr) { - case SNE_RAPIDMSG: - if (rs) *rs = strdup((char *)sxmsg_payload(msg)); - fprintf(stdout, "Rapidly replied: '%s'\n", (char *)sxmsg_payload(msg)); - sxmsg_clean(msg); - break; - case SNE_REPLYREQ: - if(sxmsg_datalen(msg)) fprintf(stdout, "Replied (confirmation required): %s\n", - (char *)sxmsg_payload(msg)); - mr = sxmsg_return(msg, SNE_SUCCESS); - fprintf(stderr, "mr = %d\n", mr); - break; - case SNE_SUCCESS: - fprintf(stdout, "Success.\n"); - break; - default: - fprintf(stderr, "ERROR: %d\n", mr); - break; - } -#ifdef DEBUG - // printf("%s: got rs %d\n", __FUNCTION__, mr); -#endif /* DEBUG */ - return mr; -} - -int main(int argc, char **argv) -{ - char *rootca = NULL, *cert = NULL; - int port = DEFAULT_PORT; - char *addr = NULL, *login = NULL, *password = NULL; - int opt; - conn_sys_t *ssys; - conn_t *co; - - while((opt = getopt(argc, argv, "p:r:a:u:l:w:")) != -1) { - switch(opt) { - case 'p': - port = atoi(optarg); - break; - case 'r': - rootca = strdup(optarg); - break; - case 'a': - addr = strdup(optarg); - break; - case 'u': - cert = strdup(optarg); - break; - case 'l': - login = strdup(optarg); - break; - case 'w': - password = strdup(optarg); - break; - default: - fprintf(stderr, "usage: %s [-p ] -r -a -u -l -w \n", argv[0]); - return EINVAL; - } - } - - if(!rootca) { - fprintf(stderr, "Root CA not pointed.\n Failure.\n"); - return EINVAL; - } - - if(!addr) { - fprintf(stderr, "Server address not pointed.\n Failure.\n"); - return EINVAL; - } - - if(!cert) { - fprintf(stderr, "User certificate not pointed.\n Failure.\n"); - return EINVAL; - } - - if(!login) { - fprintf(stderr, "User login not pointed.\n Failure.\n"); - return EINVAL; - } - - if(!password) { - fprintf(stderr, "User password not pointed.\n Failure.\n"); - return EINVAL; - } - - sntl_init(); - /* all is fine let's init connection subsystem */ - ssys = connections_create(); - if(!ssys) { - fprintf(stderr, "Subsystem init failed: %d\n", errno); - return errno; - } - /* set working 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; - } - - /* Tests */ - struct timeval beg, end; - /* try to open connection */ - connections_set_channelcall(ssys, __set_typed_list_callback); - - gettimeofday(&beg, NULL); - co = connection_link(ssys, addr, port, cert, login, password); - - if(!co) { - fprintf(stderr, "Failed to connection with %d\n", errno); - return errno; - } - gettimeofday(&end, NULL); - - if((end.tv_sec - beg.tv_sec) > 0) { - printf("Seconds: %ld ", end.tv_sec - beg.tv_sec); - printf("µS: %ld\n", end.tv_usec + (1000000 - beg.tv_usec)); - } else printf("µS: %ld\n", end.tv_usec - beg.tv_usec); - - /* ok now we should open a channel */ - chnl_t *testchannel = sxchannel_open(co, 12); - - if(!testchannel) { - fprintf(stderr, "Failed to openchannel with %d\n", errno); - return errno; - } - gettimeofday(&end, NULL); - - if((end.tv_sec - beg.tv_sec) > 0) { - printf("Seconds: %ld ", end.tv_sec - beg.tv_sec); - printf("µS: %ld\n", end.tv_usec + (1000000 - beg.tv_usec)); - } else printf("µS: %ld\n", end.tv_usec - beg.tv_usec); - - /* ok, send a message */ - char mmbuf[1024]; - char *s_ret = NULL; - sxmsg_t *msg = NULL; - size_t ln; - int mr, ee, stid; - sexp_t *sx_ret = NULL; - - ln = snprintf(mmbuf, 1024, "(dir-open \".\")"); - mr = msg_send(testchannel, mmbuf, ln, msg, &s_ret); - if (mr != SNE_RAPIDMSG) goto __finish; - - sx_ret = parse_sexp(s_ret, strlen(s_ret)); - FREE(s_ret); - if (!sx_ret || !sx_ret->list || strcmp(sx_ret->list->val, "dir-stream") || - !sx_ret->list->next || !sx_ret->list->next->val) - goto __finish; - - stid = atoi(sx_ret->list->next->val); - ln = snprintf(mmbuf, 1024, "(dir-read %d)", stid); - while (1) { - mr = msg_send(testchannel, mmbuf, ln, msg, &s_ret); - if (mr != SNE_RAPIDMSG) goto __finish; - - sx_ret = parse_sexp(s_ret, strlen(s_ret)); - if (!sx_ret || !sx_ret->list || !sx_ret->list->val) - goto __finish; - - if (!strcmp(sx_ret->list->val, "dir-end")) { - ln = snprintf(mmbuf, 1024, "(dir-close %d)", stid); - mr = msg_send(testchannel, mmbuf, ln, msg, &s_ret); - break; - } -#ifdef DEBUG - printf("%s: '%s'\n", __FUNCTION__, s_ret); -#endif /* DEBUG */ - FREE(s_ret); - } - - // switch(mr) { - // case SNE_RAPIDMSG: - // fprintf(stdout, "Rapidly replied: %s\n", (char *)sxmsg_payload(msg)); - // sxmsg_clean(msg); - // break; - // case SNE_REPLYREQ: - // if(sxmsg_datalen(msg)) fprintf(stdout, "Replied (confirmation required): %s\n", - // (char *)sxmsg_payload(msg)); - // mr = sxmsg_return(msg, SNE_SUCCESS); - // fprintf(stderr, "mr = %d\n", mr); - // break; - // case SNE_SUCCESS: - // fprintf(stdout, "Success.\n"); - // break; - // default: - // fprintf(stderr, "ERROR: %d\n", mr); - // break; - // } - -__finish: - ee = sxchannel_close(testchannel); - printf("ee = %d\n", ee); - gettimeofday(&end, NULL); - - if((end.tv_sec - beg.tv_sec) > 0) { - printf("Seconds: %ld ", end.tv_sec - beg.tv_sec); - printf("µS: %ld\n", end.tv_usec + (1000000 - beg.tv_usec)); - } else printf("µS: %ld\n", end.tv_usec - beg.tv_usec); - // sleep(10); - // /* ok, now we need to create many threads */ - // struct testdata trd; - // pthread_t thrd; - // int i; - // __init_testdata(&trd, co); - - // for(i = 0; i < 256; i++) pthread_create(&thrd, NULL, __addsthrd, &trd); - - // __wait_completion(&trd); - - connection_close(co); - - connections_destroy(ssys); - - sntl_finalize(); - - return 0; -}