/* * 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 /* 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 #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; ulong_t certid; ulong_t uid; ulong_t gid; ulong_t *gids; int n_gids; int p_attr; 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) struct __connections_subsys_type; /* * ä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 { struct __connections_subsys_type *ssys; /* < connections subsystem */ char *uuid; /** < uuid of the connection */ idx_allocator_t *idx_ch; /** < index allocation for channels */ usrtc_t *chnl_tree; /** < search tree of all channels */ usrtc_t *rpc_list; /** < search tree of possible RPC typed lists */ SSL_CTX *ctx; /** < SSL context */ SSL *ssl; /** < SSL connection */ int ssl_data_index; /** < SSL index for the custom data */ 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 */ 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 { ulong_t cid; /** < ID of the channel */ char *uuid; /** < UUID of the channel, used in advanced implementation * of the complex distributed systems */ 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; 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) */ 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 */ 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 */ } 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; 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; /* 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 *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) #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_ */