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.
libsxmp/examples/streamfld.c

286 lines
7.8 KiB
C

/*
* Secure X Message Passing Library v2 examples.
*
* (c) Originally written by somebody else ...
* (c) Alexander Vdolainen 2013-2015 <avdolainen@gmail.com>
*
* libsxmp is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libsxmp is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.";
*
*/
/*
* This is an example of sxmp usage.
* NOTE: It was developed quite fast within one day,
* btw - this the reason of some ugly code here.
*
* This is a master or simply - daemon part, it will
* listen a requests and create a stream with directory entries,
* which ridden by the client.
* Using the builtin stream functionality added since 0.4.2 version.
*
* This implements a simple client-server topology, to see
* more advanced technics check out other examples.
*
* NOTE(win32): don't have a time to test it or fix it to
* make it works on windows, if you can - u're welcome.
*/
#include <stdio.h>
#include <dirent.h>
#define __USE_GNU
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <limits.h>
#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>
#include <tdata/usrtc.h>
#include <sexpr/sexp.h>
#include <sxmp/limits.h>
#include <sxmp/sxmp.h>
#include <pthread.h>
#include <stdint.h>
#include <getopt.h>
#include <errno.h>
#include "filelist.h"
#include "helpers.h"
#include "../config.h"
#define FULL_PROGRAM_NAME "File lister master (builtin streams based)"
/* firstly we need to take an rpc calls data,
* sxmp uses usrtc from libtdata to store it
*/
static usrtc_t *fulist;
/* ok, here we will define out sxmp specific functions */
/*
* RPC list contain groups of RPC calls called channel types
* for each sxmp link depends on access rules you can change
* available channel types.
* To do so you must provide a special callback returning this list.
* Since we haven't any access restrictions in our example, just
* create a fake.
*/
static usrtc_t *__rettlist(sxlink_t *l)
{
return fulist;
}
/*
* Each sxmp link validated by certificate ID,
* i.e. when basic checking is done, you can also
* review the certificate ID, for example you need
* to disable certificate for a time being.
*
* Here we don't have those checks, just always accept
*/
static int __validate_sslpem(sxlink_t *l)
{
return 0;
}
/*
* To be more paranoic, sxmp also allow to
* check up username and password.
* We don't overview this tuff here, just
* always allow.
*/
static int __secure_check(sxlink_t *l)
{
return SXE_SUCCESS;
}
/* misc functions */
static int __ping(void *m, sexp_t *sx)
{
return sxmsg_return((sxmsg_t*)m, SXE_SUCCESS);
}
/* command line options helpers */
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 | --master-x509 <path> "
" [-p | --listen-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 host X.509 public and private certificate.\n",
"-m | --master-x509 <path>");
fprintf(fso, "\t%-33s Remote host listening port number [default: %d].\n",
"-p | --listen-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 master daemon (builtin streams).\n");
fprintf(fso, "Examples bundle for %s %s.\n", PACKAGE_NAME, PACKAGE_VERSION);
return;
}
int main(int argc, char **argv)
{
char *rootca = NULL, *cert = NULL;
sxhub_t *sxmphub = sxhub_create();
int port = DEFAULT_PORT;
int opt;
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'},
{"master-x509", required_argument, NULL, 'm'},
{"listen-port", required_argument, NULL, 'p'},
{ NULL, 0, NULL, 0 },
};
if((opt = getopt_long(argc, argv, "hvr:m:", 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 'm':
if(!(cert = strdup(optarg))) return ENOMEM;
break;
case 'p':
port = atoi(optarg);
break;
}
}
if(!rootca) {
fprintf(stderr, "Root CA not pointed.\n Failure.\n");
__help_print(stderr, argv[0]);
return EINVAL;
}
if(!cert) {
fprintf(stderr, "User certificate not pointed.\n Failure.\n");
__help_print(stderr, argv[0]);
return EINVAL;
}
sxmp_init();
/* all is fine let's init connection subsystem */
if(!sxmphub) {
fprintf(stderr, "Subsystem init failed: %d\n", opt);
return 2;
}
/* set working certificates */
opt = sxhub_setsslserts(sxmphub, 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 */
sxhub_set_authcheck(sxmphub, __secure_check);
sxhub_set_sslvalidate(sxmphub, __validate_sslpem);
/* 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 = sxmp_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 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;
}
/* ok, let's add stream functions */
opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "ping", __ping);
if(opt) {
__fail:
fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n");
return opt;
}
/* ok, setup it */
sxhub_set_rpcvalidator(sxmphub, __rettlist);
signal(SIGPIPE, SIG_IGN);
/* now we're ready to run the listen process */
int srv = openlistener_socket(port);
while(1) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
sxlink_t *link;
int client = accept(srv, (struct sockaddr*)&addr, &len); /* accept connection as usual */
link = sxlink_master_accept(sxmphub, client, NULL);
if(!link) fprintf(stderr, "Cannot create sxmp link (%d)\n", errno);
}
sxhub_destroy(sxmphub);
sxmp_finalize();
return 0;
}