added first stupid example; will test it later;
This commit is contained in:
		
							parent
							
								
									11498689e3
								
							
						
					
					
						commit
						15fb867657
					
				
							
								
								
									
										14
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								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 = \
 | ||||
|  | ||||
							
								
								
									
										21
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								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]) | ||||
|  | ||||
							
								
								
									
										2
									
								
								examples/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								examples/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| filelistc | ||||
| filelistd | ||||
							
								
								
									
										25
									
								
								examples/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								examples/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
| 
 | ||||
| @ -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 | ||||
|  | ||||
| @ -61,10 +61,386 @@ | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #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 <path> -u | --user-x509 <path> -H | --hostname <ip or hostname>" | ||||
|           " -l | --login <login> -P | --password <password> -c | --command <command>" | ||||
|           " [-o | --command-options <options>] [-p | --port <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 <path>"); | ||||
|   fprintf(fso, "\t%-33s Set pathname of the user X.509 public and private certificate.\n", | ||||
|           "-u | --user-x509 <path>"); | ||||
|   fprintf(fso, "\t%-33s Hostname or IP address of the remote host.\n", "-H | --hostname <ip or hostname>"); | ||||
|   fprintf(fso, "\t%-33s Set remote login name.\n", "-l | --login <login>"); | ||||
|   fprintf(fso, "\t%-33s Set remote user password.\n", "-P | --password <password>"); | ||||
|   fprintf(fso, "\t%-33s Command to run on the remote host.\n", "-c | --command <command>"); | ||||
|   fprintf(fso, "\t%-33s Options for a command to run on the remote host [default: NULL].\n", | ||||
|           "-o | --command-options <options>"); | ||||
|   fprintf(fso, "\t%-33s Remote host listening port number [default: %d].\n", | ||||
|           "-p | --port <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; | ||||
|   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; | ||||
| } | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
| @ -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 "<dir-name>") | ||||
|       * Return: error, or rapidly replies with (dir-stream <id>) | ||||
|     * Read directory entry: (dir-read <id>) | ||||
|       * Return: error, or rapidly replies with the following: | ||||
|         * (dir-end <id>) | ||||
|         * (dir-entry "<filename>" "<filetype>"), 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 <id>) | ||||
|        * Return: error or SNE_SUCCESS | ||||
| 2.1.2 File workout | ||||
|      * Open file: (file-open "<file-name>") | ||||
|        * Return: error, or rapidly replies with (file-id <id>) | ||||
|      * Get simple stat: (file-stat <id>) | ||||
|        * Return error, or rapidle replies with (file-stat <id> <size>) | ||||
|      * Read file data: (file-read <id> <offset>) | ||||
|        * Return error, or rapidly replies with 30k(raw data, in base64 it will be more) (file-data <id> <offset> "<B64encoded data>") | ||||
|      * Close file: (file-close <id>) | ||||
|        * Return error or SNE_SUCCESS | ||||
							
								
								
									
										352
									
								
								tests/lv2ftpc.c
									
									
									
									
									
								
							
							
						
						
									
										352
									
								
								tests/lv2ftpc.c
									
									
									
									
									
								
							| @ -1,352 +0,0 @@ | ||||
| #include <stdio.h> | ||||
| #define __USE_GNU | ||||
| #include <stdlib.h> | ||||
| #include <stdarg.h> | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| #include <pthread.h> | ||||
| #include <stdint.h> | ||||
| #include <getopt.h> | ||||
| #include <errno.h> | ||||
| #include <assert.h> | ||||
| #include <time.h> | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| #include <Winsock2.h> | ||||
| #include <signal.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/sntllv2.h> | ||||
| #include <sntl/limits.h> | ||||
| 
 | ||||
| #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 <PORTNUM>] -r <PATH to Root CA> -a <Server ip address> -u <PATH" | ||||
|               " to SSL certificate> -l <User login> -w <User password>\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; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user