v0.5.xx
Alexander Vdolainen 9 years ago
parent bbc0516191
commit 10aec3c447

@ -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;
}

Loading…
Cancel
Save