|
|
|
@ -43,6 +43,23 @@ static long __cmp_ulong(const void *a, const void *b);
|
|
|
|
|
static sxmsg_t *__allocate_msg(int *res);
|
|
|
|
|
static void __destroy_msg(sxmsg_t *msg);
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
@ -242,6 +259,7 @@ static int __insert_rpc_function(usrtc_t *tree, const char *name, int (*rpcf)(vo
|
|
|
|
|
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;
|
|
|
|
@ -253,24 +271,35 @@ static void __wake_up_waiters(conn_t *co, int opcode)
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pthread_rwlock_unlock(&(co->chnl_lock));
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __default_auth_set_context(void *cctx, sexp_t *sx)
|
|
|
|
@ -339,6 +368,7 @@ __reply:
|
|
|
|
|
/* 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);
|
|
|
|
@ -449,6 +479,7 @@ static int __default_ch_get_types(void *cctx, sexp_t *sx)
|
|
|
|
|
/* 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);
|
|
|
|
@ -512,6 +543,7 @@ __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);
|
|
|
|
@ -640,6 +672,7 @@ static int __default_ch_open(void *cctx, sexp_t *sx)
|
|
|
|
|
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);
|
|
|
|
@ -823,6 +856,7 @@ __send_repl:
|
|
|
|
|
destroy_sexp(sx);
|
|
|
|
|
if(__conn_write(co, buf, strlen(buf)) < 0) {
|
|
|
|
|
co->flags &= ~CXCONN_ESTABL;
|
|
|
|
|
co->flags |= CXCONN_BROKEN;
|
|
|
|
|
__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
}
|
|
|
|
|
free(buf);
|
|
|
|
@ -1241,12 +1275,13 @@ static int __default_msg_return(void *cctx, sexp_t *sx)
|
|
|
|
|
smsg->flags |= ESXMSG_CLOSURE;
|
|
|
|
|
|
|
|
|
|
/* Q: can we remove the message from the tree there??? */
|
|
|
|
|
/* A: yep */
|
|
|
|
|
/* 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));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&(smsg->wait));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1403,10 +1438,10 @@ static void *__cxslave_thread_listener(void *wctx)
|
|
|
|
|
|
|
|
|
|
while((r = __conn_read(co, buf, 4096)) != -1) {
|
|
|
|
|
buf[r] = '\0';
|
|
|
|
|
//if(r) printf("Got the message %s (%d bytes)\n", buf, r);
|
|
|
|
|
r = __eval_cstr(buf, conn_sys->system_rpc, co);
|
|
|
|
|
}
|
|
|
|
|
co->flags &= ~CXCONN_ESTABL;
|
|
|
|
|
co->flags |= CXCONN_BROKEN;
|
|
|
|
|
__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
@ -1426,6 +1461,7 @@ static void *__cxmaster_thread_listener(void *wctx)
|
|
|
|
|
r = __eval_cstr(buf, conn_sys->system_rpc, co);
|
|
|
|
|
}
|
|
|
|
|
co->flags &= ~CXCONN_ESTABL;
|
|
|
|
|
co->flags |= CXCONN_BROKEN;
|
|
|
|
|
__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
@ -1598,6 +1634,7 @@ static void *__msg_queue_thread(void *ctx)
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1671,6 +1708,8 @@ static int __verify_certcall(int preverify_ok, X509_STORE_CTX *ctx)
|
|
|
|
|
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) {
|
|
|
|
@ -1688,6 +1727,12 @@ static int __verify_certcall(int preverify_ok, X509_STORE_CTX *ctx)
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* subsystem: here u can told me about how it's ugly to use global pointers,
|
|
|
|
|
* yep, it's a business of fucking morons, btw it works (heh, openssl uses this
|
|
|
|
|
* ancient shit method too, many many and many others too, trust me ...).
|
|
|
|
@ -1731,6 +1776,7 @@ void *__system_queue_listener(void *data)
|
|
|
|
|
/* 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1919,10 +1965,14 @@ int connection_initiate(conn_t *co, const char *host, int port,
|
|
|
|
|
co->mqueue = mqueue;
|
|
|
|
|
|
|
|
|
|
/* init SSL certificates and context */
|
|
|
|
|
co->ctx = SSL_CTX_new(SSLv3_client_method());
|
|
|
|
|
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_depth(co->ctx, 1); /* FIXME: use configuration */
|
|
|
|
|
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, conn_sys->rootca, NULL);
|
|
|
|
@ -1996,7 +2046,8 @@ int connection_initiate(conn_t *co, const char *host, int port,
|
|
|
|
|
// we've lost the connection
|
|
|
|
|
co->flags &= ~CXCONN_ESTABL;
|
|
|
|
|
r = ESXNOCONNECT;
|
|
|
|
|
__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
co->flags |= CXCONN_BROKEN;
|
|
|
|
|
//__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
free(buf);
|
|
|
|
|
/* shutdown connection */
|
|
|
|
|
goto __fail_3;
|
|
|
|
@ -2012,8 +2063,9 @@ int connection_initiate(conn_t *co, const char *host, int port,
|
|
|
|
|
if(bytes == -1) {
|
|
|
|
|
// we've lost the connection
|
|
|
|
|
co->flags &= ~CXCONN_ESTABL;
|
|
|
|
|
co->flags |= CXCONN_BROKEN;
|
|
|
|
|
r = ESXNOCONNECT;
|
|
|
|
|
__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
//__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
free(buf);
|
|
|
|
|
/* shutdown connection */
|
|
|
|
|
goto __fail_3;
|
|
|
|
@ -2104,7 +2156,7 @@ int connection_create(conn_t *co, int sck)
|
|
|
|
|
co->mqueue = mqueue;
|
|
|
|
|
|
|
|
|
|
/* init SSL certificates and context */
|
|
|
|
|
co->ctx = SSL_CTX_new(SSLv3_server_method());
|
|
|
|
|
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 */
|
|
|
|
@ -2174,7 +2226,8 @@ int connection_create(conn_t *co, int sck)
|
|
|
|
|
if(bytes < 0) {
|
|
|
|
|
printf("Terminate SSL connection, the other end is lost.\n");
|
|
|
|
|
co->flags &= ~CXCONN_ESTABL;
|
|
|
|
|
__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
co->flags |= CXCONN_BROKEN;
|
|
|
|
|
//__wake_up_waiters(co, ESXNOCONNECT);
|
|
|
|
|
r = ESXNOCONNECT;
|
|
|
|
|
goto __fail_3;
|
|
|
|
|
}
|
|
|
|
@ -2620,6 +2673,7 @@ static int __msg_reply(sxmsg_t *msg, sexp_t *sx, struct timespec *tio, int opcod
|
|
|
|
|
msg->flags |= ESXMSG_ISREPLY; /* this is a reply */
|
|
|
|
|
|
|
|
|
|
if(!sx) 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);
|
|
|
|
@ -2642,7 +2696,6 @@ static int __msg_reply(sxmsg_t *msg, sexp_t *sx, struct timespec *tio, int opcod
|
|
|
|
|
__destroy_msg(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|