From 38f08cfe62d9422e5e67f4afda035c30ff1cc120 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 16 Jul 2015 22:54:45 +0300 Subject: [PATCH 01/56] New version check up. --- .gitignore | 4 ++++ configure.ac | 2 +- debian/changelog | 10 ++++++++++ debian/control | 4 ++-- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5845175..c296422 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,7 @@ debian/tmp debian/libsntl-dev/ debian/libsntl/ debian/source/ +aclocal +coq +*.log +*.crt diff --git a/configure.ac b/configure.ac index f03444b..36b40c5 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(libsntl, 0.2.1) +AC_INIT(libsntl, 0.3.0) #LDFLAGS="$LDFLAGS -L/mingw/lib -L/local/lib" diff --git a/debian/changelog b/debian/changelog index 3df100f..d07fdf9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +libsntl (0.3.0) stable; urgency=high + + * New improved architecture + * Performance tricks + * Long messages + * Extended API + * It's incompatible with 0.2.xx and below by protocol + + -- Alexander Vdolainen Thu, 16 Jul 2015 22:50:32 +0200 + libsntl (0.2.1) stable; urgency=low * Initial release (Closes: #nnnn) diff --git a/debian/control b/debian/control index d393f91..594e99b 100644 --- a/debian/control +++ b/debian/control @@ -12,12 +12,12 @@ Package: libsntl-dev Section: libdevel Architecture: any Depends: libsntl (= ${binary:Version}), libsexpr-dev, libssl-dev, libtdata-dev, uuid-dev -Description: Development files for libsntl +Description: Development files for libsntl (sntllv2) Development files for sntl library Package: libsntl Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libsexpr (>= 1.3.1), libssl1.0.0, libtdata (>= 0.2.2), libuuid1 -Description: Secure Networking Transport Layer implementation library +Description: Secure Networking Transport Layer v2 implementation library Library used to develop secure services From cb271ab7a039c6cbc41b3df1f2c209642fb8b9da Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 16 Jul 2015 22:58:13 +0300 Subject: [PATCH 02/56] minor header description; --- lib/connection.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/connection.c b/lib/connection.c index ef8e47e..a435ae5 100644 --- a/lib/connection.c +++ b/lib/connection.c @@ -1,5 +1,10 @@ /* - * Secure Network Transport Layer Library implementation. + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * * This is a proprietary software. See COPYING for further details. * * (c) Askele Group 2013-2015 From aeab86273816e8705c0205d38d8ec5bb5dcb546a Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 16 Jul 2015 23:36:14 +0300 Subject: [PATCH 03/56] general structures modified; --- include/sntl/connection.h | 92 ++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/include/sntl/connection.h b/include/sntl/connection.h index f784034..e6ee696 100644 --- a/include/sntl/connection.h +++ b/include/sntl/connection.h @@ -1,3 +1,16 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + /* * File: connection.h * Author: vdo @@ -22,7 +35,7 @@ #include -/* error codes */ +/* TODO: remove to the special separate file - error codes */ #define ESXOREPLYREQ 44 /* protocol require reply with expression, * or expression return for the request */ #define ESXOTIMEDOUT 45 /* timedout */ @@ -43,12 +56,7 @@ typedef struct __perm_context_type { char *login; char *passwd; - ulong_t certid; - ulong_t uid; - ulong_t gid; - ulong_t *gids; - int n_gids; - int p_attr; + uint64_t certid; struct in_addr *addr; void *priv; } perm_ctx_t; @@ -58,32 +66,50 @@ typedef struct __perm_context_type { #define CXCONN_ESTABL (1 << 3) #define CXCONN_BROKEN (1 << 4) +/* 8 byte header */ +typedef struct __sntllv2_head_type { + uint16_t msgid; + uint16_t payload_length; + uint8_t attr; + uint8_t opcode; + uint16_t reserve; +}__attribute__((packed)) sntllv2_head_t; struct __connections_subsys_type; +struct __channel_t; +struct __message_t; /* * älä jätä kommentteja omalla kielellä! yksinkertaisia englanti sijaan! * i found somebody who write comments and messages in non-english, - * itäs a fucking practice - forget it. + * it's a fucking practice - forget it. */ typedef struct __connection_t { + /* General section */ struct __connections_subsys_type *ssys; /* < connections subsystem */ char *uuid; /** < uuid of the connection */ + /* Channels section */ idx_allocator_t *idx_ch; /** < index allocation for channels */ - usrtc_t *chnl_tree; /** < search tree of all channels */ + pthread_mutex_t idx_ch_lock; /** < mutex for allocating and deallocating channels */ + struct __channel_t **channels; /** < channels O(1) storage */ + /* RPC section */ usrtc_t *rpc_list; /** < search tree of possible RPC typed lists */ + /* SSL related section */ SSL_CTX *ctx; /** < SSL context */ SSL *ssl; /** < SSL connection */ int ssl_data_index; /** < SSL index for the custom data */ + pthread_mutex_t sslinout[2]; /** < SSL related locks for in and out */ + /* Security section */ perm_ctx_t *pctx; /** < higher layer authentification context */ - pthread_t cthread; /** < thread for listening the connection socket */ - pthread_t rmsgthread; /** < thread for message queue (1) */ - pthread_t msgthread; /** < thread for message queue (2) */ - pth_queue_t *mqueue; /** < message queue (2) */ - pth_queue_t *rqueue; /** < message queue (1) */ - pth_dqtpoll_t *tpoll; /** < thread poll for rpc requests */ - pthread_mutex_t oplock; /** < mutex used to sync operations on connection */ - pthread_rwlock_t chnl_lock; /** < rwlock used to sync ops with channels */ - int flags; /** < flags of the connection */ + /* Messages section */ + struct __message_t **messages; /** < messages O(1) storage */ + idx_allocator_t *idx_msg; + pthread_mutex_t idx_msg_lock; + list_head_t write_pending; /** < list of messages waiting for write */ + pthread_mutex_t write_pending_lock; + uint8_t unused_messages; /** < unused message count */ + /* Other stuff */ + pthread_t thrd_poll[8]; + uint8_t flags; /** < flags of the connection */ usrtc_node_t csnode; /** < node to store the connection within list */ } conn_t; @@ -94,18 +120,9 @@ struct __message_t; #define ESXCHAN_CLOSURE (1 << 2) typedef struct __channel_t { - ulong_t cid; /** < ID of the channel */ - char *uuid; /** < UUID of the channel, used in advanced implementation - * of the complex distributed systems */ + uint16_t cid; /** < ID of the channel */ conn_t *connection; /** < pointer to the parent connection */ - idx_allocator_t *idx_msg; /** < index allocation for messages */ - usrtc_t *msgs_tree; /** < search tree of the existing messages */ - struct __message_t *sysmsg; /** < system message used to operate with channel */ struct __connection_rpc_list_type *rpc_list; /** < rpc functions list */ - pthread_mutex_t oplock; /** < operation ops lock */ - pthread_rwlock_t msglock; /** < rwlock used to operate with messages */ - usrtc_node_t node; /** < node for connection search tree */ - int use_count; /** < use count */ int flags; /** < flags of the channel */ } chnl_t; @@ -137,15 +154,12 @@ typedef struct __sexp_payload_t { */ typedef struct __message_t { chnl_t *pch; /** < channel of the message(if applicable) */ - ulong_t mid; /** < unique ID within connection context */ - char *uuid; /** < UUID of the message, used for special messages */ - usrtc_node_t pendingq_node; /** < node for the pending queue */ - pthread_mutex_t wait; /** < special wait mutex, used for sync */ + pthread_mutex_t wait; /** < special wait mutex, used for pending list and sync */ void *payload; /** < payload */ - sexp_t *initial_sx; - int opcode; /** < opcode for system and pulse messages */ - int flags; /** < flags of the message (type, state etc ...)*/ - int use_count; /** < use count */ + uint16_t payload_length; /** < payload length */ + uint8_t opcode; /** < opcode for system and pulse messages */ + uint16_t flags; /** < flags of the message (type, state etc ...)*/ + uint16_t idx; } sxmsg_t; typedef struct __connection_rpc_entry_type { @@ -169,11 +183,6 @@ typedef struct __connection_rpc_list_type { */ typedef struct __connections_subsys_type { usrtc_t *connections; - pth_queue_t *ioq; /** < general messages queue */ - pth_queue_t *ioqueue; /** < system messages queue */ - /* system threads */ - pthread_t iog_thread; /** < general io queue */ - pthread_t ios_thread; /** < system io queue */ pthread_rwlock_t rwlock; char *rootca, *certpem, *certkey; /* path name to the certificates */ cx_rpc_list_t *system_rpc; @@ -185,6 +194,7 @@ typedef struct __connections_subsys_type { int (*set_typed_list_callback)(conn_t *, int, char *); /** < this function is a callback * during setting up a typed channel */ void (*on_destroy)(conn_t *); /** < callback on connection destroy */ + void (*on_pulse)(conn_t *, sxmsg_t *); /** < callback on pulse emit */ void *priv; } conn_sys_t; From 2d20080776c1932512719192fa24c430f177fab0 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 17 Jul 2015 02:03:19 +0300 Subject: [PATCH 04/56] connections separated; --- lib/connex.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 lib/connex.c diff --git a/lib/connex.c b/lib/connex.c new file mode 100644 index 0000000..56fac0b --- /dev/null +++ b/lib/connex.c @@ -0,0 +1,254 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#define EBADE 1 +#define NETDB_SUCCESS 0 +#else +#include +#include +#include +#include +#endif + +#include +#include + +#include +#include + +#include + +static int __insert_rpc_function(usrtc_t *tree, const char *name, int (*rpcf)(void *, sexp_t *)) +{ + cx_rpc_t *ent = malloc(sizeof(cx_rpc_t)); + usrtc_node_t *node; + + if(!ent) return ENOMEM; + else node = &ent->node; + + if(!(ent->name = strdup(name))) { + free(ent); + return ENOMEM; + } else ent->rpcf = rpcf; + + usrtc_node_init(node, ent); + usrtc_insert(tree, node, ent->name); + + return 0; +} + +static void __destroy_rpc_list_tree(usrtc_t *tree) +{ + usrtc_node_t *node; + cx_rpc_t *ent; + + for(node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) { + ent = (cx_rpc_t *)usrtc_node_getdata(node); + usrtc_delete(tree, node); + free(ent->name); + free(ent); + } + + return; +} + +/* negotiation functions */ +/** + * Proto: (auth-set-credentials "" "") + * Return - message return; opcode as a return of this function. + * in batch mode message with 0 index used always + */ +static int __set_credentials(void *cctx, sexp_t *sx) +{ + register int idx; + conn_t *co = (conn_t *)cctx; + conn_sys_t *ssys = co->ssys; + sexp_t *isx; + char *login = NULL; + char *passwd = NULL; + + /* take a deal with S-exp */ + SEXP_ITERATE_LIST(sx, isx, idx) { + if(isx->ty == SEXP_LIST) return SNE_BADPROTO; + + if(idx > 0 && isx->aty != SEXP_DQUOTE) return SNE_BADPROTO; + if(idx == 1) login = isx->val; + else if(idx == 2) passwd = isx->val; + else if(idx > 2) return SNE_BADPROTO; + } + + if(!login || !passwd) return SNE_BADPROTO; + + co->pctx->login = strdup(login); + co->pctx->passwd = strdup(passwd); + if(!co->pctx->login || !co->pctx->passwd) { + if(co->pctx->login) free(co->pctx->login); + if(co->pctx->passwd) free(co->pctx->passwd); + return SNE_ENOMEM; + } + + if(ssys->secure_check) return ssys->secure_check(co); + else return SNE_SUCCESS; +} + +static int __get_channels_list(void *cctx, sexp_t *sx) +{ + conn_t *co = (conn_t *)cctx; + conn_sys_t *ssys = co->ssys; + sx_msg_t *msg = co->messages[0]; + char *buf = msg->payload; + usrtc_node_t *node; + rpc_typed_list_t *list_ent; + size_t maxlen = 65535 - sizeof(sntllv2_head_t); + size_t len, ulen = 0; + + /* we will avoid S-exp scanning here */ + + buf += sizeof(sntllv2_head_t); + ulen += snprintf(buf + ulen, maxlen - ulen, "(set-channels-list "); + for(node = usrtc_first(co->rpc_list); node != NULL; + node = usrtc_next(co->rpc_list, node)) { /* fill the list */ + list_ent = (rpc_typed_list_t *)usrtc_node_getdata(node); + ulen += snprintf(buf + ulen, maxlen - ulen, "(:%d \"%s\")", + list_ent->type_id, list_ent->description); + } + ulen += snprintf(buf + ulen, maxlen - ulen, ")"); + msg->payload_length = ulen + sizeof(sntllv2_head_t); + + return SNE_SUCCESS; +} + +static int __set_channels_list(void *cctx, sexp_t *sx) +{ + register int idx; + conn_t *co = (conn_t *)cctx; + conn_sys_t *ssys = co->ssys; + sexp_t *isx, *iisx; + int id, r; + + SEXP_ITERATE_LIST(sx, isx, idx) { + if(!idx) continue; + + if(isx->ty != SEXP_LIST) return SNE_BADPROTO; + if(sexp_list_length(isx) != 2) return SNE_BADPROTO; + + /* get id */ + sexp_list_car(isx, &iisx); + if(iisx->ty == SEXP_LIST) return SNE_BADPROTO; + if(iisx->aty != SEXP_BASIC) return SNE_BADPROTO; + if(iisx->val[0] != ':') return SNE_BADPROTO; + id = atoi(iisx->val + sizeof(char)); + + /* get short description */ + sexp_list_cdr(isx, &iisx); + if(iisx->ty == SEXP_LIST) return SNE_BADPROTO; + if(iisx->aty != SEXP_DQUOTE) return SNE_BADPROTO; + + /* ok, here we go */ + if(ssys->set_typed_list_callback) { + r = ssys->set_typed_list_callback(co, id, iisx->val); + if(r != SNE_SUCCESS) return r; + } + } + + return SNE_SUCCESS; +} + +static int __init_systemrpc_tree(usrtc_t *rtree) +{ + /* batch mode negotiation context functions */ + if(__insert_rpc_function(rtree, "auth-set-credentials", __set_credentials)) goto __fail; + if(__insert_rpc_function(rtree, "get-channels-list", __get_channels_list)) goto __fail; + if(__insert_rpc_function(rtree, "set-channels-list", __set_channels_list)) goto __fail; + + return 0; + + __fail: + __destroy_rpc_list_tree(rtree); + return ENOMEM; +} + +int connections_init(conn_sys_t *ssys) +{ + int r = 0; + + if(!ssys) return EINVAL; + else memset(ssys, 0, sizeof(conn_sys_t)); + + if(!(ssys->connections = malloc(sizeof(usrtc_t)))) return ENOMEM; + + /* init connections list */ + usrtc_init(ssys->connections, USRTC_REDBLACK, MAX_CONNECTIONS, + __cmp_cstr); + if((r = pthread_rwlock_init(&(ssys->rwlock), NULL))) + goto __fini; + + /* init RPC list related functions */ + if(!(ssys->system_rpc = malloc(sizeof(cx_rpc_list_t)))) { + r = ENOMEM; + goto __lfini; + } else { + if(!(ssys->system_rpc->rpc_tree = malloc(sizeof(usrtc_t)))) { + r = ENOMEM; + goto __lfini; + } + usrtc_init(ssys->system_rpc->rpc_tree, USRTC_SPLAY, 256, __cmp_cstr); + r = __init_systemrpc_tree(ssys->system_rpc->rpc_tree); + if(r) { + free(ssys->system_rpc->rpc_tree); + goto __lfini; + } + } + + return 0; + + __lfini: + if(ssys->system_rpc) free(ssys->system_rpc); + pthread_rwlock_destroy(&(ssys->rwlock)); + __fini: + if(ssys->connections) free(ssys->connections); + + return r; +} + +conn_sys_t *connections_create(void) +{ + int r = 0; + conn_sys_t *nsys = malloc(sizeof(conn_sys_t)); + + if(!nsys) { + errno = ENOMEM; + return NULL; + } + + r = connections_init(nsys); + if(r) { + errno = r; + free(nsys); + return NULL; + } + + return nsys; +} From b09d7d6a1089f2f294f269c01b7e7bced58185f2 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 17 Jul 2015 03:27:22 +0300 Subject: [PATCH 05/56] adding more and more ; --- lib/sntllv2.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 lib/sntllv2.c diff --git a/lib/sntllv2.c b/lib/sntllv2.c new file mode 100644 index 0000000..a05fcfe --- /dev/null +++ b/lib/sntllv2.c @@ -0,0 +1,287 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#define EBADE 1 +#define NETDB_SUCCESS 0 +#else +#include +#include +#include +#include +#endif + +#include +#include + +#include +#include + +#include + +static int ex_ssldata_index; /** < index used to work with additional data + * provided to the special call during SSL handshake */ + +/* this function is an ugly implementation to get C string with uuid */ +extern char *__generate_uuid(void); + +/* this is a callback to perform a custom SSL certs chain validation, + * as I promised here the comments, a lot of ... + * The first shit: 0 means validation failed, 1 otherwise + * The second shit: X509 API, I guess u will love it ;-) + * openssl calls this function for each certificate in chain, + * since our case is a simple (depth of chain is one, since we're + * don't care for public certificates lists or I cannot find any reasons to + * do it ...), amount of calls reduced, and in this case we're interested + * only in top of chain i.e. actual certificate used on client side, + * the validity of signing for other certificates within chain is + * guaranteed by the ssl itself. + * u know, we need to lookup in database, or elsewhere... some information + * about client certificate, and decide - is it valid, or not?, if so + * yep I mean it's valid, we can assign it's long fucking number to + * security context, to use in ongoing full scaled connection handshaking. + */ +static int __verify_certcall(int preverify_ok, X509_STORE_CTX *ctx) +{ + // X509 *cert = X509_STORE_CTX_get_current_cert(ctx); + int err = X509_STORE_CTX_get_error(ctx), depth = X509_STORE_CTX_get_error_depth(ctx); + SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + conn_t *co = SSL_get_ex_data(ssl, ex_ssldata_index); /* this is a custom data we're set before */ + conn_sys_t *ssys = co->ssys; + + /* now we need to check for certificates with a long chain, + * so since we have a short one, reject long ones */ + if(depth > VERIFY_DEPTH) { /* longer than we expect */ + preverify_ok = 0; /* yep, 0 means error for those function callback in openssl, fucking set */ + err = X509_V_ERR_CERT_CHAIN_TOO_LONG; + X509_STORE_CTX_set_error(ctx, err); + } + + if(!preverify_ok) return 0; + + /* ok, now we're on top of SSL (depth == 0) certs chain, + * and we can validate client certificate */ + if(!depth) { + co->pctx->certid = + ASN1_INTEGER_get((const ASN1_INTEGER *)X509_get_serialNumber(ctx->current_cert)); + /* now we're need to check the ssl cert */ + if(ssys->validate_sslpem) { + if(ssys->validate_sslpem(co)) return 0; + else return 1; + } else return 0; + } + + return preverify_ok; +} + +/* dummy just to check the server side */ +static int __verify_certcall_dummy(int preverify_ok, X509_STORE_CTX *ctx) +{ + return preverify_ok; +} + +int sntl_init(void) +{ + /* init SSL library */ + SSL_library_init(); + + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + + ex_ssldata_index = SSL_get_ex_new_index(0, "__ssldata index", NULL, NULL, NULL); + + return 0; +} + +conn_t *__connection_minimal_alloc(struct in_addr *addr) +{ + conn_t *co = malloc(sizeof(conn_t)); + int r; + + if(!co) { r = ENOMEM; goto __fail; } + else memset(co, 0, sizeof(conn_t)); + + if(!(co->messages = malloc(sizeof(uintptr_t)*1024))) { r = ENOMEM; goto __fail; } + else memset(co->messages, 0, sizeof(uintptr_t)*1024); + + if(!(co->pctx = malloc(sizeof(perm_ctx_t)))) { r = ENOMEM; goto __fail; } + else memset(co->pctx, 0, sizeof(perm_ctx_t)); + if(addr) { + if(!(co->pctx->addr = malloc(sizeof(struct in_addr)))) { r = ENOMEM; goto __fail; } + + memcpy(co->pctx->addr, addr, sizeof(struct in_addr)); + } + + if(!(co->uuid = __generate_uuid())) { r = ENOMEM; goto __fail; } + + return co; + + __fail: + if(co) { + if(co->pctx) { + if(co->pctx->addr) free(co->pctx->addr); + free(co->pctx); + } + if(co->messages) free(co->messages); + free(co); + } + errno = r; + return NULL; +} + +static void __connection_minimal_free(conn_t *co) +{ + if(co) { + if(co->pctx) { + if(co->pctx->addr) free(co->pctx->addr); + free(co->pctx); + } + if(co->messages) free(co->messages); + free(co->uuid); + free(co); + } + + return; +} + +int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, + struct in_addr *addr) +{ + void *buf = NULL; + char *bbuf; + conn_t *coc = __connection_minimal_alloc(addr); + sx_msg_t *msg = NULL; + sntllv2_head_t *head; + size_t rd; + + if(!coc) return SNE_ENOMEM; + + /* ok, now we need to init ssl stuff */ + co->ssys = ssys; + + /* init SSL certificates and context */ + co->ctx = SSL_CTX_new(TLSv1_2_server_method()); + if(!co->ctx) { goto __fail; } + else { + /* set verify context */ + SSL_CTX_set_verify(co->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + __verify_certcall); + /* set verify depth */ + SSL_CTX_set_verify_depth(co->ctx, VERIFY_DEPTH); + } + + /* load certificates */ + SSL_CTX_load_verify_locations(co->ctx, ssys->rootca, NULL); + /* set the local certificate from CertFile */ + if(SSL_CTX_use_certificate_file(co->ctx, ssys->certpem, + SSL_FILETYPE_PEM)<=0) { + ERR_print_errors_fp(stderr); + goto __fail; + } + /* set the private key from KeyFile (may be the same as CertFile) */ + if(SSL_CTX_use_PrivateKey_file(co->ctx, ssys->certkey, + SSL_FILETYPE_PEM)<=0) { + goto __fail; + } + /* verify private key */ + if (!SSL_CTX_check_private_key(co->ctx)) { + goto __fail; + } + + /* now we will create an SSL connection */ + co->ssl = SSL_new(co->ctx); + if(!co->ssl) goto __fail; + else SSL_set_fd(co->ssl, sck); /* attach connected socket */ + + SSL_set_accept_state(co->ssl); + /* set the context to verify ssl connection */ + SSL_set_ex_data(co->ssl, ex_ssldata_index, (void *)co); + SSL_set_accept_state(co->ssl); + if(SSL_accept(co->ssl) == -1) { + goto __fail; + } + + /* ok, now we are able to allocate and so on */ + /* set connection to the batch mode */ + co->flags |= SNSX_BATCHMODE; + /* allocate our first buffer */ + buf = mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(buf == MAP_FAILED) goto __fail2; + /* allocate first message */ + if(!(msg = malloc(sizeof(sx_msg_t)))) goto __fail2; + else { + memset(msg, 0, sizeof(sx_msg_t)); + coc->messages[0] = msg; + } + bbuf = (char *)buf; + bbuf += sizeof(sntllv2_head_t); + + sexp_t *sx; + while(co->flags & SNSX_BATCHMODE) { + rd = __conn_read(co, buf, sizeof(sntllv2_head_t)); + if(rd == sizeof(sntllv2_head_t)) { + head = (sntllv2_head_t *)buf; + + /* check for returns */ + if(head->opcode != SNE_SUCCESS) goto __fail3; + + rd = __conn_read(co, bbuf, head->payload_length); + if(rd != head->payload_length) goto __fail3; + bbuf[rd] = '\0'; + sx = parse_sexp(bbuf, rd); + if(!sx) goto __fail3; + + /* initialize message */ + msg->payload = bbuf; + msg->payload_length = 0; + /* deal with it */ + r = __eval_syssexp(co, sx); + if(r != SNE_SUCCESS) { /* fuck */ + head->opcode = r; + head->payload_length = 0; + __conn_write(co, buf, sizeof(sntllv2_head_t)); + goto __fail3; + } + + destroy_sexp(sx); + } else goto __fail3; + } + + return SNE_SUCCESS; + + __fail3: + if(ssys->on_destroy) ssys->on_destroy(co); + __fail2: + if(msg) free(msg); + if(buf != MAP_FAILED) munmap(buf, 65536); + SSL_shutdown(co->ssl); + __fail: + if(coc) { + if(co->ssl) SSL_free(co->ssl); + if(co->ctx) SSL_CTX_free(co->ctx); + __connection_minimal_free(coc); + } + close(sck); + return SNE_FAILED; +} From 569176169fef27862e1acec4955d464a329f60da Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 17 Jul 2015 04:03:19 +0300 Subject: [PATCH 06/56] stay tuned folksgit add lib/sntllv2.c lib/connex.c; --- lib/connex.c | 6 ++++++ lib/sntllv2.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/lib/connex.c b/lib/connex.c index 56fac0b..bb846e7 100644 --- a/lib/connex.c +++ b/lib/connex.c @@ -137,6 +137,9 @@ static int __get_channels_list(void *cctx, sexp_t *sx) ulen += snprintf(buf + ulen, maxlen - ulen, ")"); msg->payload_length = ulen + sizeof(sntllv2_head_t); + /* we're ready for messaging mode */ + co->flags |= SNSX_MESSAGINGMODE; + return SNE_SUCCESS; } @@ -173,6 +176,9 @@ static int __set_channels_list(void *cctx, sexp_t *sx) } } + /* we're ready for messaging mode */ + co->flags |= SNSX_MESSAGINGMODE; + return SNE_SUCCESS; } diff --git a/lib/sntllv2.c b/lib/sntllv2.c index a05fcfe..d1c41a0 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -165,6 +165,27 @@ static void __connection_minimal_free(conn_t *co) return; } +static int __eval_syssexp(conn_t *co, sexp_t *sx) +{ + cx_rpc_list_t *rpc_list = co->ssys->system_rpc; + usrtc_node_t *node; + cx_rpc_t *rentry; + char *rpcf; + + if(sx->ty == SEXP_LIST) + rpcf = sx->list->val; + else return SNE_BADPROTO; + + /* find an appropriate function */ + node = usrtc_lookup(rpc_list->rpc_tree, rpcf); + + if(!node) return SNE_ENORPC; + else rentry = (cx_rpc_t *)usrtc_node_getdata(node); + + /* call it */ + return rentry->rpcf((void *)co, sx); +} + int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, struct in_addr *addr) { @@ -218,9 +239,7 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, /* set the context to verify ssl connection */ SSL_set_ex_data(co->ssl, ex_ssldata_index, (void *)co); SSL_set_accept_state(co->ssl); - if(SSL_accept(co->ssl) == -1) { - goto __fail; - } + if(SSL_accept(co->ssl) == -1) goto __fail; /* ok, now we are able to allocate and so on */ /* set connection to the batch mode */ @@ -245,6 +264,12 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, /* check for returns */ if(head->opcode != SNE_SUCCESS) goto __fail3; + else { /* opcode is fine */ + /* if we're ready for messaging mode, turn off batch mode */ + if(co->flags & SNSX_MESSAGINGMODE) co->flags &= ~SNSX_BATCHMODE; + } + + if(!head->payload_length) continue; /* pass the following check up */ rd = __conn_read(co, bbuf, head->payload_length); if(rd != head->payload_length) goto __fail3; @@ -257,10 +282,16 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, msg->payload_length = 0; /* deal with it */ r = __eval_syssexp(co, sx); - if(r != SNE_SUCCESS) { /* fuck */ - head->opcode = r; + head->opcode = r; + if(r != SNE_SUCCESS) { /* we finish */ head->payload_length = 0; __conn_write(co, buf, sizeof(sntllv2_head_t)); + destroy_sexp(sx); + goto __fail3; + } + rd = __conn_write(co, buf, sizeof(sntllv2_head_t) + msg->payload_length); + if(rd != sizeof(sntllv2_head_t) + msg->payload_length) { + destroy_sexp(sx); goto __fail3; } @@ -268,8 +299,16 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, } else goto __fail3; } + /* if we're there - negotiation is done, going to init messaging mode */ + r = __connection_second_alloc(co); + if(r != SNE_SUCCESS) goto __fail3; + + /* and now we're need to create a thread poll */ + return SNE_SUCCESS; + __fail4: + __connection_second_free(co); __fail3: if(ssys->on_destroy) ssys->on_destroy(co); __fail2: From 5fd1ecc7960dbd02aef33a549f3f03a16398138f Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 17 Jul 2015 14:58:07 +0300 Subject: [PATCH 07/56] errno added; --- include/sntl/errno.h | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 include/sntl/errno.h diff --git a/include/sntl/errno.h b/include/sntl/errno.h new file mode 100644 index 0000000..0572936 --- /dev/null +++ b/include/sntl/errno.h @@ -0,0 +1,48 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#ifndef __SNTL_ERRNO_H__ +#define __SNTL_ERRNO_H__ + +#define __SNTL_EPREFIX 200 + +#define SNE_SUCCESS 200 +#define SNE_FAILED 201 +#define SNE_ENOMEM 202 +#define SNE_BADPROTO 203 +#define SNE_ENORPC 204 +#define SNE_EPERM 205 +#define SNE_TOOLONG 206 +#define SNE_EBUSY 207 +#define SNE_WOULDBLOCK 208 +#define SNE_LINKERROR 209 +#define SNE_NOSUCHMSG 210 +#define SNE_NOSUCHCHAN 211 +#define SNE_ETIMEDOUT 212 +#define SNE_IGNORED 213 +#define SNE_REPLYREQ 214 +#define SNE_RAPIDMSG 215 + +/* some old errors for compatibility */ +#define ESXOREPLYREQ SNE_REPLYREQ /* protocol require reply with expression, + * or expression return for the request */ +#define ESXOTIMEDOUT SNE_ETIMEDOUT /* timedout */ +#define ESXRCBADPROT SNE_BADPROTO /* invalid protocol */ +#define ESXNOCONNECT SNE_LINKERROR /* connection is lost */ +#define ESXNOCHANSUP SNE_NOSUCHCHAN +#define ESXRAPIDREPLY SNE_RAPIDMSG + +const char *sntll_errno2cstr(int); + +#endif /* __SNTL_ERRNO_H__ */ + From bbc05161913bdd7b759819fbecd2155d05d9f71d Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 19 Jul 2015 05:06:01 +0300 Subject: [PATCH 08/56] more commits; --- include/sntl/connection.h | 27 +-- include/sntl/errno.h | 6 + lib/connex.c | 5 + lib/sntllv2.c | 337 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 346 insertions(+), 29 deletions(-) diff --git a/include/sntl/connection.h b/include/sntl/connection.h index e6ee696..f1b65f7 100644 --- a/include/sntl/connection.h +++ b/include/sntl/connection.h @@ -33,17 +33,9 @@ #include #include +#include #include -/* TODO: remove to the special separate file - error codes */ -#define ESXOREPLYREQ 44 /* protocol require reply with expression, - * or expression return for the request */ -#define ESXOTIMEDOUT 45 /* timedout */ -#define ESXRCBADPROT 46 /* invalid protocol */ -#define ESXNOCONNECT 47 /* connection is lost */ -#define ESXNOCHANSUP 48 -#define ESXRAPIDREPLY 49 - #define VERIFY_DEPTH 1 /* FIXME: */ #define MAX_CONNECTIONS 32768 @@ -88,9 +80,9 @@ typedef struct __connection_t { struct __connections_subsys_type *ssys; /* < connections subsystem */ char *uuid; /** < uuid of the connection */ /* Channels section */ - idx_allocator_t *idx_ch; /** < index allocation for channels */ + idx_allocator_t idx_ch; /** < index allocation for channels */ pthread_mutex_t idx_ch_lock; /** < mutex for allocating and deallocating channels */ - struct __channel_t **channels; /** < channels O(1) storage */ + volatile struct __channel_t **channels; /** < channels O(1) storage */ /* RPC section */ usrtc_t *rpc_list; /** < search tree of possible RPC typed lists */ /* SSL related section */ @@ -101,15 +93,15 @@ typedef struct __connection_t { /* Security section */ perm_ctx_t *pctx; /** < higher layer authentification context */ /* Messages section */ - struct __message_t **messages; /** < messages O(1) storage */ - idx_allocator_t *idx_msg; + struct __message_t** volatile messages; /** < messages O(1) storage */ + idx_allocator_t idx_msg; pthread_mutex_t idx_msg_lock; list_head_t write_pending; /** < list of messages waiting for write */ pthread_mutex_t write_pending_lock; - uint8_t unused_messages; /** < unused message count */ + volatile uint8_t unused_messages; /** < unused message count */ /* Other stuff */ pthread_t thrd_poll[8]; - uint8_t flags; /** < flags of the connection */ + volatile uint8_t flags; /** < flags of the connection */ usrtc_node_t csnode; /** < node to store the connection within list */ } conn_t; @@ -155,11 +147,8 @@ typedef struct __sexp_payload_t { typedef struct __message_t { chnl_t *pch; /** < channel of the message(if applicable) */ pthread_mutex_t wait; /** < special wait mutex, used for pending list and sync */ + sntllv2_head_t mhead; void *payload; /** < payload */ - uint16_t payload_length; /** < payload length */ - uint8_t opcode; /** < opcode for system and pulse messages */ - uint16_t flags; /** < flags of the message (type, state etc ...)*/ - uint16_t idx; } sxmsg_t; typedef struct __connection_rpc_entry_type { diff --git a/include/sntl/errno.h b/include/sntl/errno.h index 0572936..e6e0f4c 100644 --- a/include/sntl/errno.h +++ b/include/sntl/errno.h @@ -32,6 +32,12 @@ #define SNE_IGNORED 213 #define SNE_REPLYREQ 214 #define SNE_RAPIDMSG 215 +#define SNE_ESSL 216 +#define SNE_NOCHANNELS 217 +#define SNE_MCHANNELS 218 +#define SNE_MMESSAGES 219 +#define SNE_LINKBROKEN 220 +#define SNE_INVALINDEX 221 /* some old errors for compatibility */ #define ESXOREPLYREQ SNE_REPLYREQ /* protocol require reply with expression, diff --git a/lib/connex.c b/lib/connex.c index bb846e7..d3570e5 100644 --- a/lib/connex.c +++ b/lib/connex.c @@ -126,6 +126,11 @@ static int __get_channels_list(void *cctx, sexp_t *sx) /* we will avoid S-exp scanning here */ + /* call the function */ + if(ssys->get_rpc_typed_list_tree) + co->rpc_list = ssys->get_rpc_typed_list_tree(co); + if(!co->rpc_list) return SNE_EPERM; + buf += sizeof(sntllv2_head_t); ulen += snprintf(buf + ulen, maxlen - ulen, "(set-channels-list "); for(node = usrtc_first(co->rpc_list); node != NULL; diff --git a/lib/sntllv2.c b/lib/sntllv2.c index d1c41a0..3381197 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -40,6 +40,36 @@ #include +typedef struct __sntll_bundle_type { + void *buf; + conn_t *conn; +} sntllv2_bundle_t; + +static sntllv2_bundle_t *__sntll_bundle_create(conn_t *co) +{ + sntllv2_bundle_t *n = malloc(sizeof(sntllv2_bundle_t)); + + if(!n) return NULL; + else memset(n, 0, sizeof(sntllv2_bundle_t)); + + n->buf = mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(n->buf == MAP_FAILED) { + free(n); + return NULL; + } + + n->conn = co; + + return n; +} + +static void __sntll_bundle_destroy(sntllv2_bundle_t *n) +{ + munmap(n->buf, 65536) + free(n); + return; +} + static int ex_ssldata_index; /** < index used to work with additional data * provided to the special call during SSL handshake */ @@ -150,6 +180,49 @@ conn_t *__connection_minimal_alloc(struct in_addr *addr) return NULL; } +static int __connection_second_alloc(conn_t *co) +{ + usrtc_node_init(&co->csnode, co); + + if((idx_allocator_init(&co->idx_ch, 512, 0))) goto __fail; + if((idx_allocator_init(&co->idx_msg, 1024, 0))) goto __fail; + + if(!(co->channels = malloc(sizeof(uintptr_t)*512))) goto __fail; + else memset(co->channels, 0, sizeof(uintptr_t)*512); + + /* init mutexes */ + co->idx_ch_lock = PTHREAD_MUTEX_INITIALIZER; + co->idx_msg_lock = PTHREAD_MUTEX_INITIALIZER; + co->write_pending_lock = PTHREAD_MUTEX_INITIALIZER; + co->sslinout[0] = PTHREAD_MUTEX_INITIALIZER; + co->sslinout[1] = PTHREAD_MUTEX_INITIALIZER; + + /* init list */ + list_head_init(&co->write_pending); + + return SNE_SUCCESS; + + __fail: + idx_allocator_destroy(&co->idx_msg); + idx_allocator_destroy(&co->idx_ch); + return SNE_ENOMEM; +} + +static void __connection_second_free(conn_t *co) +{ + if(co->channels) free(co->channels); + idx_allocator_destroy(&co->idx_msg); + idx_allocator_destroy(&co->idx_ch); + + pthread_mutex_destroy(co->idx_ch_lock); + pthread_mutex_destroy(co->idx_msg_lock); + pthread_mutex_destroy(co->write_pending_lock); + pthread_mutex_destroy(co->sslinout[0]); + pthread_mutex_destroy(co->sslinout[1]); + + return; +} + static void __connection_minimal_free(conn_t *co) { if(co) { @@ -186,6 +259,227 @@ static int __eval_syssexp(conn_t *co, sexp_t *sx) return rentry->rpcf((void *)co, sx); } +static void *__sntll_thread(void *b) +{ + sntllv2_bundle_t *bun = (sntllv2_bundle_t *)b; + conn_t *co = bun->co; + void *buf = bun->buf; + char *bbuf = (char*)buf; + sntllv2_head_t *mhead = (sntllv2_head_t *)buf; + sxmsg_t *msg; + chnl_t *channel; + pthread_t self = pthread_self(); + int dispatch = 0; + + /* byte buffer is following head */ + bbuf += sizeof(sntllv2_head_t); + + __wait_alive: + /* flag test - FIXME: make it atomic (it will works atomically on x86, btw on others not) */ + if(!(co->flags & SNSX_ALIVE)) { + if(co->flags & SNSX_CLOSED) goto __finish; + else { + usleep(20); + goto __wait_alive; + } + } + + /* check up a thread */ + if(pthread_equal(self, co->thrd_poll[7])) /* dispatcher */ + dispatch = 1; + + /* the following logic : (except dispatcher) + * 1. check up pending write -> if exists write one and start again., otherwise go next + * 2. read from ssl connection (we will sleep if other already acquire the lock) + */ + while(1) { + __again: + pthread_mutex_lock(&(co->sslinout[0])); + rd = __conn_read(co, mhead, sizeof(sntllv2_head_t)); + if(rd != sizeof(sntllv2_bundle_t)) { + __sslproto_error: + co->flags |= SNSX_CLOSED; + pthread_mutex_unlock(&(co->sslinout[0])); + goto __finish; + } else { + /* check up if we can read or not */ + if(mhead->payload_length) { + rd = __conn_read(co, bbuf, mhead->payload_length); + if(rd < 0) goto __sslproto_error; + else pthread_mutex_unlock(&(co->sslinout[0])); + if(rd != mhead->payload_length) { + /* if we're need to do something */ + if(mhead->msgid >= 1024) { + mhead->opcode = SNE_INVALINDEX; + goto __return_error; + } else msg = co->messages[mhead->msgid]; + if(!msg) { + if(mhead->attr & SXMSG_OPEN) mhead->opcode = SNE_BADPROTO; + else { + if((mhead->attr & SXMSG_PROTO) || (mhead->attr & SXMSG_LINK)) + mhead->opcode = SNE_BADPROTO; + else mhead->opcode = SNE_NOSUCHMSG; + } + } + __return_error: + mhead->attr |= SXMSG_CLOSED; + mhead->payload_length = 0; + pthread_mutex_lock(&(co->sslinout[1])); + wr = __conn_write(co, mhead, sizeof(sntllv2_head_t)); + pthread_mutex_unlock(&(co->sslinout[1])); + if(wr < 0) goto __finish; + else goto __again; + } + } else pthread_mutex_unlock(&(co->sslinout[0])); + /* take a message */ + if(mhead->attr & SXMSG_PROTO) { /* protocol message i.e. channel open/close */ + /* ok, check up the side */ + if(mhead->attr & SXMSG_REPLYREQ) { /* means we're not initiators and we don't need to allocate a message */ + if(mhead->attr & SXMSG_OPEN) + mhead->opcode = _channel_open(co, &mhead->reserve); + else mhead->opcode = _channel_close(co, mhead->reserve); + + /* set flags */ + mhead->payload_length = 0; + mhead->attr &= ~SXMSG_REPLYREQ; + pthread_mutex_lock(&(co->sslinout[1])); + wr = __conn_write(co, mhead, sizeof(sntllv2_head_t)); + pthread_mutex_unlock(&(co->sslinout[1])); + if(wr < 0) goto __finish; + } else { /* it's came back */ + /* reply came ... */ + if(mhead->msgid >= 1024) { + __inval_idx_nor: + fprintf(stderr, "[sntllv2] Invalid index of the message.\n"); + goto __again; + } + msg = co->messages[mhead->msgid]; + if(!msg) goto __inval_idx_nor; + + /* ok now we'are copy data and unlock wait mutex */ + memcpy(&msg->mhead, mhead, sizeof(sntllv2_head_t)); + pthread_mutex_unlock(&msg->wait); + } + } else if(mhead->attr & SXMSG_LINK) { /* link layer messages */ + if(mhead->attr & SXMSG_CLOSE) goto __finish; /* close the link */ + if(mhead->attr & SXMSG_PULSE) { /* it's a link pulse messages */ + /* TODO: syncronization and so on */ + } + } else { /* regular messages */ + if((mhead->attr & SXMSG_OPEN) && (mhead->attr & SXMSG_REPLYREQ)) { /* dialog initiation */ + channel = co->channels[mhead->reserve]; + if(!channel) { /* ok, we'are failed */ + mhead->opcode = SNE_NOSUCHCHAN; + __ret_regerr: + mhead->payload_length = 0; + mhead->attr &= ~SXMSG_REPLYREQ; + mhead->attr &= ~SXMSG_OPEN; + mhead->attr |= SXMSG_CLOSE; + pthread_mutex_lock(&(co->sslinout[1])); + wr = __conn_write(co, mhead, sizeof(sntllv2_head_t)); + pthread_mutex_unlock(&(co->sslinout[1])); + if(wr < 0) goto __finish; + else goto __again; + } + /* if message is busy - fails */ + msg = co->messages[mhead->msgid]; + if(msg) { mhead->opcode = SNE_EBUSY; goto __ret_regerr; } + + /* now we will take a deal */ + if(!(msg = malloc(sizeof(sxmsg_t)))) { + mhead->opcode = SNE_ENOMEM; goto __ret_regerr; + } else { + /* set mutex and channel */ + msg->wait = PTHREAD_MUTEX_INITIALIZER; + msg->pch = channel; + /* copy header only */ + memcpy(&msg->mhead, mhead, sizeof(sntllv2_head_t)); + msg->payload = bbuf; + } + + pthread_mutex_lock(&co->idx_ch_lock); + idx_reserve(&co->idx_ch, mhead->msgid); + co->messages[mhead->msgid] = msg; + pthread_mutex_unlock(&co->idx_ch_lock); + + /* now we are able to process the message */ + __message_process(msg); + } else if(mhead->attr & SXMSG_CLOSE) { + /* check for the message */ + if(mhead->msgid >= 1024) goto __inval_idx_nor; + msg = co->messages[mhead->msgid]; + if(!msg) goto __inval_idx_nor; + + if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ + pthread_mutex_lock(&co->idx_ch_lock); + idx_free(&co->idx_ch, mhead->msgid); + co->messages[mhead->msgid] = NULL; + pthread_mutex_unlock(&co->idx_ch_lock); + + /* now just free it */ + pthread_mutex_destroy(&msg->wait); + free(msg); + } else { + memcpy(&msg->mhead, mhead, sizeof(sntllv2_head_t)); + if(mhead->payload_length) { + msg->payload = malloc(mhead->payload_length); + if(msg->payload) memcpy(msg->payload, bbuf, mhead->payload_length); + else msg->mhead.opcode = SNE_ENOMEM; + } + pthread_mutex_unlock(&msg->wait); /* wake up thread waiting for */ + } + } else if((!(mhead->attr & SXMSG_CLOSE) && !(mhead->attr & SXMSG_OPEN)) && + (mhead->attr & SXMSG_REPLYREQ)) { /* ongoing dialog */ + /* check for the message */ + if(mhead->msgid >= 1024) goto __inval_idx_nor; + msg = co->messages[mhead->msgid]; + if(!msg) goto __inval_idx_nor; + + if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ + pthread_mutex_lock(&co->idx_ch_lock); + idx_free(&co->idx_ch, mhead->msgid); + co->messages[mhead->msgid] = NULL; + pthread_mutex_unlock(&co->idx_ch_lock); + + /* now just free it */ + pthread_mutex_destroy(&msg->wait); + free(msg); + + /* we must reply */ + mhead->opcode = SNE_ETIMEDOUT; + goto __ret_regerr; + } else { + memcpy(&msg->mhead, mhead, sizeof(sntllv2_head_t)); + if(mhead->payload_length) { + msg->payload = malloc(mhead->payload_length); + if(msg->payload) memcpy(msg->payload, bbuf, mhead->payload_length); + else { + mhead->opcode = msg->mhead.opcode = SNE_ENOMEM; /* we will return it to waitee */ + msg->mhead.attr &= ~SXMSG_REPLYREQ; /* doesn't need to reply */ + /* reply here now */ + mhead->payload_length = 0; + mhead->attr &= ~SXMSG_REPLYREQ; + mhead->attr &= ~SXMSG_OPEN; + mhead->attr |= SXMSG_CLOSE; + pthread_mutex_lock(&(co->sslinout[1])); + wr = __conn_write(co, mhead, sizeof(sntllv2_head_t)); + pthread_mutex_unlock(&(co->sslinout[1])); + if(wr < 0) goto __finish; + } + } + pthread_mutex_unlock(&msg->wait); /* wake up thread waiting for */ + } else + { mhead->opcode = SNE_BADPROTO; goto __ret_regerr; } + } + } + } + } + + __finish: + __sntll_bundle_destroy(b); /* destroy bundle */ + return NULL; +} + int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, struct in_addr *addr) { @@ -194,7 +488,9 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, conn_t *coc = __connection_minimal_alloc(addr); sx_msg_t *msg = NULL; sntllv2_head_t *head; + sntllv2_bundle_t *bundle; size_t rd; + int r = SNE_FAILED; if(!coc) return SNE_ENOMEM; @@ -203,7 +499,7 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, /* init SSL certificates and context */ co->ctx = SSL_CTX_new(TLSv1_2_server_method()); - if(!co->ctx) { goto __fail; } + if(!co->ctx) { r = SNE_ENOMEM; goto __fail; } else { /* set verify context */ SSL_CTX_set_verify(co->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, @@ -218,37 +514,40 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, if(SSL_CTX_use_certificate_file(co->ctx, ssys->certpem, SSL_FILETYPE_PEM)<=0) { ERR_print_errors_fp(stderr); + r = SNE_ESSL; goto __fail; } /* set the private key from KeyFile (may be the same as CertFile) */ if(SSL_CTX_use_PrivateKey_file(co->ctx, ssys->certkey, SSL_FILETYPE_PEM)<=0) { + r = SNE_ESSL; goto __fail; } /* verify private key */ if (!SSL_CTX_check_private_key(co->ctx)) { + r = SNE_ESSL; goto __fail; } /* now we will create an SSL connection */ co->ssl = SSL_new(co->ctx); - if(!co->ssl) goto __fail; + if(!co->ssl) { r = SNE_ENOMEM; goto __fail; } else SSL_set_fd(co->ssl, sck); /* attach connected socket */ SSL_set_accept_state(co->ssl); /* set the context to verify ssl connection */ SSL_set_ex_data(co->ssl, ex_ssldata_index, (void *)co); SSL_set_accept_state(co->ssl); - if(SSL_accept(co->ssl) == -1) goto __fail; + if(SSL_accept(co->ssl) == -1) { r = SNE_EPERM; goto __fail; } /* ok, now we are able to allocate and so on */ /* set connection to the batch mode */ co->flags |= SNSX_BATCHMODE; /* allocate our first buffer */ buf = mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if(buf == MAP_FAILED) goto __fail2; + if(buf == MAP_FAILED) { r = SNE_ENOMEM; goto __fail2; } /* allocate first message */ - if(!(msg = malloc(sizeof(sx_msg_t)))) goto __fail2; + if(!(msg = malloc(sizeof(sx_msg_t)))) { r = SNE_ENOMEM; goto __fail2; } else { memset(msg, 0, sizeof(sx_msg_t)); coc->messages[0] = msg; @@ -263,7 +562,7 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, head = (sntllv2_head_t *)buf; /* check for returns */ - if(head->opcode != SNE_SUCCESS) goto __fail3; + if(head->opcode != SNE_SUCCESS) { r = head->opcode; goto __fail3; } else { /* opcode is fine */ /* if we're ready for messaging mode, turn off batch mode */ if(co->flags & SNSX_MESSAGINGMODE) co->flags &= ~SNSX_BATCHMODE; @@ -272,7 +571,7 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, if(!head->payload_length) continue; /* pass the following check up */ rd = __conn_read(co, bbuf, head->payload_length); - if(rd != head->payload_length) goto __fail3; + if(rd != head->payload_length) { r = SNE_LINKERROR; goto __fail3; } bbuf[rd] = '\0'; sx = parse_sexp(bbuf, rd); if(!sx) goto __fail3; @@ -296,17 +595,35 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, } destroy_sexp(sx); - } else goto __fail3; + } else { r = SNE_LINKERROR; goto __fail3; } } /* if we're there - negotiation is done, going to init messaging mode */ r = __connection_second_alloc(co); - if(r != SNE_SUCCESS) goto __fail3; + if(r != SNE_SUCCESS) goto __fail3; /* and now we're need to create a thread poll */ + if(!(bundle = malloc(sizeof(sntllv2_bundle_t)))) { r = SNE_ENOMEM; goto __fail4; } + else { + bundle->buf = buf; + bundle->conn = co; + } + for(i = 0; i < 8; i++) { + if(bundle == 0xdead) bundle = __sntll_bundle_create(co); + if(!bundle) goto __fail5; + r = pthread_create(&thrd_poll[i], NULL, __sntll_thread, bundle); + if(r) goto __fail5; + else bundle = 0xdead; + } + + /* all is done, connection now ready */ + co->flags |= SNSX_ALIVE; return SNE_SUCCESS; + __fail5: + r = SNE_ENOMEM; + /* bundles will be freed by the threads when SSL_read will fails. */ __fail4: __connection_second_free(co); __fail3: @@ -322,5 +639,5 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, __connection_minimal_free(coc); } close(sck); - return SNE_FAILED; + return r; } From 10aec3c4475fc77009f28f3f676e50613c36322c Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 19 Jul 2015 06:20:47 +0300 Subject: [PATCH 09/56] link; --- lib/sntllv2.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 3 deletions(-) diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 3381197..2c9c11d 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -480,13 +480,14 @@ static void *__sntll_thread(void *b) return NULL; } +/* FIXME: AWARE coc and co - fix it */ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, struct in_addr *addr) { void *buf = NULL; char *bbuf; conn_t *coc = __connection_minimal_alloc(addr); - sx_msg_t *msg = NULL; + sxmsg_t *msg = NULL; sntllv2_head_t *head; sntllv2_bundle_t *bundle; size_t rd; @@ -547,9 +548,9 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, buf = mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(buf == MAP_FAILED) { r = SNE_ENOMEM; goto __fail2; } /* allocate first message */ - if(!(msg = malloc(sizeof(sx_msg_t)))) { r = SNE_ENOMEM; goto __fail2; } + if(!(msg = malloc(sizeof(sxmsg_t)))) { r = SNE_ENOMEM; goto __fail2; } else { - memset(msg, 0, sizeof(sx_msg_t)); + memset(msg, 0, sizeof(sxmsg_t)); coc->messages[0] = msg; } bbuf = (char *)buf; @@ -641,3 +642,195 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, close(sck); return r; } + +conn_t *connection_link(conn_sys_t *ssys, const char *host, + int port, const char *SSL_cert, const char *login, + const char *passwd) +{ + conn_t *co = __connection_minimal_alloc(addr); + struct hostent *host_; + struct sockaddr_in addr; + int r = SNE_SUCCESS, sck; +#ifdef WIN32 + WSADATA wsaData; +#endif + char hostbuf[2048]; + void *buf = NULL; + char *bbuf; + sntllv2_head_t *head; + sntllv2_bundle_t *bundle; + size_t rd; + + r = SNE_IGNORED; + if(!host || !SSL_cert) goto __fail; + if(!co) { r = SNE_ENOMEM; goto __fail; } + +#ifdef WIN32 + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif + + /* ok, now we need to init ssl stuff */ + co->ssys = ssys; + + /* init SSL certificates and context */ + co->ctx = SSL_CTX_new(TLSv1_2_client_method()); + if(!co->ctx) { r = SNE_ENOMEM; goto __fail; } + else { + /* set verify context */ + SSL_CTX_set_verify(co->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + __verify_certcall_dummy); + /* set verify depth */ + SSL_CTX_set_verify_depth(co->ctx, VERIFY_DEPTH); + } + + /* load certificates */ + SSL_CTX_load_verify_locations(co->ctx, ssys->rootca, NULL); + /* set the local certificate from CertFile */ + if(SSL_CTX_use_certificate_file(co->ctx, SSL_cert, + SSL_FILETYPE_PEM)<=0) { + ERR_print_errors_fp(stderr); + r = SNE_ESSL; + goto __fail; + } + /* set the private key from KeyFile (may be the same as CertFile) */ + if(SSL_CTX_use_PrivateKey_file(co->ctx, SSL_cert, + SSL_FILETYPE_PEM)<=0) { + r = SNE_ESSL; + goto __fail; + } + /* verify private key */ + if (!SSL_CTX_check_private_key(co->ctx)) { + r = SNE_ESSL; + goto __fail; + } + + /* resolve host */ +#ifdef WIN32 + host_ = gethostbyname(host); +#else + r = __resolvehost(host, hostbuf, 2048, &host_); +#endif + if(r) { + r = SNE_FAILED; + goto __fail; + } + + /* create a socket */ + sck = socket(PF_INET, SOCK_STREAM, 0); + bzero(&addr, sizeof(addr)); + + /* try to connect it */ + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = *(uint32_t*)(host_->h_addr); + r = connect(sck, (struct sockaddr*)&addr, sizeof(addr)); + if(r) { + close(sck); + r = SNE_FAILED; /* couldn't connect to the desired host */ + goto __fail; + } + + /* SSL handshake */ + co->ssl = SSL_new(co->ctx); /* TODO: checkout for it */ + SSL_set_fd(co->ssl, sck); /* attach connected socket */ + SSL_set_connect_state(co->ssl); + if(SSL_connect(co->ssl) == -1) { + r = SNE_EPERM; + /* shutdown connection */ + goto __fail; + } /* if success we're ready to use established SSL channel */ + + /* set connection to the batch mode */ + co->flags |= SNSX_BATCHMODE; + + /* allocate our first buffer */ + buf = mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if(buf == MAP_FAILED) { r = SNE_ENOMEM; goto __fail2; } + /* allocate first message */ + if(!(msg = malloc(sizeof(sxmsg_t)))) { r = SNE_ENOMEM; goto __fail2; } + else { + memset(msg, 0, sizeof(sxmsg_t)); + co->messages[0] = msg; + } + bbuf = (char *)buf; + bbuf += sizeof(sntllv2_head_t); + head = (sntllv2_head_t *)buf; + + sexp_t *sx; + size_t ln; + while(co->flags & SNSX_BATCHMODE) { + /* form a message -- credentials */ + ln = snprintf(bbuf, 65535 - sizeof(sntllv2_head_t), "(auth-set-credentials \"%s\" \"%s\")", + login ? login : "nil", passwd ? passwd : "nil"); + head->opcode = SNE_SUCCESS; + head->payload_length = ln; + wr = __conn_write(co, buf, ln + sizeof(sntllv2_head_t)); + if(wr < 0) goto __fail2; + + rd = __conn_read(co, head, sizeof(sntllv2_head_t)); + if(rd < 0) goto __fail2; + if(head->opcode != SNE_SUCCESS) goto __fail2; + + /* ok, get available channels */ + head->opcode = SNE_SUCCESS; + head->payload_length = ln; + ln = snprintf(bbuf, 65535 - sizeof(sntllv2_head_t), "(get-channels-list)"); + wr = __conn_write(co, buf, ln + sizeof(sntllv2_head_t)); + if(wr < 0) goto __fail2; + + rd = __conn_read(co, head, sizeof(sntllv2_head_t)); + if(rd < 0) goto __fail2; + if(head->opcode != SNE_SUCCESS) goto __fail2; + if(!head->payload_length) goto __fail2; + rd = __conn_read(co, bbuf, head->payload_length); + if(rd < 0) goto __fail2; + + /* perform a parsing of the desired message */ + bbuf[rd] = '\0'; + sx = parse_sexp(bbuf, rd); + r = __eval_syssexp(co, sx); + destroy_sexp(sx); + head->opcode = r; + head->payload_length = 0; + wr = __conn_write(co, head, sizeof(sntllv2_head_t)); + if(wr < 0) goto __fail2; + if(r != SNE_SUCCESS) goto __fail2; + } + + /* if we're there - negotiation is done, going to init messaging mode */ + r = __connection_second_alloc(co); + if(r != SNE_SUCCESS) goto __fail3; + + /* and now we're need to create a thread poll */ + if(!(bundle = malloc(sizeof(sntllv2_bundle_t)))) { r = SNE_ENOMEM; goto __fail4; } + else { + bundle->buf = buf; + bundle->conn = co; + } + for(i = 0; i < 8; i++) { + if(bundle == 0xdead) bundle = __sntll_bundle_create(co); + if(!bundle) goto __fail5; + r = pthread_create(&thrd_poll[i], NULL, __sntll_thread, bundle); + if(r) goto __fail5; + else bundle = 0xdead; + } + + /* all is done, connection now ready */ + co->flags |= SNSX_ALIVE; + + return co; + + __fail2: + if(buf != MAP_FAILED) munmap(buf, 65536); + SSL_shutdown(co->ssl); + close(sck); + __fail: + if(co) { + if(co->ssl) SSL_free(co->ssl); + if(co->ctx) SSL_CTX_free(co->ctx); + __connection_minimal_free(co); + } + errno = r; + return NULL; +} + From 1872fddbbffd3f82a5e1548f289dc6090b49ae1d Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 19 Jul 2015 06:42:29 +0300 Subject: [PATCH 10/56] read write; --- lib/sntllv2.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 2c9c11d..a3a5405 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -45,6 +45,126 @@ typedef struct __sntll_bundle_type { conn_t *conn; } sntllv2_bundle_t; +static int __conn_read(conn_t *co, void *buf, size_t buf_len) +{ + int rfd = SSL_get_fd(co->ssl), r; + fd_set readset, writeset; + int ofcmode, read_blocked = 0, read_blocked_on_write = 0; + + /* First we make the socket nonblocking */ +#ifndef WIN32 + ofcmode = fcntl(rfd, F_GETFL,0); + ofcmode |= O_NDELAY; + if(fcntl(rfd, F_SETFL, ofcmode)) + fprintf(stderr, "Couldn't make socket nonblocking"); +#endif + + __retry: + + do { + __try_again: + r = SSL_read(co->ssl, buf, (int)buf_len); + switch(SSL_get_error (co->ssl, r)) { + case SSL_ERROR_NONE: + return r; + break; + case SSL_ERROR_WANT_READ: + /* get prepare to select */ + read_blocked = 1; + break; + case SSL_ERROR_WANT_WRITE: /* here we blocked on write */ + read_blocked_on_write = 1; + break; + case SSL_ERROR_SYSCALL: + if(errno == EAGAIN || errno == EINTR) goto __try_again; + else { + fprintf(stderr, "SSL syscall error.\n"); + goto __close_conn; + } + break; + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + fprintf(stderr, "SSL negotiation required. Trying again.\n"); + goto __try_again; + break; + case SSL_ERROR_SSL: + fprintf(stderr, "SSL error occured. Connection will be closed.\n"); + goto __close_conn; + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, "SSL connection is cleary closed.\n"); + default: + __close_conn: + fprintf(stderr, "(RD)Unknown error on %s (errno = %d)\n", co->uuid, errno); + return -1; + } + } while(SSL_pending(co->ssl) && !read_blocked); + + __select_retry: + + if(read_blocked) { + FD_ZERO(&readset); + FD_SET(rfd, &readset); + /* waits until something will be ready to read */ + r = select(rfd + 1, &readset, NULL, NULL, NULL); + if(r < 0) { + if(errno == EINTR || errno == EAGAIN) goto __select_retry; + printf("(RD) select (%d) on %s\n", errno, co->uuid); + return -1; + } + if(!r) { + printf("Nothing to wait for\n"); + return 0; + } + read_blocked = 0; + if(r && FD_ISSET(rfd, &readset)) goto __retry; /* try to read again */ + } + if(read_blocked_on_write) { /* we was blocked on write */ + FD_ZERO(&readset); + FD_ZERO(&writeset); + FD_SET(rfd, &readset); + FD_SET(rfd, &writeset); + + r = select(rfd + 1, &readset, &writeset, NULL, NULL); + read_blocked_on_write = 0; + if(r && FD_ISSET(rfd, &writeset)) goto __retry; + } + + return 0; +} + +static int __conn_write(conn_t *co, void *buf, size_t buf_len) +{ + int r, rfd = SSL_get_fd(co->ssl); + fd_set writeset; + + __retry: + r = SSL_write(co->ssl, buf, (int)buf_len); + switch(SSL_get_error(co->ssl, r)) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + /* here we should block */ + FD_ZERO(&writeset); + FD_SET(rfd, &writeset); + r = select(rfd + 1, NULL, &writeset, NULL, NULL); + if(r && FD_ISSET(rfd, &writeset)) goto __retry; + break; + case SSL_ERROR_SYSCALL: + if(errno == EAGAIN || errno == EINTR) goto __retry; + else goto __close_conn; + break; + default: + pthread_mutex_unlock(&(co->oplock)); + __close_conn: + if(r < 0) { + fprintf(stderr, "[sntllv2] (WR)Unknown error on %s (%d)\n", co->uuid, r); + return -1; + } else return 0; + } + + return 0; +} + static sntllv2_bundle_t *__sntll_bundle_create(conn_t *co) { sntllv2_bundle_t *n = malloc(sizeof(sntllv2_bundle_t)); From 7b025730d77493ad0c9a85bfa7cc9d2d316a00d1 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 18:34:07 +0300 Subject: [PATCH 11/56] more compilable sources; --- .gitignore | 1 + configure.ac | 2 +- include/sntl/sntllv2.h | 228 ++++++++++++++++++++++++ lib/Makefile.am | 18 +- lib/chansx.c | 50 ++++++ lib/connection.c | 6 + lib/connex.c | 13 +- lib/{libsntl.pc.in => libsntllv2.pc.in} | 4 +- lib/sntllv2.c | 129 ++++++++------ 9 files changed, 379 insertions(+), 72 deletions(-) create mode 100644 include/sntl/sntllv2.h create mode 100644 lib/chansx.c rename lib/{libsntl.pc.in => libsntllv2.pc.in} (84%) diff --git a/.gitignore b/.gitignore index c296422..e7be69f 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ aclocal coq *.log *.crt +lib/libsntllv2.pc diff --git a/configure.ac b/configure.ac index 36b40c5..d03ab05 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ AM_CONDITIONAL(BUILD_WIN32, test "x$enable_win32_build" = "xyes") AC_OUTPUT([ Makefile -lib/libsntl.pc +lib/libsntllv2.pc lib/Makefile include/Makefile examples/Makefile]) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h new file mode 100644 index 0000000..43806bf --- /dev/null +++ b/include/sntl/sntllv2.h @@ -0,0 +1,228 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#ifndef __SNTL_SNTLLV2_H__ +#define __SNTL_SNTLLV2_H__ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#define VERIFY_DEPTH 1 /* FIXME: */ + +typedef struct __perm_context_type { + char *login; + char *passwd; + uint64_t certid; + struct in_addr *addr; + void *priv; +} perm_ctx_t; + +/* 8 byte header */ +typedef struct __sntllv2_head_type { + uint16_t msgid; + uint16_t payload_length; + uint8_t attr; + uint8_t opcode; + uint16_t reserve; +}__attribute__((packed)) sntllv2_head_t; + +struct __connections_subsys_type; +struct __channel_t; +struct __message_t; + +/* flags for the connection link */ +#define SNSX_BATCHMODE (1 << 1) +#define SNSX_MESSAGINGMODE (1 << 2) +#define SNSX_ALIVE (1 << 3) +#define SNSX_CLOSED (1 << 4) + +/* + * älä jätä kommentteja omalla kielellä! yksinkertaisia englanti sijaan! + * i found somebody who write comments and messages in non-english, + * it's a fucking practice - forget it. + */ +typedef struct __connection_t { + /* General section */ + struct __connections_subsys_type *ssys; /* < connections subsystem */ + char *uuid; /** < uuid of the connection */ + /* Channels section */ + idx_allocator_t idx_ch; /** < index allocation for channels */ + pthread_mutex_t idx_ch_lock; /** < mutex for allocating and deallocating channels */ + struct __channel_t **channels; /** < channels O(1) storage */ + /* RPC section */ + usrtc_t *rpc_list; /** < search tree of possible RPC typed lists */ + /* SSL related section */ + SSL_CTX *ctx; /** < SSL context */ + SSL *ssl; /** < SSL connection */ + int ssl_data_index; /** < SSL index for the custom data */ + pthread_mutex_t sslinout[2]; /** < SSL related locks for in and out */ + /* Security section */ + perm_ctx_t *pctx; /** < higher layer authentification context */ + /* Messages section */ + struct __message_t **messages; /** < messages O(1) storage */ + idx_allocator_t idx_msg; + pthread_mutex_t idx_msg_lock; + list_head_t write_pending; /** < list of messages waiting for write */ + pthread_mutex_t write_pending_lock; + volatile uint8_t unused_messages; /** < unused message count */ + /* Other stuff */ + pthread_t thrd_poll[8]; + volatile uint8_t flags; /** < flags of the connection */ + usrtc_node_t csnode; /** < node to store the connection within list */ +} conn_t; + +struct __connection_rpc_list_type; +struct __message_t; + +typedef struct __channel_t { + uint16_t cid; /** < ID of the channel */ + conn_t *connection; /** < pointer to the parent connection */ + struct __connection_rpc_list_type *rpc_list; /** < rpc functions list */ + int flags; /** < flags of the channel */ +} chnl_t; + +/* message flags */ +#define SXMSG_OPEN (1 << 1) +#define SXMSG_CLOSED (1 << 2) +#define SXMSG_PROTO (1 << 3) +#define SXMSG_LINK (1 << 4) +#define SXMSG_REPLYREQ (1 << 5) +#define SXMSG_PULSE (1 << 6) +#define SXMSG_TIMEDOUT (1 << 7) + +/** + * \brief Message used in sntl message passing + * + * This structure used to manage a message within a channel + * of the sntl structure stack. + */ +typedef struct __message_t { + chnl_t *pch; /** < channel of the message(if applicable) */ + pthread_mutex_t wait; /** < special wait mutex, used for pending list and sync */ + sntllv2_head_t mhead; + void *payload; /** < payload */ +} sxmsg_t; + +#define sxmsg_payload(m) (m)->payload +#define sxmsg_datalen(m) (m)->mhead.payload_length +#define sxmsg_rapidbuf(m) (m)->payload +#define sxmsg_retcode(m) (m)->mhead.opcode +#define sxmsg_waitlock(m) pthread_mutex_lock(&((m)->wait)) +#define sxmsg_waitunlock(m) pthread_mutex_unlock(&((m)->wait)) + +typedef struct __connection_rpc_entry_type { + char *name; + int (*rpcf)(void *, sexp_t *); + usrtc_node_t node; +} cx_rpc_t; + +typedef struct __connection_rpc_list_type { + usrtc_t *rpc_tree; /** < search tree for the rpc lookup */ + char *opt_version; /** < reserved for future implementations */ +} cx_rpc_list_t; + +#define MAX_CONNECTIONS 32768 + +/** + * \brief Connection subsystem structure. + * + * This structure used for management and control a set of a + * determined connections with the same RPC lists and the same + * mode (server, client). + * + */ +typedef struct __connections_subsys_type { + usrtc_t *connections; + pthread_rwlock_t rwlock; + char *rootca, *certpem, *certkey; /* path name to the certificates */ + cx_rpc_list_t *system_rpc; + /* special functions pointers */ + int (*validate_sslpem)(conn_t *); /** < this function used to validate SSL certificate while SSL handshake */ + int (*secure_check)(conn_t *); /** < this function authorize user to login, + * and also should check SSL cert and user, and already made sessions */ + usrtc_t* (*get_rpc_typed_list_tree)(conn_t *); /** < this function is used to set RPC list of the functions */ + int (*set_typed_list_callback)(conn_t *, int, char *); /** < this function is a callback + * during setting up a typed channel */ + void (*on_destroy)(conn_t *); /** < callback on connection destroy */ + void (*on_pulse)(conn_t *, sxmsg_t *); /** < callback on pulse emit */ + void *priv; +} conn_sys_t; + +#define connections_set_sslvalidate(c, f) (c)->validate_sslpem = (f) +#define connections_set_authcheck(c, f) (c)->secure_check = (f) +#define connections_set_rpcvalidator(c, f) (c)->get_rpc_typed_list_tree = (f) +#define connections_set_channelcall(c, f) (c)->set_typed_list_callback = (f) +#define connections_set_ondestroy(c, f) (c)->on_destroy = (f) +#define connections_set_onpulse(c, f) (c)->on_pulse = (f) + +typedef struct __rpc_typed_list_type { + int type_id; + char *description; + cx_rpc_list_t *rpc_list; + usrtc_node_t lnode; +} rpc_typed_list_t; + +/* API */ +int connections_init(conn_sys_t *ssys); + +conn_sys_t *connections_create(void); + +int connections_destroy(conn_sys_t *ssys); + +int connections_free(conn_sys_t *ssys); + +/* create links */ +conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr); +conn_t *connection_link(conn_sys_t *ssys, const char *host, + int port, const char *SSL_cert, const char *login, + const char *passwd); +int connection_close(conn_t *co); + +/* channels */ +chnl_t *sxchannel_open(conn_t *co, int type); +int sxchannel_close(chnl_t *channel); + +/* messages */ +/* + * creates a message with a payload. + * Will return a error code, and, if applicable, pointer to message + */ +int sxmsg_send(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg); +/* the same - postponed message i.e. will be written to the queue - not to write immendatly */ +int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg); +/* send a pulse message */ +int sxmsg_pulse(conn_t *co, const char *data, size_t datalen); +/* the same but will be postponed */ +int sxmsg_pulse_pp(conn_t *co, const char *data, size_t datalen); +int sxmsg_reply(sxmsg_t *msg, const char *data, size_t datalen); +int sxmsg_reply_pp(sxmsg_t *msg, const char *data, size_t datalen); +int sxmsg_rreply(sxmsg_t *msg, const char *data, size_t datalen); +int sxmsg_rreply_pp(sxmsg_t *msg, const char *data, size_t datalen); +int sxmsg_return(sxmsg_t *msg, int opcode); +int sxmsg_return_pp(sxmsg_t *msg, int opcode); + +#endif /* __SNTL_SNTLLV2_H__ */ + + diff --git a/lib/Makefile.am b/lib/Makefile.am index eaa6fbb..38070d9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -10,25 +10,25 @@ AM_CFLAGS =\ -Wall\ -g -lib_LTLIBRARIES = libsntl.la +lib_LTLIBRARIES = libsntllv2.la -libsntl_la_SOURCES = \ - support.c queue.c rpclist.c message.c channel.c connection.c +libsntllv2_la_SOURCES = \ + connex.c sntllv2.c -libsntl_la_LDFLAGS = -Wl,--export-dynamic +libsntllv2_la_LDFLAGS = -Wl,--export-dynamic -libsntl_la_LIBADD = -lpthread -lcrypto $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) +libsntllv2_la_LIBADD = -lpthread -lcrypto $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) if BUILD_WIN32 -libsntl_la_LIBADD += -luuid +libsntllv2_la_LIBADD += -luuid else -libsntl_la_LIBADD += $(LIBUUID_LIBS) +libsntllv2_la_LIBADD += $(LIBUUID_LIBS) endif !BUILD_WIN32 pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libsntl.pc +pkgconfig_DATA = libsntllv2.pc EXTRA_DIST = \ - libsntl.pc.in + libsntllv2.pc.in diff --git a/lib/chansx.c b/lib/chansx.c new file mode 100644 index 0000000..6d469dc --- /dev/null +++ b/lib/chansx.c @@ -0,0 +1,50 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#define EBADE 1 +#define NETDB_SUCCESS 0 +#else +#include +#include +#include +#include +#endif + +#include +#include + +#include +#include + +#include + +/* locally used functions */ +uint8_t _channel_open(conn_t *co, uint16_t *chid) +{ +} + +uint8_t _channel_close(conn_t *co, uint16_t chid) +{ +} diff --git a/lib/connection.c b/lib/connection.c index a435ae5..5b4f5e5 100644 --- a/lib/connection.c +++ b/lib/connection.c @@ -54,6 +54,12 @@ static int ex_ssldata_index; /** < index used to work with additional data int sntl_init(void) { + /* init SSL library */ + SSL_library_init(); + + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + ex_ssldata_index = SSL_get_ex_new_index(0, "__ssldata index", NULL, NULL, NULL); return 0; diff --git a/lib/connex.c b/lib/connex.c index d3570e5..4b52a10 100644 --- a/lib/connex.c +++ b/lib/connex.c @@ -38,7 +38,7 @@ #include #include -#include +#include static int __insert_rpc_function(usrtc_t *tree, const char *name, int (*rpcf)(void *, sexp_t *)) { @@ -117,12 +117,12 @@ static int __get_channels_list(void *cctx, sexp_t *sx) { conn_t *co = (conn_t *)cctx; conn_sys_t *ssys = co->ssys; - sx_msg_t *msg = co->messages[0]; + sxmsg_t *msg = co->messages[0]; char *buf = msg->payload; usrtc_node_t *node; rpc_typed_list_t *list_ent; size_t maxlen = 65535 - sizeof(sntllv2_head_t); - size_t len, ulen = 0; + size_t ulen = 0; /* we will avoid S-exp scanning here */ @@ -140,7 +140,7 @@ static int __get_channels_list(void *cctx, sexp_t *sx) list_ent->type_id, list_ent->description); } ulen += snprintf(buf + ulen, maxlen - ulen, ")"); - msg->payload_length = ulen + sizeof(sntllv2_head_t); + msg->mhead.payload_length = ulen + sizeof(sntllv2_head_t); /* we're ready for messaging mode */ co->flags |= SNSX_MESSAGINGMODE; @@ -201,6 +201,11 @@ static int __init_systemrpc_tree(usrtc_t *rtree) return ENOMEM; } +static long __cmp_cstr(const void *a, const void *b) +{ + return (long)strcmp((const char *)a, (const char *)b); +} + int connections_init(conn_sys_t *ssys) { int r = 0; diff --git a/lib/libsntl.pc.in b/lib/libsntllv2.pc.in similarity index 84% rename from lib/libsntl.pc.in rename to lib/libsntllv2.pc.in index 622a506..4b09ce6 100644 --- a/lib/libsntl.pc.in +++ b/lib/libsntllv2.pc.in @@ -5,9 +5,9 @@ datarootdir=@datarootdir@ datadir=@datadir@ includedir=@includedir@ -Name: libsntl +Name: libsntllv2 Description: Secure Network Transport Layer library implementation Version: @VERSION@ Requires: -Libs: -L${libdir} -lsntl +Libs: -L${libdir} -lsntllv2 Cflags: -I${includedir} diff --git a/lib/sntllv2.c b/lib/sntllv2.c index a3a5405..a5f0654 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #ifdef WIN32 @@ -36,9 +37,10 @@ #include #include +#include #include -#include +#include typedef struct __sntll_bundle_type { void *buf; @@ -56,7 +58,7 @@ static int __conn_read(conn_t *co, void *buf, size_t buf_len) ofcmode = fcntl(rfd, F_GETFL,0); ofcmode |= O_NDELAY; if(fcntl(rfd, F_SETFL, ofcmode)) - fprintf(stderr, "Couldn't make socket nonblocking"); + fprintf(stderr, "[sntllv2] (RD)Couldn't make socket nonblocking"); #endif __retry: @@ -78,24 +80,24 @@ static int __conn_read(conn_t *co, void *buf, size_t buf_len) case SSL_ERROR_SYSCALL: if(errno == EAGAIN || errno == EINTR) goto __try_again; else { - fprintf(stderr, "SSL syscall error.\n"); + fprintf(stderr, "[sntllv2] (RD)SSL syscall error.\n"); goto __close_conn; } break; case SSL_ERROR_WANT_CONNECT: case SSL_ERROR_WANT_ACCEPT: - fprintf(stderr, "SSL negotiation required. Trying again.\n"); + fprintf(stderr, "[sntllv2] (RD)SSL negotiation required. Trying again.\n"); goto __try_again; break; case SSL_ERROR_SSL: - fprintf(stderr, "SSL error occured. Connection will be closed.\n"); + fprintf(stderr, "[sntllv2] (RD)SSL error occured. Connection will be closed.\n"); goto __close_conn; break; case SSL_ERROR_ZERO_RETURN: - fprintf(stderr, "SSL connection is cleary closed.\n"); + fprintf(stderr, "[sntllv2] (RD)SSL connection is cleary closed.\n"); default: __close_conn: - fprintf(stderr, "(RD)Unknown error on %s (errno = %d)\n", co->uuid, errno); + fprintf(stderr, "[sntllv2] (RD)Unknown error on %s (errno = %d)\n", co->uuid, errno); return -1; } } while(SSL_pending(co->ssl) && !read_blocked); @@ -109,11 +111,11 @@ static int __conn_read(conn_t *co, void *buf, size_t buf_len) r = select(rfd + 1, &readset, NULL, NULL, NULL); if(r < 0) { if(errno == EINTR || errno == EAGAIN) goto __select_retry; - printf("(RD) select (%d) on %s\n", errno, co->uuid); + fprintf(stderr, "[sntllv2] (RD)Select (%d) on %s\n", errno, co->uuid); return -1; } if(!r) { - printf("Nothing to wait for\n"); + fprintf(stderr, "[sntllv2] (RD)Nothing to wait for\n"); return 0; } read_blocked = 0; @@ -130,7 +132,7 @@ static int __conn_read(conn_t *co, void *buf, size_t buf_len) if(r && FD_ISSET(rfd, &writeset)) goto __retry; } - return 0; + return r; } static int __conn_write(conn_t *co, void *buf, size_t buf_len) @@ -154,15 +156,14 @@ static int __conn_write(conn_t *co, void *buf, size_t buf_len) else goto __close_conn; break; default: - pthread_mutex_unlock(&(co->oplock)); __close_conn: if(r < 0) { fprintf(stderr, "[sntllv2] (WR)Unknown error on %s (%d)\n", co->uuid, r); return -1; - } else return 0; + } else return r; } - return 0; + return r; } static sntllv2_bundle_t *__sntll_bundle_create(conn_t *co) @@ -185,7 +186,7 @@ static sntllv2_bundle_t *__sntll_bundle_create(conn_t *co) static void __sntll_bundle_destroy(sntllv2_bundle_t *n) { - munmap(n->buf, 65536) + munmap(n->buf, 65536); free(n); return; } @@ -311,14 +312,14 @@ static int __connection_second_alloc(conn_t *co) else memset(co->channels, 0, sizeof(uintptr_t)*512); /* init mutexes */ - co->idx_ch_lock = PTHREAD_MUTEX_INITIALIZER; - co->idx_msg_lock = PTHREAD_MUTEX_INITIALIZER; - co->write_pending_lock = PTHREAD_MUTEX_INITIALIZER; - co->sslinout[0] = PTHREAD_MUTEX_INITIALIZER; - co->sslinout[1] = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_init(&co->idx_ch_lock, NULL); + pthread_mutex_init(&co->idx_msg_lock, NULL); + pthread_mutex_init(&co->write_pending_lock, NULL); + pthread_mutex_init(&co->sslinout[0], NULL); + pthread_mutex_init(&co->sslinout[1], NULL); /* init list */ - list_head_init(&co->write_pending); + list_init_head(&co->write_pending); return SNE_SUCCESS; @@ -334,11 +335,11 @@ static void __connection_second_free(conn_t *co) idx_allocator_destroy(&co->idx_msg); idx_allocator_destroy(&co->idx_ch); - pthread_mutex_destroy(co->idx_ch_lock); - pthread_mutex_destroy(co->idx_msg_lock); - pthread_mutex_destroy(co->write_pending_lock); - pthread_mutex_destroy(co->sslinout[0]); - pthread_mutex_destroy(co->sslinout[1]); + pthread_mutex_destroy(&co->idx_ch_lock); + pthread_mutex_destroy(&co->idx_msg_lock); + pthread_mutex_destroy(&co->write_pending_lock); + pthread_mutex_destroy(&co->sslinout[0]); + pthread_mutex_destroy(&co->sslinout[1]); return; } @@ -382,7 +383,7 @@ static int __eval_syssexp(conn_t *co, sexp_t *sx) static void *__sntll_thread(void *b) { sntllv2_bundle_t *bun = (sntllv2_bundle_t *)b; - conn_t *co = bun->co; + conn_t *co = bun->conn; void *buf = bun->buf; char *bbuf = (char*)buf; sntllv2_head_t *mhead = (sntllv2_head_t *)buf; @@ -390,6 +391,7 @@ static void *__sntll_thread(void *b) chnl_t *channel; pthread_t self = pthread_self(); int dispatch = 0; + size_t rd, wr; /* byte buffer is following head */ bbuf += sizeof(sntllv2_head_t); @@ -481,7 +483,7 @@ static void *__sntll_thread(void *b) pthread_mutex_unlock(&msg->wait); } } else if(mhead->attr & SXMSG_LINK) { /* link layer messages */ - if(mhead->attr & SXMSG_CLOSE) goto __finish; /* close the link */ + if(mhead->attr & SXMSG_CLOSED) goto __finish; /* close the link */ if(mhead->attr & SXMSG_PULSE) { /* it's a link pulse messages */ /* TODO: syncronization and so on */ } @@ -494,7 +496,7 @@ static void *__sntll_thread(void *b) mhead->payload_length = 0; mhead->attr &= ~SXMSG_REPLYREQ; mhead->attr &= ~SXMSG_OPEN; - mhead->attr |= SXMSG_CLOSE; + mhead->attr |= SXMSG_CLOSED; pthread_mutex_lock(&(co->sslinout[1])); wr = __conn_write(co, mhead, sizeof(sntllv2_head_t)); pthread_mutex_unlock(&(co->sslinout[1])); @@ -510,7 +512,7 @@ static void *__sntll_thread(void *b) mhead->opcode = SNE_ENOMEM; goto __ret_regerr; } else { /* set mutex and channel */ - msg->wait = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_init(&msg->wait, NULL); msg->pch = channel; /* copy header only */ memcpy(&msg->mhead, mhead, sizeof(sntllv2_head_t)); @@ -524,7 +526,7 @@ static void *__sntll_thread(void *b) /* now we are able to process the message */ __message_process(msg); - } else if(mhead->attr & SXMSG_CLOSE) { + } else if(mhead->attr & SXMSG_CLOSED) { /* check for the message */ if(mhead->msgid >= 1024) goto __inval_idx_nor; msg = co->messages[mhead->msgid]; @@ -548,7 +550,7 @@ static void *__sntll_thread(void *b) } pthread_mutex_unlock(&msg->wait); /* wake up thread waiting for */ } - } else if((!(mhead->attr & SXMSG_CLOSE) && !(mhead->attr & SXMSG_OPEN)) && + } else if((!(mhead->attr & SXMSG_CLOSED) && !(mhead->attr & SXMSG_OPEN)) && (mhead->attr & SXMSG_REPLYREQ)) { /* ongoing dialog */ /* check for the message */ if(mhead->msgid >= 1024) goto __inval_idx_nor; @@ -580,7 +582,7 @@ static void *__sntll_thread(void *b) mhead->payload_length = 0; mhead->attr &= ~SXMSG_REPLYREQ; mhead->attr &= ~SXMSG_OPEN; - mhead->attr |= SXMSG_CLOSE; + mhead->attr |= SXMSG_CLOSED; pthread_mutex_lock(&(co->sslinout[1])); wr = __conn_write(co, mhead, sizeof(sntllv2_head_t)); pthread_mutex_unlock(&(co->sslinout[1])); @@ -588,9 +590,8 @@ static void *__sntll_thread(void *b) } } pthread_mutex_unlock(&msg->wait); /* wake up thread waiting for */ - } else - { mhead->opcode = SNE_BADPROTO; goto __ret_regerr; } - } + } + } else { mhead->opcode = SNE_BADPROTO; goto __ret_regerr; } } } } @@ -600,20 +601,21 @@ static void *__sntll_thread(void *b) return NULL; } -/* FIXME: AWARE coc and co - fix it */ -int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, - struct in_addr *addr) +conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr) { void *buf = NULL; char *bbuf; - conn_t *coc = __connection_minimal_alloc(addr); + conn_t *co = __connection_minimal_alloc(addr); sxmsg_t *msg = NULL; sntllv2_head_t *head; sntllv2_bundle_t *bundle; size_t rd; int r = SNE_FAILED; - if(!coc) return SNE_ENOMEM; + if(!co) { + errno = SNE_ENOMEM; + return NULL; + } /* ok, now we need to init ssl stuff */ co->ssys = ssys; @@ -671,7 +673,7 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, if(!(msg = malloc(sizeof(sxmsg_t)))) { r = SNE_ENOMEM; goto __fail2; } else { memset(msg, 0, sizeof(sxmsg_t)); - coc->messages[0] = msg; + co->messages[0] = msg; } bbuf = (char *)buf; bbuf += sizeof(sntllv2_head_t); @@ -699,7 +701,7 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, /* initialize message */ msg->payload = bbuf; - msg->payload_length = 0; + msg->mhead.payload_length = 0; /* deal with it */ r = __eval_syssexp(co, sx); head->opcode = r; @@ -709,8 +711,8 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, destroy_sexp(sx); goto __fail3; } - rd = __conn_write(co, buf, sizeof(sntllv2_head_t) + msg->payload_length); - if(rd != sizeof(sntllv2_head_t) + msg->payload_length) { + rd = __conn_write(co, buf, sizeof(sntllv2_head_t) + msg->mhead.payload_length); + if(rd != sizeof(sntllv2_head_t) + msg->mhead.payload_length) { destroy_sexp(sx); goto __fail3; } @@ -729,18 +731,22 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, bundle->buf = buf; bundle->conn = co; } + int i; for(i = 0; i < 8; i++) { - if(bundle == 0xdead) bundle = __sntll_bundle_create(co); + if(bundle == (void *)0xdead) bundle = __sntll_bundle_create(co); if(!bundle) goto __fail5; - r = pthread_create(&thrd_poll[i], NULL, __sntll_thread, bundle); + r = pthread_create(&co->thrd_poll[i], NULL, __sntll_thread, bundle); if(r) goto __fail5; - else bundle = 0xdead; + else bundle = (void *)0xdead; } /* all is done, connection now ready */ co->flags |= SNSX_ALIVE; - return SNE_SUCCESS; + r = SNE_SUCCESS; + errno = r; + + return co; __fail5: r = SNE_ENOMEM; @@ -754,20 +760,22 @@ int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, if(buf != MAP_FAILED) munmap(buf, 65536); SSL_shutdown(co->ssl); __fail: - if(coc) { + if(co) { if(co->ssl) SSL_free(co->ssl); if(co->ctx) SSL_CTX_free(co->ctx); - __connection_minimal_free(coc); + __connection_minimal_free(co); } close(sck); - return r; + errno = r; + + return NULL; } conn_t *connection_link(conn_sys_t *ssys, const char *host, int port, const char *SSL_cert, const char *login, const char *passwd) { - conn_t *co = __connection_minimal_alloc(addr); + conn_t *co = __connection_minimal_alloc(NULL); struct hostent *host_; struct sockaddr_in addr; int r = SNE_SUCCESS, sck; @@ -779,7 +787,9 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, char *bbuf; sntllv2_head_t *head; sntllv2_bundle_t *bundle; - size_t rd; + sxmsg_t *msg; + size_t rd, wr; + int i; r = SNE_IGNORED; if(!host || !SSL_cert) goto __fail; @@ -928,11 +938,11 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, bundle->conn = co; } for(i = 0; i < 8; i++) { - if(bundle == 0xdead) bundle = __sntll_bundle_create(co); + if(bundle == (void *)0xdead) bundle = __sntll_bundle_create(co); if(!bundle) goto __fail5; - r = pthread_create(&thrd_poll[i], NULL, __sntll_thread, bundle); + r = pthread_create(&co->thrd_poll[i], NULL, __sntll_thread, bundle); if(r) goto __fail5; - else bundle = 0xdead; + else bundle = (void *)0xdead; } /* all is done, connection now ready */ @@ -940,6 +950,13 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, return co; + __fail5: + r = SNE_ENOMEM; + /* bundles will be freed by the threads when SSL_read will fails. */ + __fail4: + __connection_second_free(co); + __fail3: + if(ssys->on_destroy) ssys->on_destroy(co); __fail2: if(buf != MAP_FAILED) munmap(buf, 65536); SSL_shutdown(co->ssl); From f142cd3f6f2ef882157d9bbc8f7f3ea2b5a52a33 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 18:59:32 +0300 Subject: [PATCH 12/56] added internal channel ops; --- lib/Makefile.am | 2 +- lib/chansx.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/internal.h | 8 ++++++++ lib/sntllv2.c | 2 ++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 lib/internal.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 38070d9..457cf4c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,7 +14,7 @@ lib_LTLIBRARIES = libsntllv2.la libsntllv2_la_SOURCES = \ - connex.c sntllv2.c + connex.c sntllv2.c chansx.c libsntllv2_la_LDFLAGS = -Wl,--export-dynamic diff --git a/lib/chansx.c b/lib/chansx.c index 6d469dc..1b4ced3 100644 --- a/lib/chansx.c +++ b/lib/chansx.c @@ -43,8 +43,60 @@ /* locally used functions */ uint8_t _channel_open(conn_t *co, uint16_t *chid) { + chnl_t *chan; + uint16_t typeid = *chid; /* our type */ + uint16_t chidx; + usrtc_t *rpc_list = co->rpc_list; + usrtc_node_t *node; + rpc_typed_list_t *rlist; + cx_rpc_list_t *rpclist; + + node = usrtc_lookup(rpc_list, (void *)&typeid); + if(!node) return SNE_EPERM; + else rlist = (rpc_typed_list_t *)usrtc_node_getdata(node); + + if(rlist) rpclist = rlist->rpc_list; + else return SNE_FAILED; + + chan = malloc(sizeof(chnl_t)); + if(!chan) return SNE_ENOMEM; + + /* init channel */ + chan->connection = co; + chan->rpc_list = rpclist; + chan->flags = 0; + + pthread_mutex_lock(&co->idx_ch_lock); + chidx = idx_allocate(&co->idx_ch); + pthread_mutex_unlock(&co->idx_ch_lock); + + if(chidx == IDX_INVAL) { + free(chan); + return SNE_MCHANNELS; + } + + chan->cid = chidx; + co->channels[chidx] = chan; + *chid = chidx; + + return SNE_SUCCESS; } uint8_t _channel_close(conn_t *co, uint16_t chid) { + chnl_t *chan; + + if(chid > 512) return SNE_INVALINDEX; + else chan = co->channels[chid]; + + if(!chan) return SNE_NOSUCHCHAN; + + pthread_mutex_lock(&co->idx_ch_lock); + idx_free(&co->idx_ch, chid); + co->channels[chid] = NULL; + pthread_mutex_unlock(&co->idx_ch_lock); + + free(chan); + + return SNE_SUCCESS; } diff --git a/lib/internal.h b/lib/internal.h new file mode 100644 index 0000000..4ce1281 --- /dev/null +++ b/lib/internal.h @@ -0,0 +1,8 @@ +#ifndef __SNTLL_INTERNAL_H__ +#define __SNTLL_INTERNAL_H__ + +/* channel operations */ +uint8_t _channel_open(conn_t *co, uint16_t *chid); +uint8_t _channel_close(conn_t *co, uint16_t chid); + +#endif /* __SNTLL_INTERNAL_H__ */ diff --git a/lib/sntllv2.c b/lib/sntllv2.c index a5f0654..4868bbb 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -42,6 +42,8 @@ #include +#include "internal.h" + typedef struct __sntll_bundle_type { void *buf; conn_t *conn; From f51d128ac2d9ec911dd65ff3ac3561e49f95021a Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 19:15:08 +0300 Subject: [PATCH 13/56] messagesx.c: initial; --- include/sntl/limits.h | 19 +++++++++++++++++++ include/sntl/sntllv2.h | 5 +++++ lib/Makefile.am | 2 +- lib/internal.h | 3 +++ lib/messagesx.c | 33 +++++++++++++++++++++++++++++++++ lib/rpclist.c | 19 ++----------------- lib/sntllv2.c | 24 +++++++++++++++++++++++- 7 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 include/sntl/limits.h create mode 100644 lib/messagesx.c diff --git a/include/sntl/limits.h b/include/sntl/limits.h new file mode 100644 index 0000000..79c4630 --- /dev/null +++ b/include/sntl/limits.h @@ -0,0 +1,19 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#ifndef __SNTL_LIMITS_H__ +#define __SNTL_LIMITS_H__ + +#define MAX_RPC_LIST 512 + +#endif /* __SNTL_LIMITS_H__ */ diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index 43806bf..d25e7eb 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -223,6 +223,11 @@ int sxmsg_rreply_pp(sxmsg_t *msg, const char *data, size_t datalen); int sxmsg_return(sxmsg_t *msg, int opcode); int sxmsg_return_pp(sxmsg_t *msg, int opcode); +/* RPC List API */ +#define SNTL_FILTER_INC 0xa +#define SNTL_FILTER_EXC 0xb +#define SNTL_FILTER_END -1 + #endif /* __SNTL_SNTLLV2_H__ */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 457cf4c..bda15f2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,7 +14,7 @@ lib_LTLIBRARIES = libsntllv2.la libsntllv2_la_SOURCES = \ - connex.c sntllv2.c chansx.c + connex.c sntllv2.c chansx.c messagesx.c rpclist.c libsntllv2_la_LDFLAGS = -Wl,--export-dynamic diff --git a/lib/internal.h b/lib/internal.h index 4ce1281..f9c90d7 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -5,4 +5,7 @@ uint8_t _channel_open(conn_t *co, uint16_t *chid); uint8_t _channel_close(conn_t *co, uint16_t chid); +/* messages */ +void _message_process(sxmsg_t *msg); + #endif /* __SNTLL_INTERNAL_H__ */ diff --git a/lib/messagesx.c b/lib/messagesx.c new file mode 100644 index 0000000..0a830ca --- /dev/null +++ b/lib/messagesx.c @@ -0,0 +1,33 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +void _message_process(sxmsg_t *msg) +{ + return; +} diff --git a/lib/rpclist.c b/lib/rpclist.c index 444b3ad..456656f 100644 --- a/lib/rpclist.c +++ b/lib/rpclist.c @@ -10,29 +10,14 @@ #include #include #include -#include -#include -#include -#ifdef WIN32 -#include -#else -#include -#include -#include -#include -#endif - #include - - -#include - #include #include -#include +#include +#include static long __cmp_int(const void *a, const void *b) { diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 4868bbb..6c3888a 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -49,6 +49,28 @@ typedef struct __sntll_bundle_type { conn_t *conn; } sntllv2_bundle_t; +/* networking helpers */ +#ifndef WIN32 +int __resolvehost(const char *hostname, char *buf, int buf_len, + struct hostent **rhp) +{ + struct hostent *hostbuf ;//= malloc(sizeof(struct hostent)); + struct hostent *hp = *rhp = NULL; + int herr = 0, hres = 0; + + + hostbuf = malloc(sizeof(struct hostent)); + if(!hostbuf) return NO_ADDRESS; + hres = gethostbyname_r(hostname, hostbuf, + buf, buf_len, &hp, &herr); + + if(hres) return NO_ADDRESS; + *rhp = hp; + + return NETDB_SUCCESS; +} +#endif + static int __conn_read(conn_t *co, void *buf, size_t buf_len) { int rfd = SSL_get_fd(co->ssl), r; @@ -527,7 +549,7 @@ static void *__sntll_thread(void *b) pthread_mutex_unlock(&co->idx_ch_lock); /* now we are able to process the message */ - __message_process(msg); + _message_process(msg); } else if(mhead->attr & SXMSG_CLOSED) { /* check for the message */ if(mhead->msgid >= 1024) goto __inval_idx_nor; From b76c7610c557e1393c370154fe86589cd9adf5ac Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 19:27:27 +0300 Subject: [PATCH 14/56] message process added; --- lib/messagesx.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/messagesx.c b/lib/messagesx.c index 0a830ca..b5ab773 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -29,5 +29,31 @@ void _message_process(sxmsg_t *msg) { + chnl_t *chan = msg->pch; + sexp_t *sx, *isx; + usrtc_t *listrpc = chan->rpc_list->rpc_tree; + usrtc_node_t *node; + cx_rpc_t *rpcc; + int r; + + sx = parse_sexp(msg->payload, msg->mhead.payload_length); + if(!sx) sxmsg_return(msg, SNE_BADPROTO); + + sexp_list_car(sx, &isx); + if(!isx) { r = SNE_BADPROTO; goto __return_err; } + if(isx->ty == SEXP_LIST) { r = SNE_BADPROTO; goto __return_err; } + if(isx->aty != SEXP_BASIC) { r = SNE_BADPROTO; goto __return_err; } + + node = usrtc_lookup(listrpc, (void *)isx->val); + if(!node) { r = SNE_ENORPC; goto __return_err; } + else rpcc = (cx_rpc_t *)usrtc_node_getdata(node); + + rpcc->rpcf((void *)msg, sx); /* sx *MUST* be destroy asap */ + + return; + + __return_err: + destroy_sexp(sx); + sxmsg_return(msg, r); return; } From 2868ee8f95e4638446a52211c09f19e0a251afdd Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 20:24:41 +0300 Subject: [PATCH 15/56] channel_* --- lib/chansx.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/lib/chansx.c b/lib/chansx.c index 1b4ced3..7f14707 100644 --- a/lib/chansx.c +++ b/lib/chansx.c @@ -100,3 +100,152 @@ uint8_t _channel_close(conn_t *co, uint16_t chid) return SNE_SUCCESS; } + +chnl_t *sxchannel_open(conn_t *co, int type) +{ + chnl_t *chan = NULL; + sxmsg_t *msg = NULL; + sntllv2_head_t *head; + int msgidx, r; + + if(!co) { + r = SNE_FAILED; + goto __reterr; + } + + if(!(chan = malloc(sizeof(chnl_t)))) { + __enomem: + r = SNE_ENOMEM; + goto __reterr; + } + if(!(msg = malloc(sizeof(sxmsg_t)))) goto __enomem; + + /* early init for the channel */ + chan->connection = co; + chan->flags = 0; + + /* early init for the message */ + pthread_mutex_init(&msg->wait, NULL); + pthread_mutex_lock(&msg->wait); + msg->pch = chan; + msg->payload = NULL; + memset(&msg->mhead, 0, sizeof(sntllv2_head_t)); + head = &msg->mhead; + + /* form a header */ + head->attr = SXMSG_PROTO | SXMSG_REPLYREQ | SXMSG_OPEN; + head->payload_length = 0; + head->reserve = (uint16_t)type; + + /* try to alloc a message */ + pthread_mutex_lock(&co->idx_msg_lock); + msgidx = idx_allocate(&co->idx_msg); + if(msgidx != IDX_INVAL) co->messages[msgidx] = msg; + pthread_mutex_unlock(&co->idx_msg_lock); + + if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; } + + /* now we're ready to write it */ + r = _sntll_writemsg(co, msg); + if(r == SNE_SUCCESS) pthread_mutex_lock(&msg->wait); + else goto __reterr3; + + /* we will wakeup on return */ + if(msg->mhead.opcode != SNE_SUCCESS) { r = msg->mhead.opcode; goto __reterr3; } + + /* ok all is fine */ + chan->cid = msg->mhead.reserve; + pthread_mutex_lock(&co->idx_ch_lock); + idx_reserve(&co->idx_ch, msg->mhead.reserve); + co->channels[msg->mhead.reserve] = chan; + pthread_mutex_unlock(&co->idx_ch_lock); + + /* destroy a message */ + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, msgidx); + co->messages[msgidx] = NULL; + pthread_mutex_unlock(&co->idx_msg_lock); + + /* free allocated resources */ + pthread_mutex_unlock(&msg->wait); + pthread_mutex_destroy(&msg->wait); + free(msg); + + return chan; + + __reterr3: + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, msgidx); + co->messages[msgidx] = NULL; + pthread_mutex_unlock(&co->idx_msg_lock); + __reterr2: + pthread_mutex_unlock(&msg->wait); + pthread_mutex_destroy(&msg->wait); + __reterr: + if(chan) free(chan); + if(msg) free(msg); + errno = r; + return NULL; +} + +int sxchannel_close(chnl_t *channel) +{ + int r = SNE_SUCCESS; + sxmsg_t *msg; + sntllv2_head_t *head; + conn_t *co; + int msgidx; + + /* check channel validity */ + if(!channel) return SNE_FAILED; + else if(!(co = channel->connection)) return SNE_FAILED; + if(channel->cid > 512) return SNE_IGNORED; + if(channel != co->channels[channel->cid]) return SNE_IGNORED; + + if(!(msg = malloc(sizeof(sxmsg_t)))) return SNE_ENOMEM; + head = &msg->mhead; + memset(head, 0, sizeof(sntllv2_head_t)); + + /* setup head */ + head->attr = SXMSG_PROTO | SXMSG_REPLYREQ; /* close channel */ + head->reserve = channel->cid; + + /* setup message */ + pthread_mutex_init(&msg->wait, NULL); + pthread_mutex_lock(&msg->wait); + msg->pch = channel; + + /* allocate it */ + pthread_mutex_lock(&co->idx_msg_lock); + msgidx = idx_allocate(&co->idx_msg); + if(msgidx != IDX_INVAL) co->messages[msgidx] = msg; + pthread_mutex_unlock(&co->idx_msg_lock); + + if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; } + + r = _sntll_writemsg(co, msg); + if(r == SNE_SUCCESS) { + pthread_mutex_lock(&msg->wait); + r = head->opcode; + + /* we will free this anyway */ + pthread_mutex_lock(&co->idx_ch_lock); + idx_free(&co->idx_ch, channel->cid); + co->channels[channel->cid] = NULL; + pthread_mutex_unlock(&co->idx_ch_lock); + free(channel); + } + + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, msgidx); + co->messages[msgidx] = NULL; + pthread_mutex_unlock(&co->idx_msg_lock); + + __reterr2: + pthread_mutex_unlock(&msg->wait); + pthread_mutex_destroy(&msg->wait); + free(msg); + + return r; +} + From 847ce7b54ef71c46bc454fd6c868f7e75621e7ac Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 20:33:51 +0300 Subject: [PATCH 16/56] writemsg added; --- lib/internal.h | 3 +++ lib/sntllv2.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/internal.h b/lib/internal.h index f9c90d7..121106a 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -1,6 +1,9 @@ #ifndef __SNTLL_INTERNAL_H__ #define __SNTLL_INTERNAL_H__ +/* link related */ +int _sntll_writemsg(conn_t *co, sxmsg_t *msg); + /* channel operations */ uint8_t _channel_open(conn_t *co, uint16_t *chid); uint8_t _channel_close(conn_t *co, uint16_t chid); diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 6c3888a..2b0ccfb 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -190,6 +190,35 @@ static int __conn_write(conn_t *co, void *buf, size_t buf_len) return r; } +int _sntll_writemsg(conn_t *co, sxmsg_t *msg) +{ + sntllv2_head_t *head; + size_t rd; + int r; + + if(!co || !msg) return SNE_FAILED; + + /* check message for validity */ + head = &msg->mhead; + if(head->payload_length && !msg->payload) return SNE_FAILED; + + /* write the head and payload if applicable */ + pthread_mutex_lock(&co->sslinout[2]); + rd = __conn_write(co, head, sizeof(sntllv2_head_t)); + if(rd < 0) { + co->flags |= SNSX_CLOSED; + r = SNE_ESSL; + } else if(head->payload_length) rd = __conn_write(co, msg->payload, head->payload_length); + /* check up again */ + if(rd < 0) { + co->flags |= SNSX_CLOSED; + r = SNE_ESSL; + } + pthread_mutex_unlock(&co->sslinout[2]); + + return r; +} + static sntllv2_bundle_t *__sntll_bundle_create(conn_t *co) { sntllv2_bundle_t *n = malloc(sizeof(sntllv2_bundle_t)); From 4d10b4dc8604a4ad1d03f3f86794d67a6ce059cc Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 20:36:00 +0300 Subject: [PATCH 17/56] minor fix; --- lib/sntllv2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 2b0ccfb..050c85d 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -208,14 +208,15 @@ int _sntll_writemsg(conn_t *co, sxmsg_t *msg) if(rd < 0) { co->flags |= SNSX_CLOSED; r = SNE_ESSL; - } else if(head->payload_length) rd = __conn_write(co, msg->payload, head->payload_length); - /* check up again */ - if(rd < 0) { - co->flags |= SNSX_CLOSED; - r = SNE_ESSL; + } else if(head->payload_length) { + rd = __conn_write(co, msg->payload, head->payload_length); + /* check up again */ + if(rd < 0) { co->flags |= SNSX_CLOSED; r = SNE_ESSL; } } pthread_mutex_unlock(&co->sslinout[2]); + if(!(co->flags & SNSX_CLOSED)) r = SNE_SUCCESS; + return r; } From 1a7b18d749c59714ef7908c056e08acbfb7d6c11 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Mon, 20 Jul 2015 20:41:11 +0300 Subject: [PATCH 18/56] protos added; --- lib/messagesx.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/lib/messagesx.c b/lib/messagesx.c index b5ab773..03ee245 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -57,3 +57,57 @@ void _message_process(sxmsg_t *msg) sxmsg_return(msg, r); return; } + +int sxmsg_send(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg) +{ + return SNE_FAILED; +} + +/* the same - postponed message i.e. will be written to the queue - not to write immendatly */ +int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg) +{ + return SNE_FAILED; +} + +/* send a pulse message */ +int sxmsg_pulse(conn_t *co, const char *data, size_t datalen) +{ + return SNE_FAILED; +} + +/* the same but will be postponed */ +int sxmsg_pulse_pp(conn_t *co, const char *data, size_t datalen) +{ + return SNE_FAILED; +} + +int sxmsg_reply(sxmsg_t *msg, const char *data, size_t datalen) +{ + return SNE_FAILED; +} + +int sxmsg_reply_pp(sxmsg_t *msg, const char *data, size_t datalen) +{ + return SNE_FAILED; +} + +int sxmsg_rreply(sxmsg_t *msg, const char *data, size_t datalen) +{ + return SNE_FAILED; +} + +int sxmsg_rreply_pp(sxmsg_t *msg, const char *data, size_t datalen) +{ + return SNE_FAILED; +} + +int sxmsg_return(sxmsg_t *msg, int opcode) +{ + return SNE_FAILED; +} + +int sxmsg_return_pp(sxmsg_t *msg, int opcode) +{ + return SNE_FAILED; +} + From d56d8bd14d1e2e5331b96a52dc827e7d0cdac3d5 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 02:24:08 +0300 Subject: [PATCH 19/56] added messages passing, not all; --- include/sntl/sntllv2.h | 5 ++ lib/messagesx.c | 135 +++++++++++++++++++++++++++++++++++++++-- lib/sntllv2.c | 3 +- 3 files changed, 136 insertions(+), 7 deletions(-) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index d25e7eb..0b83ffc 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -96,6 +96,11 @@ typedef struct __connection_t { struct __connection_rpc_list_type; struct __message_t; +typedef struct __pp_msg_type { + struct __message_t *msg; + list_node_t node; +} ppmsg_t; + typedef struct __channel_t { uint16_t cid; /** < ID of the channel */ conn_t *connection; /** < pointer to the parent connection */ diff --git a/lib/messagesx.c b/lib/messagesx.c index 03ee245..c0faca0 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -27,6 +27,8 @@ #include +#include "internal.h" + void _message_process(sxmsg_t *msg) { chnl_t *chan = msg->pch; @@ -58,15 +60,86 @@ void _message_process(sxmsg_t *msg) return; } -int sxmsg_send(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg) +static inline int __sxmsg_send(chnl_t *channel, const char *data, size_t datalen, + sxmsg_t **omsg, int pp) { - return SNE_FAILED; + conn_t *co; + sxmsg_t *msg; + sntllv2_head_t *head; + ppmsg_t *ppm; + int msgidx, r; + + if(!channel) return SNE_FAILED; + if(!data || !datalen) return SNE_FAILED; + + if(!(msg = malloc(sizeof(sxmsg_t)))) return SNE_ENOMEM; + else memset(msg, 0, sizeof(sxmsg_t)); + + co = channel->connection; + head = &msg->mhead; + /* form a head */ + head->attr = SXMSG_OPEN | SXMSG_REPLYREQ; + head->reserve = channel->cid; + head->payload_length = datalen; + /* init message itself */ + pthread_mutex_init(&msg->wait, NULL); + pthread_mutex_lock(&msg->wait); + msg->pch = channel; + msg->payload = (void *)data; + + pthread_mutex_lock(&co->idx_msg_lock); + msgidx = idx_allocate(&co->idx_msg); + if(msgidx != IDX_INVAL) co->messages[msgidx] = msg; + pthread_mutex_unlock(&co->idx_msg_lock); + + if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __freemsg; } + else head->msgid = (uint16_t)msgidx; + + /* ready to send it */ + if(!pp) { + r = _sntll_writemsg(co, msg); + if(r != SNE_SUCCESS) goto __closemsg; + } else { /* postponed */ + if(!(ppm = malloc(sizeof(ppmsg_t)))) { r = SNE_ENOMEM; goto __closemsg; } + list_init_node(&ppm->node); + ppm->msg = msg; + + /* under locking here */ + pthread_mutex_lock(&co->write_pending_lock); + list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */ + pthread_mutex_unlock(&co->write_pending_lock); + } + + pthread_mutex_lock(&msg->wait); /* we will sleep here */ + + if(head->payload_length) { + *omsg = msg; + return head->opcode; + } else r = head->opcode; + + __closemsg: + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, msgidx); + co->messages[msgidx] = NULL; + pthread_mutex_unlock(&co->idx_msg_lock); + __freemsg: + /* free resources for message */ + pthread_mutex_unlock(&msg->wait); + pthread_mutex_destroy(&msg->wait); + free(msg); + + return r; +} + +int sxmsg_send(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **omsg) +{ + return __sxmsg_send(channel, data, datalen, omsg, 0); } /* the same - postponed message i.e. will be written to the queue - not to write immendatly */ -int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg) +int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **omsg) { - return SNE_FAILED; + return __sxmsg_send(channel, data, datalen, omsg, 1); } /* send a pulse message */ @@ -101,13 +174,63 @@ int sxmsg_rreply_pp(sxmsg_t *msg, const char *data, size_t datalen) return SNE_FAILED; } +static inline int __sxmsg_return(sxmsg_t *msg, int opcode, int pp) +{ + chnl_t *ch; + conn_t *co; + sntllv2_head_t *head; + ppmsg_t *ppm; + int r; + + /* a little bit of paranoid tests */ + if(!msg) return SNE_FAILED; + if(!(ch = msg->pch)) return SNE_FAILED; + if(!(co = ch->connection)) return SNE_FAILED; + + head = &msg->mhead; + head->attr = 0; + head->attr |= SXMSG_CLOSED; + head->opcode = opcode; + head->payload_length = 0; + + if(!pp) { + /* free index */ + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, head->msgid); + co->messages[head->msgid] = NULL; + pthread_mutex_unlock(&co->idx_msg_lock); + + r = _sntll_writemsg(co, msg); + } else { + if(!(ppm = malloc(sizeof(ppmsg_t)))) return SNE_ENOMEM; + else { /* remove it */ + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, head->msgid); + co->messages[head->msgid] = NULL; + pthread_mutex_unlock(&co->idx_msg_lock); + } + + list_init_node(&ppm->node); + ppm->msg = msg; + + /* under locking here */ + pthread_mutex_lock(&co->write_pending_lock); + list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */ + pthread_mutex_unlock(&co->write_pending_lock); + + r = SNE_SUCCESS; + } + + return r; +} + int sxmsg_return(sxmsg_t *msg, int opcode) { - return SNE_FAILED; + return __sxmsg_return(msg, opcode, 0); } int sxmsg_return_pp(sxmsg_t *msg, int opcode) { - return SNE_FAILED; + return __sxmsg_return(msg, opcode, 1); } diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 050c85d..35961d7 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -570,7 +570,7 @@ static void *__sntll_thread(void *b) msg->pch = channel; /* copy header only */ memcpy(&msg->mhead, mhead, sizeof(sntllv2_head_t)); - msg->payload = bbuf; + if(mhead->payload_length) msg->payload = bbuf; } pthread_mutex_lock(&co->idx_ch_lock); @@ -602,6 +602,7 @@ static void *__sntll_thread(void *b) if(msg->payload) memcpy(msg->payload, bbuf, mhead->payload_length); else msg->mhead.opcode = SNE_ENOMEM; } + /* TODO: remove this message from list */ pthread_mutex_unlock(&msg->wait); /* wake up thread waiting for */ } } else if((!(mhead->attr & SXMSG_CLOSED) && !(mhead->attr & SXMSG_OPEN)) && From ad24dd439111a4c4ac5ab3bae27c6aafc178e78a Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 02:26:00 +0300 Subject: [PATCH 20/56] removed obsolete code; --- lib/channel.c | 316 -------------------------------------------------- 1 file changed, 316 deletions(-) delete mode 100644 lib/channel.c diff --git a/lib/channel.c b/lib/channel.c deleted file mode 100644 index 9dea04d..0000000 --- a/lib/channel.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Secure Network Transport Layer Library implementation. - * This is a proprietary software. See COPYING for further details. - * - * (c) Askele Group 2013-2015 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#else -#include -#include -#include -#include -#endif - - -#include -#include - -#include -#include - -#include - -extern char *__generate_uuid(void); - -extern void __destroy_msg(sxmsg_t *msg); - -extern int __create_sys_msg(sxmsg_t **msg, char *uuid, chnl_t *ch, - sxpayload_t *data); - -static long __cmp_ulong(const void *a, const void *b) -{ - return (long)(*(ulong_t *)a - *(ulong_t *)b); -} - -int __alloc_channel(ulong_t cid, conn_t *co, rpc_typed_list_t *rlist, chnl_t **channel) -{ - int r = 0; - chnl_t *ch = malloc(sizeof(chnl_t)); - usrtc_t *msg_tree = malloc(sizeof(usrtc_t)); - idx_allocator_t *idx_msg = malloc(sizeof(idx_allocator_t)); - - if(!idx_msg) goto __fin_enomem; - else if(idx_allocator_init(idx_msg, MAX_MSGINDEX, 0)) goto __fin_enomem; - - if(!ch || !msg_tree) { - __fin_up2: - idx_allocator_destroy(idx_msg); - __fin_enomem: - r = ENOMEM; - goto __fin_up; - } else { - usrtc_init(msg_tree, USRTC_REDBLACK, MAX_PENDINGMSG, __cmp_ulong); - ch->cid = cid; - ch->flags = ch->use_count = 0; - ch->uuid = NULL; - usrtc_node_init(&ch->node, ch); - if(rlist) ch->rpc_list = rlist->rpc_list; - else ch->rpc_list = NULL; - /* init locks */ - if(pthread_rwlock_init(&(ch->msglock), NULL)) { - r = ENOMEM; - goto __fin_up2; - } - if(pthread_mutex_init(&(ch->oplock), NULL)) { - pthread_rwlock_destroy(&(ch->msglock)); - r = ENOMEM; - goto __fin_up2; - } - /* assign all the stuff */ - ch->idx_msg = idx_msg; - ch->msgs_tree = msg_tree; - ch->connection = co; - } - - __fin_up: - if(r) { - if(idx_msg) free(idx_msg); - if(ch) free(ch); - if(msg_tree) free(msg_tree); - return r; - } else { - *channel = ch; - return 0; - } -} - -/* channels */ -int channel_open(conn_t *co, chnl_t **ch, int type) -{ - chnl_t *nch = NULL; - conn_sys_t *ssys = co->ssys; - int r = 0; - char *uuid_; - sxpayload_t *pl; - ulong_t cid; - rpc_typed_list_t *rpclist = NULL; - usrtc_node_t *node = NULL; - sxmsg_t *sms; - - if(!(co->flags & CXCONN_ESTABL)) { - return ESXNOCONNECT; - } - - uuid_ = __generate_uuid(); - pl = malloc(sizeof(sxpayload_t)); - node = usrtc_lookup(co->rpc_list, &type); - - if(node) rpclist = (rpc_typed_list_t *)usrtc_node_getdata(node); - - if(!uuid_) { - if(pl) free(pl); - return ENOMEM; - } - - if(!pl) { - __ffail: - if(uuid_) free(uuid_); - return ENOMEM; - } else { - pl->sx = NULL; - if(!(pl->cstr = malloc(sizeof(char)*ESX_SYSMSG_SIZE))) { - free(pl); goto __ffail; - } else memset(pl->cstr, 0, sizeof(char)*ESX_SYSMSG_SIZE); - } - - pthread_rwlock_wrlock(&(co->chnl_lock)); - cid = idx_allocate(co->idx_ch); - pthread_rwlock_unlock(&(co->chnl_lock)); - if(cid == IDX_INVAL) { - r = ENOMEM; - goto __fini_op; - } - - if((r = __alloc_channel(cid, co, rpclist, &nch))) { - goto __fini_op; - } else nch->flags |= ESXCHAN_PENDING; - - nch->uuid = uuid_; - - /* ok now we're ready to create a message and push channel to the list */ - if((r = __create_sys_msg(&sms, uuid_, nch, pl))) { - __fail_chan: - /* destroy the channel*/ - goto __fini_op; - } else { - /* put the channel to the channels search tree */ - pthread_rwlock_wrlock(&(co->chnl_lock)); - //printf("inserting cid = %d\n", nch->cid); - usrtc_insert(co->chnl_tree, &nch->node, &nch->cid); - pthread_rwlock_unlock(&(co->chnl_lock)); - - /* put system message to the run queue */ - /* first form the message */ - snprintf(pl->cstr, sizeof(char)*ESX_SYSMSG_SIZE, - "(ch-open ((:id %ld)(:uuid %s)(:type %d)))", nch->cid, nch->uuid, type); - nch->sysmsg = sms; /* assign system message to the channel */ - /* put it */ - if((r = pth_queue_add(ssys->ioqueue, (void *)sms, SYS_MSG))) { - __fail_chan_r: - /* remove it from the search tree */ - pthread_rwlock_wrlock(&(co->chnl_lock)); - usrtc_delete(co->chnl_tree, &nch->node); - pthread_rwlock_unlock(&(co->chnl_lock)); - goto __fail_chan; - } - if(!(sms->flags & ESXMSG_PENDING)) { - /* was processed too fast */ - goto __process_smsg; - } else pthread_mutex_lock(&(sms->wait)); /* will sleep until got a reply */ - __process_smsg: - if(sms->opcode) { - r = sms->opcode; - goto __fail_chan_r; - } else r = 0; - nch->flags &= ~ESXCHAN_PENDING; /* mark it as established */ - free(pl->cstr); - free(pl); - __destroy_msg(nch->sysmsg); - } - - __fini_op: - if(r) { - if(uuid_) free(uuid_); - if(pl) { - if(pl->cstr) free(pl->cstr); - free(pl); - } - pthread_rwlock_wrlock(&(co->chnl_lock)); - idx_free(co->idx_ch, nch->cid); - pthread_rwlock_unlock(&(co->chnl_lock)); - idx_allocator_destroy(nch->idx_msg); - free(nch->idx_msg); - free(nch->msgs_tree); - pthread_mutex_destroy(&(nch->oplock)); - pthread_rwlock_destroy(&(nch->msglock)); - - free(nch); - } else *ch = nch; - - return r; -} - -int channel_close(chnl_t *chnl) -{ - char *uuid_; - usrtc_node_t *node = NULL; - int r = 0; - conn_t *co = chnl->connection; - conn_sys_t *ssys = co->ssys; - sxmsg_t *sms; - sxpayload_t *pl; - - if(!(co->flags & CXCONN_ESTABL)) { - return ESXNOCONNECT; - } - - pthread_rwlock_rdlock(&(co->chnl_lock)); - node = usrtc_lookup(co->chnl_tree, &chnl->cid); - pthread_rwlock_unlock(&(co->chnl_lock)); - if(!node) { - return ENOENT; - } - - pthread_rwlock_wrlock(&(chnl->msglock)); - /* check unprocessed messages */ - if(!usrtc_isempty(chnl->msgs_tree)) { /* messages on the queue */ - pthread_rwlock_unlock(&(chnl->msglock)); - return EBUSY; - } - - uuid_ = __generate_uuid(); - pl = malloc(sizeof(sxpayload_t)); - if(!pl || !uuid_) { - pthread_rwlock_unlock(&(chnl->msglock)); - if(pl) free(pl); - if(uuid_) free(uuid_); - return ENOMEM; - } - if(__create_sys_msg(&sms, uuid_, chnl, pl)) { - pthread_rwlock_unlock(&(chnl->msglock)); - free(pl); - free(uuid_); - return ENOMEM; - } - - pl->sx = NULL; - if(!(pl->cstr = malloc(sizeof(char) * ESX_SYSMSG_SIZE))) { - pthread_rwlock_unlock(&(chnl->msglock)); - free(pl); - free(uuid_); - return ENOMEM; - } - memset(pl->cstr, 0, sizeof(char) * ESX_SYSMSG_SIZE); - - /* put system message to the run queue */ - /* first form the message */ - snprintf(pl->cstr, sizeof(char) * ESX_SYSMSG_SIZE, - "(ch-close (:id %ld))", chnl->cid); - chnl->sysmsg = sms; /* assign system message to the channel */ - /* put it */ - if((r = pth_queue_add(ssys->ioqueue, (void *)sms, SYS_MSG))) { - pthread_rwlock_unlock(&(chnl->msglock)); - return r; - } - if(!(sms->flags & ESXMSG_PENDING)) { - /* was processed too fast */ - goto __process_smsg; - } else pthread_mutex_lock(&(sms->wait)); /* will sleep until got a reply */ - - __process_smsg: - if(sms->opcode) { - pthread_rwlock_unlock(&(chnl->msglock)); - r = sms->opcode; - return r; - } else r = 0; - chnl->flags &= ~ESXCHAN_PENDING; /* mark it as established */ - /* remove channel from the search tree */ - pthread_rwlock_wrlock(&(chnl->connection->chnl_lock)); - usrtc_delete(chnl->connection->chnl_tree, &chnl->node); - /* free index */ - idx_free(co->idx_ch, chnl->cid); - pthread_rwlock_unlock(&(chnl->connection->chnl_lock)); - - pthread_rwlock_unlock(&(chnl->msglock)); - - __destroy_msg(chnl->sysmsg); - free(uuid_); - - free(pl->cstr); - free(pl); - free(chnl->uuid); - idx_allocator_destroy(chnl->idx_msg); - free(chnl->idx_msg); - free(chnl->msgs_tree); - pthread_mutex_destroy(&(chnl->oplock)); - pthread_rwlock_destroy(&(chnl->msglock)); - - free(chnl); - - return 0; -} - From ebfadad3e91fbe23018f524de5e60bee442521ac Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 02:38:32 +0300 Subject: [PATCH 21/56] code cleanup; --- include/Makefile.am | 2 +- include/sntl/pth_queue.h | 117 -- lib/Makefile.am | 2 +- lib/chansx.c | 2 + lib/connection.c | 2477 ------------------------------------- lib/message.c | 286 ----- lib/queue.c | 465 ------- lib/{support.c => uuid.c} | 30 - 8 files changed, 4 insertions(+), 3377 deletions(-) delete mode 100644 include/sntl/pth_queue.h delete mode 100644 lib/connection.c delete mode 100644 lib/message.c delete mode 100644 lib/queue.c rename lib/{support.c => uuid.c} (71%) diff --git a/include/Makefile.am b/include/Makefile.am index 7af89e1..cafb1ff 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1 +1 @@ -nobase_include_HEADERS = sntl/pth_queue.h sntl/connection.h +nobase_include_HEADERS = sntl/sntllv2.h sntl/errno.h sntl/limits.h diff --git a/include/sntl/pth_queue.h b/include/sntl/pth_queue.h deleted file mode 100644 index 521e849..0000000 --- a/include/sntl/pth_queue.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This is a proprietary software. See COPYING for further details. - * - * (c) 2013 Copyright Askele, inc. - * (c) 2013 Copyright Askele Ingria, inc. - * (c) 2014 Copyright Confident, inc. (granted permission to use in commercial software) - */ - -/** - * @file pth_queue.h - * @author Alexander Vdolainen - * @date 4 Nov 2013, 20 Dec 2014 (dynamic polls) - * @brief queue implementation for threads intercommunication - * - */ - -#ifndef __PTH_QUEUE_H__ -#define __PTH_QUEUE_H__ - -#include -#include - -/* possible message types, ones with POLL_ prefix valid on for pth_dqtpoll_* */ -#define SYS_MSG 0x0f0affee -#define USR_MSG 0x0afeeffe -#define POLL_DECREASE 0x0afafafe -#define POLL_INCREASE 0x0afaffff -#define NIL_MSG 0x0 -#define END_MSG 0xdead0000 - -/* max amount of threads within the poll */ -#define MAX_POLL_VALUE 32 - -typedef struct pth_msg_s { - void *data; /** < message payload */ - unsigned int msgtype; /** < message type ID */ - unsigned int qlength; /** < current queue length (actual on add moment), - * it makes no sense with few readers */ - usrtc_node_t node; -} pth_msg_t; - -typedef struct pth_queue_s { - unsigned int length; - /* sync */ - pthread_mutex_t mutex; - pthread_cond_t cond; - /* queue data */ - usrtc_t qtree; - /* cache */ - usrtc_t msgcache; -} pth_queue_t; - -int pth_queue_init(pth_queue_t *queue); - -int pth_queue_add(pth_queue_t *queue, void *data, unsigned int msgtype); - -int pth_queue_get(pth_queue_t *queue, const struct timespec *timeout, - pth_msg_t *msg); - -unsigned int pth_queue_length(pth_queue_t *queue); - -int pth_queue_destroy(pth_queue_t *queue, int freedata, - void (*free_msg)(void *)); - -/* dynamic queue thread poll ... bbrrr .... ok, ok with beer - * Dynamic queue thread poll is a queue like pth_queue, - * but also it has itäs own mamagement for threads - that's - * why dynamic. - * Ideally, the model is trying to achieve the following: - * 1. one thread in queue while no or very small amount of jobs in the queue - * 2. grow until max threads is reached while too many requests - * 3. gently slide down volume of threads after job heat - * 4. minimal additional drawbacks (i hate something periodically running, - * it's bad practice) - * The model is quite simple, we should make spurious wakeups equal to zero, - * if no - decrease poll value, and, if we don't have thread available - - * create it. - */ -typedef struct pth_dqtpoll_s { - pth_queue_t *queue; /** < Job queue */ - pthread_t *poll; /** < Thread descriptors */ - int (*jobdata_callback)(void *); /** < Callback to have a deal with data */ - int flags; /** < Flags */ - idx_allocator_t *idx; /** < index allocator for the poll threads */ - pthread_rwlock_t stats_lock; /** < rwlock for stats data */ - unsigned long spurious_wakeups; /** < amount of spurios wakeups */ - int poll_value; /** < value of the poll (totally) */ - struct timeval sched_time; - int msgop; -} pth_dqtpoll_t; - -/* flags for poll */ -#define DQTPOLL_RUNNING (1 << 1) /* poll is running */ -#define DQTPOLL_DEADSTAGE (1 << 2) /* poll in the stage of destroy */ - -/* keep it stupid */ -#define DQTPOLL_DELTAMS 500000 -#define DQTPOLL_DELTASE 0 - -/* init poll, structure must be allocated */ -int pth_dqtpoll_init(pth_dqtpoll_t*, int (*jobdata_callback)(void *)); - -/* run poll: poll */ -int pth_dqtpoll_run(pth_dqtpoll_t*); - -/* add the job to the queue: poll, job data, message type */ -int pth_dqtpoll_add(pth_dqtpoll_t*, void*, unsigned int); - -/* destroy the poll: poll, force flag - * if force flag is set (!= 0), give up - * about jobs, if no, do the job, but don't - * accept the new ones, and destroy all poll - * with last thread. - */ -int pth_dqtpoll_destroy(pth_dqtpoll_t*, int); - -#endif /* __PTH_QUEUE_H__ */ diff --git a/lib/Makefile.am b/lib/Makefile.am index bda15f2..5e9e6a7 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,7 +14,7 @@ lib_LTLIBRARIES = libsntllv2.la libsntllv2_la_SOURCES = \ - connex.c sntllv2.c chansx.c messagesx.c rpclist.c + connex.c sntllv2.c chansx.c messagesx.c rpclist.c uuid.c libsntllv2_la_LDFLAGS = -Wl,--export-dynamic diff --git a/lib/chansx.c b/lib/chansx.c index 7f14707..cc2df7e 100644 --- a/lib/chansx.c +++ b/lib/chansx.c @@ -40,6 +40,8 @@ #include +#include "internal.h" + /* locally used functions */ uint8_t _channel_open(conn_t *co, uint16_t *chid) { diff --git a/lib/connection.c b/lib/connection.c deleted file mode 100644 index 5b4f5e5..0000000 --- a/lib/connection.c +++ /dev/null @@ -1,2477 +0,0 @@ -/* - * Secure Network Transport Layer Library v2 implementation. - * (sntllv2) it superseed all versions before due to the: - * - memory consumption - * - new features such as pulse emitting - * - performance optimization - * - * This is a proprietary software. See COPYING for further details. - * - * (c) Askele Group 2013-2015 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#define EBADE 1 -#define NETDB_SUCCESS 0 -#else -#include -#include -#include -#include -#endif - -#include -#include - -#include -#include - -#include - -struct __rpc_job -{ - sxmsg_t *msg; - sexp_t *sx; - int (*rpcf) (void *, sexp_t *); -}; - -conn_sys_t *conn_sys = NULL; - -static int ex_ssldata_index; /** < index used to work with additional data - * provided to the special call during SSL handshake */ - -int sntl_init(void) -{ - /* init SSL library */ - SSL_library_init(); - - OpenSSL_add_all_algorithms(); - SSL_load_error_strings(); - - ex_ssldata_index = SSL_get_ex_new_index(0, "__ssldata index", NULL, NULL, NULL); - - return 0; -} - -static long __cmp_ulong(const void *a, const void *b); - -/* message alloc and destroy */ -extern sxmsg_t *__allocate_msg(int *res); -extern void __destroy_msg(sxmsg_t *msg); - -/* connections */ -static void __connections_subsystem_connection_remove(conn_t *); -static void __connection_free(conn_t *co); - -/* examination */ -static inline int __exam_connection(conn_t *co) -{ - int r = 0; - - pthread_mutex_lock(&co->oplock); - if(co->flags | CXCONN_BROKEN) { - /* wake up all */ - /* destroy thread poll */ - /* free all memory and sync primitives */ - r = 1; - } - pthread_mutex_unlock(&co->oplock); - - return r; -} - -static int __rpc_callback(void *data) -{ - struct __rpc_job *job = (struct __rpc_job *)data; - int rc = 0; - - rc = job->rpcf((void *)(job->msg), job->sx); - - free(job); - - return rc; -} - -extern int __alloc_channel(ulong_t cid, conn_t *co, rpc_typed_list_t *rlist, - chnl_t **channel); - -static int __conn_read(conn_t *co, void *buf, size_t buf_len) -{ - int rfd = SSL_get_fd(co->ssl), r; - fd_set readset, writeset; - int ofcmode, read_blocked = 0, read_blocked_on_write = 0; - - /* First we make the socket nonblocking */ -#ifndef WIN32 - ofcmode = fcntl(rfd, F_GETFL,0); - ofcmode |= O_NDELAY; - if(fcntl(rfd, F_SETFL, ofcmode)) - fprintf(stderr, "Couldn't make socket nonblocking"); -#endif - - __retry: - - do { - __try_again: - r = SSL_read(co->ssl, buf, (int)buf_len); - switch(SSL_get_error (co->ssl, r)) { - case SSL_ERROR_NONE: - return r; - break; - case SSL_ERROR_WANT_READ: - /* get prepare to select */ - read_blocked = 1; - break; - case SSL_ERROR_WANT_WRITE: /* here we blocked on write */ - read_blocked_on_write = 1; - break; - case SSL_ERROR_SYSCALL: - if(errno == EAGAIN || errno == EINTR) goto __try_again; - else { - fprintf(stderr, "SSL syscall error.\n"); - goto __close_conn; - } - break; - case SSL_ERROR_WANT_CONNECT: - case SSL_ERROR_WANT_ACCEPT: - fprintf(stderr, "SSL negotiation required. Trying again.\n"); - goto __try_again; - break; - case SSL_ERROR_SSL: - fprintf(stderr, "SSL error occured. Connection will be closed.\n"); - goto __close_conn; - break; - case SSL_ERROR_ZERO_RETURN: - fprintf(stderr, "SSL connection is cleary closed.\n"); - default: - __close_conn: - fprintf(stderr, "(RD)Unknown error on %s (errno = %d)\n", co->uuid, errno); - return -1; - } - } while(SSL_pending(co->ssl) && !read_blocked); - - __select_retry: - - if(read_blocked) { - FD_ZERO(&readset); - FD_SET(rfd, &readset); - /* waits until something will be ready to read */ - r = select(rfd + 1, &readset, NULL, NULL, NULL); - if(r < 0) { - if(errno == EINTR || errno == EAGAIN) goto __select_retry; - printf("(RD) select (%d) on %s\n", errno, co->uuid); - return -1; - } - if(!r) { - printf("Nothing to wait for\n"); - return 0; - } - read_blocked = 0; - if(r && FD_ISSET(rfd, &readset)) goto __retry; /* try to read again */ - } - if(read_blocked_on_write) { /* we was blocked on write */ - FD_ZERO(&readset); - FD_ZERO(&writeset); - FD_SET(rfd, &readset); - FD_SET(rfd, &writeset); - - r = select(rfd + 1, &readset, &writeset, NULL, NULL); - read_blocked_on_write = 0; - if(r && FD_ISSET(rfd, &writeset)) goto __retry; - } - - return 0; -} - -static int __conn_write(conn_t *co, void *buf, size_t buf_len) -{ - int r, rfd = SSL_get_fd(co->ssl); - fd_set writeset; - - pthread_mutex_lock(&(co->oplock)); - __retry: - r = SSL_write(co->ssl, buf, (int)buf_len); - switch(SSL_get_error(co->ssl, r)) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - /* here we should block */ - FD_ZERO(&writeset); - FD_SET(rfd, &writeset); - r = select(rfd + 1, NULL, &writeset, NULL, NULL); - if(r && FD_ISSET(rfd, &writeset)) goto __retry; - break; - case SSL_ERROR_SYSCALL: - if(errno == EAGAIN || errno == EINTR) goto __retry; - else goto __close_conn; - break; - default: - pthread_mutex_unlock(&(co->oplock)); - __close_conn: - if(r < 0) { - fprintf(stderr, "(WR)Unknown error on %s (%d)\n", co->uuid, r); - return -1; - } else return 0; - } - pthread_mutex_unlock(&(co->oplock)); - - return 0; -} - -static long __cmp_cstr(const void *a, const void *b) -{ - return strcmp((char *)a, (char *)b); -} - -static long __cmp_int(const void *a, const void *b) -{ - return *(int *)a - *(int *)b; -} - -static long __cmp_ulong(const void *a, const void *b) -{ - return *(ulong_t *)a - *(ulong_t *)b; -} - -extern int __resolvehost(const char *hostname, char *buf, int buf_len, - struct hostent **rhp); - -static void __destroy_rpc_list_tree(usrtc_t *tree) -{ - usrtc_node_t *node; - cx_rpc_t *ent; - - for(node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) { - ent = (cx_rpc_t *)usrtc_node_getdata(node); - usrtc_delete(tree, node); - free(ent->name); - free(ent); - } - - return; -} - -static int __insert_rpc_function(usrtc_t *tree, const char *name, int (*rpcf)(void *, sexp_t *)) -{ - cx_rpc_t *ent = malloc(sizeof(cx_rpc_t)); - usrtc_node_t *node; - - if(!ent) return ENOMEM; - else node = &ent->node; - - if(!(ent->name = strdup(name))) { - free(ent); - return ENOMEM; - } else ent->rpcf = rpcf; - - usrtc_node_init(node, ent); - usrtc_insert(tree, node, ent->name); - - return 0; -} - -/* wake up all waiters on messages with given opcode */ -static void __wake_up_waiters(conn_t *co, int opcode) -{ - usrtc_node_t *node = NULL, *last_node = NULL; - usrtc_node_t *msg_node = NULL, *last_msg_node = NULL; - chnl_t *ch; - sxmsg_t *smsg = NULL; - - pthread_rwlock_wrlock(&(co->chnl_lock)); - - if(!co->chnl_tree) goto __skip; - node = usrtc_first(co->chnl_tree); - last_node = usrtc_last(co->chnl_tree); - - /* going through channels tree */ - while(!usrtc_isempty(co->chnl_tree)) { - ch = (chnl_t *)usrtc_node_getdata(node); - - pthread_rwlock_rdlock(&(ch->msglock)); - msg_node = usrtc_first(ch->msgs_tree); - last_msg_node = usrtc_last(ch->msgs_tree); - - while(!usrtc_isempty(ch->msgs_tree)) { /* messages bypassing */ - smsg = (sxmsg_t *)usrtc_node_getdata(msg_node); - smsg->opcode = opcode; - - /* wake up waiting thread */ - pthread_mutex_unlock(&(smsg->wait)); - - if(msg_node == last_msg_node) break; - msg_node = usrtc_next(ch->msgs_tree, msg_node); - } - - pthread_rwlock_unlock(&(ch->msglock)); - - if(node == last_node) break; - node = usrtc_next(co->chnl_tree, node); - } - - __skip: - pthread_rwlock_unlock(&(co->chnl_lock)); - - return; -} - -/* (!) NOTE: this call use only after all threads are dead ! */ -static void __destroy_all_channels(conn_t *co) -{ - usrtc_node_t *node = NULL; - chnl_t *ch; - - for(node = usrtc_first(co->chnl_tree); node != NULL; node = - usrtc_first(co->chnl_tree)) { - ch = (chnl_t *)usrtc_node_getdata(node); - - /* free allocated resources */ - if(ch->uuid) free(ch->uuid); - idx_allocator_destroy(ch->idx_msg); /* allocator */ - free(ch->idx_msg); - free(ch->msgs_tree); - /* locks */ - pthread_mutex_destroy(&(ch->oplock)); - pthread_rwlock_destroy(&(ch->msglock)); - - /* remove it */ - usrtc_delete(co->chnl_tree, node); - - /* free */ - free(ch); - } - - return; -} - -static int __default_auth_set_context(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - conn_sys_t *ssys = co->ssys; - char *val, *var, *tbuf = NULL; - sexp_t *lsx, *sx_iter, *sx_in; - int llen, idx, err = 0; - - //co->pctx = malloc(sizeof(perm_ctx_t)); - - /* skip keyword itself */ - lsx = sx->list->next; - /* now we expect a list of lists */ - if(lsx->ty != SEXP_LIST) { - err = ESXRCBADPROT; - goto __reply; - } - /* take length of the list */ - llen = sexp_list_length(lsx); - if(!llen) return 0; /* other side will not set any security attributes */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sexp_list_car(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - err = ESXRCBADPROT; - goto __reply; - } else val = sx_in->val; - - if(sexp_list_length(sx_iter) < 2) continue; /* we will ignore it */ - - sexp_list_cdr(sx_iter, &sx_in); - if(!SEXP_IS_TYPE(sx_in, SEXP_DQUOTE)) { - err = ESXRCBADPROT; - goto __reply; - } else var = sx_in->val; - - /* ok, now we need to analyze parameters */ - if(!strcmp(val, ":user") && var) { - co->pctx->login = strdup(var); - } else if(!strcmp(val, ":passwd") && var) { - co->pctx->passwd = strdup(var); - } else { - /* just ignore in default implementation */ - } - } else continue; /* ignore */ - } - - /* ok, now we need to fill security context */ - tbuf = malloc(2048); - if(!tbuf) { - err = ENOMEM; - goto __reply; - } - if(ssys->secure_check) - err = ssys->secure_check(co); - -__reply: - if(err) { - snprintf(tbuf, 2048, "(auth-set-error (%d))", err); - } else { - snprintf(tbuf, 2048, "(auth-set-attr (:attr %d)(:uid %ld)(:gid %ld))", - co->pctx->p_attr, co->pctx->uid, co->pctx->gid); - } - /* we will send it */ - if(__conn_write(co, tbuf, strlen(tbuf)) < 0) { - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - __wake_up_waiters(co, ESXNOCONNECT); - } - destroy_sexp(sx); - - free(tbuf); - return err; -} - -static int __default_auth_set_attr(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - char *val, *var; - sexp_t *lsx, *sx_iter, *sx_in; - int llen, idx, r = 0; - - /* skip keyword itself */ - lsx = sx->list->next; - /* now we expect a list of lists */ - if(lsx->ty != SEXP_LIST) { - r = ESXRCBADPROT; - goto __finish; - } - /* take length of the list */ - llen = sexp_list_length(lsx); - if(!llen) return 0; /* other side will not set any security attributes */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sexp_list_car(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - goto __finish; - } else val = sx_in->val; - - if(sexp_list_length(sx_iter) < 2) continue; /* we will ignore it */ - - sexp_list_cdr(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - goto __finish; - } else var = sx_in->val; - - /* ok, now we need to analyze parameters */ - if(!strcmp(val, ":attr")) { - co->pctx->p_attr = atoi(var); - } else if(!strcmp(val, ":uid")) { - co->pctx->uid = (ulong_t)atoll(var); - } else if(!strcmp(val, ":gid")) { - co->pctx->gid = (ulong_t)atoll(var); - } else { - /* just ignore in default implementation */ - } - } else continue; /* ignore */ - } - -__finish: - destroy_sexp(sx); - return r; -} - -static int __default_auth_set_error(void *cctx, sexp_t *sx) -{ - char *errstr = NULL; - int r; - - /* skip keyword itself */ - sx->list = sx->list->next; - /* be sure - this is a list */ - if(sx->ty != SEXP_LIST) return ESXRCBADPROT; - else sx = sx->list; /* get it */ - errstr = sx->list->val; - r = atoi(errstr); - - destroy_sexp(sx); - return r; -} - -static int __default_ch_get_types(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - conn_sys_t *ssys = co->ssys; - usrtc_node_t *node; - rpc_typed_list_t *list_ent; - char *tbuf = malloc(4096), *tt; - int err = 0; - - /* if we cannot allocate anything ... */ - if(!tbuf) return ENOMEM; - /* ok here we go */ - co->rpc_list = ssys->get_rpc_typed_list_tree(co); - /* ok, here we're don't need to parse anything */ - if(!usrtc_count(co->rpc_list)) { - err = ENXIO; - snprintf(tbuf, 4096, "(ch-gl-error (%d))", err); - } else { - tt = tbuf; - snprintf(tt, 4096, "(ch-set-types ("); - tt += strlen(tt); - for(node = usrtc_first(co->rpc_list); node != NULL; - node = usrtc_next(co->rpc_list, node), tt += strlen(tt)) { - list_ent = (rpc_typed_list_t *)usrtc_node_getdata(node); - snprintf(tt, 4096, "(:%d \"%s\")", list_ent->type_id, list_ent->description); - } - snprintf(tt, 4096, "))"); - } - - /* reply to this rpc */ - if(__conn_write(co, tbuf, strlen(tbuf)) < 0) { - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - __wake_up_waiters(co, ESXNOCONNECT); - } - free(tbuf); - destroy_sexp(sx); - - return err; -} - -static int __default_ch_set_types(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - conn_sys_t *ssys = co->ssys; - char buf[1024], *val, *var; - int r = 0, llen, typeid, idx; - sexp_t *lsx, *sx_iter, *sx_in; - - /* skip keyword itself */ - lsx = sx->list->next; - /* now we expect a list of lists */ - if(lsx->ty != SEXP_LIST) { - r = ESXRCBADPROT; - goto __send_reply; - } - - /* take length of the list */ - llen = sexp_list_length(lsx); - - if(!llen) return 0; /* other side will not set any security attributes */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sexp_list_car(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - goto __send_reply; - } else val = sx_in->val; - - if(sexp_list_length(sx_iter) < 2) continue; /* we will ignore it */ - - sexp_list_cdr(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_DQUOTE)) { - r = ESXRCBADPROT; - goto __send_reply; - } else var = sx_in->val; - - /* ok, now we need to analyze parameters */ - if(*val != ':') { - r = ESXRCBADPROT; - goto __send_reply; - } else { - if(ssys->set_typed_list_callback) { - typeid = atoi((char *)(val + sizeof(char))); - if(ssys->set_typed_list_callback(co, typeid, var)) { - destroy_sexp(sx); - return ENXIO; - } - } /* FIXME: if no function, accept or decline ? */ - } - } else continue; /* ignore */ - } - - __send_reply: - snprintf(buf, 1024, "(ch-gl-error (%d))", r); - - if(__conn_write(co, buf, strlen(buf)) < 0) { - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - __wake_up_waiters(co, ESXNOCONNECT); - } - destroy_sexp(sx); - - return r; -} - -static int __default_ch_gl_error(void *cctx, sexp_t *sx) -{ - int r; - char *errstr; - conn_t *co = (conn_t *)cctx; - - if(co->flags & CXCONN_ESTABL) return EINVAL; /* error, we're already have channels list */ - - /* skip keyword itself */ - sx->list = sx->list->next; - /* be sure - this is a list */ - if(sx->ty != SEXP_LIST) return ESXRCBADPROT; - else sx = sx->list; /* get it */ - errstr = sx->list->val; - r = atoi(errstr); - - if(!r) co->flags |= CXCONN_ESTABL; - - return r; -} - -static int __default_ch_open(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - usrtc_node_t *node; - char *val, *var, *uuid = NULL, *buf; - int typ = -1, idx, llen, r; - ulong_t cid; - sexp_t *lsx, *sx_iter, *sx_in; - rpc_typed_list_t *rlist; - chnl_t *channel; - - /* skip keyword itself */ - lsx = sx->list->next; - /* now we expect a list of lists */ - if(lsx->ty != SEXP_LIST) { - printf("%s:%d\n", __FUNCTION__, __LINE__); - r = ESXRCBADPROT; - goto __send_repl; - } - - /* take length of the list */ - llen = sexp_list_length(lsx); - if(!llen) return 0; /* other side will not set any security attributes */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sexp_list_car(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - printf("%s:%d\n", __FUNCTION__, __LINE__); - r = ESXRCBADPROT; - goto __send_repl; - } else val = sx_in->val; - - if(sexp_list_length(sx_iter) < 2) continue; /* we will ignore it */ - - sexp_list_cdr(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - printf("%s:%d\n", __FUNCTION__, __LINE__); - goto __send_repl; - } else var = sx_in->val; - - /* ok, now we need to analyze parameters */ - if(*val != ':') { - r = ESXRCBADPROT; - goto __send_repl; - } else { - if(!strcmp((char *)(val + sizeof(char)), "type")) - typ = atoi(var); - else if(!strcmp((char *)(val + sizeof(char)), "id")) - cid = atoll(var); - else if(!strcmp((char *)(val + sizeof(char)), "uuid")) - uuid = var; - } - } else continue; /* ignore */ - } - - /* additional check for type of the channel */ - node = usrtc_lookup(co->rpc_list, &typ); - if(!node) { - r = ESXNOCHANSUP; - /* printf("%s:%d (usrtc count: %d) (typ %d)\n", __FUNCTION__, __LINE__, - usrtc_count(co->rpc_list), typ);*/ - node = usrtc_first(co->rpc_list); - rlist = (rpc_typed_list_t *)usrtc_node_getdata(node); - printf("---- rlist->type_id = %d\n", rlist->type_id); - goto __send_repl; - } else rlist = (rpc_typed_list_t *)usrtc_node_getdata(node); - - /* now we need to check up the channel */ - pthread_rwlock_rdlock(&(co->chnl_lock)); - node = usrtc_lookup(co->chnl_tree, &cid); - if(node) { - pthread_rwlock_unlock(&(co->chnl_lock)); - r = EEXIST; - goto __send_repl; - } else { - idx_reserve(co->idx_ch, cid); - pthread_rwlock_unlock(&(co->chnl_lock)); /* now we should alloc channel */ - if((r = __alloc_channel(cid, co, rlist, &channel))) { - pthread_rwlock_wrlock(&(co->chnl_lock)); - idx_free(co->idx_ch, cid); - pthread_rwlock_unlock(&(co->chnl_lock)); - goto __send_repl; - } else { - /* now we ready to confirm channel creation */ - pthread_rwlock_wrlock(&(co->chnl_lock)); - usrtc_insert(co->chnl_tree, &(channel->node), &(channel->cid)); - pthread_rwlock_unlock(&(co->chnl_lock)); - r = 0; - } - } - - __send_repl: - buf = malloc(2048); - snprintf(buf, 2048, "(ch-open-ret ((:error %d)(:uuid %s)(:id %ld)))", r, - uuid, cid); - if(__conn_write(co, buf, strlen(buf)) < 0) { - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - __wake_up_waiters(co, ESXNOCONNECT); - } - destroy_sexp(sx); - free(buf); - - return r; -} - -static int __default_ch_open_ret(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - chnl_t *chan; - usrtc_node_t *node; - int err = 0, r, llen, idx; - ulong_t id; - char *val, *var; - sexp_t *lsx, *sx_iter, *sx_in; - sxmsg_t *sms = NULL; - - /* skip keyword itself */ - lsx = sx->list->next; - /* now we expect a list of lists */ - if(lsx->ty != SEXP_LIST) { - //printf("%s:%d\n", __FUNCTION__, __LINE__); - r = ESXRCBADPROT; - goto __mark_msg; - } - /* take length of the list */ - llen = sexp_list_length(lsx); - if(!llen) return EINVAL; /* !! other side will not set any security attributes */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sexp_list_car(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - goto __mark_msg; - } else val = sx_in->val; - - if(sexp_list_length(sx_iter) < 2) continue; /* we will ignore it */ - - sexp_list_cdr(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - goto __mark_msg; - } else var = sx_in->val; - - /* ok, now we need to analyze parameters */ - if(*val != ':') { - r = ESXRCBADPROT; - goto __mark_msg; - } else { - if(!strcmp((char *)(val + sizeof(char)), "error")) - err = atoi(var); - else if(!strcmp((char *)(val + sizeof(char)), "id")) - id = atoll(var); - } - } else continue; /* ignore */ - } - - /* try to find desired channel to intercept message */ - pthread_rwlock_rdlock(&(co->chnl_lock)); - node = usrtc_lookup(co->chnl_tree, (void *)&id); - //printf("channels (%d)\n", usrtc_count(co->chnl_tree)); - pthread_rwlock_unlock(&(co->chnl_lock)); - if(node) { - chan = (chnl_t *)usrtc_node_getdata(node); - sms = chan->sysmsg; - } - - __mark_msg: - if(!sms) return r; - sms->flags &= ~ESXMSG_PENDING; /* the message is done */ - sms->opcode = err; - - destroy_sexp(sx); - - /* unlock mutex to wake up the waiting thread */ - pthread_mutex_unlock(&(sms->wait)); - - return 0; -} - -static int __default_ch_close(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - usrtc_node_t *node; - char *val, *var, *buf; - int idx, llen, r; - ulong_t cid = -1; - sexp_t *lsx, *sx_iter, *sx_in; - chnl_t *channel = NULL; - - r = 0; - /* skip keyword itself */ - lsx = sx->list->next; - /* now we expect a list of lists */ - if(lsx->ty != SEXP_LIST) { - printf("%s:%d\n", __FUNCTION__, __LINE__); - r = ESXRCBADPROT; - goto __send_repl; - } - - /* take length of the list */ - llen = sexp_list_length(lsx); - if(!llen) return 0; /* other side will not set any security attributes */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - continue; - } - if(!SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - printf("%s:%d\n", __FUNCTION__, __LINE__); - r = ESXRCBADPROT; - goto __send_repl; - } else val = sx_iter->val; - - sx_in = sx_iter->next; - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - printf("%s:%d\n", __FUNCTION__, __LINE__); - goto __send_repl; - } else var = sx_in->val; - - /* ok, now we need to analyze parameters */ - if(*val != ':') { - r = ESXRCBADPROT; - goto __send_repl; - } else { - if(!strcmp((char *)(val + sizeof(char)), "id")) { - cid = atoll(var); - break; - } - } - } - - /* additional check for type of the channel */ - pthread_rwlock_rdlock(&(co->chnl_lock)); - node = usrtc_lookup(co->chnl_tree, &cid); - pthread_rwlock_unlock(&(co->chnl_lock)); - if(!node) { - r = ENOENT; - /* there are no such channel exist */ - destroy_sexp(sx); - goto __send_repl; - } - channel = (chnl_t *)usrtc_node_getdata(node); - - /* check up the message queue */ - pthread_rwlock_rdlock(&(channel->msglock)); - if(usrtc_count(channel->msgs_tree)) { - /* we have some undelivered messages in the queue */ - destroy_sexp(sx); - r = EBUSY; - goto __send_repl; - } - pthread_rwlock_unlock(&(channel->msglock)); - - /* remove channel from the search tree */ - pthread_rwlock_wrlock(&(co->chnl_lock)); - usrtc_delete(co->chnl_tree, &(channel->node)); - /* free index */ - idx_free(co->idx_ch, channel->cid); - pthread_rwlock_unlock(&(co->chnl_lock)); - - idx_allocator_destroy(channel->idx_msg); - free(channel->idx_msg); - free(channel->msgs_tree); - pthread_mutex_destroy(&(channel->oplock)); - pthread_rwlock_destroy(&(channel->msglock)); - free(channel); - - destroy_sexp(sx); - - __send_repl: - buf = malloc(2048); - snprintf(buf, 2048, "(ch-close-ret ((:id %ld) (:error %d)))", cid, r); - - if(__conn_write(co, buf, strlen(buf)) < 0) { - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - __wake_up_waiters(co, ESXNOCONNECT); - } - free(buf); - - return 0; -} - -static int __default_ch_close_ret(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - chnl_t *chan; - usrtc_node_t *node; - int err = 0, r, llen, idx; - ulong_t id; - char *val, *var; - sexp_t *lsx, *sx_iter, *sx_in; - sxmsg_t *sms = NULL; - - /* skip keyword itself */ - lsx = sx->list->next; - /* now we expect a list of lists */ - if(lsx->ty != SEXP_LIST) { - r = ESXRCBADPROT; - goto __mark_msg; - } - /* take length of the list */ - llen = sexp_list_length(lsx); - if(!llen) return EINVAL; /* !! other side will not set any security attributes */ - - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sexp_list_car(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - goto __mark_msg; - } else val = sx_in->val; - - if(sexp_list_length(sx_iter) < 2) continue; /* we will ignore it */ - - sexp_list_cdr(sx_iter, &sx_in); - - if(!SEXP_IS_TYPE(sx_in, SEXP_BASIC)) { - r = ESXRCBADPROT; - goto __mark_msg; - } else var = sx_in->val; - - /* ok, now we need to analyze parameters */ - if(*val != ':') { - r = ESXRCBADPROT; - goto __mark_msg; - } else { - if(!strcmp((char *)(val + sizeof(char)), "error")) - err = atoi(var); - else if(!strcmp((char *)(val + sizeof(char)), "id")) - id = atoll(var); - } - } else continue; /* ignore */ - } - - /* try to find desired channel to intercept message */ - pthread_rwlock_rdlock(&(co->chnl_lock)); - node = usrtc_lookup(co->chnl_tree, (void *)&id); - pthread_rwlock_unlock(&(co->chnl_lock)); - - if(node) { - chan = (chnl_t *)usrtc_node_getdata(node); - sms = chan->sysmsg; - } - - __mark_msg: - - if(!sms) return r; - sms->flags &= ~ESXMSG_PENDING; /* the message is done */ - sms->opcode = err; - - destroy_sexp(sx); - /* unlock mutex to wake up the waiting thread */ - pthread_mutex_unlock(&(sms->wait)); - - return 0; -} - -/* create a nould of the message */ -static int __create_reg_msg_mould(sxmsg_t **msg, chnl_t *ch, ulong_t mid) -{ - int r = 0; - sxmsg_t *sm = __allocate_msg(&r); - - if(r) return r; - else { - sm->pch = ch; - sm->flags = (ESXMSG_USR | ESXMSG_PENDING); - sm->mid = mid; - - /* ok reserve message ID */ - pthread_mutex_lock(&(ch->oplock)); - idx_reserve(ch->idx_msg, mid); - pthread_mutex_unlock(&(ch->oplock)); - - pthread_mutex_lock(&(sm->wait)); - *msg = sm; - } - - return 0; -} - -static int __default_msg(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - usrtc_node_t *node = NULL; - chnl_t *chan = NULL; - int r = 0; - sexp_t *lsx = NULL, *sx_iter = NULL; - sexp_t *sx_sublist = NULL, *sx_value = NULL; - ulong_t chnl_id = -1; - ulong_t msg_id = -1; - sexp_t *msg = NULL; - sxmsg_t *smsg = NULL; - int idx; - - /* get parameters from the message */ - if(sexp_list_cdr(sx, &lsx)) return ESXRCBADPROT; - if(!SEXP_IS_LIST(lsx)) return ESXRCBADPROT; - - /* find channel id */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sx_sublist = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":chid")) { - continue; // ignore it - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - chnl_id = atol(sx_value->val); - } else continue; // ignore it - } - } - lsx = sx_sublist; - /* find message id */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - msg = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":msgid")) { - continue; // ignore - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - msg_id = atol(sx_value->val); - } else continue; // ignore it - } - } - - if(msg_id < 0 || chnl_id < 0) { - return ESXRCBADPROT; - } - /* find channel */ - if(!(node = usrtc_lookup(co->chnl_tree, &chnl_id))) return ENOENT; - else chan = (chnl_t *)usrtc_node_getdata(node); - /* lookup for the message */ - pthread_rwlock_rdlock(&(chan->msglock)); - if(!(node = usrtc_lookup(chan->msgs_tree, &msg_id))) { - pthread_rwlock_unlock(&(chan->msglock)); - /* here, rpc lookup has no sense, just put this job to the queue */ - /* btw, we're need to create a message first */ - r = __create_reg_msg_mould(&smsg, chan, msg_id); - if(r) return r; - - /* assign the message */ - smsg->opcode = 0; - smsg->payload = (void *)msg; - - /* assign initial S-expression structure */ - smsg->initial_sx = sx; - - /* put the message to the search tree */ - pthread_rwlock_wrlock(&(chan->msglock)); - usrtc_insert(chan->msgs_tree, &(smsg->pendingq_node), &(smsg->mid)); - pthread_rwlock_unlock(&(chan->msglock)); - } else { - pthread_rwlock_unlock(&(chan->msglock)); - smsg = (sxmsg_t *)usrtc_node_getdata(node); - msg_return(smsg, EEXIST); - return EEXIST; - } - /* put job to the queue and give up */ - r = pth_queue_add(co->rqueue, (void *)smsg, USR_MSG); - if(r) { /* cannot put job to the queue */ - msg_return(smsg, r); - pthread_rwlock_wrlock(&(chan->msglock)); - usrtc_delete(chan->msgs_tree, &(smsg->pendingq_node)); - pthread_rwlock_unlock(&(chan->msglock)); - __destroy_msg(smsg); - return r; - } - - /* put to the IN queue */ - return r; -} - -/* TODO: optimize amount of code: (must be first) - * __default_msg_return - * __default_msg_reply - * there are many copy-n-paste code!!!!! - */ - -static int __default_msg_return(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - usrtc_node_t *node = NULL; - chnl_t *chan = NULL; - int r = 0; - sexp_t *lsx = NULL, *sx_iter = NULL; - sexp_t *sx_sublist = NULL, *sx_value = NULL; - ulong_t chnl_id = -1; - ulong_t msg_id = -1; - sexp_t *msg = NULL; - sxmsg_t *smsg = NULL; - int idx, opcode; - - /* get parameters from the message */ - if(sexp_list_cdr(sx, &lsx)) { - r = ESXRCBADPROT; - goto __finish; - } - if(!SEXP_IS_LIST(lsx)) { - r = ESXRCBADPROT; - goto __finish; - } - - /* get parameters */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sx_sublist = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":chid")) { - continue; // ignore it - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - chnl_id = atol(sx_value->val); - } else continue; // ignore it - } - } - lsx = sx_sublist; - /* find message id */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - msg = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":msgid")) { - continue; // ignore - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - msg_id = atol(sx_value->val); - } else continue; // ignore it - } - } - /* get opcode */ - sexp_list_car(msg, &lsx); - opcode = atoi(lsx->val); - - if(msg_id < 0 || chnl_id < 0) { - r = ESXRCBADPROT; - goto __finish; - } - - if(!(node = usrtc_lookup(co->chnl_tree, &chnl_id))) return ENOENT; - else chan = (chnl_t *)usrtc_node_getdata(node); - /* lookup for the message */ - pthread_rwlock_rdlock(&(chan->msglock)); - if(!(node = usrtc_lookup(chan->msgs_tree, &msg_id))) { - pthread_rwlock_unlock(&(chan->msglock)); - r = ENOENT; - goto __finish; - } else { - pthread_rwlock_unlock(&(chan->msglock)); - smsg = (sxmsg_t *)usrtc_node_getdata(node); - smsg->opcode = opcode; - if(smsg->flags & ESXMSG_ISREPLY) - destroy_sexp((sexp_t *)smsg->payload); - smsg->payload = NULL; - smsg->flags |= ESXMSG_CLOSURE; - - /* Q: can we remove the message from the tree there??? */ - /* A: actually no */ - /* first remove the message from tree */ - if(smsg->flags & ESXMSG_RMONRETR) { - pthread_rwlock_wrlock(&(chan->msglock)); - usrtc_delete(chan->msgs_tree, &(smsg->pendingq_node)); - pthread_rwlock_unlock(&(chan->msglock)); - } - if(smsg->flags & ESXMSG_PENDING) { - destroy_sexp(sx); - pthread_mutex_unlock(&(smsg->wait)); - return r; - } else { - /* nobody want it */ - destroy_sexp(smsg->initial_sx); - __destroy_msg(smsg); - } - } - -__finish: - destroy_sexp(sx); - return r; -} - -static int __default_msg_rapid(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - usrtc_node_t *node = NULL; - chnl_t *chan = NULL; - int r = 0; - sexp_t *lsx = NULL, *sx_iter = NULL; - sexp_t *sx_sublist = NULL, *sx_value = NULL; - ulong_t chnl_id = -1; - ulong_t msg_id = -1; - sexp_t *msg = NULL; - sxmsg_t *smsg = NULL; - int idx; - - /* get parameters from the message */ - if(sexp_list_cdr(sx, &lsx)) { - r = ESXRCBADPROT; - goto __finish; - } - if(!SEXP_IS_LIST(lsx)) { - r = ESXRCBADPROT; - goto __finish; - } - - /* get parameters */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sx_sublist = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":chid")) { - continue; // ignore it - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - chnl_id = atol(sx_value->val); - } else continue; // ignore it - } - } - lsx = sx_sublist; - /* find message id */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - msg = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":msgid")) { - continue; // ignore - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - msg_id = atol(sx_value->val); - } else continue; // ignore it - } - } - - if(msg_id < 0 || chnl_id < 0) { - r = ESXRCBADPROT; - goto __finish; - } - - if(!(node = usrtc_lookup(co->chnl_tree, &chnl_id))) return ENOENT; - else chan = (chnl_t *)usrtc_node_getdata(node); - /* lookup for the message */ - pthread_rwlock_rdlock(&(chan->msglock)); - if(!(node = usrtc_lookup(chan->msgs_tree, &msg_id))) { - pthread_rwlock_unlock(&(chan->msglock)); - r = ENOENT; - goto __finish; - } else { - pthread_rwlock_unlock(&(chan->msglock)); - smsg = (sxmsg_t *)usrtc_node_getdata(node); - smsg->opcode = ESXRAPIDREPLY; - smsg->payload = copy_sexp(msg); - smsg->flags |= ESXMSG_ISREPLY; - /* are we'are ready to remove this ? */ - if(smsg->flags & ESXMSG_RMONRETR) { - pthread_rwlock_wrlock(&(chan->msglock)); - usrtc_delete(chan->msgs_tree, &(smsg->pendingq_node)); - pthread_rwlock_unlock(&(chan->msglock)); - } - if(smsg->flags & ESXMSG_PENDING) { - destroy_sexp(sx); - pthread_mutex_unlock(&(smsg->wait)); - return r; - } else { - /* nobody want it */ - destroy_sexp(smsg->initial_sx); - __destroy_msg(smsg); - } - } - -__finish: - destroy_sexp(sx); - return r; -} - -static int __default_msg_reply(void *cctx, sexp_t *sx) -{ - conn_t *co = (conn_t *)cctx; - usrtc_node_t *node = NULL; - chnl_t *chan = NULL; - int r = 0; - sexp_t *lsx = NULL, *sx_iter = NULL; - sexp_t *sx_sublist = NULL, *sx_value = NULL; - ulong_t chnl_id = -1; - ulong_t msg_id = -1; - sexp_t *msg = NULL; - sxmsg_t *smsg = NULL; - int idx; - - /* get parameters from the message */ - if(sexp_list_cdr(sx, &lsx)) { - r = ESXRCBADPROT; - goto __finish; - } - if(!SEXP_IS_LIST(lsx)) { - r = ESXRCBADPROT; - goto __finish; - } - - /* get parameters */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - sx_sublist = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":chid")) { - continue; // ignore it - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - chnl_id = atol(sx_value->val); - } else continue; // ignore it - } - } - lsx = sx_sublist; - /* find message id */ - SEXP_ITERATE_LIST(lsx, sx_iter, idx) { - if(SEXP_IS_LIST(sx_iter)) { - msg = sx_iter; - continue; - } else { - if(SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { - if(strcmp(sx_iter->val, ":msgid")) { - continue; // ignore - } - sx_value = sx_iter->next; - if(!sx_value || !SEXP_IS_TYPE(sx_value, SEXP_BASIC)) { - continue; - } - msg_id = atol(sx_value->val); - } else continue; // ignore it - } - } - - if(msg_id < 0 || chnl_id < 0) { - r = ESXRCBADPROT; - goto __finish; - } - - if(!(node = usrtc_lookup(co->chnl_tree, &chnl_id))) return ENOENT; - else chan = (chnl_t *)usrtc_node_getdata(node); - /* lookup for the message */ - pthread_rwlock_rdlock(&(chan->msglock)); - if(!(node = usrtc_lookup(chan->msgs_tree, &msg_id))) { - pthread_rwlock_unlock(&(chan->msglock)); - r = ENOENT; - goto __finish; - } else { - pthread_rwlock_unlock(&(chan->msglock)); - smsg = (sxmsg_t *)usrtc_node_getdata(node); - smsg->opcode = ESXOREPLYREQ; - smsg->payload = copy_sexp(msg); - smsg->flags |= ESXMSG_ISREPLY; - pthread_mutex_unlock(&(smsg->wait)); - } - -__finish: - destroy_sexp(sx); - return r; -} - -static int __init_systemrpc_tree(usrtc_t *rtree) -{ - /* security context functions */ - if(__insert_rpc_function(rtree, "auth-set-context", __default_auth_set_context)) goto __fail; - if(__insert_rpc_function(rtree, "auth-set-attr", __default_auth_set_attr)) goto __fail; - if(__insert_rpc_function(rtree, "auth-set-error", __default_auth_set_error)) goto __fail; - /* channels negotiation ops */ - if(__insert_rpc_function(rtree, "ch-get-types", __default_ch_get_types)) goto __fail; - if(__insert_rpc_function(rtree, "ch-gl-error", __default_ch_gl_error)) goto __fail; - if(__insert_rpc_function(rtree, "ch-set-types", __default_ch_set_types)) goto __fail; - if(__insert_rpc_function(rtree, "ch-open", __default_ch_open)) goto __fail; - if(__insert_rpc_function(rtree, "ch-open-ret", __default_ch_open_ret)) goto __fail; - if(__insert_rpc_function(rtree, "ch-close", __default_ch_close)) goto __fail; - if(__insert_rpc_function(rtree, "ch-close-ret", __default_ch_close_ret)) goto __fail; - /* messaging functions */ - if(__insert_rpc_function(rtree, "ch-msg", __default_msg)) goto __fail; - if(__insert_rpc_function(rtree, "ch-msg-rete", __default_msg_return)) goto __fail; - if(__insert_rpc_function(rtree, "ch-msg-rapid", __default_msg_rapid)) goto __fail; - if(__insert_rpc_function(rtree, "ch-msg-repl", __default_msg_reply)) goto __fail; - - return 0; - - __fail: - __destroy_rpc_list_tree(rtree); - return ENOMEM; -} - -static int __eval_cstr(char *cstr, cx_rpc_list_t *rpc_list, void *ctx) -{ - int r = ENOENT; - sexp_t *sx; - usrtc_node_t *node; - cx_rpc_t *rentry; - char *rpcf; - - if(!(sx = parse_sexp(cstr, strlen(cstr)))) return EBADE; - - if(sx->ty == SEXP_LIST) - rpcf = sx->list->val; - else goto __enoent; - - /* find an appropriate function */ - node = usrtc_lookup(rpc_list->rpc_tree, rpcf); - - if(!node) { - __enoent: - fprintf(stderr, "Invalid S-expression catched.\n"); - destroy_sexp(sx); - return ENOENT; - } - else rentry = (cx_rpc_t *)usrtc_node_getdata(node); - - /* call it */ - r = rentry->rpcf(ctx, sx); - //if(r) destroy_sexp(sx); - - return r; -} - -static void *__cxslave_thread_listener(void *wctx) -{ - conn_t *co = (conn_t *)wctx; - conn_sys_t *ssys = co->ssys; - char *buf = malloc(4096); - int r; - - while((r = __conn_read(co, buf, 4096)) != -1) { - buf[r] = '\0'; - r = __eval_cstr(buf, ssys->system_rpc, co); - } - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - - /* ok the first of all we're need to wake up all */ - __wake_up_waiters(co, ESXNOCONNECT); - /* now we need to end the poll */ - pth_dqtpoll_destroy(co->tpoll, 1); /* force */ - - __connection_free(co); - - free(buf); - - return NULL; -} - -static void *__cxmaster_thread_listener(void *wctx) -{ - conn_t *co = (conn_t *)wctx; - conn_sys_t *ssys = co->ssys; - char *buf = malloc(4096); - int r; - - while((r = __conn_read(co, buf, 4096)) != -1) { - buf[r] = '\0'; - r = __eval_cstr(buf, ssys->system_rpc, co); - } - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - - /* ok the first of all we're need to wake up all */ - __wake_up_waiters(co, ESXNOCONNECT); - /* now we need to end the poll */ - pth_dqtpoll_destroy(co->tpoll, 1); /* force */ - - __connection_free(co); - - free(buf); - - return NULL; -} - -static void *__rmsg_queue_thread(void *ctx) -{ - conn_t *co = (conn_t *)ctx; - pth_msg_t *tmp = malloc(sizeof(pth_msg_t)); - sxmsg_t *msg; - chnl_t *ch; - int r = 0; - char *rpcf; - sexp_t *sx; - usrtc_node_t *node = NULL; - cx_rpc_t *rpccall; - struct __rpc_job *rjob = NULL; - - if(!tmp) return NULL; - - while(1) { - r = pth_queue_get(co->rqueue, NULL, tmp); - if(r) { - __fini: - free(tmp); - return NULL; - } else if(tmp->msgtype == END_MSG) goto __fini; - msg = tmp->data; - if(!msg) continue; /* spurious !! */ - - /* check to right job */ - if(!(msg->flags & ESXMSG_USR)) { /* not a regular message */ - msg->flags |= ESXMSG_NOWAY; /* mark it's as undeliverable */ - msg->flags &= ~ESXMSG_PENDING; - - pthread_mutex_unlock(&(msg->wait)); /* wake up the waitee */ - continue; - } else { - /* now we're need to have a deal with the rpc calling, other - we don't care */ - ch = msg->pch; - sx = (sexp_t *)msg->payload; - - if(!sx) { - r = ESXRCBADPROT; - goto __err_ret; - } - /* get the function name */ - if((sx->ty == SEXP_LIST) && (sx->list != NULL)) - rpcf = sx->list->val; - else { - r = ESXRCBADPROT; - goto __err_ret; - } - - node = usrtc_lookup(ch->rpc_list->rpc_tree, rpcf); - if(!node) { - r = ENOENT; - __err_ret: - msg_return(msg, r); - } else { - rpccall = (cx_rpc_t *)usrtc_node_getdata(node); - /* call this ! */ - rjob = malloc(sizeof(struct __rpc_job)); // TODO: check it - rjob->msg = msg; - rjob->sx = sx; - rjob->rpcf = rpccall->rpcf; - pth_dqtpoll_add(co->tpoll, (void *)rjob, USR_MSG); // TODO: check it - } - } - } - - return NULL; -} - -static void *__msg_queue_thread(void *ctx) -{ - conn_t *co = (conn_t *)ctx; - pth_msg_t *tmp = malloc(sizeof(pth_msg_t)); - sxmsg_t *msg; - chnl_t *ch; - int r = 0, len; - char *buf = malloc(4096), *tb; - sexp_t *sx; - - if(!tmp || !buf) { - if(tmp) free(tmp); - if(buf) free(buf); - return NULL; - } - - while(1) { - r = pth_queue_get(co->mqueue, NULL, tmp); - if(r) { - __fini: - free(buf); - free(tmp); - return NULL; - } - - /* message workout */ - if(tmp->msgtype == END_MSG) goto __fini; - msg = tmp->data; - if(!msg) continue; /* spurious message */ - - if(!(msg->flags & ESXMSG_USR)) { /* not a regular message */ - msg->flags |= ESXMSG_NOWAY; /* mark it's as undeliverable */ - msg->flags &= ~ESXMSG_PENDING; - - pthread_mutex_unlock(&(msg->wait)); /* wake up the waitee */ - continue; - } else { - ch = msg->pch; - - /* now we need to complete the request */ - sx = (sexp_t *)msg->payload; tb = buf; - if(!(msg->flags & ESXMSG_PULSE)) { /* %s))) */ - if(!(msg->flags & ESXMSG_ISREPLY)) - snprintf(buf, 4096, "(ch-msg (:chid %lu (:msgid %lu ", ch->cid, - msg->mid); - else { - if(!sx) { - snprintf(buf, 4096, "(ch-msg-rete (:chid %lu (:msgid %lu (%d))))", ch->cid, - msg->mid, msg->opcode); - /* mark it to close */ - msg->flags |= ESXMSG_CLOSURE; - /* ok, here we will write it and wait, destroying dialog while reply */ - - goto __ssl_write; - } else { - if(msg->flags & ESXMSG_ISRAPID) { - msg->flags |= ESXMSG_CLOSURE; - pthread_mutex_unlock(&(msg->wait)); /* wake it up */ - snprintf(buf, 4096, "(ch-msg-rapid (:chid %lu (:msgid %lu ", ch->cid, - msg->mid); - } else - snprintf(buf, 4096, "(ch-msg-repl (:chid %lu (:msgid %lu ", ch->cid, - msg->mid); - } - } - - len = strlen(buf); - tb += len*sizeof(char); - if(print_sexp(tb, 4096 - (len + 4*sizeof(char)), sx) == -1) { - msg->opcode = ENOMEM; - /* we don't need to wake up anybody */ - if(msg->flags & ESXMSG_TIMEDOUT) { - /* clean up all the shit: - * 1. remove from message tree - * 2. destroy message itself - */ - destroy_sexp(msg->initial_sx); - msg->initial_sx = NULL; - msg->payload = NULL; - if(msg->flags & ESXMSG_ISREPLY) - destroy_sexp(msg->payload); - } else { - pthread_mutex_unlock(&(msg->wait)); - } - } - } - - len = strlen(tb); - tb += len*sizeof(char); - strcat(tb, ")))"); - - __ssl_write: - if(msg->flags & ESXMSG_CLOSURE) { - /* wake up it */ - pthread_mutex_unlock(&(msg->wait)); - /* first remove the message from tree */ - pthread_rwlock_wrlock(&(ch->msglock)); - usrtc_delete(ch->msgs_tree, &(msg->pendingq_node)); - pthread_rwlock_unlock(&(ch->msglock)); - /* destroy */ - destroy_sexp(msg->initial_sx); - if(msg->flags & ESXMSG_ISREPLY && msg->payload) - destroy_sexp((sexp_t *)msg->payload); - __destroy_msg(msg); - } - - /* write it */ - if(__conn_write(co, (void *)buf, strlen(buf) + sizeof(char)) < 0) { - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - __wake_up_waiters(co, ESXNOCONNECT); - } - - } - - len = 0; - } - - free(buf); - - return NULL; -} - -/* this function is an ugly implementation to get C string with uuid */ -extern char *__generate_uuid(void); - -/* this is a callback to perform a custom SSL certs chain validation, - * as I promised here the comments, a lot of ... - * The first shit: 0 means validation failed, 1 otherwise - * The second shit: X509 API, I guess u will love it ;-) - * openssl calls this function for each certificate in chain, - * since our case is a simple (depth of chain is one, since we're - * don't care for public certificates lists or I cannot find any reasons to - * do it ...), amount of calls reduced, and in this case we're interested - * only in top of chain i.e. actual certificate used on client side, - * the validity of signing for other certificates within chain is - * guaranteed by the ssl itself. - * u know, we need to lookup in database, or elsewhere... some information - * about client certificate, and decide - is it valid, or not?, if so - * yep I mean it's valid, we can assign it's long fucking number to - * security context, to use in ongoing full scaled connection handshaking. - */ -static int __verify_certcall(int preverify_ok, X509_STORE_CTX *ctx) -{ - // X509 *cert = X509_STORE_CTX_get_current_cert(ctx); - int err = X509_STORE_CTX_get_error(ctx), depth = X509_STORE_CTX_get_error_depth(ctx); - SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - conn_t *co = SSL_get_ex_data(ssl, ex_ssldata_index); /* this is a custom data we're set before */ - conn_sys_t *ssys = co->ssys; - - /* now we need to check for certificates with a long chain, - * so since we have a short one, reject long ones */ - if(depth > VERIFY_DEPTH) { /* longer than we expect */ - preverify_ok = 0; /* yep, 0 means error for those function callback in openssl, fucking set */ - err = X509_V_ERR_CERT_CHAIN_TOO_LONG; - X509_STORE_CTX_set_error(ctx, err); - } - - if(!preverify_ok) return 0; - - /* ok, now we're on top of SSL (depth == 0) certs chain, - * and we can validate client certificate */ - if(!depth) { - co->pctx->certid = - ASN1_INTEGER_get((const ASN1_INTEGER *)X509_get_serialNumber(ctx->current_cert)); - /* now we're need to check the ssl cert */ - if(ssys->validate_sslpem) { - if(ssys->validate_sslpem(co)) return 0; - else return 1; - } else return 0; - } - - return preverify_ok; -} - -/* dummy just to check the server side */ -static int __verify_certcall_dummy(int preverify_ok, X509_STORE_CTX *ctx) -{ - return preverify_ok; -} - -/* thread serve the whole connections set i.e. subsystem - * actually it works with system messages - */ -static void *__system_queue_listener(void *data) -{ - conn_sys_t *ssys = (conn_sys_t *)data; - int r; - pth_msg_t *tmp = malloc(sizeof(pth_msg_t)); - sxmsg_t *sysmsg; - sxpayload_t *payload; - chnl_t *chan; - conn_t *co; - - if(!tmp) return NULL; - - while(1) { - r = pth_queue_get(ssys->ioqueue, NULL, tmp); - if(r) { - free(tmp); - return NULL; - } - - /* ok message is delivered */ - sysmsg = tmp->data; - if(!sysmsg) continue; /* ignore dummy messages */ - - if(!(sysmsg->flags & ESXMSG_SYS)) { /* not a system message */ - sysmsg->flags |= ESXMSG_NOWAY; /* mark it's as undeliverable */ - sysmsg->flags &= ~ESXMSG_PENDING; - pthread_mutex_unlock(&(sysmsg->wait)); /* wake up the waitee */ - continue; - } else { - chan = sysmsg->pch; - co = chan->connection; - payload = (sxpayload_t *)sysmsg->payload; - /* write the buf */ - if(__conn_write(co, (void *)payload->cstr, strlen(payload->cstr) + 1) < 0) { - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - __wake_up_waiters(co, ESXNOCONNECT); - } - } - } - - return NULL; -} - -/* general initialization must be called within app uses connection layer */ -int connections_init(conn_sys_t *ssys) -{ - int r = 0; - - if(!ssys) return EINVAL; - else if(!(ssys->connections = malloc(sizeof(usrtc_t)))) { - r = ENOMEM; - goto __fail; - } - - /* zeroing */ - ssys->rootca = ssys->certkey = ssys->certpem = NULL; - ssys->validate_sslpem = NULL; - ssys->secure_check = NULL; - ssys->on_destroy = NULL; - /* init connections list */ - usrtc_init(ssys->connections, USRTC_REDBLACK, MAX_CONNECTIONS, - __cmp_cstr); - if((r = pthread_rwlock_init(&(ssys->rwlock), NULL))) - goto __fail_1; - - /* init queues */ - if(!(ssys->ioq = malloc(sizeof(pth_queue_t)))) { /* general io queue */ - r = ENOMEM; - goto __fail_2; - } - if((r = pth_queue_init(ssys->ioq))) goto __fail_3; - if(!(ssys->ioqueue = malloc(sizeof(pth_queue_t)))) { /* system io queue */ - r = ENOMEM; - goto __fail_2; - } - if((r = pth_queue_init(ssys->ioqueue))) goto __fail_3_1; - - /* init SSL certificates checking functions */ - /* init RPC list related functions */ - if(!(ssys->system_rpc = malloc(sizeof(cx_rpc_list_t)))) { - r = ENOMEM; - goto __fail_3; - } else { - if(!(ssys->system_rpc->rpc_tree = malloc(sizeof(usrtc_t)))) { - r = ENOMEM; - __fail_rpc: - free(ssys->system_rpc); - goto __fail_3_1; - } - usrtc_init(ssys->system_rpc->rpc_tree, USRTC_SPLAY, 256, __cmp_cstr); - r = __init_systemrpc_tree(ssys->system_rpc->rpc_tree); - if(r) { - free(ssys->system_rpc->rpc_tree); - goto __fail_rpc; - } - } - - /* init SSL library */ - SSL_library_init(); - - OpenSSL_add_all_algorithms(); - SSL_load_error_strings(); - - /* create threads for queue */ - if((r = pthread_create(&ssys->ios_thread, NULL, __system_queue_listener, (void *)ssys))) { - goto __fail_rpc; - } - - return 0; - - __fail_3_1: - free(ssys->ioqueue); - __fail_3: - free(ssys->ioq); - __fail_2: - pthread_rwlock_destroy(&(ssys->rwlock)); - __fail_1: - free(ssys->connections); - __fail: - - return r; -} - -/* load certificates */ -int connections_setsslserts(conn_sys_t *ssys, const char *rootca, - const char *certpem, const char *certkey) -{ - int r = ENOMEM; - - if(!ssys) return EINVAL; - /* simply copying */ - if(!(ssys->rootca = strdup(rootca))) return ENOMEM; - if(!(ssys->certkey = strdup(certkey))) goto __fail; - if(!(ssys->certpem = strdup(certpem))) goto __fail; - - r = 0; - return 0; - __fail: - if(ssys->rootca) free(ssys->rootca); - if(ssys->certkey) free(ssys->certkey); - if(ssys->certpem) free(ssys->certpem); - - return r; -} - -int connections_setrpclist_function(conn_sys_t *ssys, - usrtc_t* (*get_rpc_typed_list_tree) - (conn_t *)) -{ - if(!ssys) return EINVAL; - ssys->get_rpc_typed_list_tree = get_rpc_typed_list_tree; - - return 0; -} - -static void __connections_subsystem_connection_remove(conn_t *co) -{ - pthread_rwlock_wrlock(&(co->ssys->rwlock)); - usrtc_delete(co->ssys->connections, &(co->csnode)); - pthread_rwlock_unlock(&(co->ssys->rwlock)); - - return; -} - -#define __TMPBUFLEN 2048 - -/* connection_initiate: perform a connection thru the socket to the - * host with master certificate, i.e. it's a slave one for client. - */ -int connection_initiate_m(conn_sys_t *ssys, conn_t *co, const char *host, - int port, const char *SSL_cert, perm_ctx_t *pctx) -{ - int r = 0, sd; - int bytes = 0; - char *uuid; - char *buf = NULL; - struct hostent *host_; - struct sockaddr_in addr; -#ifdef WIN32 - WSADATA wsaData; -#endif - usrtc_t *ch_tree, *rpc_tree; - pth_queue_t *mqueue = malloc(sizeof(pth_queue_t)); - pth_queue_t *rqueue = malloc(sizeof(pth_queue_t)); - pth_dqtpoll_t *tpoll = malloc(sizeof(pth_dqtpoll_t)); - idx_allocator_t *idx_ch = malloc(sizeof(idx_allocator_t)); - - if(!mqueue) { - __fallenomem: - r = ENOMEM; - __fall0: - if(rqueue) free(rqueue); - if(mqueue) free(mqueue); - if(tpoll) free(tpoll); - if(idx_ch) free(idx_ch); - return r; - } - -#ifdef WIN32 - WSAStartup(MAKEWORD(2, 2), &wsaData); -#endif - - if(!tpoll) goto __fallenomem; - if(!idx_ch) goto __fallenomem; - - if(!co) { - __falleinval: - r = EINVAL; - goto __fall0; - } else if(!ssys) goto __falleinval; - - if(!host) goto __falleinval; - if(!SSL_cert) goto __falleinval; - if(!pctx) goto __falleinval; - - memset(co, 0, sizeof(conn_t)); - /* setup connections set */ - co->ssys = ssys; - - - pth_dqtpoll_init(tpoll, __rpc_callback); - - if(!idx_ch) return ENOMEM; - else r = idx_allocator_init(idx_ch, MAX_CHANNELS*MAX_MULTI, 0); - if(r) return r; - - if(!(uuid = __generate_uuid())) { - return ENOMEM; - } - - if(!(ch_tree = malloc(sizeof(usrtc_t)))) { - r = ENOMEM; - goto __fail; - } - - if(!(rpc_tree = malloc(sizeof(usrtc_t)))) { - r = ENOMEM; - goto __fail_1; - } - - if((r = pthread_mutex_init(&co->oplock, NULL))) goto __fail_2; - if((r = pthread_rwlock_init(&co->chnl_lock, NULL))) goto __fail_3; - - usrtc_init(rpc_tree, USRTC_REDBLACK, MAX_RPC_LIST, __cmp_int); - usrtc_init(ch_tree, USRTC_REDBLACK, MAX_CHANNELS, __cmp_ulong); - - co->idx_ch = idx_ch; - - /* assign message queue */ - if((r = pth_queue_init(mqueue))) goto __fail_3; - co->mqueue = mqueue; - /* assign repl message queue */ - if((r = pth_queue_init(rqueue))) goto __fail_3; - co->rqueue = rqueue; - - /* init SSL certificates and context */ - co->ctx = SSL_CTX_new(TLSv1_2_client_method()); - if(!co->ctx) { ERR_print_errors_fp(stderr); - r = EINVAL; goto __fail_3; } - else { - SSL_CTX_set_verify(co->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, - __verify_certcall_dummy); - SSL_CTX_set_verify_depth(co->ctx, 1); /* FIXME: use configuration */ - } - - /* load certificates */ - SSL_CTX_load_verify_locations(co->ctx, ssys->rootca, NULL); - /* set the local certificate from CertFile */ - if(SSL_CTX_use_certificate_file(co->ctx, SSL_cert, - SSL_FILETYPE_PEM)<=0) { - r = EINVAL; - goto __fail_3; - } - /* set the private key from KeyFile (may be the same as CertFile) */ - - if(SSL_CTX_use_PrivateKey_file(co->ctx, SSL_cert, - SSL_FILETYPE_PEM)<=0) { - r = EINVAL; - goto __fail_3; - } - - /* verify private key */ - if (!SSL_CTX_check_private_key(co->ctx)) { - r = EINVAL; - goto __fail_3; - } - - /* assign allocated memory */ - co->rpc_list = rpc_tree; - co->chnl_tree = ch_tree; - co->uuid = uuid; - - /* connect to the pointed server */ - /* resolve host */ - if(!(buf = malloc(__TMPBUFLEN))) { - r = ENOMEM; - goto __fail_3; - } - - //r=__resolvehost(host, buf, __TMPBUFLEN, &host_); -#ifdef WIN32 - host_ = gethostbyname(host); -#else - r = __resolvehost(host, buf, __TMPBUFLEN, &host_); -#endif - - if(r) { - r = ENOENT; - free(buf); - goto __fail_3; - } - - // /* create a socket */ - sd = socket(PF_INET, SOCK_STREAM, 0); - bzero(&addr, sizeof(addr)); - - /* try to connect it */ - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = *(uint32_t*)(host_->h_addr); - r=connect(sd, (struct sockaddr*)&addr, sizeof(addr)); - - if ( r != 0) { - printf("connect error %d %s \n",r, strerror(errno)); - close(sd); - free(buf); - r = ENOENT; /* couldn't connect to the desired host */ - goto __fail_3; - } - - /* now we will create an SSL connection */ - co->ssl = SSL_new(co->ctx); - SSL_set_fd(co->ssl, sd); /* attach connected socket */ - // BIO_set_nbio(SSL_get_rbio(co->ssl), 1); - SSL_set_connect_state(co->ssl); - if(SSL_connect(co->ssl) == -1) { - r = EBADE; - free(buf); - /* shutdown connection */ - goto __fail_3; - } /* if success we're ready to use established SSL channel */ - - /* auth and RPC contexts sync */ - co->pctx = pctx; - snprintf(buf, __TMPBUFLEN, "(auth-set-context ((:user \"%s\")(:passwd \"%s\")))", - pctx->login, pctx->passwd); - /* send an auth request */ - if(__conn_write(co, buf, strlen(buf) + sizeof(char))) { - __finalize: - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - r = ESXNOCONNECT; - free(buf); - __retry_shut: - if(!SSL_shutdown(co->ssl)) { - usleep(100); - goto __retry_shut; - } - /* shutdown connection */ - goto __fail_3; - } - /* read the message reply */ - - bytes = __conn_read(co, buf, __TMPBUFLEN); - if(bytes == -1) { - // we've lost the connection - co->flags &= ~CXCONN_ESTABL; - r = ESXNOCONNECT; - co->flags |= CXCONN_BROKEN; - free(buf); - /* shutdown connection */ - goto __fail_3; - } - - buf[bytes] = 0; - - /* perform an rpc call */ - r = __eval_cstr(buf, ssys->system_rpc, (void *)co); - - if(!r) { /* all is fine security context is good */ - snprintf(buf, __TMPBUFLEN, "(ch-get-types)"); /* now we should receive possible channel types */ - if(__conn_write(co, buf, strlen(buf) + sizeof(char))) { - goto __finalize; - } - - /* read the message reply */ - bytes = __conn_read(co, buf, __TMPBUFLEN); - if(bytes == -1) { - goto __finalize; - } - - buf[bytes] = 0; - /* perform an rpc call */ - r = __eval_cstr(buf, ssys->system_rpc, (void *)co); - } - - free(buf); /* now we can free the temporary buffer */ - /* a listening thread creation (incoming messages) */ - if(!r) { /* success let's start a listening thread */ - r = pthread_create(&co->cthread, NULL, __cxslave_thread_listener, (void *)co); - if(!r) { - /* add connection to the list */ - usrtc_node_init(&co->csnode, co); - co->flags = (CXCONN_SLAVE | CXCONN_ESTABL); /* set the right flags */ - pthread_rwlock_wrlock(&ssys->rwlock); - usrtc_insert(ssys->connections, &co->csnode, (void *)co->uuid); - pthread_rwlock_unlock(&ssys->rwlock); - } - r = pthread_create(&co->msgthread, NULL, __msg_queue_thread, (void *)co); - if(r) goto __finalize; - r = pthread_create(&co->rmsgthread, NULL, __rmsg_queue_thread, (void *)co); - if(r) goto __finalize; - - pth_dqtpoll_run(tpoll); - co->tpoll = tpoll; - - return 0; - } - - __fail_3: - pthread_mutex_destroy(&co->oplock); - __fail_2: - free(rpc_tree); - __fail_1: - free(ch_tree); - __fail: - free(uuid); - return r; -} - -int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, - struct in_addr *addr) -{ - int r = 0; - int bytes = 0; - char *uuid; - char *buf = NULL; - usrtc_t *ch_tree, *rpc_tree; - pth_queue_t *rqueue = malloc(sizeof(pth_queue_t)); - pth_queue_t *mqueue = malloc(sizeof(pth_queue_t)); - pth_dqtpoll_t *tpoll = malloc(sizeof(pth_dqtpoll_t)); - if(!tpoll) return ENOMEM; // TODO: fallback - idx_allocator_t *idx_ch = malloc(sizeof(idx_allocator_t)); - - if(!co) return EINVAL; - else memset(co, 0, sizeof(conn_t)); - - pth_dqtpoll_init(tpoll, __rpc_callback); // TODO: check it - - if(!idx_ch) return ENOMEM; - else r = idx_allocator_init(idx_ch, MAX_CHANNELS*MAX_MULTI, 0); - if(r) return r; - - if(!(uuid = __generate_uuid())) return ENOMEM; - if(!(ch_tree = malloc(sizeof(usrtc_t)))) { - r = ENOMEM; - goto __fail; - } - if(!(rpc_tree = malloc(sizeof(usrtc_t)))) { - r = ENOMEM; - goto __fail_1; - } - if((r = pthread_mutex_init(&co->oplock, NULL))) goto __fail_2; - if((r = pthread_rwlock_init(&co->chnl_lock, NULL))) goto __fail_3; - - usrtc_init(rpc_tree, USRTC_REDBLACK, MAX_RPC_LIST, __cmp_int); - usrtc_init(ch_tree, USRTC_REDBLACK, MAX_CHANNELS, __cmp_ulong); - - co->idx_ch = idx_ch; - - /* setup connections set */ - co->ssys = ssys; - - /* assign message queue */ - r = pth_queue_init(rqueue); - if(r) goto __fail_3; - co->rqueue = rqueue; - /* assigned outbone message queue master also has this one */ - r = pth_queue_init(mqueue); - if(r) goto __fail_3; - co->mqueue = mqueue; - - /* init SSL certificates and context */ - co->ctx = SSL_CTX_new(TLSv1_2_server_method()); - if(!co->ctx) { r = EINVAL; printf("%s:%d\n", __FUNCTION__, __LINE__);goto __fail_3; } - else { - /* set verify context */ - SSL_CTX_set_verify(co->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, - __verify_certcall); - /* set verify depth */ - SSL_CTX_set_verify_depth(co->ctx, VERIFY_DEPTH); - } - - /* load certificates */ - SSL_CTX_load_verify_locations(co->ctx, ssys->rootca, NULL); - /* set the local certificate from CertFile */ - if(SSL_CTX_use_certificate_file(co->ctx, ssys->certpem, - SSL_FILETYPE_PEM)<=0) { - printf("certpem1 = %s\n", ssys->certpem); - ERR_print_errors_fp(stderr); - r = EINVAL; printf("%s:%d\n", __FUNCTION__, __LINE__); - goto __fail_3; - } - /* set the private key from KeyFile (may be the same as CertFile) */ - if(SSL_CTX_use_PrivateKey_file(co->ctx, ssys->certkey, - SSL_FILETYPE_PEM)<=0) { - r = EINVAL; printf("%s:%d\n", __FUNCTION__, __LINE__); - goto __fail_3; - } - /* verify private key */ - if (!SSL_CTX_check_private_key(co->ctx)) { - r = EINVAL; printf("%s:%d\n", __FUNCTION__, __LINE__); - goto __fail_3; - } - - /* assign allocated memory */ - co->rpc_list = rpc_tree; - co->chnl_tree = ch_tree; - co->uuid = uuid; - - if(!(buf = malloc(__TMPBUFLEN))) { - r = ENOMEM; - goto __fail_3; - } - - /* now we will create an SSL connection */ - co->ssl = SSL_new(co->ctx); - co->pctx = malloc(sizeof(perm_ctx_t)); - SSL_set_fd(co->ssl, sck); /* attach connected socket */ - /* ok now we need to initialize address */ - if(addr) { - co->pctx->addr = malloc(sizeof(struct in_addr)); - memcpy(co->pctx->addr, addr, sizeof(struct in_addr)); - } else co->pctx->addr = NULL; - - SSL_set_accept_state(co->ssl); - /* set the context to verify ssl connection */ - SSL_set_ex_data(co->ssl, ex_ssldata_index, (void *)co); - //BIO_set_nbio(SSL_get_rbio(co->ssl), 1); - SSL_set_accept_state(co->ssl); - if(SSL_accept(co->ssl) == -1) { - r = EBADE; - free(buf); - /* shutdown connection */ - goto __fail_3; - } /* if success we're ready to use established SSL channel */ - - /*******************************************/ - /*-=Protocol part of connection establish=-*/ - /*******************************************/ - while(!(co->flags & CXCONN_ESTABL)) { /* read the initiation stage connections */ - bytes = __conn_read(co, buf, __TMPBUFLEN); - if(bytes > 0) { - buf[bytes] = 0; - r = __eval_cstr(buf, ssys->system_rpc, (void *)co); - if(r) { - fprintf(stderr, "Initiation func return %d\n", r); - free(buf); - SSL_shutdown(co->ssl); - goto __fail_3; - } - } else { - if(bytes < 0) { - printf("Terminate SSL connection, the other end is lost.\n"); - co->flags &= ~CXCONN_ESTABL; - co->flags |= CXCONN_BROKEN; - free(buf); - if(ssys->on_destroy) ssys->on_destroy(co); - SSL_shutdown(co->ssl); - r = ESXNOCONNECT; - goto __fail_3; - } - } - } - - /* before it will be done assign rpc list */ - if(ssys->get_rpc_typed_list_tree) - co->rpc_list = ssys->get_rpc_typed_list_tree(co); - - free(buf); - r = pthread_create(&co->cthread, NULL, __cxmaster_thread_listener, (void *)co); - if(!r) { - /* add connection to the list */ - usrtc_node_init(&co->csnode, co); - co->flags |= CXCONN_MASTER; /* set the right flags */ - pthread_rwlock_wrlock(&ssys->rwlock); - usrtc_insert(ssys->connections, &co->csnode, (void *)co->uuid); - pthread_rwlock_unlock(&ssys->rwlock); - /* threads poll --- */ - r = pthread_create(&co->msgthread, NULL, __msg_queue_thread, (void *)co); - if(r) goto __fail_3; - r = pthread_create(&co->rmsgthread, NULL, __rmsg_queue_thread, (void *)co); - if(r) goto __fail_3; - - pth_dqtpoll_run(tpoll); - co->tpoll = tpoll; - } - - return r; - - __fail_3: - pthread_mutex_destroy(&co->oplock); - __fail_2: - free(rpc_tree); - __fail_1: - free(ch_tree); - __fail: - free(uuid); - return r; -} - -int connection_close(conn_t *co) -{ - void *nil; - - pthread_cancel(co->cthread); - /* wait for the main listener */ - pthread_join(co->cthread, &nil); - /* ok the first of all we're need to wake up all */ - __wake_up_waiters(co, ESXNOCONNECT); - /* now we need to end the poll */ - pth_dqtpoll_destroy(co->tpoll, 1); /* force */ - - __connection_free(co); - - return 0; -} - -extern int __create_reg_msg(sxmsg_t **msg, chnl_t *ch); - -extern int __create_sys_msg(sxmsg_t **msg, char *uuid, chnl_t *ch, sxpayload_t *data); - -static void __connection_free(conn_t *co) -{ - pth_msg_t msg; - void *nil; - - /* since we doesn't works with IN queue and job dispatching - * close the thread - */ - msg.msgtype = END_MSG; - msg.data = NULL; - pth_queue_add(co->rqueue, &msg, END_MSG); /* it will drop the thread */ - pthread_join(co->rmsgthread, &nil); /* wait for it */ - /* message sending dispatch thread must be finished too */ - pth_queue_add(co->mqueue, &msg, END_MSG); /* it will drop the thread */ - pthread_join(co->msgthread, &nil); /* wait for it */ - /* since we don't have any threads working with channels destroy them */ - __destroy_all_channels(co); - /* permission context and callback of exists */ - if(co->ssys->on_destroy) co->ssys->on_destroy(co); - else { /* we don't have a handler */ - if(co->pctx->login) free(co->pctx->login); - if(co->pctx->passwd) free(co->pctx->passwd); - } - __connections_subsystem_connection_remove(co); - /* now we're ready to free other resources */ - if(co->uuid) free(co->uuid); - /* idx allocator */ - idx_allocator_destroy(co->idx_ch); - free(co->idx_ch); - free(co->chnl_tree); - /* kill SSL context */ - SSL_shutdown(co->ssl); - close(SSL_get_fd(co->ssl)); - SSL_free(co->ssl); - SSL_CTX_free(co->ctx); - /* destroy queues */ - pth_queue_destroy(co->mqueue, 0, NULL); - pth_queue_destroy(co->rqueue, 0, NULL); - /* locks */ - pthread_rwlock_destroy(&(co->chnl_lock)); - pthread_mutex_destroy(&(co->oplock)); - /* kill permission context */ - if(co->pctx) free(co->pctx); - - return; -} diff --git a/lib/message.c b/lib/message.c deleted file mode 100644 index 9df5d3f..0000000 --- a/lib/message.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Secure Network Transport Layer Library implementation. - * This is a proprietary software. See COPYING for further details. - * - * (c) Askele Group 2013-2015 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef WIN32 -#include -#else -#include -#include -#include -#include -#endif - -#include -#include - -#include -#include - -#include - -void __destroy_msg(sxmsg_t *msg) -{ - chnl_t *ch = msg->pch; - - if(msg->flags & ESXMSG_USR) { - pthread_mutex_lock(&(ch->oplock)); - idx_free(ch->idx_msg, msg->mid); - pthread_mutex_unlock(&(ch->oplock)); - } else if(msg->flags & ESXMSG_SYS) { - //if(msg->uuid) free(msg->uuid); - } - - pthread_mutex_unlock(&(msg->wait)); - pthread_mutex_destroy(&(msg->wait)); - free(msg); - return; -} - -sxmsg_t *__allocate_msg(int *res) -{ - sxmsg_t *msg = malloc(sizeof(sxmsg_t)); - int r = 0; - - if(!msg) { - *res = ENOMEM; - return NULL; - } else { - memset(msg, 0, sizeof(sxmsg_t)); - if((r = pthread_mutex_init(&(msg->wait), NULL))) { - free(msg); - *res = r; - return NULL; - } - - usrtc_node_init(&(msg->pendingq_node), msg); - } - - *res = 0; - - return msg; -} - -int __create_reg_msg(sxmsg_t **msg, chnl_t *ch) -{ - int r = 0; - sxmsg_t *sm = __allocate_msg(&r); - - if(r) return r; - else { - sm->pch = ch; - sm->flags = (ESXMSG_USR | ESXMSG_PENDING); - - /* ok allocate message ID */ - pthread_mutex_lock(&(ch->oplock)); - sm->mid = idx_allocate(ch->idx_msg); - pthread_mutex_unlock(&(ch->oplock)); - - pthread_mutex_lock(&(sm->wait)); - *msg = sm; - } - - return 0; -} - -int __create_sys_msg(sxmsg_t **msg, char *uuid, chnl_t *ch, sxpayload_t *data) -{ - int r = 0; - sxmsg_t *m = __allocate_msg(&r); - - if(r) return r; - else { - /* fill values */ - m->pch = ch; - m->uuid = uuid; - m->payload = data; - /* set the right flags */ - m->flags = (ESXMSG_SYS | ESXMSG_PENDING); - /* we need to lock the wait mutex */ - pthread_mutex_lock(&(m->wait)); - - *msg = m; - } - - return 0; -} - -/* message passing */ - -/* - * How message sending works: - * 1. Create a message structure assigned to the channel, - * 2. Put S-expression context to it - * 3. Put the message to the queue - * 4. expect the result waiting on the lock mutex - */ -static int __message_send(chnl_t *ch, sexp_t *sx, sxmsg_t **msg, struct timespec *tio) -{ - int r = 0; - sxmsg_t *m = NULL; - conn_t *co = ch->connection; - - if(!(co->flags & CXCONN_ESTABL)) { - destroy_sexp(sx); - return ESXNOCONNECT; - } - - *msg = NULL; - - r = __create_reg_msg(&m, ch); - if(r) return r; - else { - /* put the message to the search tree */ - pthread_rwlock_wrlock(&(ch->msglock)); - usrtc_insert(ch->msgs_tree, &(m->pendingq_node), &(m->mid)); - pthread_rwlock_unlock(&(ch->msglock)); - - /* message assign */ - m->opcode = 0; - m->payload = (void *)sx; - /* assign initial sx */ - m->initial_sx = sx; - - /* put the message to the run queue */ - r = pth_queue_add(co->mqueue, (void *)m, USR_MSG); - if(r) return r; /* FIXME: better give up */ - - if(m->flags & ESXMSG_PENDING) { - if(!tio) pthread_mutex_lock(&(m->wait)); - else pthread_mutex_timedlock(&(m->wait), tio); - } - if(tio && (m->flags & ESXMSG_PENDING)) - return ESXOTIMEDOUT; - if(!m->payload) { - r = m->opcode; - /* first remove the message from tree */ - pthread_rwlock_wrlock(&(ch->msglock)); - usrtc_delete(ch->msgs_tree, &(m->pendingq_node)); - pthread_rwlock_unlock(&(ch->msglock)); - /* destroy s expression */ - destroy_sexp(m->initial_sx); - /* destroy */ - __destroy_msg(m); - } else { - *msg = m; - if(m->opcode == ESXNOCONNECT || m->opcode == ESXRAPIDREPLY) - r = m->opcode; - else r = ESXOREPLYREQ; - /* FIXME: remove ugly code */ - if(m->opcode == ESXRAPIDREPLY) { - /* first remove the message from tree */ - pthread_rwlock_wrlock(&(ch->msglock)); - usrtc_delete(ch->msgs_tree, &(m->pendingq_node)); - pthread_rwlock_unlock(&(ch->msglock)); - } - } - } - - return r; -} - -int msg_send(chnl_t *ch, sexp_t *sx, sxmsg_t **msg) -{ - return __message_send(ch, sx, msg, NULL); -} - -int msg_send_timed(chnl_t *ch, sexp_t *sx, sxmsg_t **msg, struct timespec *tio) -{ - return __message_send(ch, sx, msg, tio); -} - -static int __msg_reply(sxmsg_t *msg, sexp_t *sx, struct timespec *tio, int opcode, - int israpid) -{ - int r = 0; - chnl_t *ch = msg->pch; - conn_t *co = ch->connection; - - if(!(co->flags & CXCONN_ESTABL)) { - destroy_sexp(sx); - return ESXNOCONNECT; - } - - if(msg->flags & ESXMSG_ISREPLY) - destroy_sexp((sexp_t *)msg->payload); - - msg->payload = sx; - msg->opcode = opcode; - msg->flags |= ESXMSG_PENDING; /* pending */ - msg->flags |= ESXMSG_ISREPLY; /* this is a reply */ - if(israpid) msg->flags |= ESXMSG_ISRAPID; /* message is a rapid message */ - - if(!sx || israpid) msg->flags &= ~ESXMSG_PENDING; - else msg->flags |= ESXMSG_RMONRETR; - - /* put the message to the queue */ - r = pth_queue_add(co->mqueue, (void *)msg, USR_MSG); - if(r) return r; /* FIXME: better give up */ - if(!sx || israpid) { - /* wait for write */ - //pthread_mutex_lock(&(msg->wait)); - return 0; - } - - if(msg->flags & ESXMSG_PENDING) { - if(!tio) pthread_mutex_lock(&(msg->wait)); - else pthread_mutex_timedlock(&(msg->wait), tio); - } - - if(tio && (msg->flags & ESXMSG_PENDING)) { - msg->flags &= ~ESXMSG_PENDING; /* we will not wait for it */ - return ESXOTIMEDOUT; - } - - r = msg->opcode; - - if(msg->flags & ESXMSG_CLOSURE) { - __destroy_msg(msg); - } - - return r; -} - -int msg_return(sxmsg_t *msg, int opcode) -{ - return __msg_reply(msg, NULL, NULL, opcode, 0); -} - -int msg_reply(sxmsg_t *msg, sexp_t *sx) -{ - return __msg_reply(msg, sx, NULL, 0, 0); -} - -int msg_reply_timed(sxmsg_t *msg, sexp_t *sx, struct timespec *tio) -{ - return __msg_reply(msg, sx, tio, 0, 0); -} - -int msg_reply_rapid(sxmsg_t *msg, sexp_t *sx) -{ - return __msg_reply(msg, sx, NULL, 0, 1); -} - -int msg_rapid_clean(sxmsg_t *msg) -{ - destroy_sexp(msg->initial_sx); - if(msg->payload) destroy_sexp(msg->payload); - __destroy_msg(msg); - - return 0; -} diff --git a/lib/queue.c b/lib/queue.c deleted file mode 100644 index 2dce4e1..0000000 --- a/lib/queue.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * This is a proprietary software. See COPYING for further details. - * - * - * - * (c) Askele Group 2013-2015 - */ - -#include -#include -#include -#include -#include -#include -#include -/**/ -#ifdef WIN32 -#include -#else - - -#include - -#endif - -/**/ -// #include -#include -#include - -#include - -#include - -#define MAX_QUEUE_SIZE 4096 -#define MAX_QUEUE_POOL 256 - -static long __cmp_uint(const void *a, const void *b) -{ - return (long)(*(unsigned int *)a - *(unsigned int *)b); -} - -static inline pth_msg_t *__get_newmsg(pth_queue_t *queue) -{ - usrtc_t *tree = &queue->msgcache; - usrtc_node_t *node; - pth_msg_t *tmp; - - if(usrtc_count(tree)) { - node = usrtc_first(tree); - tmp = (pth_msg_t *)usrtc_node_getdata(node); - usrtc_delete(tree, node); - } else { - tmp = malloc(sizeof(pth_msg_t)); - tree = &queue->qtree; - node = &tmp->node; - usrtc_node_init(node, tmp); - } - /* insert it */ - tree = &queue->qtree; - tmp->qlength = usrtc_count(tree); - usrtc_insert(tree, node, (void *)(&tmp->qlength)); - - return tmp; -} - -static inline void __release_msg(pth_queue_t *queue, pth_msg_t *msg) -{ - usrtc_node_t *node = &msg->node; - usrtc_t *tree = &queue->qtree; - - tree = &queue->qtree; /* remove from queue */ - usrtc_delete(tree, node); - - tree = &queue->msgcache; - - if(usrtc_count(tree) >= MAX_QUEUE_POOL) - free(msg); - else { - msg->data = NULL; - msg->msgtype = NIL_MSG; - usrtc_insert(tree, node, (void *)&msg->qlength); - } - - return; -} - -int pth_queue_init(pth_queue_t *queue) -{ - int r = 0; - - memset(queue, 0, sizeof(pth_queue_t)); - if((r = pthread_cond_init(&queue->cond, NULL))) - return r; - - if((r = pthread_mutex_init(&queue->mutex, NULL))) { - pthread_cond_destroy(&queue->cond); - return r; - } - - usrtc_init(&queue->qtree, USRTC_AVL, MAX_QUEUE_SIZE, __cmp_uint); - usrtc_init(&queue->msgcache, USRTC_AVL, MAX_QUEUE_POOL, __cmp_uint); - - return r; -} - -int pth_queue_add(pth_queue_t *queue, void *data, unsigned int msgtype) -{ - pth_msg_t *newmsg; - - pthread_mutex_lock(&queue->mutex); - newmsg = __get_newmsg(queue); - if (newmsg == NULL) { - pthread_mutex_unlock(&queue->mutex); - return ENOMEM; - } - - newmsg->data = data; - newmsg->msgtype = msgtype; - - if(queue->length == 0) - pthread_cond_broadcast(&queue->cond); - queue->length++; - pthread_mutex_unlock(&queue->mutex); - - return 0; -} - -int pth_queue_get(pth_queue_t *queue, const struct timespec *timeout, pth_msg_t *msg) -{ - usrtc_t *tree; - usrtc_node_t *node = NULL; - pth_msg_t *tmp; - int r = 0; - struct timespec abstimeout; - - if (queue == NULL || msg == NULL) - return EINVAL; - else - tree = &queue->qtree; - - if (timeout) { /* setup timeout */ - struct timeval now; - - gettimeofday(&now, NULL); - abstimeout.tv_sec = now.tv_sec + timeout->tv_sec; - abstimeout.tv_nsec = (now.tv_usec * 1000) + timeout->tv_nsec; - if (abstimeout.tv_nsec >= 1000000000) { - abstimeout.tv_sec++; - abstimeout.tv_nsec -= 1000000000; - } - } - - pthread_mutex_lock(&queue->mutex); - - /* Will wait until awakened by a signal or broadcast */ - while ((node = usrtc_first(tree)) == NULL && r != ETIMEDOUT) { /* Need to loop to handle spurious wakeups */ - if (timeout) - r = pthread_cond_timedwait(&queue->cond, &queue->mutex, &abstimeout); - else - pthread_cond_wait(&queue->cond, &queue->mutex); - } - if (r == ETIMEDOUT) { - pthread_mutex_unlock(&queue->mutex); - return r; - } - - tmp = (pth_msg_t *)usrtc_node_getdata(node); - queue->length--; - - msg->data = tmp->data; - msg->msgtype = tmp->msgtype; - msg->qlength = tmp->qlength; /* we will hold the msg id instead of size here */ - - __release_msg(queue, tmp); - pthread_mutex_unlock(&queue->mutex); - - return 0; -} - -int pth_queue_destroy(pth_queue_t *queue, int freedata, void (*free_msg)(void *)) -{ - int r = 0; - usrtc_t *tree = &queue->qtree; - usrtc_node_t *node = NULL; - pth_msg_t *msg; - - if (queue == NULL) return EINVAL; - - pthread_mutex_lock(&queue->mutex); - - for (node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) { - usrtc_delete(tree, node); - msg = (pth_msg_t *)usrtc_node_getdata(node); - - if(freedata) free(msg->data); - else if(free_msg) free_msg(msg->data); - - free(msg); - } - /* free cache */ - tree = &queue->msgcache; - for (node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) { - usrtc_delete(tree, node); - free(usrtc_node_getdata(node)); - } - - pthread_mutex_unlock(&queue->mutex); - r = pthread_mutex_destroy(&queue->mutex); - pthread_cond_destroy(&queue->cond); - - return r; -} - -unsigned int pth_queue_length(pth_queue_t *queue) -{ - unsigned int c; - - pthread_mutex_lock(&queue->mutex); - c = queue->length; - pthread_mutex_unlock(&queue->mutex); - - return c; -} - -/* dynamic queue thread poll */ - -struct __pthrd_data { - pth_dqtpoll_t *pthrd; - int myid; -}; - -static void *__poll_thread(void *poll) -{ - int r = 0; - struct __pthrd_data *thrdata = (struct __pthrd_data *)poll; - struct __pthrd_data *npoll = NULL; - pth_msg_t msgbuf, sysbuf; - pth_dqtpoll_t *p = thrdata->pthrd; - pth_queue_t *q = p->queue; - ulong_t myid = thrdata->myid; - struct timeval now; - int resched = 0; - long tusec, si, mdrate; - - while(1) { - resched = 0; - r = pth_queue_get(q, NULL, &msgbuf); - pthread_rwlock_wrlock(&(p->stats_lock)); - if(p->flags & DQTPOLL_DEADSTAGE) { /* poll going to be killed */ - pthread_rwlock_unlock(&(p->stats_lock)); - idx_free(p->idx, myid); - p->poll_value--; - - return NULL; - } - - /* now get the time */ - gettimeofday(&now, NULL); - if((now.tv_sec >= p->sched_time.tv_sec) && - (now.tv_usec >= p->sched_time.tv_usec)) { - resched = 1; - /* set the new schedule time */ - si = 0; - tusec = DQTPOLL_DELTAMS + now.tv_usec; - if(tusec > 1000000) { - tusec -= 1000000; - si++; - } - p->sched_time.tv_sec += si + DQTPOLL_DELTASE; - p->sched_time.tv_usec = tusec; - } - - if(resched) { /* ok now we need to resched and descrease/increase thread poll volume */ - if(p->msgop) mdrate = ((DQTPOLL_DELTASE*1000000) + DQTPOLL_DELTAMS)/p->msgop; - else mdrate = 0; - if((mdrate > p->poll_value) && (p->poll_value < MAX_POLL_VALUE)) { /* increase ! */ - if((npoll = malloc(sizeof(struct __pthrd_data)))) { - npoll->myid = idx_allocate(p->idx); - npoll->pthrd = p; - p->poll_value++; - /* create thread here */ - if(pthread_create(&(p->poll[npoll->myid]), NULL, __poll_thread, npoll)) { - idx_free(p->idx, npoll->myid); - p->poll_value--; - free(npoll); - } - } - } else if((p->poll_value > 2) && (mdrate < p->poll_value)) /* decrease */ { - memset(&sysbuf, 0, sizeof(pth_msg_t)); - pth_queue_add(p->queue, &sysbuf, POLL_DECREASE); - } - - /* init all other stuff */ - p->msgop = 0; - } - - if(r) { - pthread_rwlock_unlock(&(p->stats_lock)); - continue; - } else p->msgop++; - pthread_rwlock_unlock(&(p->stats_lock)); - - switch(msgbuf.msgtype) { - case USR_MSG: - /* do the job */ - p->jobdata_callback(msgbuf.data); - break; - case POLL_DECREASE: - pthread_rwlock_rdlock(&(p->stats_lock)); - if(p->poll_value > 2) r = 1; /* exit now */ - pthread_rwlock_unlock(&(p->stats_lock)); - if(r) { - pthread_rwlock_wrlock(&(p->stats_lock)); - idx_free(p->idx, myid); - p->poll_value--; - pthread_rwlock_unlock(&(p->stats_lock)); - free(poll); - return NULL; - } - break; - default: - /* TODO: do something ... */ - break; - } - } - - return NULL; -} - -/* init poll, structure must be allocated */ -int pth_dqtpoll_init(pth_dqtpoll_t *tpoll, int (*jobdata_callback)(void *)) -{ - int r = 0; - pth_queue_t *queue = malloc(sizeof(pth_queue_t)); - pthread_t *poll = malloc(sizeof(pthread_t)*MAX_POLL_VALUE); - idx_allocator_t *idx = malloc(sizeof(idx_allocator_t)); - struct __pthrd_data *ndata = malloc(sizeof(struct __pthrd_data)); - - /* check it for allocation */ - if(!ndata) goto __enomem; - if(!idx) goto __enomem; - if(!queue) goto __enomem; - if(!poll) goto __enomem; - - /* init all the stuff */ - if(idx_allocator_init(idx, MAX_POLL_VALUE*16, 0)) { - __enomem: - r = ENOMEM; - goto __finish; - } - if(pth_queue_init(queue)) goto __enomem; /* init queue */ - if(pthread_rwlock_init(&(tpoll->stats_lock), NULL)) goto __enomem; - - /* set parameters */ - memset(poll, 0, sizeof(pthread_t)*MAX_POLL_VALUE); - tpoll->flags = 0; - tpoll->idx = idx; - tpoll->poll = poll; - tpoll->queue = queue; - tpoll->poll_value = 2; - tpoll->spurious_wakeups = 0; - tpoll->msgop = 0; - tpoll->jobdata_callback = jobdata_callback; - - /* first thread initiation */ - idx_reserve(idx, 0); - ndata->myid = 0; - ndata->pthrd = tpoll; - if(pthread_create(&(poll[0]), NULL, __poll_thread, ndata)) { - __eadd: - pthread_rwlock_destroy(&(tpoll->stats_lock)); - goto __enomem; - } - /* second thread initiation */ - ndata = malloc(sizeof(struct __pthrd_data)); - if(!ndata) goto __eadd; - idx_reserve(idx, 1); - ndata->myid = 1; - ndata->pthrd = tpoll; - if(pthread_create(&(poll[1]), NULL, __poll_thread, ndata)) { - pthread_rwlock_destroy(&(tpoll->stats_lock)); - goto __enomem; - } - - gettimeofday(&(tpoll->sched_time), NULL); - - __finish: - if(r) { - if(ndata) free(ndata); - if(idx) free(idx); - if(queue) { - pth_queue_destroy(queue, 0, NULL); - free(queue); - } - if(poll) free(poll); - } - return r; -} - -/* run poll: poll */ -int pth_dqtpoll_run(pth_dqtpoll_t *tpoll) -{ - int r = 0; - - pthread_rwlock_wrlock(&(tpoll->stats_lock)); - if((tpoll->flags & DQTPOLL_RUNNING) || (tpoll->flags & DQTPOLL_DEADSTAGE)) r = EINVAL; - else { - tpoll->flags |= DQTPOLL_RUNNING; - } - pthread_rwlock_unlock(&(tpoll->stats_lock)); - - return r; -} - -/* add the job to the queue: poll, job data, message type */ -int pth_dqtpoll_add(pth_dqtpoll_t *tpoll, void *job, unsigned int type) -{ - int r = 0; - - r = pth_queue_add(tpoll->queue, job, type); - - return r; -} - -/* destroy the poll: poll, force flag - * if force flag is set (!= 0), give up - * about jobs, if no, do the job, but don't - * accept the new ones, and destroy all poll - * with last thread. - */ -int pth_dqtpoll_destroy(pth_dqtpoll_t *tpoll, int force) -{ - int r = 0; - pth_msg_t tmpmsg; - - pthread_rwlock_wrlock(&(tpoll->stats_lock)); - tpoll->flags |= DQTPOLL_DEADSTAGE; - pthread_rwlock_unlock(&(tpoll->stats_lock)); - - /* now we need to wait */ - while(1) { - pthread_rwlock_rdlock(&(tpoll->stats_lock)); - if(!tpoll->poll_value) { - pthread_rwlock_unlock(&(tpoll->stats_lock)); - break; - } else { - pthread_rwlock_unlock(&(tpoll->stats_lock)); - pth_queue_add(tpoll->queue, &tmpmsg, 0); /* spurious */ - } - usleep(100); /* just to sleep and free timeslice to others */ - } - - /* free all */ - pth_queue_destroy(tpoll->queue, 0, NULL); - idx_allocator_destroy(tpoll->idx); - pthread_rwlock_destroy(&(tpoll->stats_lock)); - - free(tpoll->poll); - free(tpoll->queue); - free(tpoll->idx); - - return r; -} - diff --git a/lib/support.c b/lib/uuid.c similarity index 71% rename from lib/support.c rename to lib/uuid.c index a6e5883..873addd 100644 --- a/lib/support.c +++ b/lib/uuid.c @@ -31,14 +31,6 @@ #include -#include -#include - -#include -#include - -#include - #ifdef WIN32 #define UUID_T_LENGTH 16 @@ -101,25 +93,3 @@ char *__generate_uuid(void) #endif } -/* networking helpers */ -#ifndef WIN32 -int __resolvehost(const char *hostname, char *buf, int buf_len, - struct hostent **rhp) -{ - struct hostent *hostbuf ;//= malloc(sizeof(struct hostent)); - struct hostent *hp = *rhp = NULL; - int herr = 0, hres = 0; - - - hostbuf = malloc(sizeof(struct hostent)); - if(!hostbuf) return NO_ADDRESS; - hres = gethostbyname_r(hostname, hostbuf, - buf, buf_len, &hp, &herr); - - if(hres) return NO_ADDRESS; - *rhp = hp; - - return NETDB_SUCCESS; -} -#endif - From 109d70a7162fa2e6ba9f543b5e0766e30760a4f9 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 04:06:06 +0300 Subject: [PATCH 22/56] extern C added, minor fixes; --- include/sntl/sntllv2.h | 33 ++++++++++-- lib/messagesx.c | 115 ++++++++++++++++++++++++++++++++++++----- lib/sntllv2.c | 21 +++++--- 3 files changed, 146 insertions(+), 23 deletions(-) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index 0b83ffc..cf5ec77 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -171,7 +171,7 @@ typedef struct __connections_subsys_type { int (*set_typed_list_callback)(conn_t *, int, char *); /** < this function is a callback * during setting up a typed channel */ void (*on_destroy)(conn_t *); /** < callback on connection destroy */ - void (*on_pulse)(conn_t *, sxmsg_t *); /** < callback on pulse emit */ + void (*on_pulse)(conn_t *, sexp_t *); /** < callback on pulse emit */ void *priv; } conn_sys_t; @@ -189,6 +189,10 @@ typedef struct __rpc_typed_list_type { usrtc_node_t lnode; } rpc_typed_list_t; +#ifdef __cplusplus +extern "C" { +#endif + /* API */ int connections_init(conn_sys_t *ssys); @@ -219,20 +223,39 @@ int sxmsg_send(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg) int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg); /* send a pulse message */ int sxmsg_pulse(conn_t *co, const char *data, size_t datalen); -/* the same but will be postponed */ -int sxmsg_pulse_pp(conn_t *co, const char *data, size_t datalen); int sxmsg_reply(sxmsg_t *msg, const char *data, size_t datalen); int sxmsg_reply_pp(sxmsg_t *msg, const char *data, size_t datalen); -int sxmsg_rreply(sxmsg_t *msg, const char *data, size_t datalen); -int sxmsg_rreply_pp(sxmsg_t *msg, const char *data, size_t datalen); +int sxmsg_rreply(sxmsg_t *msg, size_t datalen); int sxmsg_return(sxmsg_t *msg, int opcode); int sxmsg_return_pp(sxmsg_t *msg, int opcode); +#ifdef __cplusplus +} +#endif + /* RPC List API */ #define SNTL_FILTER_INC 0xa #define SNTL_FILTER_EXC 0xb #define SNTL_FILTER_END -1 +#ifdef __cplusplus +extern "C" { +#endif + +int sntl_rpclist_init(usrtc_t *tree); + +int sntl_rpclist_add(usrtc_t *tree, int type, const char *description, + const char *version); + +int sntl_rpclist_add_function(usrtc_t *tree, int type, const char *fu_name, + int (*rpcf)(void *, sexp_t *)); + +int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter); + +#ifdef __cplusplus +} +#endif + #endif /* __SNTL_SNTLLV2_H__ */ diff --git a/lib/messagesx.c b/lib/messagesx.c index c0faca0..213af6b 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -145,33 +145,124 @@ int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **o /* send a pulse message */ int sxmsg_pulse(conn_t *co, const char *data, size_t datalen) { - return SNE_FAILED; + sxmsg_t *msg = malloc(sizeof(sxmsg_t)); + sntllv2_head_t *head; + int r; + + /* a little bit of paranoid tests */ + if(!msg) return SNE_ENOMEM; + else memset(msg, 0, sizeof(sxmsg_t)); + + /* prepare it */ + head = &msg->mhead; + head->attr = 0; + head->attr = SXMSG_PULSE | SXMSG_LINK; + head->opcode = SNE_RAPIDMSG; + head->payload_length = datalen; + msg->payload = (void *)data; + + r = _sntll_writemsg(co, msg); + + free(msg); + + return r; } -/* the same but will be postponed */ -int sxmsg_pulse_pp(conn_t *co, const char *data, size_t datalen) +static inline int __sxmsg_reply(sxmsg_t *msg, const char *data, + size_t datalen, int pp) { - return SNE_FAILED; + chnl_t *ch; + conn_t *co; + sntllv2_head_t *head; + ppmsg_t *ppm; + int r, i; + pthread_t self = pthread_self(); + + /* a little bit of paranoid tests */ + if(!msg) return SNE_FAILED; + if(!(ch = msg->pch)) return SNE_FAILED; + if(!(co = ch->connection)) return SNE_FAILED; + + /* test for blocking */ + for(i = 0; i < 8; i++) + if(pthread_equal(self, co->thrd_poll[i])) return SNE_WOULDBLOCK; + + /* prepare it */ + head = &msg->mhead; + head->attr = 0; + head->attr |= SXMSG_REPLYREQ; + head->opcode = SNE_REPLYREQ; + head->payload_length = datalen; + msg->payload = (void *)data; + + if(!pp) { + r = _sntll_writemsg(co, msg); + if(r != SNE_SUCCESS) return r; + } else { + if(!(ppm = malloc(sizeof(ppmsg_t)))) return SNE_ENOMEM; + list_init_node(&ppm->node); + ppm->msg = msg; + + /* under locking here */ + pthread_mutex_lock(&co->write_pending_lock); + list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */ + pthread_mutex_unlock(&co->write_pending_lock); + } + + pthread_mutex_lock(&msg->wait); /* wait */ + + r = head->opcode; + + if((head->attr & SXMSG_CLOSED) && !head->payload_length) { /* dialog closed and no data exists */ + pthread_mutex_unlock(&msg->wait); /* we able to invalidate it */ + pthread_mutex_destroy(&msg->wait); + free(msg); + } + + return r; } int sxmsg_reply(sxmsg_t *msg, const char *data, size_t datalen) { - return SNE_FAILED; + return __sxmsg_reply(msg, data, datalen, 0); } int sxmsg_reply_pp(sxmsg_t *msg, const char *data, size_t datalen) { - return SNE_FAILED; + return __sxmsg_reply(msg, data, datalen, 1); } -int sxmsg_rreply(sxmsg_t *msg, const char *data, size_t datalen) +int sxmsg_rreply(sxmsg_t *msg, size_t datalen) { - return SNE_FAILED; -} + chnl_t *ch; + conn_t *co; + sntllv2_head_t *head; + int r; -int sxmsg_rreply_pp(sxmsg_t *msg, const char *data, size_t datalen) -{ - return SNE_FAILED; + /* a little bit of paranoid tests */ + if(!msg) return SNE_FAILED; + if(!(ch = msg->pch)) return SNE_FAILED; + if(!(co = ch->connection)) return SNE_FAILED; + + /* prepare it */ + head = &msg->mhead; + head->attr = 0; + head->attr |= SXMSG_CLOSED; + head->opcode = SNE_RAPIDMSG; + head->payload_length = datalen; + + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, head->msgid); + co->messages[head->msgid] = NULL; + pthread_mutex_unlock(&co->idx_msg_lock); + + r = _sntll_writemsg(co, msg); + + pthread_mutex_unlock(&msg->wait); /* we able to invalidate it */ + pthread_mutex_destroy(&msg->wait); + free(msg); + + return r; } static inline int __sxmsg_return(sxmsg_t *msg, int opcode, int pp) diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 35961d7..512d102 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -442,6 +442,7 @@ static void *__sntll_thread(void *b) char *bbuf = (char*)buf; sntllv2_head_t *mhead = (sntllv2_head_t *)buf; sxmsg_t *msg; + sexp_t *sx; chnl_t *channel; pthread_t self = pthread_self(); int dispatch = 0; @@ -540,6 +541,11 @@ static void *__sntll_thread(void *b) if(mhead->attr & SXMSG_CLOSED) goto __finish; /* close the link */ if(mhead->attr & SXMSG_PULSE) { /* it's a link pulse messages */ /* TODO: syncronization and so on */ + if(mhead->opcode == SNE_RAPIDMSG) { /* custom pulse */ + sx = parse_sexp(bbuf, mhead->payload_length); + if(sx && co->ssys->on_pulse) co->ssys->on_pulse(co, sx); + if(sx) destroy_sexp(sx); + } } } else { /* regular messages */ if((mhead->attr & SXMSG_OPEN) && (mhead->attr & SXMSG_REPLYREQ)) { /* dialog initiation */ @@ -567,6 +573,7 @@ static void *__sntll_thread(void *b) } else { /* set mutex and channel */ pthread_mutex_init(&msg->wait, NULL); + pthread_mutex_lock(&msg->wait); msg->pch = channel; /* copy header only */ memcpy(&msg->mhead, mhead, sizeof(sntllv2_head_t)); @@ -586,13 +593,15 @@ static void *__sntll_thread(void *b) msg = co->messages[mhead->msgid]; if(!msg) goto __inval_idx_nor; - if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ - pthread_mutex_lock(&co->idx_ch_lock); - idx_free(&co->idx_ch, mhead->msgid); - co->messages[mhead->msgid] = NULL; - pthread_mutex_unlock(&co->idx_ch_lock); + /* message dialog is closed - remove this right now */ + pthread_mutex_lock(&co->idx_ch_lock); + idx_free(&co->idx_ch, mhead->msgid); + co->messages[mhead->msgid] = NULL; + pthread_mutex_unlock(&co->idx_ch_lock); + if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ /* now just free it */ + pthread_mutex_unlock(&msg->wait); pthread_mutex_destroy(&msg->wait); free(msg); } else { @@ -602,7 +611,7 @@ static void *__sntll_thread(void *b) if(msg->payload) memcpy(msg->payload, bbuf, mhead->payload_length); else msg->mhead.opcode = SNE_ENOMEM; } - /* TODO: remove this message from list */ + pthread_mutex_unlock(&msg->wait); /* wake up thread waiting for */ } } else if((!(mhead->attr & SXMSG_CLOSED) && !(mhead->attr & SXMSG_OPEN)) && From ccdf306c66966782d12ece0f2c2f4f0eaf859532 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 04:38:05 +0300 Subject: [PATCH 23/56] added manual prototype; --- man/sxmsg_rreply.3SNTL | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 man/sxmsg_rreply.3SNTL diff --git a/man/sxmsg_rreply.3SNTL b/man/sxmsg_rreply.3SNTL new file mode 100644 index 0000000..deb84db --- /dev/null +++ b/man/sxmsg_rreply.3SNTL @@ -0,0 +1,16 @@ +.TH SXMSG_RREPLY 3SNTL "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.SH NAME +sxmsg_rreply \- Function used to send a rapid reply without confirmation +.SH SYNOPSIS +.B #include +.sp +.BI int sxmsg_rreply(sxmsg_t *msg, size_t datalen); +.br +.sp +.SH DESCRIPTION +.B sxmsg_rreply +Will reply rapidly to the message using already allocated buffer, which might be +retrieved via sxmsg_rapidbuf(). This function will write desired message as soon +as possible. It will not wait any write or delivery confirmation. + + From 1032f74ad2ea3f27e96a9de03f4f9045d9ed082f Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 04:57:39 +0300 Subject: [PATCH 24/56] minor addition; --- man/sxmsg_rreply.3SNTL | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/man/sxmsg_rreply.3SNTL b/man/sxmsg_rreply.3SNTL index deb84db..ad32902 100644 --- a/man/sxmsg_rreply.3SNTL +++ b/man/sxmsg_rreply.3SNTL @@ -12,5 +12,24 @@ sxmsg_rreply \- Function used to send a rapid reply without confirmation Will reply rapidly to the message using already allocated buffer, which might be retrieved via sxmsg_rapidbuf(). This function will write desired message as soon as possible. It will not wait any write or delivery confirmation. - - +.br +.SH RETURN VALUE +.B SNE_FAILED +returns if message has invalid index, channel or message pointer is NULL. +.br +.B SNE_ESSL +returns if write was failed i.e. connection link was broken, or SSL error occurs. +.br +.B SNE_SUCCESS +returns on success. +.br +.SH BUGS +Not known yet. +.SH EXAMPLE +.B Reply rapidly from the RPC function call. +.RS +.nf +.if t .ft CW +char *buf = sxmsg_rapidbuf(msg); +int ln = snprintf(buf, MAX_BBUFLEN, "(is-done)"); +return sxmsg_rreply(msg, str, ln); From e098b9ba8846066c6854818946f101a190363d6d Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 13:44:10 +0300 Subject: [PATCH 25/56] summies added; --- tests/lv2ftpc.c | 19 +++++++++++++++++++ tests/lv2ftpd.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/lv2ftpc.c create mode 100644 tests/lv2ftpd.c diff --git a/tests/lv2ftpc.c b/tests/lv2ftpc.c new file mode 100644 index 0000000..1edc43e --- /dev/null +++ b/tests/lv2ftpc.c @@ -0,0 +1,19 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#include + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/tests/lv2ftpd.c b/tests/lv2ftpd.c new file mode 100644 index 0000000..1edc43e --- /dev/null +++ b/tests/lv2ftpd.c @@ -0,0 +1,19 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + +#include + +int main(int argc, char **argv) +{ + return 0; +} From d10e0d257442dffbfb61e2daa25f384406215964 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Tue, 21 Jul 2015 14:01:20 +0300 Subject: [PATCH 26/56] proto added; --- tests/lv2ftp-proto.txt | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/lv2ftp-proto.txt diff --git a/tests/lv2ftp-proto.txt b/tests/lv2ftp-proto.txt new file mode 100644 index 0000000..191fa40 --- /dev/null +++ b/tests/lv2ftp-proto.txt @@ -0,0 +1,30 @@ +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 From 928c48f20caba6063db6bbc1a511e1f2f89294d8 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Wed, 22 Jul 2015 16:59:22 +0300 Subject: [PATCH 27/56] added clients; --- tests/lv2sc.c | 0 tests/lv2sd.c | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 tests/lv2sc.c create mode 100644 tests/lv2sd.c diff --git a/tests/lv2sc.c b/tests/lv2sc.c new file mode 100644 index 0000000..e69de29 diff --git a/tests/lv2sd.c b/tests/lv2sd.c new file mode 100644 index 0000000..7c50b51 --- /dev/null +++ b/tests/lv2sd.c @@ -0,0 +1,279 @@ +/* + * Secure Network Transport Layer Library v2 implementation. + * (sntllv2) it superseed all versions before due to the: + * - memory consumption + * - new features such as pulse emitting + * - performance optimization + * + * This is a proprietary software. See COPYING for further details. + * + * (c) Askele Group 2013-2015 + * + */ + + +#include +#define __USE_GNU +#include +#include +#include +#ifdef WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#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) +{ +// 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; + conn_sys_t *ssys = connections_create(); + 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 */ + if(ssys) { + fprintf(stderr, "Subsystem init failed: %d\n", opt); + return 2; + } + /* 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(ssys, __secure_check); + connections_subsystem_set_sslvalidator(ssys, __validate_sslpem); + /* set a callback, it's optional and doesn't required in server side apps */ + connections_subsystem_set_rpctlist_call(ssys, __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; + + int client = accept(srv, (struct sockaddr*)&addr, &len); /* accept connection as usual */ + co = connection_master_link(ssys, client, NULL); /* create connection, that's all */ + if(!co) { + fprintf(stderr, "Cannot create connetion (%d)\n", opt); + } + } + + return 0; +} From 960414e7a9a1d8a5a6addf0b740d77b2edbab20a Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 14:53:47 +0300 Subject: [PATCH 28/56] updated man; --- man/sxmsg_rreply.3SNTL | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/man/sxmsg_rreply.3SNTL b/man/sxmsg_rreply.3SNTL index ad32902..aebbc4f 100644 --- a/man/sxmsg_rreply.3SNTL +++ b/man/sxmsg_rreply.3SNTL @@ -4,16 +4,28 @@ sxmsg_rreply \- Function used to send a rapid reply without confirmation .SH SYNOPSIS .B #include .sp -.BI int sxmsg_rreply(sxmsg_t *msg, size_t datalen); +int sxmsg_rreply(sxmsg_t +.BI *msg +, size_t +.BI datalen +); .br .sp .SH DESCRIPTION .B sxmsg_rreply -Will reply rapidly to the message using already allocated buffer, which might be -retrieved via sxmsg_rapidbuf(). This function will write desired message as soon -as possible. It will not wait any write or delivery confirmation. +Will reply rapidly to the message using already allocated buffer, which must be +retrieved via +.B sxmsg_rapidbuf(). +This function will write desired message as soon +as possible. It will not wait any write or delivery confirmation. It will close +message dialog if message is valid. .br .SH RETURN VALUE +Upon successful completion, the function shall rapidly send a message reply and close +the message dialog returning +.B SNE_SUCCESS +Othrewise other error code will be returned. +.SH ERRORS .B SNE_FAILED returns if message has invalid index, channel or message pointer is NULL. .br @@ -33,3 +45,13 @@ Not known yet. char *buf = sxmsg_rapidbuf(msg); int ln = snprintf(buf, MAX_BBUFLEN, "(is-done)"); return sxmsg_rreply(msg, str, ln); +.SH APPLICATION USAGE +This function will be useful in RPC functions required to reply ASAP i.e. for getting some data. It RPC function takes a lot of time it's better to use other functions and postponed message processing. +.SH RATIONALE +Use for lightweight RPC functions, this method may be used only in RPC call i.e. within SNTL thread context. +.SH COPYRIGHT +This is a proprietary software. See COPYING for further details. +.br +(c) Askele Group 2013-2015 +.SH AUTHOR +Alexander Vdolainen (vdo@askele.com) From 6d553ffab89190e2b5149f3ae08707dca325e0c5 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 14:57:15 +0300 Subject: [PATCH 29/56] manual skel added; --- man/connections_create.3SNTL | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 man/connections_create.3SNTL diff --git a/man/connections_create.3SNTL b/man/connections_create.3SNTL new file mode 100644 index 0000000..e90c225 --- /dev/null +++ b/man/connections_create.3SNTL @@ -0,0 +1,59 @@ +.TH CONNECTIONS_CREATE 3SNTL "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.SH NAME +connections_create \- Allocate and initialize connections system +.br +connections_init \- Initialize connections system +.br +connections_destroy \- Destroy connections system +.br +connections_free \- Free all stuff allocated for connections system +.SH SYNOPSIS +.B #include +.sp +conn_sys_t *connections_create(void); + +int connections_init(conn_sys_t *ssys); + +int connections_destroy(conn_sys_t *ssys); + +int connections_free(conn_sys_t *ssys); + +.br +.sp +.SH DESCRIPTION +.br +.SH RETURN VALUE +Upon successful completion, the function shall rapidly send a message reply and close +the message dialog returning +.B SNE_SUCCESS +Othrewise other error code will be returned. +.SH ERRORS +.B SNE_FAILED +returns if message has invalid index, channel or message pointer is NULL. +.br +.B SNE_ESSL +returns if write was failed i.e. connection link was broken, or SSL error occurs. +.br +.B SNE_SUCCESS +returns on success. +.br +.SH BUGS +Not known yet. +.SH EXAMPLE +.B Reply rapidly from the RPC function call. +.RS +.nf +.if t .ft CW +char *buf = sxmsg_rapidbuf(msg); +int ln = snprintf(buf, MAX_BBUFLEN, "(is-done)"); +return sxmsg_rreply(msg, str, ln); +.SH APPLICATION USAGE +This function will be useful in RPC functions required to reply ASAP i.e. for getting some data. It RPC function takes a lot of time it's better to use other functions and postponed message processing. +.SH RATIONALE +Use for lightweight RPC functions, this method may be used only in RPC call i.e. within SNTL thread context. +.SH COPYRIGHT +This is a proprietary software. See COPYING for further details. +.br +(c) Askele Group 2013-2015 +.SH AUTHOR +Alexander Vdolainen (vdo@askele.com) From aa62df3885f59f937d49fbf5d71a397e4bf52582 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 14:57:30 +0300 Subject: [PATCH 30/56] forgotten function added; --- include/sntl/sntllv2.h | 3 +++ lib/connex.c | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index cf5ec77..38a6fd3 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -202,6 +202,9 @@ int connections_destroy(conn_sys_t *ssys); int connections_free(conn_sys_t *ssys); +int connections_setsslserts(conn_sys_t *ssys, const char *rootca, + const char *certpem, const char *certkey); + /* create links */ conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr); conn_t *connection_link(conn_sys_t *ssys, const char *host, diff --git a/lib/connex.c b/lib/connex.c index 4b52a10..20ce312 100644 --- a/lib/connex.c +++ b/lib/connex.c @@ -268,3 +268,24 @@ conn_sys_t *connections_create(void) return nsys; } + +int connections_setsslserts(conn_sys_t *ssys, const char *rootca, + const char *certpem, const char *certkey) +{ + int r = ENOMEM; + + if(!ssys) return EINVAL; + /* simply copying */ + if(!(ssys->rootca = strdup(rootca))) return ENOMEM; + if(!(ssys->certkey = strdup(certkey))) goto __fail; + if(!(ssys->certpem = strdup(certpem))) goto __fail; + + r = 0; + return 0; + __fail: + if(ssys->rootca) free(ssys->rootca); + if(ssys->certkey) free(ssys->certkey); + if(ssys->certpem) free(ssys->certpem); + + return r; +} From cf3d8ad72d6479a71cd416bf4612442bf0251e21 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 15:00:13 +0300 Subject: [PATCH 31/56] removed obsolete header related to the older branches; --- include/sntl/connection.h | 311 -------------------------------------- 1 file changed, 311 deletions(-) delete mode 100644 include/sntl/connection.h diff --git a/include/sntl/connection.h b/include/sntl/connection.h deleted file mode 100644 index f1b65f7..0000000 --- a/include/sntl/connection.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Secure Network Transport Layer Library v2 implementation. - * (sntllv2) it superseed all versions before due to the: - * - memory consumption - * - new features such as pulse emitting - * - performance optimization - * - * This is a proprietary software. See COPYING for further details. - * - * (c) Askele Group 2013-2015 - * - */ - -/* - * File: connection.h - * Author: vdo - * - * Created on September 24, 2014, 2:36 AM - */ - -#ifndef __ESXC_CONNECTION_H_ -#define __ESXC_CONNECTION_H_ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#define VERIFY_DEPTH 1 /* FIXME: */ - -#define MAX_CONNECTIONS 32768 -#define MAX_CHANNELS 4096 -#define MAX_RPC_LIST 2048 -#define MAX_MULTI 12 -#define MAX_PENDINGMSG 16384 -#define MAX_MSGINDEX ((MAX_PENDINGMSG) * (MAX_MULTI)) - -typedef struct __perm_context_type { - char *login; - char *passwd; - uint64_t certid; - struct in_addr *addr; - void *priv; -} perm_ctx_t; - -#define CXCONN_MASTER (1 << 1) -#define CXCONN_SLAVE (1 << 2) -#define CXCONN_ESTABL (1 << 3) -#define CXCONN_BROKEN (1 << 4) - -/* 8 byte header */ -typedef struct __sntllv2_head_type { - uint16_t msgid; - uint16_t payload_length; - uint8_t attr; - uint8_t opcode; - uint16_t reserve; -}__attribute__((packed)) sntllv2_head_t; - -struct __connections_subsys_type; -struct __channel_t; -struct __message_t; -/* - * älä jätä kommentteja omalla kielellä! yksinkertaisia englanti sijaan! - * i found somebody who write comments and messages in non-english, - * it's a fucking practice - forget it. - */ -typedef struct __connection_t { - /* General section */ - struct __connections_subsys_type *ssys; /* < connections subsystem */ - char *uuid; /** < uuid of the connection */ - /* Channels section */ - idx_allocator_t idx_ch; /** < index allocation for channels */ - pthread_mutex_t idx_ch_lock; /** < mutex for allocating and deallocating channels */ - volatile struct __channel_t **channels; /** < channels O(1) storage */ - /* RPC section */ - usrtc_t *rpc_list; /** < search tree of possible RPC typed lists */ - /* SSL related section */ - SSL_CTX *ctx; /** < SSL context */ - SSL *ssl; /** < SSL connection */ - int ssl_data_index; /** < SSL index for the custom data */ - pthread_mutex_t sslinout[2]; /** < SSL related locks for in and out */ - /* Security section */ - perm_ctx_t *pctx; /** < higher layer authentification context */ - /* Messages section */ - struct __message_t** volatile messages; /** < messages O(1) storage */ - idx_allocator_t idx_msg; - pthread_mutex_t idx_msg_lock; - list_head_t write_pending; /** < list of messages waiting for write */ - pthread_mutex_t write_pending_lock; - volatile uint8_t unused_messages; /** < unused message count */ - /* Other stuff */ - pthread_t thrd_poll[8]; - volatile uint8_t flags; /** < flags of the connection */ - usrtc_node_t csnode; /** < node to store the connection within list */ -} conn_t; - -struct __connection_rpc_list_type; -struct __message_t; - -#define ESXCHAN_PENDING (1 << 1) -#define ESXCHAN_CLOSURE (1 << 2) - -typedef struct __channel_t { - uint16_t cid; /** < ID of the channel */ - conn_t *connection; /** < pointer to the parent connection */ - struct __connection_rpc_list_type *rpc_list; /** < rpc functions list */ - int flags; /** < flags of the channel */ -} chnl_t; - -typedef struct __sexp_payload_t { - char *cstr; - sexp_t *sx; -} sxpayload_t; - -#define ESX_SYSMSG_SIZE 512 - -#define ESXMSG_SYS (1 << 1) -#define ESXMSG_USR (1 << 2) -#define ESXMSG_PENDING (1 << 3) -#define ESXMSG_NOWAY (1 << 4) -#define ESXMSG_TIMEDOUT (1 << 5) -#define ESXMSG_PULSE (1 << 6) /* obsolete flag */ -#define ESXMSG_NOWAIT (1 << 7) -#define ESXMSG_ISREPLY (1 << 8) -#define ESXMSG_CLOSURE (1 << 9) -#define ESXMSG_RMONRETR (1 << 10) -#define ESXMSG_KILLTHRD (1 << 11) -#define ESXMSG_ISRAPID (1 << 12) - -/** - * \brief Message used in sntl message passing - * - * This structure used to manage a message within a channel - * of the sntl structure stack. - */ -typedef struct __message_t { - chnl_t *pch; /** < channel of the message(if applicable) */ - pthread_mutex_t wait; /** < special wait mutex, used for pending list and sync */ - sntllv2_head_t mhead; - void *payload; /** < payload */ -} sxmsg_t; - -typedef struct __connection_rpc_entry_type { - char *name; - int (*rpcf)(void *, sexp_t *); - usrtc_node_t node; -} cx_rpc_t; - -typedef struct __connection_rpc_list_type { - usrtc_t *rpc_tree; /** < search tree for the rpc lookup */ - char *opt_version; /** < reserved for future implementations */ -} cx_rpc_list_t; - -/** - * \brief Connection subsystem structure. - * - * This structure used for management and control a set of a - * determined connections with the same RPC lists and the same - * mode (server, client). - * - */ -typedef struct __connections_subsys_type { - usrtc_t *connections; - pthread_rwlock_t rwlock; - char *rootca, *certpem, *certkey; /* path name to the certificates */ - cx_rpc_list_t *system_rpc; - /* special functions pointers */ - int (*validate_sslpem)(conn_t *); /** < this function used to validate SSL certificate while SSL handshake */ - int (*secure_check)(conn_t *); /** < this function authorize user to login, - * and also should check SSL cert and user, and already made sessions */ - usrtc_t* (*get_rpc_typed_list_tree)(conn_t *); /** < this function is used to set RPC list of the functions */ - int (*set_typed_list_callback)(conn_t *, int, char *); /** < this function is a callback - * during setting up a typed channel */ - void (*on_destroy)(conn_t *); /** < callback on connection destroy */ - void (*on_pulse)(conn_t *, sxmsg_t *); /** < callback on pulse emit */ - void *priv; -} conn_sys_t; - -typedef struct __rpc_typed_list_type { - int type_id; - char *description; - cx_rpc_list_t *rpc_list; - usrtc_node_t lnode; -} rpc_typed_list_t; - -/* General API */ -/* subsystem */ - -extern conn_sys_t *conn_sys; /* an old obsolete method */ -/* old API from 0.1.xx */ -#define connections_subsystem_init() { conn_sys = (conn_sys_t *)malloc(sizeof(conn_sys_t)); connections_init(conn_sys); } - -#define connections_subsystem_setsslserts(a, b, c) connections_setsslserts(conn_sys, a, b, c) - -#define connections_subsystem_setrpclist_function(a) connections_setrpclist_function(conn_sys, a) - -#define connections_set_priv(c, p) (c)->priv = (void *)p - -#define connections_get_priv(c) (c)->priv - -#ifdef __cplusplus -extern "C" { -#endif - - /** call this function before use sntl related functions */ -int sntl_init(void); - -/* new */ -int connections_init(conn_sys_t *ssys); - -int connections_setsslserts(conn_sys_t *ssys, const char *rootca, - const char *certpem, const char *certkey); - -int connections_setrpclist_function(conn_sys_t *ssys, - usrtc_t* (*get_rpc_typed_list_tree)(conn_t *)); - - -#ifdef __cplusplus -} -#endif - -#define connections_subsystem_set_securecheck(c, fuu) (c)->secure_check = fuu -#define connections_subsystem_set_sslvalidator(c, fuu) (c)->validate_sslpem = fuu -#define connections_subsystem_set_rpctlist_call(c, fuu) (c)->set_typed_list_callback = fuu -#define connections_subsystem_set_on_destroy(c, fuu) (c)->on_destroy = fuu - -/* connection - compatibility (old versions) macros */ -#define connection_create(c, s) connection_create_fapi((c), (s), NULL) -#define connection_initiate(c, h, p, s, p1) connection_initiate_m(conn_sys, c, h, p, s, p1) -#define connection_create_fapi(c, s, a) connection_create_fapi_m(conn_sys, c, s, a) -#ifdef __cplusplus -extern "C" { -#endif - -/* new */ -int connection_initiate_m(conn_sys_t *ssys, conn_t *co, const char *host, - int port, const char *SSL_cert, perm_ctx_t *pctx); - -int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck, - struct in_addr *addr); - -int connection_close(conn_t *co); - -/* channels */ -int channel_open(conn_t *co, chnl_t **ch, int type); - -int channel_close(chnl_t *chnl); - -/* message passing */ -int msg_send(chnl_t *ch, sexp_t *sx, sxmsg_t **msg); - -int msg_send_timed(chnl_t *ch, sexp_t *sx, sxmsg_t **msg, struct timespec *tio); - -int msg_return(sxmsg_t *msg, int opcode); - -int msg_reply(sxmsg_t *msg, sexp_t *sx); - -int msg_reply_timed(sxmsg_t *msg, sexp_t *sx, struct timespec *tio); - -/* reply with S expression without confirmation of delivery and applying */ -int msg_reply_rapid(sxmsg_t *msg, sexp_t *sx); - -/* this is required to clean the message in case if it's a rapid message */ -int msg_rapid_clean(sxmsg_t *msg); - -#ifdef __cplusplus -} -#endif - -/* additional functions */ -#define sntl_msg_get_secctx(m) (m)->pch->connection->pctx - -/* RPC List API */ -#define SNTL_FILTER_INC 0xa -#define SNTL_FILTER_EXC 0xb -#define SNTL_FILTER_END -1 - -#ifdef __cplusplus -extern "C" { -#endif - -int sntl_rpclist_init(usrtc_t *tree); - -int sntl_rpclist_add(usrtc_t *tree, int type, const char *description, - const char *version); - -int sntl_rpclist_add_function(usrtc_t *tree, int type, const char *fu_name, - int (*rpcf)(void *, sexp_t *)); - -int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter); - -#ifdef __cplusplus -} -#endif - -/* for DEBUG purposes */ -#define __DBGLINE fprintf(stderr, "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__) - -#endif /* __ESXC_CONNECTION_H_ */ - From da1fbf80ad75393cdbb980ba970bd0ace7ecab7b Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 15:25:16 +0300 Subject: [PATCH 32/56] Added tests build; --- Makefile.am | 8 +++++++- configure.ac | 12 +++++++++++- tests/Makefile.am | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/Makefile.am diff --git a/Makefile.am b/Makefile.am index 2c15d00..f281664 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,13 @@ else EXAMPLES = endif -SUBDIRS = include lib $(EXAMPLES) +if BUILD_TESTS +TESTS = tests +else +TESTS = +endif + +SUBDIRS = include lib $(EXAMPLES) $(TESTS) libsntldocdir = ${prefix}/doc/libsntl libsntldoc_DATA = \ diff --git a/configure.ac b/configure.ac index d03ab05..26d18e5 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,15 @@ AS_IF([test "x$enable_build_examples" = "xyes"], [ AM_CONDITIONAL(BUILD_EXAMPLES, test "x$enable_build_examples" = "xyes") +AC_ARG_ENABLE([build_tests], + AS_HELP_STRING([--enable-build-tests], [Enable build test programs])) + +AS_IF([test "x$enable_build_tests" = "xyes"], [ + AC_DEFINE([BUILD_TESTS], 1, [build test programs enabled]) +]) + +AM_CONDITIONAL(BUILD_TESTS, test "x$enable_build_tests" = "xyes") + dnl ************win32********* AC_ARG_ENABLE([win32], @@ -57,4 +66,5 @@ Makefile lib/libsntllv2.pc lib/Makefile include/Makefile -examples/Makefile]) +examples/Makefile +tests/Makefile]) diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..dfa9ce4 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,37 @@ +## 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/libsntllv2.la + +if !BUILD_WIN32 + +bin_PROGRAMS = lv2sd lv2sc + +lv2sd_SOURCES = lv2sd.c +lv2sd_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ + $(LIBUUID_LIBS) $(libsntl) + +lv2sc_SOURCES = lv2sc.c +lv2sc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ + $(LIBUUID_LIBS) $(libsntl) + +else BUILD_WIN32 + +bin_PROGRAMS = lv2sc + +lv2sc_SOURCES = lv2sc.c +lv2sc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ + $(LIBUUID_LIBS) $(libsntl) -lws2_32 + +endif BUILD_WIN32 + From 500550c6afa2462325bd33bda6366ba5a5241eb2 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 15:40:28 +0300 Subject: [PATCH 33/56] added forgotten limit; --- include/sntl/limits.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sntl/limits.h b/include/sntl/limits.h index 79c4630..f69a45b 100644 --- a/include/sntl/limits.h +++ b/include/sntl/limits.h @@ -16,4 +16,6 @@ #define MAX_RPC_LIST 512 +#define MAX_RBBUF_LEN (65536 - sizeof(sntllv2_head_t)) + #endif /* __SNTL_LIMITS_H__ */ From a430edc0d70eec85932bbe3fad532b669127e02a Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 15:41:00 +0300 Subject: [PATCH 34/56] daemon updated to use new sntllv2 library API; --- tests/lv2sd.c | 57 +++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/tests/lv2sd.c b/tests/lv2sd.c index 7c50b51..3175526 100644 --- a/tests/lv2sd.c +++ b/tests/lv2sd.c @@ -35,7 +35,8 @@ #include #include -#include +#include +#include #include // #include @@ -104,52 +105,58 @@ usrtc_t *__rettlist(conn_t *c) /* 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; - + char *buf; + int idx; + size_t ln = 0; + if(sexp_list_cdr(sx, &lsx)) { printf("Invalid protocol\n"); - return EINVAL; + return sxmsg_return(msg, SNE_BADPROTO); } - + 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; + fprintf(stderr, "Invalid value type\n"); + return sxmsg_return(msg, SNE_BADPROTO); } sum += atoi(sx_iter->val); } - rc = msg_return(msg, sum); - return rc; + + buf = sxmsg_rapidbuf(msg); + ln = snprintf(buf, MAX_RBBUF_LEN, "(add-result %ld)", sum); + + return sxmsg_rreply(msg, ln); } static int __ar_multiply(void *data, sexp_t *sx) { sexp_t *lsx = NULL; + sxmsg_t *msg = (sxmsg_t *)data; + char *buf; int idx; sexp_t *sx_iter; + size_t ln; + if(sexp_list_cdr(sx, &lsx)) { printf("Invalid protocol\n"); - return EINVAL; + return sxmsg_return(msg, SNE_BADPROTO); } - + 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; + return sxmsg_return(msg, SNE_BADPROTO); } mult *= atoi(sx_iter->val); } - char buf[128]; - sprintf(buf, "(ar_mult_set (%ld))", mult); - printf("result %s\n", buf); - - return 0; + buf = sxmsg_rapidbuf(msg); + ln = snprintf(buf, MAX_RBBUF_LEN, "(multiply-result %ld)", mult); + + return sxmsg_rreply(msg, ln); } /* define a little bit */ @@ -210,12 +217,12 @@ int main(int argc, char **argv) } /* all is fine let's init connection subsystem */ - if(ssys) { + if(!ssys) { fprintf(stderr, "Subsystem init failed: %d\n", opt); return 2; } /* set wroking certificates */ - opt = connections_subsystem_setsslserts(rootca, cert, cert); + opt = connections_setsslserts(ssys, rootca, cert, cert); if(opt) { fprintf(stderr, "Subsystem init failed (set SSL x.509 pems): %d\n", opt); return opt; @@ -226,10 +233,10 @@ int main(int argc, char **argv) free(cert); /* set important callbacks to do the security checking */ - connections_subsystem_set_securecheck(ssys, __secure_check); - connections_subsystem_set_sslvalidator(ssys, __validate_sslpem); + connections_set_authcheck(ssys, __secure_check); + connections_set_sslvalidate(ssys, __validate_sslpem); /* set a callback, it's optional and doesn't required in server side apps */ - connections_subsystem_set_rpctlist_call(ssys, __set_typed_list_callback); + connections_set_channelcall(ssys, __set_typed_list_callback); /* ok, now we need to construct RPC lists (channels) */ if(!(fulist = malloc(sizeof(usrtc_t)))) { @@ -259,7 +266,7 @@ int main(int argc, char **argv) if(opt) goto __fail; /* ok, setup it */ - connections_subsystem_setrpclist_function(__rettlist); + connections_set_rpcvalidator(ssys, __rettlist); /* now we're ready to run the listen process */ int srv = __openlistener(port); From 62287773c9fa0b68d6fb3c6a389119c0bc21aa22 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 15:52:24 +0300 Subject: [PATCH 35/56] updated gitignore, client code added; --- .gitignore | 2 + tests/lv2sc.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/.gitignore b/.gitignore index e7be69f..1c67f6c 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ coq *.log *.crt lib/libsntllv2.pc +lv2sd +lv2sc diff --git a/tests/lv2sc.c b/tests/lv2sc.c index e69de29..56b14a5 100644 --- a/tests/lv2sc.c +++ b/tests/lv2sc.c @@ -0,0 +1,129 @@ +#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 a little bit */ +#define DEFAULT_PORT 13133 +#define CHANNEL_COUNT 200 +#define CLIENT_COUNT 100 +#define MESSAGES_PER_SESSION 10000 +#define ITERATION_COUNT 1000 + +#define FAILS_ONLY + +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; + } + + /* 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 */ + /* try to open connection */ + connections_set_channelcall(ssys, NULL); + + co = connection_link(ssys, addr, port, cert, login, password); + + if(!co) { + fprintf(stderr, "Failed to connection with %d\n", errno); + return errno; + } + + return 0; +} From c4d53c6f228f62cdcc30eb18b938761e0d8c1813 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 16:11:32 +0300 Subject: [PATCH 36/56] fix; --- tests/lv2sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lv2sd.c b/tests/lv2sd.c index 3175526..e3f9cca 100644 --- a/tests/lv2sd.c +++ b/tests/lv2sd.c @@ -182,7 +182,6 @@ int main(int argc, char **argv) // memset(&sigpipe, 0, sizeof(struct sigaction)); // sigpipe.sa_handler = sigpipe_handler; // sigaction(SIGPIPE, &sigpipe, NULL); - char *rootca = NULL, *cert = NULL; conn_sys_t *ssys = connections_create(); int port = DEFAULT_PORT; @@ -216,6 +215,7 @@ int main(int argc, char **argv) return EINVAL; } + sntllv2_init(); /* all is fine let's init connection subsystem */ if(!ssys) { fprintf(stderr, "Subsystem init failed: %d\n", opt); From 438633a911b22478f0d0175c06ad4cb157d05a81 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 17:49:17 +0300 Subject: [PATCH 37/56] fixes; --- include/sntl/sntllv2.h | 2 ++ lib/connex.c | 4 ++-- lib/sntllv2.c | 15 ++++++++++++--- tests/lv2sc.c | 1 + tests/lv2sd.c | 4 ++-- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index 38a6fd3..508bd05 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -259,6 +259,8 @@ int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter); } #endif +#define blub(txt) fprintf(stderr, "%s:%d in %s > %s\n", __FILE__, __LINE__, __FUNCTION__, txt) + #endif /* __SNTL_SNTLLV2_H__ */ diff --git a/lib/connex.c b/lib/connex.c index 20ce312..870da90 100644 --- a/lib/connex.c +++ b/lib/connex.c @@ -130,8 +130,7 @@ static int __get_channels_list(void *cctx, sexp_t *sx) if(ssys->get_rpc_typed_list_tree) co->rpc_list = ssys->get_rpc_typed_list_tree(co); if(!co->rpc_list) return SNE_EPERM; - - buf += sizeof(sntllv2_head_t); + //buf += sizeof(sntllv2_head_t); ulen += snprintf(buf + ulen, maxlen - ulen, "(set-channels-list "); for(node = usrtc_first(co->rpc_list); node != NULL; node = usrtc_next(co->rpc_list, node)) { /* fill the list */ @@ -183,6 +182,7 @@ static int __set_channels_list(void *cctx, sexp_t *sx) /* we're ready for messaging mode */ co->flags |= SNSX_MESSAGINGMODE; + co->flags &= ~SNSX_BATCHMODE; return SNE_SUCCESS; } diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 512d102..42fa773 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -752,7 +752,10 @@ conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr) if(head->opcode != SNE_SUCCESS) { r = head->opcode; goto __fail3; } else { /* opcode is fine */ /* if we're ready for messaging mode, turn off batch mode */ - if(co->flags & SNSX_MESSAGINGMODE) co->flags &= ~SNSX_BATCHMODE; + if(co->flags & SNSX_MESSAGINGMODE) { + co->flags &= ~SNSX_BATCHMODE; + break; + } } if(!head->payload_length) continue; /* pass the following check up */ @@ -768,6 +771,7 @@ conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr) msg->mhead.payload_length = 0; /* deal with it */ r = __eval_syssexp(co, sx); + memcpy(head, &msg->mhead, sizeof(sntllv2_head_t)); head->opcode = r; if(r != SNE_SUCCESS) { /* we finish */ head->payload_length = 0; @@ -956,6 +960,7 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, /* form a message -- credentials */ ln = snprintf(bbuf, 65535 - sizeof(sntllv2_head_t), "(auth-set-credentials \"%s\" \"%s\")", login ? login : "nil", passwd ? passwd : "nil"); + head->opcode = SNE_SUCCESS; head->payload_length = ln; wr = __conn_write(co, buf, ln + sizeof(sntllv2_head_t)); @@ -963,12 +968,15 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, rd = __conn_read(co, head, sizeof(sntllv2_head_t)); if(rd < 0) goto __fail2; - if(head->opcode != SNE_SUCCESS) goto __fail2; + if(head->opcode != SNE_SUCCESS) { + r = head->opcode; + goto __fail2; + } /* ok, get available channels */ head->opcode = SNE_SUCCESS; - head->payload_length = ln; ln = snprintf(bbuf, 65535 - sizeof(sntllv2_head_t), "(get-channels-list)"); + head->payload_length = ln; wr = __conn_write(co, buf, ln + sizeof(sntllv2_head_t)); if(wr < 0) goto __fail2; @@ -982,6 +990,7 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, /* perform a parsing of the desired message */ bbuf[rd] = '\0'; sx = parse_sexp(bbuf, rd); + if(!sx) { r = SNE_BADPROTO; goto __fail2; } r = __eval_syssexp(co, sx); destroy_sexp(sx); head->opcode = r; diff --git a/tests/lv2sc.c b/tests/lv2sc.c index 56b14a5..4e81fe1 100644 --- a/tests/lv2sc.c +++ b/tests/lv2sc.c @@ -101,6 +101,7 @@ int main(int argc, char **argv) return EINVAL; } + sntl_init(); /* all is fine let's init connection subsystem */ ssys = connections_create(); if(!ssys) { diff --git a/tests/lv2sd.c b/tests/lv2sd.c index e3f9cca..e20c845 100644 --- a/tests/lv2sd.c +++ b/tests/lv2sd.c @@ -81,7 +81,7 @@ static int __validate_sslpem(conn_t *co) */ static int __secure_check(conn_t *co) { - return 0; + return SNE_SUCCESS; } /* @@ -215,7 +215,7 @@ int main(int argc, char **argv) return EINVAL; } - sntllv2_init(); + sntl_init(); /* all is fine let's init connection subsystem */ if(!ssys) { fprintf(stderr, "Subsystem init failed: %d\n", opt); From e68b7290b82931a6103dbdc050b919957930094b Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Thu, 23 Jul 2015 23:50:22 +0300 Subject: [PATCH 38/56] bugs fixed; --- include/sntl/sntllv2.h | 3 + lib/chansx.c | 24 ++++--- lib/messagesx.c | 6 ++ lib/sntllv2.c | 57 ++++++++++----- tests/lv2sc.c | 154 ++++++++++++++++++++++++++++++++++++++++- tests/lv2sd.c | 2 +- 6 files changed, 218 insertions(+), 28 deletions(-) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index 508bd05..4cfa653 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -231,6 +231,7 @@ int sxmsg_reply_pp(sxmsg_t *msg, const char *data, size_t datalen); int sxmsg_rreply(sxmsg_t *msg, size_t datalen); int sxmsg_return(sxmsg_t *msg, int opcode); int sxmsg_return_pp(sxmsg_t *msg, int opcode); +void sxmsg_clean(sxmsg_t *msg); #ifdef __cplusplus } @@ -261,6 +262,8 @@ int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter); #define blub(txt) fprintf(stderr, "%s:%d in %s > %s\n", __FILE__, __LINE__, __FUNCTION__, txt) +#define dumphead(head) fprintf(stderr, "id: %d, opcode: %d, attr: %d, len = %d\n", head->msgid, head->opcode, head->attr, head->payload_length) + #endif /* __SNTL_SNTLLV2_H__ */ diff --git a/lib/chansx.c b/lib/chansx.c index cc2df7e..f0e9fdb 100644 --- a/lib/chansx.c +++ b/lib/chansx.c @@ -46,14 +46,14 @@ uint8_t _channel_open(conn_t *co, uint16_t *chid) { chnl_t *chan; - uint16_t typeid = *chid; /* our type */ + int typeid = *chid; /* our type */ uint16_t chidx; usrtc_t *rpc_list = co->rpc_list; usrtc_node_t *node; rpc_typed_list_t *rlist; cx_rpc_list_t *rpclist; - node = usrtc_lookup(rpc_list, (void *)&typeid); + node = usrtc_lookup(rpc_list, &typeid); if(!node) return SNE_EPERM; else rlist = (rpc_typed_list_t *)usrtc_node_getdata(node); @@ -87,6 +87,7 @@ uint8_t _channel_open(conn_t *co, uint16_t *chid) uint8_t _channel_close(conn_t *co, uint16_t chid) { chnl_t *chan; + ulong_t chidx = chid; if(chid > 512) return SNE_INVALINDEX; else chan = co->channels[chid]; @@ -94,8 +95,8 @@ uint8_t _channel_close(conn_t *co, uint16_t chid) if(!chan) return SNE_NOSUCHCHAN; pthread_mutex_lock(&co->idx_ch_lock); - idx_free(&co->idx_ch, chid); - co->channels[chid] = NULL; + idx_free(&co->idx_ch, chidx); + co->channels[chidx] = NULL; pthread_mutex_unlock(&co->idx_ch_lock); free(chan); @@ -117,6 +118,7 @@ chnl_t *sxchannel_open(conn_t *co, int type) if(!(chan = malloc(sizeof(chnl_t)))) { __enomem: + if(chan) free(chan); r = SNE_ENOMEM; goto __reterr; } @@ -146,6 +148,7 @@ chnl_t *sxchannel_open(conn_t *co, int type) pthread_mutex_unlock(&co->idx_msg_lock); if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; } + else head->msgid = msgidx; /* now we're ready to write it */ r = _sntll_writemsg(co, msg); @@ -156,13 +159,15 @@ chnl_t *sxchannel_open(conn_t *co, int type) if(msg->mhead.opcode != SNE_SUCCESS) { r = msg->mhead.opcode; goto __reterr3; } /* ok all is fine */ + msgidx = msg->mhead.reserve; chan->cid = msg->mhead.reserve; pthread_mutex_lock(&co->idx_ch_lock); - idx_reserve(&co->idx_ch, msg->mhead.reserve); - co->channels[msg->mhead.reserve] = chan; + idx_reserve(&co->idx_ch, msgidx); + co->channels[msgidx] = chan; pthread_mutex_unlock(&co->idx_ch_lock); /* destroy a message */ + msgidx = head->msgid; pthread_mutex_lock(&co->idx_msg_lock); idx_free(&co->idx_msg, msgidx); co->messages[msgidx] = NULL; @@ -196,7 +201,7 @@ int sxchannel_close(chnl_t *channel) sxmsg_t *msg; sntllv2_head_t *head; conn_t *co; - int msgidx; + int msgidx, chidx; /* check channel validity */ if(!channel) return SNE_FAILED; @@ -231,9 +236,10 @@ int sxchannel_close(chnl_t *channel) r = head->opcode; /* we will free this anyway */ + chidx = channel->cid; pthread_mutex_lock(&co->idx_ch_lock); - idx_free(&co->idx_ch, channel->cid); - co->channels[channel->cid] = NULL; + idx_free(&co->idx_ch, chidx); + co->channels[chidx] = NULL; pthread_mutex_unlock(&co->idx_ch_lock); free(channel); } diff --git a/lib/messagesx.c b/lib/messagesx.c index 213af6b..03ba12c 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -325,3 +325,9 @@ int sxmsg_return_pp(sxmsg_t *msg, int opcode) return __sxmsg_return(msg, opcode, 1); } +void sxmsg_clean(sxmsg_t *msg) +{ + free(msg->payload); + free(msg); + return; +} diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 42fa773..68113df 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -203,7 +203,7 @@ int _sntll_writemsg(conn_t *co, sxmsg_t *msg) if(head->payload_length && !msg->payload) return SNE_FAILED; /* write the head and payload if applicable */ - pthread_mutex_lock(&co->sslinout[2]); + pthread_mutex_lock(&co->sslinout[1]); rd = __conn_write(co, head, sizeof(sntllv2_head_t)); if(rd < 0) { co->flags |= SNSX_CLOSED; @@ -213,7 +213,7 @@ int _sntll_writemsg(conn_t *co, sxmsg_t *msg) /* check up again */ if(rd < 0) { co->flags |= SNSX_CLOSED; r = SNE_ESSL; } } - pthread_mutex_unlock(&co->sslinout[2]); + pthread_mutex_unlock(&co->sslinout[1]); if(!(co->flags & SNSX_CLOSED)) r = SNE_SUCCESS; @@ -359,6 +359,8 @@ static int __connection_second_alloc(conn_t *co) { usrtc_node_init(&co->csnode, co); + memset(&co->idx_ch, 0, sizeof(idx_allocator_t)); + memset(&co->idx_msg, 0, sizeof(idx_allocator_t)); if((idx_allocator_init(&co->idx_ch, 512, 0))) goto __fail; if((idx_allocator_init(&co->idx_msg, 1024, 0))) goto __fail; @@ -447,6 +449,7 @@ static void *__sntll_thread(void *b) pthread_t self = pthread_self(); int dispatch = 0; size_t rd, wr; + ulong_t mid; /* byte buffer is following head */ bbuf += sizeof(sntllv2_head_t); @@ -472,8 +475,15 @@ static void *__sntll_thread(void *b) while(1) { __again: pthread_mutex_lock(&(co->sslinout[0])); + if(co->flags & SNSX_CLOSED) { + pthread_mutex_unlock(&(co->sslinout[0])); + goto __finish; + } rd = __conn_read(co, mhead, sizeof(sntllv2_head_t)); - if(rd != sizeof(sntllv2_bundle_t)) { +#ifdef _VERBOSE_DEBUG + dumphead(mhead); +#endif + if(rd != sizeof(sntllv2_head_t)) { __sslproto_error: co->flags |= SNSX_CLOSED; pthread_mutex_unlock(&(co->sslinout[0])); @@ -530,7 +540,8 @@ static void *__sntll_thread(void *b) fprintf(stderr, "[sntllv2] Invalid index of the message.\n"); goto __again; } - msg = co->messages[mhead->msgid]; + mid = mhead->msgid; + msg = co->messages[mid]; if(!msg) goto __inval_idx_nor; /* ok now we'are copy data and unlock wait mutex */ @@ -580,10 +591,11 @@ static void *__sntll_thread(void *b) if(mhead->payload_length) msg->payload = bbuf; } - pthread_mutex_lock(&co->idx_ch_lock); - idx_reserve(&co->idx_ch, mhead->msgid); + mid = mhead->msgid; + pthread_mutex_lock(&co->idx_msg_lock); + idx_reserve(&co->idx_msg, mid); co->messages[mhead->msgid] = msg; - pthread_mutex_unlock(&co->idx_ch_lock); + pthread_mutex_unlock(&co->idx_msg_lock); /* now we are able to process the message */ _message_process(msg); @@ -594,10 +606,10 @@ static void *__sntll_thread(void *b) if(!msg) goto __inval_idx_nor; /* message dialog is closed - remove this right now */ - pthread_mutex_lock(&co->idx_ch_lock); - idx_free(&co->idx_ch, mhead->msgid); + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, mhead->msgid); co->messages[mhead->msgid] = NULL; - pthread_mutex_unlock(&co->idx_ch_lock); + pthread_mutex_unlock(&co->idx_msg_lock); if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ /* now just free it */ @@ -622,10 +634,10 @@ static void *__sntll_thread(void *b) if(!msg) goto __inval_idx_nor; if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ - pthread_mutex_lock(&co->idx_ch_lock); - idx_free(&co->idx_ch, mhead->msgid); + pthread_mutex_lock(&co->idx_msg_lock); + idx_free(&co->idx_msg, mhead->msgid); co->messages[mhead->msgid] = NULL; - pthread_mutex_unlock(&co->idx_ch_lock); + pthread_mutex_unlock(&co->idx_msg_lock); /* now just free it */ pthread_mutex_destroy(&msg->wait); @@ -775,7 +787,7 @@ conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr) head->opcode = r; if(r != SNE_SUCCESS) { /* we finish */ head->payload_length = 0; - __conn_write(co, buf, sizeof(sntllv2_head_t)); + __conn_write(co, head, sizeof(sntllv2_head_t)); destroy_sexp(sx); goto __fail3; } @@ -793,6 +805,10 @@ conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr) r = __connection_second_alloc(co); if(r != SNE_SUCCESS) goto __fail3; + /* free message */ + co->messages[0] = NULL; + free(msg); + /* and now we're need to create a thread poll */ if(!(bundle = malloc(sizeof(sntllv2_bundle_t)))) { r = SNE_ENOMEM; goto __fail4; } else { @@ -992,18 +1008,27 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, sx = parse_sexp(bbuf, rd); if(!sx) { r = SNE_BADPROTO; goto __fail2; } r = __eval_syssexp(co, sx); + if(!r) r = SNE_SUCCESS; destroy_sexp(sx); + + /* write back */ head->opcode = r; head->payload_length = 0; wr = __conn_write(co, head, sizeof(sntllv2_head_t)); - if(wr < 0) goto __fail2; - if(r != SNE_SUCCESS) goto __fail2; + if(wr < 0) { + blub("fuck"); + r = SNE_LINKERROR; goto __fail2;} + if(r != SNE_SUCCESS) { r = SNE_LINKERROR; goto __fail2;} } /* if we're there - negotiation is done, going to init messaging mode */ r = __connection_second_alloc(co); if(r != SNE_SUCCESS) goto __fail3; + /* free message */ + co->messages[0] = NULL; + free(msg); + /* and now we're need to create a thread poll */ if(!(bundle = malloc(sizeof(sntllv2_bundle_t)))) { r = SNE_ENOMEM; goto __fail4; } else { diff --git a/tests/lv2sc.c b/tests/lv2sc.c index 4e81fe1..81565a9 100644 --- a/tests/lv2sc.c +++ b/tests/lv2sc.c @@ -34,12 +34,95 @@ /* define a little bit */ #define DEFAULT_PORT 13133 #define CHANNEL_COUNT 200 -#define CLIENT_COUNT 100 +#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", + 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 main(int argc, char **argv) { char *rootca = NULL, *cert = NULL; @@ -116,15 +199,82 @@ int main(int argc, char **argv) } /* Tests */ + struct timeval beg, end; /* try to open connection */ - connections_set_channelcall(ssys, NULL); + 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]; + sxmsg_t *msg; + size_t ln; + ln = snprintf(mmbuf, 1024, "(ar-add (10 10))"); + int mr = sxmsg_send(testchannel, 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", + 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; + } + + int 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); return 0; } + diff --git a/tests/lv2sd.c b/tests/lv2sd.c index e20c845..591e2ec 100644 --- a/tests/lv2sd.c +++ b/tests/lv2sd.c @@ -90,7 +90,7 @@ static int __secure_check(conn_t *co) static int __set_typed_list_callback(conn_t *co, int ch, char *desc) { printf("allowed channel %d (%s)\n", ch, desc); - return 0; + return SNE_SUCCESS; } /* list of rpc calls functions */ From 06dec797d44cad3017b493ac27eca9e1c528357c Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 24 Jul 2015 13:41:16 +0300 Subject: [PATCH 39/56] destroysexp on behalf on the sntl now; --- lib/messagesx.c | 4 +++- tests/lv2sd.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/messagesx.c b/lib/messagesx.c index 03ba12c..c49155e 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -50,7 +50,9 @@ void _message_process(sxmsg_t *msg) if(!node) { r = SNE_ENORPC; goto __return_err; } else rpcc = (cx_rpc_t *)usrtc_node_getdata(node); - rpcc->rpcf((void *)msg, sx); /* sx *MUST* be destroy asap */ + rpcc->rpcf((void *)msg, sx); + + destroy_sexp(sx); return; diff --git a/tests/lv2sd.c b/tests/lv2sd.c index 591e2ec..6fd8809 100644 --- a/tests/lv2sd.c +++ b/tests/lv2sd.c @@ -153,6 +153,7 @@ static int __ar_multiply(void *data, sexp_t *sx) } mult *= atoi(sx_iter->val); } + buf = sxmsg_rapidbuf(msg); ln = snprintf(buf, MAX_RBBUF_LEN, "(multiply-result %ld)", mult); From eba6c0b9fbd7d8f1ce36515510148917aa7995db Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 24 Jul 2015 18:34:24 +0300 Subject: [PATCH 40/56] fixed bugs with message handling on heavyloaded connection; --- lib/chansx.c | 18 +++++++++--------- lib/messagesx.c | 18 ++++++++++-------- lib/sntllv2.c | 34 ++++++++++++++++++++++------------ tests/lv2sc.c | 2 +- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/lib/chansx.c b/lib/chansx.c index f0e9fdb..7ffac6f 100644 --- a/lib/chansx.c +++ b/lib/chansx.c @@ -90,7 +90,7 @@ uint8_t _channel_close(conn_t *co, uint16_t chid) ulong_t chidx = chid; if(chid > 512) return SNE_INVALINDEX; - else chan = co->channels[chid]; + else chan = co->channels[chidx]; if(!chan) return SNE_NOSUCHCHAN; @@ -109,7 +109,7 @@ chnl_t *sxchannel_open(conn_t *co, int type) chnl_t *chan = NULL; sxmsg_t *msg = NULL; sntllv2_head_t *head; - int msgidx, r; + int msgidx, r, ccid; if(!co) { r = SNE_FAILED; @@ -159,15 +159,14 @@ chnl_t *sxchannel_open(conn_t *co, int type) if(msg->mhead.opcode != SNE_SUCCESS) { r = msg->mhead.opcode; goto __reterr3; } /* ok all is fine */ - msgidx = msg->mhead.reserve; chan->cid = msg->mhead.reserve; + ccid = chan->cid; pthread_mutex_lock(&co->idx_ch_lock); - idx_reserve(&co->idx_ch, msgidx); - co->channels[msgidx] = chan; + idx_reserve(&co->idx_ch, ccid); + co->channels[ccid] = chan; pthread_mutex_unlock(&co->idx_ch_lock); /* destroy a message */ - msgidx = head->msgid; pthread_mutex_lock(&co->idx_msg_lock); idx_free(&co->idx_msg, msgidx); co->messages[msgidx] = NULL; @@ -201,13 +200,14 @@ int sxchannel_close(chnl_t *channel) sxmsg_t *msg; sntllv2_head_t *head; conn_t *co; - int msgidx, chidx; + int msgidx = 0, chidx = 0; /* check channel validity */ if(!channel) return SNE_FAILED; else if(!(co = channel->connection)) return SNE_FAILED; if(channel->cid > 512) return SNE_IGNORED; - if(channel != co->channels[channel->cid]) return SNE_IGNORED; + else chidx = channel->cid; + if(channel != co->channels[chidx]) return SNE_IGNORED; if(!(msg = malloc(sizeof(sxmsg_t)))) return SNE_ENOMEM; head = &msg->mhead; @@ -229,6 +229,7 @@ int sxchannel_close(chnl_t *channel) pthread_mutex_unlock(&co->idx_msg_lock); if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; } + else head->msgid = msgidx; r = _sntll_writemsg(co, msg); if(r == SNE_SUCCESS) { @@ -236,7 +237,6 @@ int sxchannel_close(chnl_t *channel) r = head->opcode; /* we will free this anyway */ - chidx = channel->cid; pthread_mutex_lock(&co->idx_ch_lock); idx_free(&co->idx_ch, chidx); co->channels[chidx] = NULL; diff --git a/lib/messagesx.c b/lib/messagesx.c index c49155e..c63d83d 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -239,7 +239,7 @@ int sxmsg_rreply(sxmsg_t *msg, size_t datalen) chnl_t *ch; conn_t *co; sntllv2_head_t *head; - int r; + int r, mid; /* a little bit of paranoid tests */ if(!msg) return SNE_FAILED; @@ -253,9 +253,10 @@ int sxmsg_rreply(sxmsg_t *msg, size_t datalen) head->opcode = SNE_RAPIDMSG; head->payload_length = datalen; + mid = head->msgid; pthread_mutex_lock(&co->idx_msg_lock); - idx_free(&co->idx_msg, head->msgid); - co->messages[head->msgid] = NULL; + idx_free(&co->idx_msg, mid); + co->messages[mid] = NULL; pthread_mutex_unlock(&co->idx_msg_lock); r = _sntll_writemsg(co, msg); @@ -273,7 +274,7 @@ static inline int __sxmsg_return(sxmsg_t *msg, int opcode, int pp) conn_t *co; sntllv2_head_t *head; ppmsg_t *ppm; - int r; + int r, mid; /* a little bit of paranoid tests */ if(!msg) return SNE_FAILED; @@ -285,12 +286,13 @@ static inline int __sxmsg_return(sxmsg_t *msg, int opcode, int pp) head->attr |= SXMSG_CLOSED; head->opcode = opcode; head->payload_length = 0; + mid = head->msgid; if(!pp) { /* free index */ pthread_mutex_lock(&co->idx_msg_lock); - idx_free(&co->idx_msg, head->msgid); - co->messages[head->msgid] = NULL; + idx_free(&co->idx_msg, mid); + co->messages[mid] = NULL; pthread_mutex_unlock(&co->idx_msg_lock); r = _sntll_writemsg(co, msg); @@ -298,8 +300,8 @@ static inline int __sxmsg_return(sxmsg_t *msg, int opcode, int pp) if(!(ppm = malloc(sizeof(ppmsg_t)))) return SNE_ENOMEM; else { /* remove it */ pthread_mutex_lock(&co->idx_msg_lock); - idx_free(&co->idx_msg, head->msgid); - co->messages[head->msgid] = NULL; + idx_free(&co->idx_msg, mid); + co->messages[mid] = NULL; pthread_mutex_unlock(&co->idx_msg_lock); } diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 68113df..c033ea3 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -495,11 +495,16 @@ static void *__sntll_thread(void *b) if(rd < 0) goto __sslproto_error; else pthread_mutex_unlock(&(co->sslinout[0])); if(rd != mhead->payload_length) { + mid = mhead->msgid; /* if we're need to do something */ if(mhead->msgid >= 1024) { mhead->opcode = SNE_INVALINDEX; goto __return_error; - } else msg = co->messages[mhead->msgid]; + } else { + pthread_mutex_lock(&co->idx_msg_lock); + msg = co->messages[mid]; + pthread_mutex_unlock(&co->idx_msg_lock); + } if(!msg) { if(mhead->attr & SXMSG_OPEN) mhead->opcode = SNE_BADPROTO; else { @@ -541,7 +546,9 @@ static void *__sntll_thread(void *b) goto __again; } mid = mhead->msgid; + pthread_mutex_lock(&co->idx_msg_lock); msg = co->messages[mid]; + pthread_mutex_unlock(&co->idx_msg_lock); if(!msg) goto __inval_idx_nor; /* ok now we'are copy data and unlock wait mutex */ @@ -575,7 +582,8 @@ static void *__sntll_thread(void *b) else goto __again; } /* if message is busy - fails */ - msg = co->messages[mhead->msgid]; + mid = mhead->msgid; + msg = co->messages[mid]; if(msg) { mhead->opcode = SNE_EBUSY; goto __ret_regerr; } /* now we will take a deal */ @@ -591,10 +599,9 @@ static void *__sntll_thread(void *b) if(mhead->payload_length) msg->payload = bbuf; } - mid = mhead->msgid; pthread_mutex_lock(&co->idx_msg_lock); idx_reserve(&co->idx_msg, mid); - co->messages[mhead->msgid] = msg; + co->messages[mid] = msg; pthread_mutex_unlock(&co->idx_msg_lock); /* now we are able to process the message */ @@ -602,13 +609,15 @@ static void *__sntll_thread(void *b) } else if(mhead->attr & SXMSG_CLOSED) { /* check for the message */ if(mhead->msgid >= 1024) goto __inval_idx_nor; - msg = co->messages[mhead->msgid]; - if(!msg) goto __inval_idx_nor; + mid = mhead->msgid; + pthread_mutex_lock(&co->idx_msg_lock); + msg = co->messages[mid]; + if(!msg) { + pthread_mutex_unlock(&co->idx_msg_lock); goto __inval_idx_nor; } /* message dialog is closed - remove this right now */ - pthread_mutex_lock(&co->idx_msg_lock); - idx_free(&co->idx_msg, mhead->msgid); - co->messages[mhead->msgid] = NULL; + idx_free(&co->idx_msg, mid); + co->messages[mid] = NULL; pthread_mutex_unlock(&co->idx_msg_lock); if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ @@ -630,13 +639,14 @@ static void *__sntll_thread(void *b) (mhead->attr & SXMSG_REPLYREQ)) { /* ongoing dialog */ /* check for the message */ if(mhead->msgid >= 1024) goto __inval_idx_nor; - msg = co->messages[mhead->msgid]; + mid = mhead->msgid; + msg = co->messages[mid]; if(!msg) goto __inval_idx_nor; if(msg->mhead.attr & SXMSG_TIMEDOUT) { /* nobody wait for it */ pthread_mutex_lock(&co->idx_msg_lock); - idx_free(&co->idx_msg, mhead->msgid); - co->messages[mhead->msgid] = NULL; + idx_free(&co->idx_msg, mid); + co->messages[mid] = NULL; pthread_mutex_unlock(&co->idx_msg_lock); /* now just free it */ diff --git a/tests/lv2sc.c b/tests/lv2sc.c index 81565a9..b2e11b9 100644 --- a/tests/lv2sc.c +++ b/tests/lv2sc.c @@ -96,7 +96,7 @@ static void *__addsthrd(void *a) mr = sxmsg_send(mch, mmbuf, ln, &msg); switch(mr) { case SNE_RAPIDMSG: - fprintf(stdout, "Rapidly replied: %s\n", (char *)sxmsg_payload(msg)); + //fprintf(stdout, "Rapidly replied: %s\n", (char *)sxmsg_payload(msg)); sxmsg_clean(msg); break; case SNE_REPLYREQ: From dc6a9781cd5576138f60e8fa1d981100a36885bd Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 24 Jul 2015 20:58:42 +0300 Subject: [PATCH 41/56] destroy of the connection added; --- include/sntl/sntllv2.h | 1 + lib/sntllv2.c | 61 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index 4cfa653..d8c2494 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -90,6 +90,7 @@ typedef struct __connection_t { /* Other stuff */ pthread_t thrd_poll[8]; volatile uint8_t flags; /** < flags of the connection */ + volatile uint8_t usecount; usrtc_node_t csnode; /** < node to store the connection within list */ } conn_t; diff --git a/lib/sntllv2.c b/lib/sntllv2.c index c033ea3..5b4b78d 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -436,6 +436,63 @@ static int __eval_syssexp(conn_t *co, sexp_t *sx) return rentry->rpcf((void *)co, sx); } +#define _CONN_INUSE(co) (co)->usecount++; +#define _CONN_NOTINUSE(co) (co)->usecount--; +#define _CONN_UCOUNT(co) (co)->usecount + +static void __connection_destroy(conn_t *co) +{ + int i = 0; + sxmsg_t *msg; + chnl_t *chan; + sntllv2_head_t *head; + conn_sys_t *ssys = co->ssys; + + /* first we will unpin all messages and mark it as errors on */ + if(co->unused_messages) { + /*TODO: kill it all */ + } + + /* go thru messages */ + pthread_mutex_lock(&co->idx_msg_lock); + for(i = 0; i < 1024; i++) { + msg = co->messages[i]; + if(!msg) continue; + else head = &msg->mhead; + head->opcode = SNE_LINKERROR; + pthread_mutex_unlock(&msg->wait); + co->messages[i] = NULL; + idx_free(&co->idx_msg, i); + } + pthread_mutex_unlock(&co->idx_msg_lock); + + /* ok now we will free the channels */ + pthread_mutex_lock(&co->idx_ch_lock); + for(i = 0; i < 512; i++) { + chan = co->channels[i]; + if(!chan) continue; + idx_free(&co->idx_ch, i); + free(chan); + } + pthread_mutex_unlock(&co->idx_ch_lock); + + /* update use count */ + _CONN_NOTINUSE(co); + + /* ok, let's free other if we can */ + if(!_CONN_UCOUNT(co)) { + if(ssys->on_destroy) ssys->on_destroy(co); + SSL_shutdown(co->ssl); + close(SSL_get_fd(co->ssl)); + SSL_free(co->ssl); + SSL_CTX_free(co->ctx); + __connection_second_free(co); + __connection_minimal_free(co); + } + + return; +} + static void *__sntll_thread(void *b) { sntllv2_bundle_t *bun = (sntllv2_bundle_t *)b; @@ -468,6 +525,9 @@ static void *__sntll_thread(void *b) if(pthread_equal(self, co->thrd_poll[7])) /* dispatcher */ dispatch = 1; + /* update use count */ + _CONN_INUSE(co); + /* the following logic : (except dispatcher) * 1. check up pending write -> if exists write one and start again., otherwise go next * 2. read from ssl connection (we will sleep if other already acquire the lock) @@ -683,6 +743,7 @@ static void *__sntll_thread(void *b) } __finish: + __connection_destroy(co); __sntll_bundle_destroy(b); /* destroy bundle */ return NULL; } From bb28ee9a6331822dab9748766444de652447e620 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 25 Jul 2015 01:07:55 +0300 Subject: [PATCH 42/56] fixed; --- lib/sntllv2.c | 23 +++++++++++++---------- tests/lv2sd.c | 15 ++------------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/lib/sntllv2.c b/lib/sntllv2.c index 5b4b78d..a7f7dff 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -466,22 +466,25 @@ static void __connection_destroy(conn_t *co) } pthread_mutex_unlock(&co->idx_msg_lock); - /* ok now we will free the channels */ - pthread_mutex_lock(&co->idx_ch_lock); - for(i = 0; i < 512; i++) { - chan = co->channels[i]; - if(!chan) continue; - idx_free(&co->idx_ch, i); - free(chan); - } - pthread_mutex_unlock(&co->idx_ch_lock); - /* update use count */ _CONN_NOTINUSE(co); /* ok, let's free other if we can */ if(!_CONN_UCOUNT(co)) { + /* ok now we will free the channels */ + pthread_mutex_lock(&co->idx_ch_lock); + for(i = 0; i < 512; i++) { + chan = co->channels[i]; + if(!chan) continue; + idx_free(&co->idx_ch, i); + free(chan); + } + pthread_mutex_unlock(&co->idx_ch_lock); + if(ssys->on_destroy) ssys->on_destroy(co); + if(co->pctx->login) free(co->pctx->login); + if(co->pctx->passwd) free(co->pctx->passwd); + SSL_shutdown(co->ssl); close(SSL_get_fd(co->ssl)); SSL_free(co->ssl); diff --git a/tests/lv2sd.c b/tests/lv2sd.c index 6fd8809..feb455b 100644 --- a/tests/lv2sd.c +++ b/tests/lv2sd.c @@ -170,24 +170,13 @@ static void sigpipe_handler(int a) 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; conn_sys_t *ssys = connections_create(); int port = DEFAULT_PORT; int opt; + signal(SIGPIPE, SIG_IGN); + while((opt = getopt(argc, argv, "p:r:u:")) != -1) { switch(opt) { case 'p': From f3d13966afe27a805effba926eafbcc04fd1fd0f Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 25 Jul 2015 02:37:21 +0300 Subject: [PATCH 43/56] added connection_close; --- include/sntl/sntllv2.h | 2 ++ lib/sntllv2.c | 18 ++++++++++++++++++ tests/lv2sc.c | 2 ++ 3 files changed, 22 insertions(+) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index d8c2494..9486481 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -195,6 +195,8 @@ extern "C" { #endif /* API */ +int sntl_init(void); + int connections_init(conn_sys_t *ssys); conn_sys_t *connections_create(void); diff --git a/lib/sntllv2.c b/lib/sntllv2.c index a7f7dff..f701311 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -746,6 +746,7 @@ static void *__sntll_thread(void *b) } __finish: + co->flags |= SNSX_CLOSED; __connection_destroy(co); __sntll_bundle_destroy(b); /* destroy bundle */ return NULL; @@ -1143,3 +1144,20 @@ conn_t *connection_link(conn_sys_t *ssys, const char *host, return NULL; } +int connection_close(conn_t *co) +{ + sntllv2_head_t mhead; + + memset(&mhead, 0, sizeof(sntllv2_head_t)); + /* setup header */ + mhead.attr = SXMSG_LINK | SXMSG_CLOSED; + + pthread_mutex_lock(&(co->sslinout[1])); + __conn_write(co, &mhead, sizeof(sntllv2_head_t)); + pthread_mutex_unlock(&(co->sslinout[1])); + + /* we will not wait anything */ + co->flags |= SNSX_CLOSED; + + return SNE_SUCCESS; +} diff --git a/tests/lv2sc.c b/tests/lv2sc.c index b2e11b9..5e1cf4a 100644 --- a/tests/lv2sc.c +++ b/tests/lv2sc.c @@ -275,6 +275,8 @@ int main(int argc, char **argv) __wait_completion(&trd); + connection_close(co); + return 0; } From 617e170087a6e5ea0d982158a6a643dacaa6278d Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 25 Jul 2015 03:25:35 +0300 Subject: [PATCH 44/56] pending messages ready; --- include/sntl/sntllv2.h | 2 +- lib/messagesx.c | 3 ++ lib/sntllv2.c | 65 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index 9486481..0731e8a 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -86,7 +86,7 @@ typedef struct __connection_t { pthread_mutex_t idx_msg_lock; list_head_t write_pending; /** < list of messages waiting for write */ pthread_mutex_t write_pending_lock; - volatile uint8_t unused_messages; /** < unused message count */ + volatile uint8_t pending_messages; /** < pending message count */ /* Other stuff */ pthread_t thrd_poll[8]; volatile uint8_t flags; /** < flags of the connection */ diff --git a/lib/messagesx.c b/lib/messagesx.c index c63d83d..6e33d74 100644 --- a/lib/messagesx.c +++ b/lib/messagesx.c @@ -108,6 +108,7 @@ static inline int __sxmsg_send(chnl_t *channel, const char *data, size_t datalen /* under locking here */ pthread_mutex_lock(&co->write_pending_lock); + co->pending_messages++; list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */ pthread_mutex_unlock(&co->write_pending_lock); } @@ -207,6 +208,7 @@ static inline int __sxmsg_reply(sxmsg_t *msg, const char *data, /* under locking here */ pthread_mutex_lock(&co->write_pending_lock); + co->pending_messages++; list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */ pthread_mutex_unlock(&co->write_pending_lock); } @@ -310,6 +312,7 @@ static inline int __sxmsg_return(sxmsg_t *msg, int opcode, int pp) /* under locking here */ pthread_mutex_lock(&co->write_pending_lock); + co->pending_messages++; list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */ pthread_mutex_unlock(&co->write_pending_lock); diff --git a/lib/sntllv2.c b/lib/sntllv2.c index f701311..332b0fc 100644 --- a/lib/sntllv2.c +++ b/lib/sntllv2.c @@ -443,14 +443,34 @@ static int __eval_syssexp(conn_t *co, sexp_t *sx) static void __connection_destroy(conn_t *co) { int i = 0; - sxmsg_t *msg; + sxmsg_t *msg, *omsg; + ppmsg_t *ppm; + list_node_t *iter, *siter; chnl_t *chan; sntllv2_head_t *head; conn_sys_t *ssys = co->ssys; /* first we will unpin all messages and mark it as errors on */ - if(co->unused_messages) { - /*TODO: kill it all */ + if(co->pending_messages) { + pthread_mutex_lock(&co->write_pending_lock); + list_for_each_safe(&co->write_pending, iter, siter) { + ppm = container_of(iter, ppmsg_t, node); + omsg = ppm->msg; + + /* ok, now we're able to remove it from list */ + list_del(&ppm->node); + if(omsg->mhead.attr & SXMSG_CLOSED) { /* message is closed - destroy it */ + pthread_mutex_unlock(&omsg->wait); + pthread_mutex_destroy(&omsg->wait); + free(omsg); + } else { /* wake up */ + omsg->mhead.opcode = SNE_LINKERROR; + pthread_mutex_unlock(&omsg->wait); + } + free(ppm); + co->pending_messages--; + } + pthread_mutex_unlock(&co->write_pending_lock); } /* go thru messages */ @@ -503,11 +523,14 @@ static void *__sntll_thread(void *b) void *buf = bun->buf; char *bbuf = (char*)buf; sntllv2_head_t *mhead = (sntllv2_head_t *)buf; - sxmsg_t *msg; + sxmsg_t *msg, *omsg; sexp_t *sx; chnl_t *channel; + list_node_t *iter, *siter; + ppmsg_t *ppm; pthread_t self = pthread_self(); - int dispatch = 0; + struct timespec wtick; + int dispatch = 0, e; size_t rd, wr; ulong_t mid; @@ -537,7 +560,37 @@ static void *__sntll_thread(void *b) */ while(1) { __again: - pthread_mutex_lock(&(co->sslinout[0])); + if(co->flags & SNSX_CLOSED) goto __finish; /* go away if required asap */ + /* works with pending messages */ + if(co->pending_messages) { + pthread_mutex_lock(&co->write_pending_lock); + list_for_each_safe(&co->write_pending, iter, siter) { + ppm = container_of(iter, ppmsg_t, node); + omsg = ppm->msg; + if(_sntll_writemsg(co, omsg) != SNE_SUCCESS) { + pthread_mutex_unlock(&co->write_pending_lock); + goto __finish; /* write failed - finishing ... */ + } + + /* ok, now we're able to remove it from list */ + list_del(&ppm->node); + if(omsg->mhead.attr & SXMSG_CLOSED) { /* message is closed - destroy it */ + pthread_mutex_unlock(&omsg->wait); + pthread_mutex_destroy(&omsg->wait); + free(omsg); + } + free(ppm); + co->pending_messages--; + } + pthread_mutex_unlock(&co->write_pending_lock); + } + + if(!dispatch) pthread_mutex_lock(&(co->sslinout[0])); + else { /* dispatch thread ticking every ət */ + wtick.tv_sec = time(NULL) + 1; + e = pthread_mutex_timedlock(&(co->sslinout[0]), &wtick); + if(e == ETIMEDOUT) goto __again; + } if(co->flags & SNSX_CLOSED) { pthread_mutex_unlock(&(co->sslinout[0])); goto __finish; From d13af92d0d81a9646d27497c5f7055041a690026 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 25 Jul 2015 03:28:30 +0300 Subject: [PATCH 45/56] keep gcc happy; --- tests/lv2sc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/lv2sc.c b/tests/lv2sc.c index 5e1cf4a..999f2cc 100644 --- a/tests/lv2sc.c +++ b/tests/lv2sc.c @@ -101,7 +101,7 @@ static void *__addsthrd(void *a) break; case SNE_REPLYREQ: if(sxmsg_datalen(msg)) fprintf(stdout, "Replied (confirmation required): %s\n", - sxmsg_payload(msg)); + (char *)sxmsg_payload(msg)); mr = sxmsg_return(msg, SNE_SUCCESS); fprintf(stderr, "mr = %d\n", mr); break; @@ -244,7 +244,7 @@ int main(int argc, char **argv) break; case SNE_REPLYREQ: if(sxmsg_datalen(msg)) fprintf(stdout, "Replied (confirmation required): %s\n", - sxmsg_payload(msg)); + (char *)sxmsg_payload(msg)); mr = sxmsg_return(msg, SNE_SUCCESS); fprintf(stderr, "mr = %d\n", mr); break; From 3b06cd02288d2176575104951e99ba5c3b648353 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 25 Jul 2015 03:45:03 +0300 Subject: [PATCH 46/56] returning back to sntl name; --- configure.ac | 2 +- debian/changelog | 12 ++++++------ debian/files | 4 ++-- debian/libsntl.substvars | 2 +- debian/shlibs.local.ex | 2 +- lib/Makefile.am | 16 ++++++++-------- lib/{libsntllv2.pc.in => libsntl.pc.in} | 2 +- tests/Makefile.am | 2 +- 8 files changed, 21 insertions(+), 21 deletions(-) rename lib/{libsntllv2.pc.in => libsntl.pc.in} (90%) diff --git a/configure.ac b/configure.ac index 26d18e5..b8d9cc7 100644 --- a/configure.ac +++ b/configure.ac @@ -63,7 +63,7 @@ AM_CONDITIONAL(BUILD_WIN32, test "x$enable_win32_build" = "xyes") AC_OUTPUT([ Makefile -lib/libsntllv2.pc +lib/libsntl.pc lib/Makefile include/Makefile examples/Makefile diff --git a/debian/changelog b/debian/changelog index d07fdf9..faaba8b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,12 +1,12 @@ libsntl (0.3.0) stable; urgency=high - * New improved architecture - * Performance tricks - * Long messages - * Extended API - * It's incompatible with 0.2.xx and below by protocol + * New improved architecture + * Performance tricks + * Long messages + * Extended API + * It's incompatible with 0.2.xx and below by protocol - -- Alexander Vdolainen Thu, 16 Jul 2015 22:50:32 +0200 + -- Alexander Vdolainen Thu, 16 Jul 2015 22:50:32 +0200 libsntl (0.2.1) stable; urgency=low diff --git a/debian/files b/debian/files index 164faed..9aff3c4 100644 --- a/debian/files +++ b/debian/files @@ -1,2 +1,2 @@ -libsntl-dev_0.2.1_amd64.deb libdevel extra -libsntl_0.2.1_amd64.deb libs extra +libsntl-dev_0.3.0_amd64.deb libdevel extra +libsntl_0.3.0_amd64.deb libs extra diff --git a/debian/libsntl.substvars b/debian/libsntl.substvars index 2f9fbbd..fd5aa20 100644 --- a/debian/libsntl.substvars +++ b/debian/libsntl.substvars @@ -1,2 +1,2 @@ -shlibs:Depends=libc6 (>= 2.3.2), libsexpr, libssl1.0.0 (>= 1.0.1), libtdata, libuuid1 (>= 2.20.1) +shlibs:Depends=libc6 (>= 2.2.5), libsexpr, libssl1.0.0 (>= 1.0.1), libtdata, libuuid1 (>= 2.20.1) misc:Depends= diff --git a/debian/shlibs.local.ex b/debian/shlibs.local.ex index 5c6fe79..1746db8 100644 --- a/debian/shlibs.local.ex +++ b/debian/shlibs.local.ex @@ -1 +1 @@ -libsntl 0.2.0 libsntl (>> 0.2.0), libsntl (<< 0.2.99) +libsntl 0.3.0 libsntl (>> 0.3.0), libsntl (<< 0.3.99) diff --git a/lib/Makefile.am b/lib/Makefile.am index 5e9e6a7..0b7490e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -10,25 +10,25 @@ AM_CFLAGS =\ -Wall\ -g -lib_LTLIBRARIES = libsntllv2.la +lib_LTLIBRARIES = libsntl.la -libsntllv2_la_SOURCES = \ +libsntl_la_SOURCES = \ connex.c sntllv2.c chansx.c messagesx.c rpclist.c uuid.c -libsntllv2_la_LDFLAGS = -Wl,--export-dynamic +libsntl_la_LDFLAGS = -Wl,--export-dynamic -libsntllv2_la_LIBADD = -lpthread -lcrypto $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) +libsntl_la_LIBADD = -lpthread -lcrypto $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) if BUILD_WIN32 -libsntllv2_la_LIBADD += -luuid +libsntl_la_LIBADD += -luuid else -libsntllv2_la_LIBADD += $(LIBUUID_LIBS) +libsntl_la_LIBADD += $(LIBUUID_LIBS) endif !BUILD_WIN32 pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libsntllv2.pc +pkgconfig_DATA = libsntl.pc EXTRA_DIST = \ - libsntllv2.pc.in + libsntl.pc.in diff --git a/lib/libsntllv2.pc.in b/lib/libsntl.pc.in similarity index 90% rename from lib/libsntllv2.pc.in rename to lib/libsntl.pc.in index 4b09ce6..cd463bb 100644 --- a/lib/libsntllv2.pc.in +++ b/lib/libsntl.pc.in @@ -9,5 +9,5 @@ Name: libsntllv2 Description: Secure Network Transport Layer library implementation Version: @VERSION@ Requires: -Libs: -L${libdir} -lsntllv2 +Libs: -L${libdir} -lsntl Cflags: -I${includedir} diff --git a/tests/Makefile.am b/tests/Makefile.am index dfa9ce4..3753f65 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,7 +11,7 @@ AM_CPPFLAGS = \ AM_CFLAGS = -Wall -g # where to find libsntl -libsntl = ../lib/.libs/libsntllv2.la +libsntl = ../lib/.libs/libsntl.la if !BUILD_WIN32 From 902530f59a632f66469c083e13866099853c8f92 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 25 Jul 2015 05:11:23 +0300 Subject: [PATCH 47/56] fixed debian installation of manpages... --- Makefile.am | 2 +- configure.ac | 1 + debian/emacsen-install.ex | 47 ---- debian/emacsen-remove.ex | 15 -- debian/emacsen-startup.ex | 27 -- debian/libsntl-dev.dirs | 2 + debian/libsntl-dev.install | 1 + debian/manpage.1.ex | 56 ---- debian/manpage.sgml.ex | 154 ----------- debian/manpage.xml.ex | 291 --------------------- debian/menu.ex | 2 - man/{sxmsg_rreply.3SNTL => sxmsg_rreply.3} | 2 +- 12 files changed, 6 insertions(+), 594 deletions(-) delete mode 100644 debian/emacsen-install.ex delete mode 100644 debian/emacsen-remove.ex delete mode 100644 debian/emacsen-startup.ex delete mode 100644 debian/manpage.1.ex delete mode 100644 debian/manpage.sgml.ex delete mode 100644 debian/manpage.xml.ex delete mode 100644 debian/menu.ex rename man/{sxmsg_rreply.3SNTL => sxmsg_rreply.3} (96%) diff --git a/Makefile.am b/Makefile.am index f281664..82a0896 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,7 @@ else TESTS = endif -SUBDIRS = include lib $(EXAMPLES) $(TESTS) +SUBDIRS = include lib man $(EXAMPLES) $(TESTS) libsntldocdir = ${prefix}/doc/libsntl libsntldoc_DATA = \ diff --git a/configure.ac b/configure.ac index b8d9cc7..0d3c9fb 100644 --- a/configure.ac +++ b/configure.ac @@ -66,5 +66,6 @@ Makefile lib/libsntl.pc lib/Makefile include/Makefile +man/Makefile examples/Makefile tests/Makefile]) diff --git a/debian/emacsen-install.ex b/debian/emacsen-install.ex deleted file mode 100644 index d849956..0000000 --- a/debian/emacsen-install.ex +++ /dev/null @@ -1,47 +0,0 @@ -#! /bin/sh -e -# /usr/lib/emacsen-common/packages/install/libsntl - -# Written by Jim Van Zandt , borrowing heavily -# from the install scripts for gettext by Santiago Vila -# and octave by Dirk Eddelbuettel . - -FLAVOR=$1 -PACKAGE=libsntl - -if [ ${FLAVOR} = emacs ]; then exit 0; fi - -echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR} - -#FLAVORTEST=`echo $FLAVOR | cut -c-6` -#if [ ${FLAVORTEST} = xemacs ] ; then -# SITEFLAG="-no-site-file" -#else -# SITEFLAG="--no-site-file" -#fi -FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile" - -ELDIR=/usr/share/emacs/site-lisp/${PACKAGE} -ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE} -ELRELDIR=../../../emacs/site-lisp/${PACKAGE} - -# Install-info-altdir does not actually exist. -# Maybe somebody will write it. -if test -x /usr/sbin/install-info-altdir; then - echo install/${PACKAGE}: install Info links for ${FLAVOR} - install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/share/info/${PACKAGE}.info.gz -fi - -install -m 755 -d ${ELCDIR} -cd ${ELDIR} -FILES=`echo *.el` -cd ${ELCDIR} -ln -sf ${ELRELDIR}/*.el . - -cat << EOF > path.el -(debian-pkg-add-load-path-item ".") -(setq byte-compile-warnings nil) -EOF -${FLAVOR} ${FLAGS} ${FILES} -rm -f path.el - -exit 0 diff --git a/debian/emacsen-remove.ex b/debian/emacsen-remove.ex deleted file mode 100644 index 114d368..0000000 --- a/debian/emacsen-remove.ex +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -e -# /usr/lib/emacsen-common/packages/remove/libsntl - -FLAVOR=$1 -PACKAGE=libsntl - -if [ ${FLAVOR} != emacs ]; then - if test -x /usr/sbin/install-info-altdir; then - echo remove/${PACKAGE}: removing Info links for ${FLAVOR} - install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/share/info/libsntl.info.gz - fi - - echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR} - rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE} -fi diff --git a/debian/emacsen-startup.ex b/debian/emacsen-startup.ex deleted file mode 100644 index 2cb1f63..0000000 --- a/debian/emacsen-startup.ex +++ /dev/null @@ -1,27 +0,0 @@ -;; -*-emacs-lisp-*- -;; -;; Emacs startup file, e.g. /etc/emacs/site-start.d/50libsntl.el -;; for the Debian libsntl package -;; -;; Originally contributed by Nils Naumann -;; Modified by Dirk Eddelbuettel -;; Adapted for dh-make by Jim Van Zandt - -;; The libsntl package follows the Debian/GNU Linux 'emacsen' policy and -;; byte-compiles its elisp files for each 'emacs flavor' (emacs19, -;; xemacs19, emacs20, xemacs20...). The compiled code is then -;; installed in a subdirectory of the respective site-lisp directory. -;; We have to add this to the load-path: -(let ((package-dir (concat "/usr/share/" - (symbol-name debian-emacs-flavor) - "/site-lisp/libsntl"))) -;; If package-dir does not exist, the libsntl package must have -;; removed but not purged, and we should skip the setup. - (when (file-directory-p package-dir) - (if (fboundp 'debian-pkg-add-load-path-item) - (debian-pkg-add-load-path-item package-dir) - (setq load-path (cons package-dir load-path))) - (autoload 'libsntl-mode "libsntl-mode" - "Major mode for editing libsntl files." t) - (add-to-list 'auto-mode-alist '("\\.libsntl$" . libsntl-mode)))) - diff --git a/debian/libsntl-dev.dirs b/debian/libsntl-dev.dirs index 4418816..c413e42 100644 --- a/debian/libsntl-dev.dirs +++ b/debian/libsntl-dev.dirs @@ -1,2 +1,4 @@ usr/lib usr/include +usr/share/man +usr/share/man/man3 \ No newline at end of file diff --git a/debian/libsntl-dev.install b/debian/libsntl-dev.install index 6cd8ddd..8a3bca9 100644 --- a/debian/libsntl-dev.install +++ b/debian/libsntl-dev.install @@ -2,3 +2,4 @@ usr/include/* usr/lib/lib*.a usr/lib/lib*.so usr/lib/pkgconfig/* +usr/share/man/man3/* diff --git a/debian/manpage.1.ex b/debian/manpage.1.ex deleted file mode 100644 index f41a5f5..0000000 --- a/debian/manpage.1.ex +++ /dev/null @@ -1,56 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.\" (C) Copyright 2014 Alexander Vdolainen , -.\" -.\" First parameter, NAME, should be all caps -.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection -.\" other parameters are allowed: see man(7), man(1) -.TH LIBSNTL SECTION "November 24, 2014" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -libsntl \- program to do something -.SH SYNOPSIS -.B libsntl -.RI [ options ] " files" ... -.br -.B bar -.RI [ options ] " files" ... -.SH DESCRIPTION -This manual page documents briefly the -.B libsntl -and -.B bar -commands. -.PP -.\" TeX users may be more comfortable with the \fB\fP and -.\" \fI\fP escape sequences to invode bold face and italics, -.\" respectively. -\fBlibsntl\fP is a program that... -.SH OPTIONS -These programs follow the usual GNU command line syntax, with long -options starting with two dashes (`-'). -A summary of options is included below. -For a complete description, see the Info files. -.TP -.B \-h, \-\-help -Show summary of options. -.TP -.B \-v, \-\-version -Show version of program. -.SH SEE ALSO -.BR bar (1), -.BR baz (1). -.br -The programs are documented fully by -.IR "The Rise and Fall of a Fooish Bar" , -available via the Info system. diff --git a/debian/manpage.sgml.ex b/debian/manpage.sgml.ex deleted file mode 100644 index fa85375..0000000 --- a/debian/manpage.sgml.ex +++ /dev/null @@ -1,154 +0,0 @@ - manpage.1'. You may view - the manual page with: `docbook-to-man manpage.sgml | nroff -man | - less'. A typical entry in a Makefile or Makefile.am is: - -manpage.1: manpage.sgml - docbook-to-man $< > $@ - - - The docbook-to-man binary is found in the docbook-to-man package. - Please remember that if you create the nroff version in one of the - debian/rules file targets (such as build), you will need to include - docbook-to-man in your Build-Depends control field. - - --> - - - FIRSTNAME"> - SURNAME"> - - November 24, 2014"> - - SECTION"> - vdo@daze"> - - LIBSEXPR"> - - - Debian"> - GNU"> - GPL"> -]> - - - -
- &dhemail; -
- - &dhfirstname; - &dhsurname; - - - 2003 - &dhusername; - - &dhdate; -
- - &dhucpackage; - - &dhsection; - - - &dhpackage; - - program to do something - - - - &dhpackage; - - - - - - - - DESCRIPTION - - This manual page documents briefly the - &dhpackage; and bar - commands. - - This manual page was written for the &debian; distribution - because the original program does not have a manual page. - Instead, it has documentation in the &gnu; - Info format; see below. - - &dhpackage; is a program that... - - - - OPTIONS - - These programs follow the usual &gnu; command line syntax, - with long options starting with two dashes (`-'). A summary of - options is included below. For a complete description, see the - Info files. - - - - - - - - Show summary of options. - - - - - - - - Show version of program. - - - - - - SEE ALSO - - bar (1), baz (1). - - The programs are documented fully by The Rise and - Fall of a Fooish Bar available via the - Info system. - - - AUTHOR - - This manual page was written by &dhusername; &dhemail; for - the &debian; system (and may be used by others). Permission is - granted to copy, distribute and/or modify this document under - the terms of the &gnu; General Public License, Version 2 any - later version published by the Free Software Foundation. - - - On Debian systems, the complete text of the GNU General Public - License can be found in /usr/share/common-licenses/GPL. - - - -
- - diff --git a/debian/manpage.xml.ex b/debian/manpage.xml.ex deleted file mode 100644 index 73a275f..0000000 --- a/debian/manpage.xml.ex +++ /dev/null @@ -1,291 +0,0 @@ - -.
will be generated. You may view the -manual page with: nroff -man .
| less'. A typical entry -in a Makefile or Makefile.am is: - -DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl -XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" - -manpage.1: manpage.xml - $(XP) $(DB2MAN) $< - -The xsltproc binary is found in the xsltproc package. The XSL files are in -docbook-xsl. A description of the parameters you can use can be found in the -docbook-xsl-doc-* packages. Please remember that if you create the nroff -version in one of the debian/rules file targets (such as build), you will need -to include xsltproc and docbook-xsl in your Build-Depends control field. -Alternatively use the xmlto command/package. That will also automatically -pull in xsltproc and docbook-xsl. - -Notes for using docbook2x: docbook2x-man does not automatically create the -AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as - ... . - -To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections -read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be -found in the docbook-xsl-doc-html package. - -Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` - -General documentation about man-pages and man-page-formatting: -man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ - ---> - - - - - - - - - - - - - -]> - - - - &dhtitle; - &dhpackage; - - - &dhfirstname; - &dhsurname; - Wrote this manpage for the Debian system. -
- &dhemail; -
-
-
- - 2007 - &dhusername; - - - This manual page was written for the Debian system - (and may be used by others). - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU General Public License, - Version 2 or (at your option) any later version published by - the Free Software Foundation. - On Debian systems, the complete text of the GNU General Public - License can be found in - /usr/share/common-licenses/GPL. - -
- - &dhucpackage; - &dhsection; - - - &dhpackage; - program to do something - - - - &dhpackage; - - - - - - - - - this - - - - - - - - this - that - - - - - &dhpackage; - - - - - - - - - - - - - - - - - - - DESCRIPTION - This manual page documents briefly the - &dhpackage; and bar - commands. - This manual page was written for the Debian distribution - because the original program does not have a manual page. - Instead, it has documentation in the GNU - info - 1 - format; see below. - &dhpackage; is a program that... - - - OPTIONS - The program follows the usual GNU command line syntax, - with long options starting with two dashes (`-'). A summary of - options is included below. For a complete description, see the - - info - 1 - files. - - - - - - - Does this and that. - - - - - - - Show summary of options. - - - - - - - Show version of program. - - - - - - FILES - - - /etc/foo.conf - - The system-wide configuration file to control the - behaviour of &dhpackage;. See - - foo.conf - 5 - for further details. - - - - ${HOME}/.foo.conf - - The per-user configuration file to control the - behaviour of &dhpackage;. See - - foo.conf - 5 - for further details. - - - - - - ENVIRONMENT - - - FOO_CONF - - If used, the defined file is used as configuration - file (see also ). - - - - - - DIAGNOSTICS - The following diagnostics may be issued - on stderr: - - - Bad configuration file. Exiting. - - The configuration file seems to contain a broken configuration - line. Use the option, to get more info. - - - - - &dhpackage; provides some return codes, that can - be used in scripts: - - Code - Diagnostic - - 0 - Program exited successfully. - - - 1 - The configuration file seems to be broken. - - - - - - BUGS - The program is currently limited to only work - with the foobar library. - The upstreams BTS can be found - at . - - - SEE ALSO - - - bar - 1 - , - baz - 1 - , - foo.conf - 5 - - The programs are documented fully by The Rise and - Fall of a Fooish Bar available via the - info - 1 - system. - -
- diff --git a/debian/menu.ex b/debian/menu.ex deleted file mode 100644 index d14a962..0000000 --- a/debian/menu.ex +++ /dev/null @@ -1,2 +0,0 @@ -?package(libsntl):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\ - title="libsntl" command="/usr/bin/libsntl" diff --git a/man/sxmsg_rreply.3SNTL b/man/sxmsg_rreply.3 similarity index 96% rename from man/sxmsg_rreply.3SNTL rename to man/sxmsg_rreply.3 index aebbc4f..9dfe9f7 100644 --- a/man/sxmsg_rreply.3SNTL +++ b/man/sxmsg_rreply.3 @@ -1,4 +1,4 @@ -.TH SXMSG_RREPLY 3SNTL "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.TH SXMSG_RREPLY 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual" .SH NAME sxmsg_rreply \- Function used to send a rapid reply without confirmation .SH SYNOPSIS From b6e91e99c40d40a22b0e2f44bab13132000dab36 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sat, 25 Jul 2015 05:36:04 +0300 Subject: [PATCH 48/56] added forgotten files, added man page; --- debian/libsntl-dev.manpages | 2 + man/Makefile.am | 1 + man/connections_create.3 | 73 ++++++++++++++++++++++++++++++++++++ man/connections_create.3SNTL | 59 ----------------------------- 4 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 debian/libsntl-dev.manpages create mode 100644 man/Makefile.am create mode 100644 man/connections_create.3 delete mode 100644 man/connections_create.3SNTL diff --git a/debian/libsntl-dev.manpages b/debian/libsntl-dev.manpages new file mode 100644 index 0000000..bdba65b --- /dev/null +++ b/debian/libsntl-dev.manpages @@ -0,0 +1,2 @@ +man/sxmsg_rreply.3 +man/connections_create.3 \ No newline at end of file diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..1c30c43 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1 @@ +man_MANS = sxmsg_rreply.3 connections_create.3 diff --git a/man/connections_create.3 b/man/connections_create.3 new file mode 100644 index 0000000..3211f2c --- /dev/null +++ b/man/connections_create.3 @@ -0,0 +1,73 @@ +.TH CONNECTIONS_CREATE 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.SH NAME +connections_create \- Allocate and initialize connections system +.br +connections_init \- Initialize connections system +.br +connections_destroy \- Destroy connections system +.br +connections_free \- Free all stuff allocated for connections system +.SH SYNOPSIS +.B #include +.sp +conn_sys_t *connections_create(void); + +int connections_init(conn_sys_t *ssys); + +int connections_destroy(conn_sys_t *ssys); + +int connections_free(conn_sys_t *ssys); + +.br +.sp +.SH DESCRIPTION +.B connections_create +will create a separate connections set used for handling creation and initialization of the connection links. +.B connections_init +will do the same, but it will take an already preallocated pointer. +.br +.B connections_destroy +will deallocate all related to the connections set, include pointer +.BI ssys +, but +.B connections_free +will not free this pointer consider it will be deallocated by user. +.br +.SH RETURN VALUE +Upon successful completion, the function +.B connections_create +will return a valid pointer to the connections set. +.B connections_init +will return +.B 0 +.br +Otherwise NULL will be returned and errno will be set, or error will be returned, in case of +.B connections_init + use. +.SH ERRORS +.B connections_init +will return, +.B connection_create will set +.B errno +to: +.br +.B ENOMEM +Not enough memory to allocate all required stuff. +.br +.B EINVAL +Returned if invalid pointer given. +.br +.SH BUGS +Not known yet. +.SH EXAMPLE +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH COPYRIGHT +This is a proprietary software. See COPYING for further details. +.br +(c) Askele Group 2013-2015 +.SH AUTHOR +Alexander Vdolainen (vdo@askele.com) diff --git a/man/connections_create.3SNTL b/man/connections_create.3SNTL deleted file mode 100644 index e90c225..0000000 --- a/man/connections_create.3SNTL +++ /dev/null @@ -1,59 +0,0 @@ -.TH CONNECTIONS_CREATE 3SNTL "20 July 2015" "SNTLLv2" "SNTL Library Manual" -.SH NAME -connections_create \- Allocate and initialize connections system -.br -connections_init \- Initialize connections system -.br -connections_destroy \- Destroy connections system -.br -connections_free \- Free all stuff allocated for connections system -.SH SYNOPSIS -.B #include -.sp -conn_sys_t *connections_create(void); - -int connections_init(conn_sys_t *ssys); - -int connections_destroy(conn_sys_t *ssys); - -int connections_free(conn_sys_t *ssys); - -.br -.sp -.SH DESCRIPTION -.br -.SH RETURN VALUE -Upon successful completion, the function shall rapidly send a message reply and close -the message dialog returning -.B SNE_SUCCESS -Othrewise other error code will be returned. -.SH ERRORS -.B SNE_FAILED -returns if message has invalid index, channel or message pointer is NULL. -.br -.B SNE_ESSL -returns if write was failed i.e. connection link was broken, or SSL error occurs. -.br -.B SNE_SUCCESS -returns on success. -.br -.SH BUGS -Not known yet. -.SH EXAMPLE -.B Reply rapidly from the RPC function call. -.RS -.nf -.if t .ft CW -char *buf = sxmsg_rapidbuf(msg); -int ln = snprintf(buf, MAX_BBUFLEN, "(is-done)"); -return sxmsg_rreply(msg, str, ln); -.SH APPLICATION USAGE -This function will be useful in RPC functions required to reply ASAP i.e. for getting some data. It RPC function takes a lot of time it's better to use other functions and postponed message processing. -.SH RATIONALE -Use for lightweight RPC functions, this method may be used only in RPC call i.e. within SNTL thread context. -.SH COPYRIGHT -This is a proprietary software. See COPYING for further details. -.br -(c) Askele Group 2013-2015 -.SH AUTHOR -Alexander Vdolainen (vdo@askele.com) From aa3b9bc2c3effe21f89af434e4d9ca770ce0bf6b Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 03:43:54 +0300 Subject: [PATCH 49/56] added useful macros; --- include/sntl/sntllv2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sntl/sntllv2.h b/include/sntl/sntllv2.h index 0731e8a..896eb1d 100644 --- a/include/sntl/sntllv2.h +++ b/include/sntl/sntllv2.h @@ -182,6 +182,8 @@ typedef struct __connections_subsys_type { #define connections_set_channelcall(c, f) (c)->set_typed_list_callback = (f) #define connections_set_ondestroy(c, f) (c)->on_destroy = (f) #define connections_set_onpulse(c, f) (c)->on_pulse = (f) +#define connections_set_priv(c, p) (c)->priv = (p) +#define connections_get_priv(c) (c)->priv typedef struct __rpc_typed_list_type { int type_id; From fe16a8ffacfc33fa05c2c23888f938a4ab317d50 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 05:05:02 +0300 Subject: [PATCH 50/56] added aliases for man pages; --- debian/libsntl-dev.manpages | 5 ++++- man/Makefile.am | 2 +- man/connections_create.3 | 9 ++++++++- man/connections_destroy.3 | 1 + man/connections_free.3 | 1 + man/connections_init.3 | 1 + 6 files changed, 16 insertions(+), 3 deletions(-) create mode 120000 man/connections_destroy.3 create mode 120000 man/connections_free.3 create mode 120000 man/connections_init.3 diff --git a/debian/libsntl-dev.manpages b/debian/libsntl-dev.manpages index bdba65b..8aeaab3 100644 --- a/debian/libsntl-dev.manpages +++ b/debian/libsntl-dev.manpages @@ -1,2 +1,5 @@ man/sxmsg_rreply.3 -man/connections_create.3 \ No newline at end of file +man/connections_create.3 +man/connections_destroy.3 +man/connections_free.3 +man/connections_init.3 \ No newline at end of file diff --git a/man/Makefile.am b/man/Makefile.am index 1c30c43..ca0a709 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1 +1 @@ -man_MANS = sxmsg_rreply.3 connections_create.3 +man_MANS = sxmsg_rreply.3 connections_create.3 connections_init.3 connections_destroy.3 connections_free.3 diff --git a/man/connections_create.3 b/man/connections_create.3 index 3211f2c..ade3951 100644 --- a/man/connections_create.3 +++ b/man/connections_create.3 @@ -64,7 +64,14 @@ None. .SH APPLICATION USAGE None. .SH RATIONALE -None. +Connection link destroy function might be used carefully, the logic of there functions is a +send a special link layer message that will close the connection link on the master side. +The reason to care about is a delivery of all messages, channels and other stuff, because +when this functions called all pending messages are drops. +.SH SEE ALSO +.BI connections_setsslserts(3) +, +.BI sntl_init(3) .SH COPYRIGHT This is a proprietary software. See COPYING for further details. .br diff --git a/man/connections_destroy.3 b/man/connections_destroy.3 new file mode 120000 index 0000000..5df5f7f --- /dev/null +++ b/man/connections_destroy.3 @@ -0,0 +1 @@ +connections_create.3 \ No newline at end of file diff --git a/man/connections_free.3 b/man/connections_free.3 new file mode 120000 index 0000000..5df5f7f --- /dev/null +++ b/man/connections_free.3 @@ -0,0 +1 @@ +connections_create.3 \ No newline at end of file diff --git a/man/connections_init.3 b/man/connections_init.3 new file mode 120000 index 0000000..5df5f7f --- /dev/null +++ b/man/connections_init.3 @@ -0,0 +1 @@ +connections_create.3 \ No newline at end of file From 729b8b29133a8c32a9c3d194c6f94f340fa71a80 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 05:21:18 +0300 Subject: [PATCH 51/56] added sntl_init manpage; --- debian/libsntl-dev.manpages | 3 ++- man/Makefile.am | 3 ++- man/sntl_init.3 | 45 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 man/sntl_init.3 diff --git a/debian/libsntl-dev.manpages b/debian/libsntl-dev.manpages index 8aeaab3..ccdcda1 100644 --- a/debian/libsntl-dev.manpages +++ b/debian/libsntl-dev.manpages @@ -2,4 +2,5 @@ man/sxmsg_rreply.3 man/connections_create.3 man/connections_destroy.3 man/connections_free.3 -man/connections_init.3 \ No newline at end of file +man/connections_init.3 +man/sntl_init.3 \ No newline at end of file diff --git a/man/Makefile.am b/man/Makefile.am index ca0a709..d2eb823 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1 +1,2 @@ -man_MANS = sxmsg_rreply.3 connections_create.3 connections_init.3 connections_destroy.3 connections_free.3 +man_MANS = sxmsg_rreply.3 connections_create.3 connections_init.3 connections_destroy.3 connections_free.3 \ + sntl_init.3 diff --git a/man/sntl_init.3 b/man/sntl_init.3 new file mode 100644 index 0000000..9306b68 --- /dev/null +++ b/man/sntl_init.3 @@ -0,0 +1,45 @@ +.TH SNTL_INIT 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.SH NAME +sntl_init \- Initialize all required globals to run sntl library functions +.br +.SH SYNOPSIS +.B #include +.sp +int *sntl_init(void); + +.br +.sp +.SH DESCRIPTION +.B sntl_init +will initialize all globals required to run sntl related functions, it mostly about +openssl library initialization. +.br +.SH RETURN VALUE +Always returns +.B 0 +since we cannot track openssl global initialization routines. +.br +.SH ERRORS +None errors might be returned. +.SH BUGS +None known yet. +.SH EXAMPLE +None. +.SH APPLICATION USAGE +Call this function from the main thread before using sntl library. Otherwise it will not works. There are also +useful to know if you are using other openssl functionality there are no need to initialize globals for it. +.SH RATIONALE +None. +.SH SEE ALSO +.BI connections_create(3) +, +.BI connections_destroy(3) +.SH COPYRIGHT +This is a proprietary software. See COPYING for further details. +.br +(c) Askele Group 2013-2015 +.SH AUTHOR +Alexander Vdolainen (vdo@askele.com) + + + From 29e2dc935e22d99dec837062cf0f12a89aed02d1 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 05:47:26 +0300 Subject: [PATCH 52/56] added connections_setsslserts manual page; --- debian/libsntl-dev.manpages | 3 +- man/Makefile.am | 2 +- man/connections_setsslserts.3 | 63 +++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 man/connections_setsslserts.3 diff --git a/debian/libsntl-dev.manpages b/debian/libsntl-dev.manpages index ccdcda1..2445c82 100644 --- a/debian/libsntl-dev.manpages +++ b/debian/libsntl-dev.manpages @@ -3,4 +3,5 @@ man/connections_create.3 man/connections_destroy.3 man/connections_free.3 man/connections_init.3 -man/sntl_init.3 \ No newline at end of file +man/sntl_init.3 +man/connections_setsslserts.3 \ No newline at end of file diff --git a/man/Makefile.am b/man/Makefile.am index d2eb823..fe07e27 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,2 +1,2 @@ man_MANS = sxmsg_rreply.3 connections_create.3 connections_init.3 connections_destroy.3 connections_free.3 \ - sntl_init.3 + sntl_init.3 connections_setsslserts.3 diff --git a/man/connections_setsslserts.3 b/man/connections_setsslserts.3 new file mode 100644 index 0000000..4977cea --- /dev/null +++ b/man/connections_setsslserts.3 @@ -0,0 +1,63 @@ +.TH CONNECTIONS_SETSSLSERTS 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.SH NAME +connections_setsslserts \- Setup root public certificate to check up, and also setups key and public certificate used for connections set +.br +.SH SYNOPSIS +.B #include +.sp +int connections_setsslserts(conn_sys_t *ssys, const char *rootca, + const char *certpem, const char *certkey); + +.br +.sp +.SH DESCRIPTION +.B connections_setsslserts +will setup root public certificate and private key and public certificate used to run connections set. +This is required always, see below for more information. +.br +.sp +This function just set a pathname of the certificates for +.BI ssys +where +.BI rootca +is a pathname to the public X.509 certificate +.BI certpem +is a your own X.509 certificate and +.BI certkey +is a your own key for this certificate. Therefore, +.BI certpem +and +.BI certkey +might be a single file. +.br +.SH RETURN VALUE +Will return 0 on success or errors below. +.br +.SH ERRORS +.B EINVAL +Invalid pointer given. +.br +.B ENOMEM +There are no available memory for operation. +.br +.SH BUGS +None known yet, but name is historically wrong it should be called connections_setsslcerts, btw there are many +code was written with this mistake. +.SH EXAMPLE +None. +.SH APPLICATION USAGE +Call this function *always* before linking a connection. Non master link will always avoid non-root certificate and key, +since you will required to pass it via call. +.SH RATIONALE +None. +.SH SEE ALSO +.BI connection_link(3) +, +.BI connection_link_master(3) +.SH COPYRIGHT +This is a proprietary software. See COPYING for further details. +.br +(c) Askele Group 2013-2015 +.SH AUTHOR +Alexander Vdolainen (vdo@askele.com) + From 404cc54cb077b1a2fdca7d6719453940a8975fea Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 06:02:27 +0300 Subject: [PATCH 53/56] added another manpages; --- debian/libsntl-dev.manpages | 4 ++- man/Makefile.am | 2 +- man/connections_get_priv.3 | 1 + man/connections_set_priv.3 | 57 +++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 2 deletions(-) create mode 120000 man/connections_get_priv.3 create mode 100644 man/connections_set_priv.3 diff --git a/debian/libsntl-dev.manpages b/debian/libsntl-dev.manpages index 2445c82..bc7f8c1 100644 --- a/debian/libsntl-dev.manpages +++ b/debian/libsntl-dev.manpages @@ -4,4 +4,6 @@ man/connections_destroy.3 man/connections_free.3 man/connections_init.3 man/sntl_init.3 -man/connections_setsslserts.3 \ No newline at end of file +man/connections_setsslserts.3 +man/connections_set_priv.3 +man/connections_get_priv.3 \ No newline at end of file diff --git a/man/Makefile.am b/man/Makefile.am index fe07e27..21a3388 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,2 +1,2 @@ man_MANS = sxmsg_rreply.3 connections_create.3 connections_init.3 connections_destroy.3 connections_free.3 \ - sntl_init.3 connections_setsslserts.3 + sntl_init.3 connections_setsslserts.3 connections_set_priv.3 connections_get_priv.3 diff --git a/man/connections_get_priv.3 b/man/connections_get_priv.3 new file mode 120000 index 0000000..2aeb521 --- /dev/null +++ b/man/connections_get_priv.3 @@ -0,0 +1 @@ +connections_set_priv.3 \ No newline at end of file diff --git a/man/connections_set_priv.3 b/man/connections_set_priv.3 new file mode 100644 index 0000000..faf21cd --- /dev/null +++ b/man/connections_set_priv.3 @@ -0,0 +1,57 @@ +.TH CONNECTIONS_SET_PRIV 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.SH NAME +connections_set_priv \- Set a private pointer to the connection links set +.br +connections_get_priv \- Get a private pointer of the connection links set +.br +.SH SYNOPSIS +.B #include +.sp +#define connections_set_priv(c, p) +#define connections_get_priv(c) + +.br +.sp +.SH DESCRIPTION +There macros should be used in case if you want set and get back your private pointer for something. +.br +Pointer is a +.B void* +i.e. it might be anything you pointed in the memory. +.br +.B connections_set_priv +will set a pointer +.B p +to connections set +.B c +.br +.B connections_get_priv +will return your pointer set to +.B c +connection set. +.br +.SH RETURN VALUE +None in case of +.B connections_set_priv +, a private pointer set in case of +.B connections_get_priv +.br +.SH ERRORS +None. +.br +.SH BUGS +None known yet. +.SH EXAMPLE +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH SEE ALSO +.BI connections_set_ondestroy(3) +.SH COPYRIGHT +This is a proprietary software. See COPYING for further details. +.br +(c) Askele Group 2013-2015 +.SH AUTHOR +Alexander Vdolainen (vdo@askele.com) From 46f4c7aa67585d45728fe5d094b8d526a8f29332 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 06:04:42 +0300 Subject: [PATCH 54/56] minor man fix; --- man/connections_set_priv.3 | 1 + 1 file changed, 1 insertion(+) diff --git a/man/connections_set_priv.3 b/man/connections_set_priv.3 index faf21cd..66188a9 100644 --- a/man/connections_set_priv.3 +++ b/man/connections_set_priv.3 @@ -8,6 +8,7 @@ connections_get_priv \- Get a private pointer of the connection links set .B #include .sp #define connections_set_priv(c, p) +.br #define connections_get_priv(c) .br From ff1aa8ff488e2fc5883f08dc415d0fcc355f05b0 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 06:08:01 +0300 Subject: [PATCH 55/56] minor fix in man page; --- man/sxmsg_rreply.3 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/man/sxmsg_rreply.3 b/man/sxmsg_rreply.3 index 9dfe9f7..9019bd9 100644 --- a/man/sxmsg_rreply.3 +++ b/man/sxmsg_rreply.3 @@ -3,6 +3,8 @@ sxmsg_rreply \- Function used to send a rapid reply without confirmation .SH SYNOPSIS .B #include +.br +.B #include .sp int sxmsg_rreply(sxmsg_t .BI *msg @@ -43,7 +45,7 @@ Not known yet. .nf .if t .ft CW char *buf = sxmsg_rapidbuf(msg); -int ln = snprintf(buf, MAX_BBUFLEN, "(is-done)"); +int ln = snprintf(buf, MAX_RBBUF_LEN, "(is-done)"); return sxmsg_rreply(msg, str, ln); .SH APPLICATION USAGE This function will be useful in RPC functions required to reply ASAP i.e. for getting some data. It RPC function takes a lot of time it's better to use other functions and postponed message processing. From 7012a49fa3228753ebf094360a1ec971a42621f4 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 26 Jul 2015 06:20:46 +0300 Subject: [PATCH 56/56] added connections_set_ondestroy manpage; --- debian/libsntl-dev.manpages | 3 ++- man/Makefile.am | 3 ++- man/connections_set_ondestroy.3 | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 man/connections_set_ondestroy.3 diff --git a/debian/libsntl-dev.manpages b/debian/libsntl-dev.manpages index bc7f8c1..a09594c 100644 --- a/debian/libsntl-dev.manpages +++ b/debian/libsntl-dev.manpages @@ -6,4 +6,5 @@ man/connections_init.3 man/sntl_init.3 man/connections_setsslserts.3 man/connections_set_priv.3 -man/connections_get_priv.3 \ No newline at end of file +man/connections_get_priv.3 +man/connections_set_ondestroy.3 \ No newline at end of file diff --git a/man/Makefile.am b/man/Makefile.am index 21a3388..8075986 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,2 +1,3 @@ man_MANS = sxmsg_rreply.3 connections_create.3 connections_init.3 connections_destroy.3 connections_free.3 \ - sntl_init.3 connections_setsslserts.3 connections_set_priv.3 connections_get_priv.3 + sntl_init.3 connections_setsslserts.3 connections_set_priv.3 connections_get_priv.3 \ + connections_set_ondestroy.3 diff --git a/man/connections_set_ondestroy.3 b/man/connections_set_ondestroy.3 new file mode 100644 index 0000000..7518364 --- /dev/null +++ b/man/connections_set_ondestroy.3 @@ -0,0 +1,48 @@ +.TH CONNECTIONS_ON_DESTROY 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual" +.SH NAME +connections_on_destroy \- Set callback for the connection links based on the connections set, called in case of link destroying +.br +.SH SYNOPSIS +.B #include +.sp +#define connections_set_ondestroy(c, f) + +.br +.sp +.SH DESCRIPTION +This macro should be used if you want to setup callback function fired upon a connection is closed or broken. +.br +This macro will set on +.B c +connections link set callback +.B f +which is a function pointer of the type: +.br +.sp +.B typedef void (*ondestroy_t)(conn_t *); +.br +.sp +This function will be called if connection link failed, broken etc. It will pass a pointer to the failed connection. +.SH RETURN VALUE +None. +.SH ERRORS +None. +.SH BUGS +None known yet. +.SH EXAMPLE +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH SEE ALSO +.BI connections_set_priv(3) +, +.BI connections_get_priv(3) +.SH COPYRIGHT +This is a proprietary software. See COPYING for further details. +.br +(c) Askele Group 2013-2015 +.SH AUTHOR +Alexander Vdolainen (vdo@askele.com) +